diff options
| author | Ido Hadanny <ido.hadanny@gmail.com> | 2011-09-22 21:30:13 +0300 |
|---|---|---|
| committer | Ido Hadanny <ido.hadanny@gmail.com> | 2011-09-22 21:30:13 +0300 |
| commit | 53b947df484159f5934898ba6c0aa69a9c869007 (patch) | |
| tree | 189d5903a67765c390de8f1e3423e6b80cde57d1 /roombacomm-client/src/com/hackingroomba/roombacomm/RoombaRecorderPanel.java | |
| parent | 654ca6d59e99b5e72b05dfb917bc5888c4ba6b1b (diff) | |
added stuff
Diffstat (limited to 'roombacomm-client/src/com/hackingroomba/roombacomm/RoombaRecorderPanel.java')
| -rw-r--r-- | roombacomm-client/src/com/hackingroomba/roombacomm/RoombaRecorderPanel.java | 582 |
1 files changed, 582 insertions, 0 deletions
diff --git a/roombacomm-client/src/com/hackingroomba/roombacomm/RoombaRecorderPanel.java b/roombacomm-client/src/com/hackingroomba/roombacomm/RoombaRecorderPanel.java new file mode 100644 index 0000000..5508019 --- /dev/null +++ b/roombacomm-client/src/com/hackingroomba/roombacomm/RoombaRecorderPanel.java @@ -0,0 +1,582 @@ +/* + * RoombaRecorderPanel - + * + * Copyright (c) 2006 Tod E. Kurt, tod@todbot.com, ThingM + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General + * Public License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307 USA + * + */ + +package com.hackingroomba.roombacomm; + +import java.awt.*; +import java.awt.event.*; +import javax.swing.*; +import javax.swing.event.*; +import javax.swing.text.*; +import java.util.*; + +/** + * A Panel containing controls for testing RoombaComm. + * Normally put inside of a frame, for example see RoombaCommTest + * + */ +public class RoombaRecorderPanel extends JPanel implements ActionListener,Runnable { + + JPanel ctrlPanel, selectPanel, buttonPanel, displayPanel; + JComboBox portChoices; + JCheckBox handshakeButton; + JTextArea displayText; + JButton connectButton; + JSlider speedSlider; + + RoombaCommSerial roombacomm; + + Thread thread; + ArrayList events; + ArrayList eventTimes; + //ActionEvent[] events; + //long[] eventTimes; + int eventCount; + int eventIndex; + int eventMax = 1000; // fixme: + long playStartTime; + long recStartTime; + boolean recording = false; + boolean playing = false; + boolean looping = false; + + public RoombaRecorderPanel() { + super(new BorderLayout()); + + roombacomm = new RoombaCommSerial(); + + events = new ArrayList(); + eventTimes = new ArrayList(); + eventIndex = 0; + eventCount = 0; + + makeSelectPanel(); + add(selectPanel, BorderLayout.NORTH); + + makeCtrlPanel(); + add(ctrlPanel, BorderLayout.EAST); + + makeButtonPanel(); + add(buttonPanel, BorderLayout.CENTER); + + makeDisplayPanel(); + add(displayPanel, BorderLayout.SOUTH); + + updateDisplay("RoombaComm, version "+RoombaComm.VERSION+"\n"); + + //bindKeys(); + + thread = new Thread(this); + thread.start(); + } + + /** + * Set to 'false' to hide the "h/w handshake" button, which seems to be + * only needed on Windows + */ + public void setShowHardwareHandhake(boolean b) { + handshakeButton.setVisible(b); + } + + /** */ + public boolean connect() { + String portname = (String) portChoices.getSelectedItem(); + roombacomm.debug=true; + roombacomm.waitForDSR = handshakeButton.isSelected(); + + connectButton.setText("connecting"); + if(!roombacomm.connect(portname)) { + updateDisplay("Couldn't connect to "+portname+"\n"); + connectButton.setText(" connect "); + roombacomm.debug=false; + return false; + } + updateDisplay("Roomba startup\n"); + + roombacomm.startup(); + roombacomm.control(); + roombacomm.pause(50); + roombacomm.playNote(72, 10); // C , test note + roombacomm.pause(200); + + connectButton.setText("disconnect"); + connectButton.setActionCommand("disconnect"); + updateDisplay("Roomba connected\n"); + roombacomm.debug=true; + return true; + } + + /** */ + public void disconnect() { + roombacomm.disconnect(); + connectButton.setText(" connect "); + connectButton.setActionCommand("connect"); + } + + public void stop() { + //thread.interrupt(); + if(recording) + eventCount = eventIndex; + recording = false; + playing = false; + updateDisplay("Stopped\n"); + } + public boolean play() { + if(eventCount==0) { + updateDisplay("nothing recorded\n"); + return false; + } + if(recording) + eventCount = eventIndex; + playStartTime = millis(); + playing = true; + recording = false; + eventIndex = 0; + updateDisplay("Playback...\n"); + return true; + } + public void record() { + recStartTime = millis(); + playing = false; + recording = true; + eventIndex = 0; + updateDisplay("Recording...\n"); + } + public void setLooping(boolean b) { looping = b; } + public boolean getLooping() { return looping; } + + public HashMap cut() { + HashMap m = copy(); + stop(); + eventCount=0; + return m; + } + public HashMap copy() { + HashMap m = new HashMap(); + m.put("events",events); + m.put("eventTimes",eventTimes); + m.put("portname", portChoices.getSelectedItem()); + updateDisplay("Copied "+eventCount+" events\n"); + return m; + } + public void paste(HashMap m) { + stop(); + ArrayList al1 = (ArrayList) m.get("events"); + ArrayList al2 = (ArrayList) m.get("eventTimes"); + portChoices.setSelectedItem(m.get("portname")); + if(al1!= null && al2!=null) { + events = al1; + eventTimes = al2; + eventCount = events.size(); + updateDisplay("Pasted "+eventCount+" events\n"); + } + } + + /** Implement Runnable */ + public void run() { + boolean done = false; + while(!done) { + if(playing && eventCount !=0) { + long t = ((Long)eventTimes.get(eventIndex)).longValue(); + //long t = eventTimes[eventIndex]; + if(millis() - playStartTime > t) { + ActionEvent event = (ActionEvent) events.get(eventIndex); + actionPerformed(event); + eventIndex++; + if(eventIndex == eventCount) { + if(!looping) { + playing = false; + } else { + eventIndex = 0; + playStartTime = millis(); + } + } + } + } + try { + Thread.sleep(10); + } catch(Exception e) { + done = true; + } + } + } + + /** + * Implement Actionlistener, also this is the locus for record & playback + * + */ + public void actionPerformed(ActionEvent event) { + String action = event.getActionCommand(); + String actstr = ""; + + if("comboBoxChanged".equals(action)) + return; // don't care about comboBox + + if(recording) { + long t = millis() - recStartTime; + actstr += t+":r#"+eventIndex+": "; + events.add(eventIndex, event); + eventTimes.add(eventIndex, new Long(millis()-recStartTime)); + eventIndex++; + } + if(playing) { + long t = millis() - playStartTime; + actstr += t+":p#"+eventIndex+": "; + } + updateDisplay(actstr+action+"\n"); /// DEBUG + + if("connect".equals(action)) { + updateDisplay("connecting...\n"); + connect(); + return; + } + else if("disconnect".equals(action)) { + updateDisplay("disconnecting.\n"); + disconnect(); + return; + } + else { + try { + int speed = Integer.parseInt(action); + //updateDisplay("setting speed = "+speed+"\n"); + roombacomm.setSpeed(speed); + return; + } catch(NumberFormatException e) { } + } + // stop right here if we're not connected + if(!roombacomm.connected()) { + updateDisplay("not connected!\n"); + return; + } + + //updateDisplay(action+"\n"); + if("stop".equals(action)) { + roombacomm.stop(); + } + else if("forward".equals(action)) { + roombacomm.goForward(); + } + else if("backward".equals(action)) { + roombacomm.goBackward(); + } + else if("spinleft".equals(action)) { + roombacomm.spinLeft(); + } + else if("spinright".equals(action)) { + roombacomm.spinRight(); + } + else if("turnleft".equals(action)) { + roombacomm.turnLeft(); + } + else if("turnright".equals(action)) { + roombacomm.turnRight(); + } + else if(action.matches("^turn[-+0-9]+$")) { + int turnval = Integer.parseInt(action.substring(4)); + System.out.println("turnval="+turnval); + roombacomm.turn(turnval); + } + else if("test".equals(action)) { + updateDisplay("Playing some notes\n"); + roombacomm.playNote(72, 10); // C + roombacomm.pause(200); + roombacomm.playNote(79, 10); // G + roombacomm.pause(200); + roombacomm.playNote(76, 10); // E + roombacomm.pause(200); + + updateDisplay("Spinning left, then right\n"); + roombacomm.spinLeft(); + roombacomm.pause(1000); + roombacomm.spinRight(); + roombacomm.pause(1000); + roombacomm.stop(); + + updateDisplay("Going forward, then backward\n"); + roombacomm.goForward(); + roombacomm.pause(1000); + roombacomm.goBackward(); + roombacomm.pause(1000); + roombacomm.stop(); + } + else if("reset".equals(action)) { + roombacomm.stop(); + roombacomm.startup(); + roombacomm.control(); + } + else if("power-off".equals(action)) { + roombacomm.powerOff(); + } + else if("wakeup".equals(action)) { + roombacomm.wakeup(); + } + else if("beep-lo".equals(action)) { + roombacomm.playNote(36, 10); // C1 + roombacomm.pause(200); + } + else if("beep-hi".equals(action)) { + roombacomm.playNote(120, 10); // C7 + roombacomm.pause(200); + } + else if("clean".equals(action)) { + roombacomm.clean(); + } + else if("spot".equals(action)) { + roombacomm.spot(); + } + else if("vacuum-on".equals(action)) { + roombacomm.vacuum(true); + } + else if("vacuum-off".equals(action)) { + roombacomm.vacuum(false); + } + else if("blink-leds".equals(action)) { + roombacomm.setLEDs(true,true,true, true,true,true, 255, 255); + roombacomm.pause(300); + roombacomm.setLEDs(false,false,false, false,false,false, 0, 128); + } + else if("sensors".equals(action)) { + if(roombacomm.updateSensors()) + updateDisplay(roombacomm.sensorsAsString()+"\n"); + else + updateDisplay("couldn't read Roomba. Is it connected?\n"); + } + } + + /** + * + */ + void makeSelectPanel() { + selectPanel = new JPanel(); + //Create a combo box with choices. + String[] ports = roombacomm.listPorts(); + portChoices = new JComboBox(ports); + portChoices.setSelectedIndex(0); + connectButton = new JButton(); + connectButton.setText(" connect "); + connectButton.setActionCommand("connect"); + handshakeButton = new JCheckBox("<html>h/w<br>handshake</html>"); + + //Add a border around the select panel. + selectPanel.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createTitledBorder("Select Roomba Port"), BorderFactory.createEmptyBorder())); + + selectPanel.add(portChoices); + selectPanel.add(connectButton); + selectPanel.add(handshakeButton); + + //Listen to events from the combo box. + portChoices.addActionListener(this); + connectButton.addActionListener(this); + } + + /** + * + */ + void makeCtrlPanel() { + JPanel ctrlPanel1 = new JPanel(new GridLayout(3,3)); + + JButton but_turnleft = + new JButton(createImageIcon("images/but_turnleft.png","turnleft")); + ctrlPanel1.add(but_turnleft); + JButton but_forward = + new JButton(createImageIcon("images/but_forward.png","forward")); + ctrlPanel1.add(but_forward); + JButton but_turnright = + new JButton(createImageIcon("images/but_turnright.png","turnright")); + ctrlPanel1.add(but_turnright); + + JButton but_spinleft = + new JButton(createImageIcon("images/but_spinleft.png","spinleft")); + ctrlPanel1.add(but_spinleft); + JButton but_stop = + new JButton(createImageIcon("images/but_stop.png", "stop")); + ctrlPanel1.add(but_stop); + JButton but_spinright = + new JButton(createImageIcon("images/but_spinright.png","spinright")); + ctrlPanel1.add(but_spinright); + + ctrlPanel1.add(new JLabel()); + JButton but_backward = + new JButton(createImageIcon("images/but_backward.png","backward")); + ctrlPanel1.add(but_backward); + ctrlPanel1.add(new JLabel()); + + JLabel speedLabel = new JLabel("speed (mm/s)", JLabel.CENTER); + JRadioButton speed050button = new JRadioButton("50"); + JRadioButton speed100button = new JRadioButton("100"); + JRadioButton speed150button = new JRadioButton("150"); + JRadioButton speed250button = new JRadioButton("250"); + JRadioButton speed400button = new JRadioButton("400"); + JRadioButton speed500button = new JRadioButton("500"); + speed050button.setVerticalTextPosition(SwingConstants.BOTTOM); + speed050button.setHorizontalTextPosition(SwingConstants.CENTER); + speed100button.setVerticalTextPosition(SwingConstants.BOTTOM); + speed100button.setHorizontalTextPosition(SwingConstants.CENTER); + speed150button.setVerticalTextPosition(SwingConstants.BOTTOM); + speed150button.setHorizontalTextPosition(SwingConstants.CENTER); + speed250button.setVerticalTextPosition(SwingConstants.BOTTOM); + speed250button.setHorizontalTextPosition(SwingConstants.CENTER); + speed400button.setVerticalTextPosition(SwingConstants.BOTTOM); + speed400button.setHorizontalTextPosition(SwingConstants.CENTER); + speed500button.setVerticalTextPosition(SwingConstants.BOTTOM); + speed500button.setHorizontalTextPosition(SwingConstants.CENTER); + + speed250button.setSelected(true); + + speed050button.addActionListener(this); + speed100button.addActionListener(this); + speed150button.addActionListener(this); + speed250button.addActionListener(this); + speed400button.addActionListener(this); + speed500button.addActionListener(this); + + ButtonGroup speedGroup = new ButtonGroup(); + speedGroup.add(speed050button); + speedGroup.add(speed100button); + speedGroup.add(speed150button); + speedGroup.add(speed250button); + speedGroup.add(speed400button); + speedGroup.add(speed500button); + + JPanel ctrlPanel2 = new JPanel(); + ctrlPanel2.add(speed050button); + ctrlPanel2.add(speed100button); + ctrlPanel2.add(speed150button); + ctrlPanel2.add(speed250button); + ctrlPanel2.add(speed400button); + ctrlPanel2.add(speed500button); + + ctrlPanel = new JPanel(); + ctrlPanel.setLayout(new BoxLayout(ctrlPanel, BoxLayout.Y_AXIS)); + ctrlPanel.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createTitledBorder("Movement"), BorderFactory.createEmptyBorder()));//5,5,5,5))); + ctrlPanel.add(ctrlPanel1); + ctrlPanel.add(ctrlPanel2); + ctrlPanel.add(speedLabel); + + but_turnleft.setActionCommand("turnleft"); + but_turnright.setActionCommand("turnright"); + but_spinleft.setActionCommand("spinleft"); + but_spinright.setActionCommand("spinright"); + but_forward.setActionCommand("forward"); + but_backward.setActionCommand("backward"); + but_stop.setActionCommand("stop"); + but_turnleft.addActionListener(this); + but_turnright.addActionListener(this); + but_spinleft.addActionListener(this); + but_spinright.addActionListener(this); + but_forward.addActionListener(this); + but_backward.addActionListener(this); + but_stop.addActionListener(this); + } + + /** + * + */ + void makeButtonPanel() { + buttonPanel = new JPanel(new GridLayout(8,2)); + buttonPanel.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createTitledBorder("Commands"), BorderFactory.createEmptyBorder()));//5,5,5,5))); + + JButton but_reset = new JButton("reset"); + JButton but_test = new JButton("test"); + JButton but_power = new JButton("power-off"); + JButton but_wakeup = new JButton("wakeup"); + JButton but_beeplo = new JButton("beep-lo"); + JButton but_beephi = new JButton("beep-hi"); + JButton but_clean = new JButton("clean"); + JButton but_spot = new JButton("spot"); + JButton but_vacon = new JButton("vacuum-on"); + JButton but_vacoff = new JButton("vacuum-off"); + JButton but_blinkleds = new JButton("blink-leds"); + JButton but_sensors = new JButton("sensors"); + + buttonPanel.add(but_reset); + buttonPanel.add(but_test); + buttonPanel.add(but_power); + buttonPanel.add(but_wakeup); + buttonPanel.add(but_beeplo); + buttonPanel.add(but_beephi); + buttonPanel.add(but_clean); + buttonPanel.add(but_spot); + buttonPanel.add(but_vacon); + buttonPanel.add(but_vacoff); + buttonPanel.add(but_blinkleds); + buttonPanel.add(but_sensors); + + but_reset.addActionListener(this); + but_test.addActionListener(this); + but_power.addActionListener(this); + but_wakeup.addActionListener(this); + but_beeplo.addActionListener(this); + but_beephi.addActionListener(this); + but_clean.addActionListener(this); + but_spot.addActionListener(this); + but_vacon.addActionListener(this); + but_vacoff.addActionListener(this); + but_blinkleds.addActionListener(this); + but_sensors.addActionListener(this); + } + + /** + * + */ + void makeDisplayPanel() { + displayPanel = new JPanel(); + displayPanel.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createTitledBorder("Display"), BorderFactory.createEmptyBorder()));//1,1,1,1))); + + displayText = new JTextArea(5,30); + displayText.setEditable(false); + displayText.setLineWrap(true); + DefaultCaret dc = new DefaultCaret(); + // only works on Java 1.5+ + //dc.setUpdatePolicy(DefaultCaret.ALWAYS_UPDATE); + displayText.setCaret(dc); + JScrollPane scrollPane = + new JScrollPane(displayText, + JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, + JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); + displayPanel.add(scrollPane); + } + + public void updateDisplay(String s) { + displayText.append(s); + displayText.setCaretPosition(displayText.getDocument().getLength()); + } + + /** Returns an ImageIcon, or null if the path was invalid. */ + protected static ImageIcon createImageIcon(String path, + String description) { + // yes, this is supposed to say "RoombaCommTest" + java.net.URL imgURL = RoombaCommPanel.class.getResource(path); + if (imgURL != null) { + return new ImageIcon(imgURL, description); + } else { + System.err.println("Couldn't find file: " + path); + return null; + } + } + + public int millis() { + int millisOffset = 0; + return (int) (System.currentTimeMillis() - millisOffset); + } + +} |
