2015-01-20 10:57:39 -07:00
// graphics
import java.awt.* ;
import java.awt.event.* ;
import javax.swing.* ;
2015-02-05 12:44:44 -07:00
import javax.swing.event.* ;
2015-01-20 10:57:39 -07:00
import java.awt.image.* ;
import javax.swing.border.* ;
// communication
import java.lang.* ;
import java.io.* ;
import java.net.* ;
/ * *
* Replaces GroundStation . java
* Written by Brendan Haines
* /
2015-02-05 12:44:44 -07:00
class GroundStation implements ActionListener , ChangeListener , Runnable {
2015-01-20 10:57:39 -07:00
//////////////////
///// FIELDS /////
//////////////////
/** string to hold the connection type */
private String connectionType = " " ;
/** boolean to hold connected/disconnected status */
private boolean connectionStatus = false ;
/** TCP/IP socket for communication */
private Socket tcpSocket ;
/** input buffer handling for tcpSocket */
private BufferedReader tcpIn ;
/** output handler for tcpSocket */
private PrintWriter tcpOut ;
/** thread to listen to tcpSocket */
private Thread tcpListener ;
2015-02-05 12:44:44 -07:00
/** FC arm status */
private boolean armStatus = false ;
2015-01-20 10:57:39 -07:00
// Main GUI components
/** window to hold GUI */
private JFrame mainFrame ;
/** panel to fill mainFrame */
private JPanel mainPanel ;
/** panel to hold connection options */
private JPanel connectionPanel ;
/** connection options panel */
private JPanel connectionOptionsPanel ;
/** connection type selection box */
private JComboBox connectionTypeComboBox ;
/** card layout container for different connection types */
private JPanel connectionTypePanel ;
/** JPanel to hold TCP/IP settings */
private JPanel tcpPanel ;
/** label for host address field */
private JLabel tcpHostAddressFieldLabel ;
/** text field for host address */
private JTextField tcpHostAddressField ;
/** label for port field */
private JLabel tcpHostPortFieldLabel ;
/** text field for port of socket */
private JTextField tcpHostPortField ;
/** connect/disconnect button */
private JButton connectButton ;
/** tabbed pane to hold many features */
private JTabbedPane tabbedPane ;
/** command line interface tab */
private JPanel cliPanel ;
/** panel to hold display options */
private JPanel cliOptionsPanel ;
/** checkbox to display confirmation/replies from pi */
private JCheckBox cliShowReceivedCheckBox ;
/** scrolling pane to hold command area */
private JScrollPane cliCommandScrollPane ;
/** text area to display commands */
private JTextArea cliCommandArea ;
/** panel to hold input stuff */
private JPanel cliInputPanel ;
/** text field to enter commands */
private JTextField cliInputField ;
/** send command button */
private JButton cliInputButton ;
/** control panel */
private JPanel controlPanel ;
/** arm/disarm flight controller button */
private JButton armDisarmButton ;
/** calibrate IMU button */
private JButton calibrateImuButton ;
/** motor testing tab */
private JPanel motorTestPanel ;
2015-02-05 12:44:44 -07:00
/** Motor testing enable checkbox */
private JCheckBox motorTestEnableCheckBox ;
/** Motor test values panel */
private JPanel motorTestValuesPanel ;
/** Motor 0 slider */
private JSlider motor0Slider ;
/** Motor 1 slider */
private JSlider motor1Slider ;
/** Motor 2 slider */
private JSlider motor2Slider ;
/** Motor 3 slider */
private JSlider motor3Slider ;
/** Master slider. sets all motor sliders to its value when changed */
private JSlider motorMasterSlider ;
2015-01-20 10:57:39 -07:00
////////////////////////
///// CONSTRUCTORS /////
////////////////////////
public GroundStation ( ) {
setupWindow ( ) ;
}
///////////////////
///// METHODS /////
///////////////////
/ * *
* sets up GUI
* /
private void setupWindow ( ) {
mainFrame = new JFrame ( " PiCopter Ground Station " ) ;
mainFrame . setResizable ( true ) ;
mainFrame . setDefaultCloseOperation ( JFrame . DISPOSE_ON_CLOSE ) ;
mainPanel = new JPanel ( ) ;
mainPanel . setLayout ( new BorderLayout ( ) ) ;
setupConnectionPanel ( ) ;
setupTabbedPane ( ) ;
mainPanel . add ( connectionPanel , BorderLayout . NORTH ) ;
mainPanel . add ( tabbedPane , BorderLayout . CENTER ) ;
mainFrame . add ( mainPanel ) ;
mainFrame . pack ( ) ;
mainFrame . setVisible ( true ) ;
}
/ * *
* sets up the connection panel
* /
private void setupConnectionPanel ( ) {
connectionPanel = new JPanel ( new BorderLayout ( ) ) ;
connectionPanel . setBorder ( BorderFactory . createTitledBorder ( " connection options " ) ) ;
connectionOptionsPanel = new JPanel ( new FlowLayout ( ) ) ;
connectionTypeComboBox = new JComboBox ( ) ;
connectionTypeComboBox . addItem ( " TCP/IP " ) ;
connectionTypeComboBox . setSelectedIndex ( 0 ) ;
connectionOptionsPanel . add ( connectionTypeComboBox ) ;
connectionTypePanel = new JPanel ( new CardLayout ( ) ) ;
tcpPanel = new JPanel ( new FlowLayout ( ) ) ;
tcpHostAddressFieldLabel = new JLabel ( " Host Address: " ) ;
tcpHostAddressField = new JTextField ( ) ;
tcpHostAddressField . setColumns ( 10 ) ;
tcpHostAddressField . setText ( " 192.168.42.1 " ) ;
tcpHostPortFieldLabel = new JLabel ( " Port: " ) ;
tcpHostPortField = new JTextField ( ) ;
tcpHostPortField . setColumns ( 6 ) ;
tcpHostPortField . setText ( " 51717 " ) ;
tcpPanel . add ( tcpHostAddressFieldLabel ) ;
tcpPanel . add ( tcpHostAddressField ) ;
tcpPanel . add ( tcpHostPortFieldLabel ) ;
tcpPanel . add ( tcpHostPortField ) ;
connectionTypePanel . add ( tcpPanel , " TCP/IP " ) ;
connectionOptionsPanel . add ( connectionTypePanel ) ;
connectionPanel . add ( connectionOptionsPanel , BorderLayout . NORTH ) ;
connectButton = new JButton ( " connect " ) ;
connectButton . addActionListener ( this ) ;
connectionPanel . add ( connectButton , BorderLayout . SOUTH ) ;
}
/ * *
* sets up tabs
* /
private void setupTabbedPane ( ) {
tabbedPane = new JTabbedPane ( ) ;
setupCliTab ( ) ;
setupControlTab ( ) ;
setupMotorTestTab ( ) ;
tabbedPane . add ( cliPanel , " CLI " , 0 ) ;
tabbedPane . add ( controlPanel , " Control " , 1 ) ;
tabbedPane . add ( motorTestPanel , " Motor Testing " , 2 ) ;
tabbedPane . setEnabledAt ( 1 , false ) ;
tabbedPane . setEnabledAt ( 2 , false ) ;
}
/ * *
* sets up command line interface tab
* /
private void setupCliTab ( ) {
cliPanel = new JPanel ( ) ;
cliPanel . setLayout ( new BorderLayout ( ) ) ;
cliOptionsPanel = new JPanel ( ) ;
cliOptionsPanel . setLayout ( new FlowLayout ( FlowLayout . LEFT ) ) ;
cliShowReceivedCheckBox = new JCheckBox ( " show receive " ) ;
cliShowReceivedCheckBox . setSelected ( true ) ;
cliShowReceivedCheckBox . addActionListener ( this ) ;
cliOptionsPanel . add ( cliShowReceivedCheckBox ) ;
cliCommandArea = new JTextArea ( ) ;
cliCommandArea . setEditable ( false ) ;
cliCommandScrollPane = new JScrollPane ( cliCommandArea ) ;
cliCommandScrollPane . setPreferredSize ( new Dimension ( 400 , 200 ) ) ;
new SmartScroller ( cliCommandScrollPane ) ;
cliInputPanel = new JPanel ( ) ;
cliInputPanel . setLayout ( new BorderLayout ( ) ) ;
cliInputField = new JTextField ( ) ;
cliInputField . addActionListener ( this ) ;
cliInputButton = new JButton ( " send " ) ;
cliInputButton . addActionListener ( this ) ;
cliInputPanel . add ( cliInputField , BorderLayout . CENTER ) ;
cliInputPanel . add ( cliInputButton , BorderLayout . EAST ) ;
cliPanel . add ( cliOptionsPanel , BorderLayout . NORTH ) ;
cliPanel . add ( cliCommandScrollPane , BorderLayout . CENTER ) ;
cliPanel . add ( cliInputPanel , BorderLayout . SOUTH ) ;
}
/ * *
* sets up control panel tab
* /
private void setupControlTab ( ) {
controlPanel = new JPanel ( new FlowLayout ( FlowLayout . LEFT ) ) ;
armDisarmButton = new JButton ( " arm " ) ;
armDisarmButton . addActionListener ( this ) ;
calibrateImuButton = new JButton ( " calibrate IMU " ) ;
calibrateImuButton . addActionListener ( this ) ;
controlPanel . add ( armDisarmButton ) ;
controlPanel . add ( calibrateImuButton ) ;
}
/ * *
* sets up motor testing tab
* /
private void setupMotorTestTab ( ) {
motorTestPanel = new JPanel ( ) ;
motorTestPanel . setLayout ( new BorderLayout ( ) ) ;
2015-02-05 12:44:44 -07:00
motorTestEnableCheckBox = new JCheckBox ( " Enable Motor Testing " ) ;
motorTestEnableCheckBox . setSelected ( false ) ;
motorTestEnableCheckBox . addActionListener ( this ) ;
motorTestValuesPanel = new JPanel ( ) ;
motorTestValuesPanel . setLayout ( new FlowLayout ( ) ) ;
2015-02-26 16:01:07 -07:00
motor0Slider = new JSlider ( 200 , 600 , 200 ) ;
2015-02-05 12:44:44 -07:00
motor0Slider . setOrientation ( JSlider . VERTICAL ) ;
motor0Slider . addChangeListener ( this ) ;
2015-02-26 16:01:07 -07:00
motor1Slider = new JSlider ( 200 , 600 , 200 ) ;
2015-02-05 12:44:44 -07:00
motor1Slider . setOrientation ( JSlider . VERTICAL ) ;
motor1Slider . addChangeListener ( this ) ;
2015-02-26 16:01:07 -07:00
motor2Slider = new JSlider ( 200 , 600 , 200 ) ;
2015-02-05 12:44:44 -07:00
motor2Slider . setOrientation ( JSlider . VERTICAL ) ;
motor2Slider . addChangeListener ( this ) ;
2015-02-26 16:01:07 -07:00
motor3Slider = new JSlider ( 200 , 600 , 200 ) ;
2015-02-05 12:44:44 -07:00
motor3Slider . setOrientation ( JSlider . VERTICAL ) ;
motor3Slider . addChangeListener ( this ) ;
2015-02-26 16:01:07 -07:00
motorMasterSlider = new JSlider ( 200 , 600 , 200 ) ;
2015-02-05 12:44:44 -07:00
motorMasterSlider . setOrientation ( JSlider . VERTICAL ) ;
motorMasterSlider . addChangeListener ( this ) ;
motorTestValuesPanel . add ( motor0Slider ) ;
motorTestValuesPanel . add ( motor1Slider ) ;
motorTestValuesPanel . add ( motor2Slider ) ;
motorTestValuesPanel . add ( motor3Slider ) ;
motorTestValuesPanel . add ( motorMasterSlider ) ;
enableComponents ( motorTestValuesPanel , false ) ;
motorTestPanel . add ( motorTestEnableCheckBox , BorderLayout . NORTH ) ;
motorTestPanel . add ( motorTestValuesPanel , BorderLayout . CENTER ) ;
2015-01-20 10:57:39 -07:00
}
/ * *
* enables / disables all components in a container
* @param container - the container to enable / disable components of
* @param enable - boolean value for . setEnabled ( )
* /
private void enableComponents ( Container container , boolean enable ) {
Component [ ] components = container . getComponents ( ) ;
for ( Component component : components ) {
component . setEnabled ( enable ) ;
if ( component instanceof Container ) {
enableComponents ( ( Container ) component , enable ) ;
}
}
}
/ * *
* actionPerformed method to handle ActionEvents from all buttons and GUI interaction
* /
public void actionPerformed ( ActionEvent evt ) {
// command line interface
if ( evt . getSource ( ) = = cliInputButton | | evt . getSource ( ) = = cliInputField ) {
String inputText = cliInputField . getText ( ) ;
cliInputField . setText ( " " ) ;
if ( inputText . equals ( " " ) ) return ; // if cliInput field is empty, do nothing
cliCommandArea . append ( inputText + " \ n " ) ;
if ( inputText . indexOf ( " CONNECT " ) = = 0 ) {
cliCommandArea . append ( " --ERROR - connection with command line interface not supported \ n " ) ;
}
else if ( inputText . indexOf ( " DISCONNECT " ) = = 0 ) {
disconnect ( ) ;
}
else if ( inputText . indexOf ( " SEND " ) = = 0 ) {
String sendText = inputText . substring ( 5 , inputText . length ( ) ) ;
cliCommandArea . append ( " --SENDING: " + sendText + " \ n " ) ;
tcpOut . println ( sendText ) ;
}
else if ( inputText . indexOf ( " CLEAR " ) = = 0 ) {
cliCommandArea . setText ( " " ) ;
}
else {
}
}
// connect button
else if ( evt . getSource ( ) = = connectButton & & evt . getActionCommand ( ) . equals ( " connect " ) ) {
if ( connectionTypeComboBox . getSelectedItem ( ) . equals ( " TCP/IP " ) ) {
connectionType = " TCP/IP " ;
if ( tcpHostAddressField . getText ( ) . equals ( " " ) | | tcpHostPortField . getText ( ) . equals ( " " ) ) {
System . out . println ( " must enter an address & port for TCP/IP " ) ;
}
else if ( connectTCP ( tcpHostAddressField . getText ( ) , Integer . parseInt ( tcpHostPortField . getText ( ) ) ) ) {
startTcpListener ( ) ;
}
else {
System . out . println ( " failed to connect to TCP/IP server " ) ;
}
}
else {
System . out . println ( " idk how you did that, but this protocol isn't supported...connectionTypeComboBox conains \" " + connectionTypeComboBox . getSelectedItem ( ) + " \" " ) ;
}
}
// disconnect button
else if ( evt . getSource ( ) = = connectButton & & evt . getActionCommand ( ) . equals ( " disconnect " ) ) {
disconnect ( ) ;
}
// arm button
else if ( evt . getSource ( ) . equals ( armDisarmButton ) & & evt . getActionCommand ( ) . equals ( " arm " ) ) {
cliCommandArea . append ( " --ARMING... " ) ;
tcpOut . println ( " ARM_CONTROLLER " ) ;
2015-02-05 12:44:44 -07:00
armStatus = true ;
2015-01-20 10:57:39 -07:00
armDisarmButton . setText ( " disarm " ) ;
cliCommandArea . append ( " DONE \ n " ) ;
}
// disarm button
else if ( evt . getSource ( ) . equals ( armDisarmButton ) & & evt . getActionCommand ( ) . equals ( " disarm " ) ) {
cliCommandArea . append ( " --DISARMING... " ) ;
tcpOut . println ( " DISARM_CONTROLLER " ) ;
2015-02-05 12:44:44 -07:00
armStatus = false ;
2015-01-20 10:57:39 -07:00
armDisarmButton . setText ( " arm " ) ;
cliCommandArea . append ( " DONE \ n " ) ;
}
2015-02-05 12:44:44 -07:00
// motor test checkbox
else if ( evt . getSource ( ) . equals ( motorTestEnableCheckBox ) ) {
if ( motorTestEnableCheckBox . isSelected ( ) ) {
enableComponents ( motorTestValuesPanel , true ) ;
}
else {
disableMotorTest ( ) ;
}
}
}
/ * *
* handles changes in JSlider positions
* /
public void stateChanged ( ChangeEvent evt ) {
if ( evt . getSource ( ) . equals ( motor0Slider ) ) {
tcpOut . println ( " SET_MOTOR_00_ " + motor0Slider . getValue ( ) ) ;
}
else if ( evt . getSource ( ) . equals ( motor1Slider ) ) {
tcpOut . println ( " SET_MOTOR_01_ " + motor1Slider . getValue ( ) ) ;
}
else if ( evt . getSource ( ) . equals ( motor2Slider ) ) {
tcpOut . println ( " SET_MOTOR_02_ " + motor2Slider . getValue ( ) ) ;
}
else if ( evt . getSource ( ) . equals ( motor3Slider ) ) {
tcpOut . println ( " SET_MOTOR_03_ " + motor3Slider . getValue ( ) ) ;
}
else if ( evt . getSource ( ) . equals ( motorMasterSlider ) ) {
motor0Slider . setValue ( motorMasterSlider . getValue ( ) ) ;
motor1Slider . setValue ( motorMasterSlider . getValue ( ) ) ;
motor2Slider . setValue ( motorMasterSlider . getValue ( ) ) ;
motor3Slider . setValue ( motorMasterSlider . getValue ( ) ) ;
}
2015-01-20 10:57:39 -07:00
}
/ * *
* connects over TCP / IP protocol
* @param hostAddress - the ip address of the server host
* @param hostPort - the port of the socket at the host
* @return true on success , false on failure
* /
private boolean connectTCP ( String hostAddress , int hostPort ) {
cliCommandArea . append ( " --CONNECTING WITH TCP... " ) ;
try {
tcpSocket = new Socket ( hostAddress , hostPort ) ;
tcpIn = new BufferedReader ( new InputStreamReader ( tcpSocket . getInputStream ( ) ) ) ;
tcpOut = new PrintWriter ( tcpSocket . getOutputStream ( ) , true ) ;
startTcpListener ( ) ;
}
catch ( UnknownHostException ex ) {
cliCommandArea . append ( " UnknownHostException \ n " ) ;
return false ;
}
catch ( IOException ex ) {
cliCommandArea . append ( " IOException \ n " ) ;
return false ;
}
setGuiConnected ( ) ;
connectionStatus = true ;
cliCommandArea . append ( " DONE \ n " ) ;
return true ;
}
/ * *
*
* /
private void startTcpListener ( ) {
tcpListener = new Thread ( this , " tcpListenerThread " ) ;
tcpListener . start ( ) ;
}
/ * *
* the method used by the TCP listening thread
* /
public void run ( ) {
while ( connectionStatus ) {
try {
if ( tcpIn . ready ( ) ) {
cliRxAppend ( " --READING: " + tcpIn . readLine ( ) + " \ n " ) ;
}
}
catch ( Exception ex ) { }
}
}
/ * *
* will add the message to cli view if show receive checkbox is checked
* /
public void cliRxAppend ( String message ) {
if ( cliShowReceivedCheckBox . isSelected ( ) ) {
cliCommandArea . append ( message ) ;
}
}
/ * *
*
* /
private void setGuiConnected ( ) {
connectButton . setText ( " disconnect " ) ;
tabbedPane . setEnabledAt ( 1 , true ) ; // control panel
tabbedPane . setEnabledAt ( 2 , true ) ; // motor testing panel
enableComponents ( connectionOptionsPanel , false ) ;
mainFrame . setDefaultCloseOperation ( JFrame . DO_NOTHING_ON_CLOSE ) ;
}
/ * *
*
* /
private void setGuiDisconnected ( ) {
connectButton . setText ( " connect " ) ;
tabbedPane . setSelectedIndex ( 0 ) ;
tabbedPane . setEnabledAt ( 1 , false ) ; // control panel
tabbedPane . setEnabledAt ( 2 , false ) ; // motor testing panel
enableComponents ( connectionOptionsPanel , true ) ;
mainFrame . setDefaultCloseOperation ( JFrame . DISPOSE_ON_CLOSE ) ;
}
/ * *
* disconnects from whatever connection has been set up with Raspberry Pi
* /
private void disconnect ( ) {
2015-02-05 12:44:44 -07:00
cliCommandArea . append ( " --DISCONNECTING... \ n " ) ;
2015-01-20 10:57:39 -07:00
2015-02-05 12:44:44 -07:00
disableMotorTest ( ) ;
// Thread.sleep( 5 );
2015-01-20 10:57:39 -07:00
tcpOut . println ( " DISCONNECT " ) ;
try {
tcpIn . close ( ) ;
tcpOut . close ( ) ;
}
catch ( IOException ex ) {
cliCommandArea . append ( " IOException \ n " ) ;
return ;
}
setGuiDisconnected ( ) ;
connectionStatus = false ;
cliCommandArea . append ( " DONE \ n " ) ;
}
2015-02-05 12:44:44 -07:00
/ * *
*
* /
private void disableMotorTest ( ) {
motorMasterSlider . setValue ( 150 ) ;
motor0Slider . setValue ( 150 ) ;
motor1Slider . setValue ( 150 ) ;
motor2Slider . setValue ( 150 ) ;
motor3Slider . setValue ( 150 ) ;
enableComponents ( motorTestValuesPanel , false ) ;
try {
Thread . sleep ( 500 ) ;
}
catch ( Exception e ) { }
motorTestEnableCheckBox . setSelected ( false ) ;
}
2015-01-20 10:57:39 -07:00
/ * *
* main begins the ground station
* /
public static void main ( String [ ] args ) {
GroundStation groundStation = new GroundStation ( ) ;
}
}