Title: Event Driven Programming Minus the GUI Plus a Robot
1Event Driven ProgrammingMinus the GUIPlus a
Robot
2Why Event-Driven Robotics?
- This robot consists of sensors and motors.
- Event driven programming decouples sensor
monitoring and motor controlling. Different
classes specialize, compartmentalizing the
hardware. - Can more easily switch out sensors or motors, as
long as everyone can use the same event system
and events.
3Robot Gear
- Hardware Lego Mindstorm NXT - servos, sensors
and an ARM processor - Software open-source 3rd party firmware called
leJOS, which runs compiled Java bytecode
4The old bot configuration
5Current bot configuration
6Architecture (part 1)
- Lejos library has a class, SensorPort
- SensorPort.addSensorPortListener(
SensorPortListener aListener) is a public method - SensorPortListener Interface, has one method
- void stateChanged(SensorPort source, int
oldValue, int newValue)
7This seemed a real coup
- leJOS looked to be designed for event-driven
programming - Wire up SensorPortListeners to a few sensors,
have each steer in different ways when triggered
8Problem
- API Documentation out of date. Forum search
revealed SensorPortListener was deprecated for
most sensors. - Only works on one sensor I have, touch.
- Doesnt actually work.
9Program Architecture (part 2)
- Slightly more complex.
- One class, SensorReader, iterates through a
couple of sensors. If certain values are hit,
fire a certain event. - Another class, EventHandler, receives these
events and changes the motors accordingly.
10How do these classes communicate?
- Each runs on its own thread.
- They pass messages over a shared, synchronized
queue. - This means events are handled approximately in
the order created, barring synchronization issues - (Bonus What is a better / more granular / more
responsive data structure than a regular queue,
given events with different priorities?)
11DIAGRAM
12Code sample from Architecture 1
- public static void main (String aArg)
- Robot robot new Robot()
- SensorPort.S1.
- addSensorPortListener(robot)
- robot.moveForward()
-
- In Robot
- public void moveForward()
- Motor.A.setSpeed(20)
- Motor.B.setSpeed(20)
- while (!ts.isPressed()) //ts
instanceof TouchSensor - Motor.A.forward()
- Motor.B.forward()
-
- //bonus - what part is NOT very event-driven
here?
13Code sample from Architecture 1
- public void stateChanged(SensorPort port, int
oldValue, int newValue) //replace with
diff values checking in oldValue, newValue
//otherwise not very event-driven if
(oldValue lt 500 newValue lt 500)
Motor.A.stop() - Motor.B.stop()
- Motor.A.setSpeed(20)
- Motor.B.setSpeed(20)
- Motor.A.backward()
- Motor.B.backward()
- Thread.sleep(100)
- Motor.A.stop()
- Motor.B.stop()
- Motor.A.forward()
- Motor.B.backward()
- Thread.sleep(250)
- Motor.A.stop()
- Motor.B.stop()
- moveForward()
14Architecture 2 Code
- public class SynchronizedQueueltEgt
- private final ArrayListltEgt queue
- public void push(E o)
- synchronized(queue)
- queue.add(o)
- queue.notify()
-
-
- public E pop()
- synchronized(queue)
- while (queue.isEmpty())
- queue.wait()
-
- return queue.remove(0)
-
-
15Architecture 2 code SensorReader(note ts is
a TouchSensor instance)
- public void run()
- while (true)
- if(ts.isPressed())
- queue.push(new RobotEvent(
- RobotEventInt.BACKUP))
- else
- queue.push(new RobotEvent(
- RobotEventInt.FORWARD))
-
-
- try
- Thread.sleep(200)
- catch (InterruptedException e)
- System.out.println("Sensor interrupted")
-
-
16Architecture 2 code EventResponders run method.
Both implement Runnable, an interface allowing
them to run in separate Threads.Bonus What is
missing?
- public void run()
- while(true)
- RobotEventInt curr queue.pop()
- if (curr.getName().equals(
- RobotEventInt.FORWARD))
-
- leftMotor.forward()
- rightMotor.forward()
- else if (curr.getName().equals(
- RobotEventInt.BACKUP))
-
- if (!leftMotor.isStopped()
- !rightMotor.isStopped())
-
- leftMotor.stop()
- rightMotor.stop()
-
- leftMotor.backward()
- rightMotor.backward()
17Interface Runnable
- One method
- public void run()
- Add a Runnable implementor to a Thread, run
Thread.start(), and the code in run() executes
asynchronously.
18RobotEvent
- Implements RobotEventInt, a collection of static
String values (RobotEventInt.BACKUP) and one
method, getName(), which should always be one of
RobotEventInts static String values.
19Architecture 2 Working Yet?
- Still working at it. Robot throws an error that
indicates not all classes loaded, which print
statements dont seem to verify. Runs fine until
queue.pop() in EventResponder.
20Lessons Learned
- If you learn about deprecated classes in a
library from an online forum and NOT from the
librarys API, try to switch libraries. - (Also, if you shutdown and accidentally suspend
an Ubuntu laptop and then power-cycle it, some
perfect storm wipes out /sys and some of /sbin) - (On a related note, Dropbox is great for backing
up your work)