RasPi/GroundStation/v1/GroundStation.java

558 lines
19 KiB
Java
Raw Normal View History

2015-01-20 10:57:39 -07:00
// graphics
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
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
*/
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;
/** 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;
/** 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() );
motorTestEnableCheckBox = new JCheckBox( "Enable Motor Testing" );
motorTestEnableCheckBox.setSelected( false );
motorTestEnableCheckBox.addActionListener( this );
motorTestValuesPanel = new JPanel();
motorTestValuesPanel.setLayout( new FlowLayout() );
motor0Slider = new JSlider( 150, 600, 150 );
motor0Slider.setOrientation( JSlider.VERTICAL );
motor0Slider.addChangeListener( this );
motor1Slider = new JSlider( 150, 600, 150 );
motor1Slider.setOrientation( JSlider.VERTICAL );
motor1Slider.addChangeListener( this );
motor2Slider = new JSlider( 150, 600, 150 );
motor2Slider.setOrientation( JSlider.VERTICAL );
motor2Slider.addChangeListener( this );
motor3Slider = new JSlider( 150, 600, 150 );
motor3Slider.setOrientation( JSlider.VERTICAL );
motor3Slider.addChangeListener( this );
motorMasterSlider = new JSlider( 150, 600, 150 );
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" );
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" );
armStatus = false;
2015-01-20 10:57:39 -07:00
armDisarmButton.setText( "arm" );
cliCommandArea.append( "DONE\n" );
}
// 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() {
cliCommandArea.append( "--DISCONNECTING...\n");
2015-01-20 10:57:39 -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" );
}
/**
*
*/
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();
}
}