Lejos Statemachines

Post your NXJ projects, project ideas, etc here!

Moderators: 99jonathan, roger, imaqine

Lejos Statemachines

Postby ft.zimmermann » Mon Dec 03, 2007 7:50 am

I developed a prototype eclipse plugin for modelling statemachines which can be executed and animated on the brick.

Uses a Topcased generated modeller for modelling state actions and event conditions. Java code is generated using oaw.
A small statemachine framework executes the statemachine on the brick. Optionally the executed state is highlighted in the diagram. Communication is done with BT.

I don't think that the project can be used by someboby else but me, because of lack of documentation and the fact that it is a prototype. Still your comment to the approach might be valuable to me.
Last edited by ft.zimmermann on Mon Dec 17, 2007 9:05 am, edited 1 time in total.
ft.zimmermann
Novice
 
Posts: 35
Joined: Sat Sep 01, 2007 7:18 pm
Location: Hamburg, Germany

Postby bbagnall » Wed Dec 12, 2007 4:41 pm

It sounds like a bit of an emulator. If you can get this into working form and make it available we could better judge if this would be useful for anyone.
User avatar
bbagnall
Site Admin
 
Posts: 392
Joined: Fri Aug 04, 2006 4:03 pm

Postby ft.zimmermann » Fri Dec 14, 2007 8:52 pm

Maybe the following screenshot gives an impression. It is a statemachine of a line follower for a broken line. The diagram shows the complete application. No manual programming is required. Just download and run.

When the statemachine executes on the brick, the actual states are highlighted in the diagram.


Image

I have two more working examples: BumperCar uses the touch sensor and CatChaser the Ultrasonic Sensor. This version of the software is using gmf.
Last edited by ft.zimmermann on Mon Dec 17, 2007 9:06 am, edited 1 time in total.
ft.zimmermann
Novice
 
Posts: 35
Joined: Sat Sep 01, 2007 7:18 pm
Location: Hamburg, Germany

Postby lawrie » Sat Dec 15, 2007 2:44 pm

The link to the image is not working at the moment - perhaps the site is down.

Its a bit mean giving us a glimpse of this interesting project and then not letting us see it. I would be very interested in you posting your model, plug-in source, etc, as soon as it is possible, even if it is incomplete and undocumented.

Does your PC code that animates the diagram communicate over Bluetooth with the brick to follow all the state changes and actions?

I am interested in model driven development for leJOS. I started on a Visual Programming interface for leJOS but have stopped work on it as I have too much to do getting all the basic features we need into NXJ.

It would be interesting to see if your model could be extended to include behavior programming. I am thinking that the model would consist of a set of behaviors, each of which was controlled by a state machine. The generated program would use the leJOS behavior classes.
lawrie
leJOS Team Member
 
Posts: 929
Joined: Mon Feb 05, 2007 1:27 pm

Modelling

Postby ft.zimmermann » Sun Dec 16, 2007 8:35 am

Our site is down at the moment. Sorry about this.

You are right the communication is via bluetooth. For "show" purposes I added speech output with freetts.

Right now the behaviour is entered as java code into the model. Every state has entry, do and exit behaviour like it is usual in UML. There are implicit (behaviour ended) and explit events (e.g. light on). Every transition holds a guard condition and a time constaint to program delays.

The statemachine works pretty much like the behaviour classes, but I tried to abstract from the concurrency issues, that go with standard lejos behaviours. To get it working right, there a modified pilot class. Not very elegant, but it works more or less.

To give a nonvisual impression this is the generated code

Code: Select all
import de.nordakademie.lejos.statemachine.*;
import lejos.nxt.*;
import lejos.navigation.*;
public class LineFollower {

   private NPilot pilot = new NPilot(5.3f, 11.2f, Motor.A, Motor.C);
   private LightSensor light1 = new LightSensor(SensorPort.S1, true);
   private int tolerance = 1;
   private boolean initialized = false;

   public IState driveOnLine = new AbstractState() {
      public void doIt() throws InterruptedException {
         pilot.forward();
      }
      public void entry() {
         pilot.setSpeed(320);
      }
      public String getName() {
         return "DriveOnLine";
      }
   };

   public IState searchLine = new AbstractState() {
      private int sweep = 10;
      private int dir = 1;
      public void doIt() throws InterruptedException {
         while (sweep < 40) {
            pilot.rotate(sweep * dir);
            dir *= -1;
            sweep *= 2;
         }
         pilot.rotate(dir * sweep / 4);
      }
      public void entry() {
         sweep = 10;
      }
      public String getName() {
         return "SearchLine";
      }
   };

   public IState forward = new AbstractState() {
      public void doIt() throws InterruptedException {
         pilot.travel(10);
      }
      public String getName() {
         return "Forward";
      }
   };

   public ITransition light = new AbstractTransition(searchLine) {
      public boolean guard() {
         return light1.readValue() > 40 + tolerance;
      }
      public String getName() {
         return "Light";
      }
   };

   public ITransition dark = new AbstractTransition(driveOnLine) {
      public boolean guard() {
         return light1.readValue() < 40 - tolerance;
      }
      public String getName() {
         return "Dark";
      }
   };

   public ITransition exit = new AbstractTransition() {
      public boolean guard() {
         return Button.ESCAPE.isPressed();
      }
      public String getName() {
         return "Exit";
      }
   };

   public static void main(String[] args) {
      LineFollower lineFollower = new LineFollower();
      lineFollower.arbitrate();
   }

   public synchronized void arbitrate() {
      init();
      driveOnLine.arbitrate(0);

   }
   public String getName() {
      return "LineFollower";
   }

   public boolean isRunning() {
      return initialized && driveOnLine.isRunning();
   }

   private void init() {
      if (!initialized) {
         driveOnLine.setTransitions(new ITransition[]{light, exit});
         searchLine.setImplicitTransitions(new ITransition[]{new AbstractTransition(forward) {}});
         searchLine.setTransitions(new ITransition[]{dark, exit});
         forward.setImplicitTransitions(new ITransition[]{new AbstractTransition(searchLine) {}});
         forward.setTransitions(new ITransition[]{dark});
         initialized = true;
      }
   }

}
Last edited by ft.zimmermann on Mon Dec 17, 2007 9:07 am, edited 1 time in total.
ft.zimmermann
Novice
 
Posts: 35
Joined: Sat Sep 01, 2007 7:18 pm
Location: Hamburg, Germany

Postby lawrie » Sun Dec 16, 2007 8:48 pm

Why did you need a modified Pilot class?

Is there a change to the leJOS pilot class which would make it suitable for your purpose?
lawrie
leJOS Team Member
 
Posts: 929
Joined: Mon Feb 05, 2007 1:27 pm

Postby lawrie » Sun Dec 16, 2007 9:19 pm

I am not currently very familiar with Eclipse GMF, Topcased, and oaw.

Can you explain the role of each and how they work together in your project?
lawrie
leJOS Team Member
 
Posts: 929
Joined: Mon Feb 05, 2007 1:27 pm

Postby 99jonathan » Mon Dec 17, 2007 1:30 am

A little side note here - is maschines British for machines? (as behaviour might be for behavior?)
99jonathan
Moderator
 
Posts: 122
Joined: Thu Mar 01, 2007 5:30 am

Pilot Class and Roles

Postby ft.zimmermann » Mon Dec 17, 2007 8:49 am

I started with the pilot class from lejos 0.3.
To abstract from the concurrency each pilot movement should react to interrupts by throwing an InteruptedException.
The Lejos classes use busy waits. What I mean:
Code: Select all
while (!isMoving()) Thread.yield();


( Doesn't this shift dispatching from the VM into the Java program? Maybe it will be changed later). I replaced it by

Code: Select all
while (!isMoving()){
   if (Thread.isInterrupted()) throw oldInterruptedException;
   Thread.yield();
}

Btw "throw new InterruptedException()" of course causes a memory leek, so it throws an oldInterruptedException :wink: which is a final static variable.


Role of GMF, oAW: GMF is used to develop graphical modelling tools. You define figures, labels and compartments and map them to the domain (meta)model like state, event, etc.. GMF generates a diagram editor, which has a lot of cool features and can be extended easily.
The models are stored in a xml file (EMF to be more precise), and oAW is used to generate java classes from a template. Both tools are part of the eclipse modelling project.
Last edited by ft.zimmermann on Mon Dec 17, 2007 9:39 am, edited 4 times in total.
ft.zimmermann
Novice
 
Posts: 35
Joined: Sat Sep 01, 2007 7:18 pm
Location: Hamburg, Germany

Postby MrQuincle » Mon Dec 17, 2007 9:02 am

99jonathan wrote:A little side note here - is maschines British for machines? (as behaviour might be for behavior?)


No it is German for machines. :-)
MrQuincle
New User
 
Posts: 3
Joined: Fri Dec 14, 2007 2:45 pm

Typo

Postby ft.zimmermann » Mon Dec 17, 2007 9:29 am

:oops: you're right. If I hadn't this typo in all my class and package names it would only be the embarrassing typo in the headline, now it is a lot of work too. Thank's anyhow.
ft.zimmermann
Novice
 
Posts: 35
Joined: Sat Sep 01, 2007 7:18 pm
Location: Hamburg, Germany

Postby mpscholz » Tue Jan 22, 2008 2:44 pm

Lawrie,

lawrie wrote:I am not currently very familiar with Eclipse GMF, Topcased, and oaw.
Can you explain the role of each and how they work together in your project?


Generally speaking, the general flow for a model-driven approach is as follows:

1. Model the application based on a abstract DSL (Domain-specific language describing the domain) with a concrete syntax (most of the time this is a graphical notation)
2. Run an instance of a transformation that transforms a model instance into entities of a target domain (in our case leJOS NXJ code classes)

For part 1, you need the DSL and an editor. They must have been supplied by the provider of the modelling framework (Frank Zimmermann, in this case). This is where GMF and Topcased come into play - these are tools/frameworks that allow you to define your DSL and create editors that allow developers to model into that DSL.

For part 2, you need a transformation engine - in our case OAW (Open Architecture Ware) plays that role. It allows for defining transformations from (almost) arbitrary source domains (input models) into target domains (Java source code, for instance).
leJOS Developer
mpscholz
New User
 
Posts: 20
Joined: Fri Jan 18, 2008 1:37 pm
Location: Germany

Postby lawrie » Tue Jan 22, 2008 3:05 pm

Hi Matthias,

Thanks for that explanation. I plan to look into adding graphical modelling capability to leJOS along these lines when I get the chance. My first step will be to try out this state machine language via the link to the Eclipse update site that Professor Zimmermann posted. Have you experimented with it?

I was interested in the relationship between these state machines and subsumption architecture, as supported by leJOS. Frank Zimmermann explained it to me in a previous reply. I do not quite understand the concurrency issues with Pilot, and want to look into that as well.

It would be excellent if we could have a graphical modelling language with animated models as a standard leJOS feature.

Lawrie
lawrie
leJOS Team Member
 
Posts: 929
Joined: Mon Feb 05, 2007 1:27 pm

testing statemachines

Postby ft.zimmermann » Tue Jan 22, 2008 4:41 pm

Hi lawrie,

if you like I could provide for convinience a full eclipse installation of 180 MB.

The reason I do not do it is, that our server is pretty slow. It would take at least 45 min to download.

Actually I am new to robotics. With respect to the relationship of statemachines to subsumption my point of view is the following now:

1. Roboties call on subsumption: small robust (i.e. stateless) behaviors that will be executed in a priority chain.
2. Embeddies prefer statemachines.

To explain this look at a simple line follower.
subsumption goes somehow like this:

while (alive){
if (light1<40){ // black avoidance behavior
leftMotor.forward(50); rightMotor.forward(100); //turn left
} else { // default behavior
leftMotor.forward(100); rightMotor.forward(50); //turn right
}
}


I guess you have seen this before.

The robot will move on one side of a line. If you put it on the other side it should turn.

Now if yo want to construct a both-side-of-the-line-follower you either need a state (sweep left/right which is bad, because states are not robust to incorrect sensor readings) or you use a second light sensor on the other side of the line and programm a second avoidance behavior which turn to the other side. Trading sensors for state makes the robot robust.

In my eyes the introduction of stateful behavior comes sooner or later if the robot becomes more complex. Hybrid machines are pretty common.

Nevertheles embedded systems need not to handle with inaccurate readings of sensor values. That's why these people are not so afraid of states and are willing to start a stateful design from the beginning.


The NXT is only a small machine with few sensor ports. You cannot trade sensors for state, because the average NXT owner has only one of each kind. So I think the statemachine approach is valid on the NXT.

Statemachines are hard to read and maintain, when written as a linear program. This is avoided by the visual modeler which is at least two dimensional.

Statemachines can be made robust by avaraging the sensor values and hysteresis.


Frank
ft.zimmermann
Novice
 
Posts: 35
Joined: Sat Sep 01, 2007 7:18 pm
Location: Hamburg, Germany


Return to NXJ Projects

Who is online

Users browsing this forum: No registered users and 0 guests

more stuff