threads & behaviours

27
Robo$cs & Autonomous Systems A Prac’cal Introduc’on with NXT and JAVA Threads and Behaviours Michael Wooldridge (mjw @ liv.ac.uk)

Upload: others

Post on 11-Feb-2022

11 views

Category:

Documents


0 download

TRANSCRIPT

Robo$cs  &  Autonomous  Systems    

A  Prac'cal  Introduc'on  with  NXT  and  JAVA    

Threads  and  Behaviours  

Michael  Wooldridge  (mjw @ liv.ac.uk)

Threads  on  NXT  

• More  or  less  impossible  to  do  robot  programming  without  making  use  of  threads  

• Threads  typically  used  e.g.,  to  monitor  sensors  and  ensure  reac<ve  behaviour….    

Using  Threads:  A  Case  Study  

• We  will  use  threads  to  build  a  class  that  con<nually  monitors  sensors  and  motors  and  displays  their  status  on  the  LCD  panel  

• The  thread  to  do  this  will  run  in  the  background,  allowing  us  to  focus  on  the  main  work  we  want  to  do  

• Threads  that  run  in  the  background  in  this  way  are  called  daemons  

StandardRobot.java  

• We  first  define  a  class  to  make  our  lives  a  liCle  simpler  as  programmers    

• We  can  reuse  this  class  whenever  we  use  the  standard  configura<on  robot  

import lejos.nxt.*;import lejos.nxt.addon.ColorSensorHT;public class StandardRobot { public static ColorSensorHT cs; public static TouchSensor ts; public static UltrasonicSensor us; public static NXTMotor ma, mb; public StandardRobot() {

// instantiate sensorsus = new UltrasonicSensor(SensorPort.S1);cs = new ColorSensorHT(SensorPort.S2);ts = new TouchSensor(SensorPort.S4);

// instantiate motorsma = new NXTMotor(MotorPort.A);

mb = new NXTMotor(MotorPort.B);

}}

Design  Decisions  

• What  happens  if  we  create  more  than  one  instance  of  this  class?  

• How  can  we  design  the  code  so  that  this  is  impossible?  

• This  is  the  interface  to  the  robot,  rather  than  a  robot  itself  

• How  can  we  design  a  StandardRobot  class  so  that  it  has  this  code,  and  allows  the  user  to  add  their  own  behaviour…?  

RobotMonitor.java  

• Now  we  create  our  RobotMonitor  class  

• This  will  be  a  daemon  that  sits  in  the  background,  periodically  polling  sensors  &  motors  and  displaying  their  state  on  the  LCD  panel  

RobotMonitor.java  (part  1)  import java.lang.Thread;import java.lang.Boolean;import lejos.nxt.*;public class RobotMonitor extends Thread { private static int delay; private static StandardRobot me;

public RobotMonitor(StandardRobot r, int d) {

this.setDaemon(true); me = r;delay = d;

}

RobotMonitor.java  (part  2)  public void run() { while(true) { LCD.clear(); LCD.drawString("Color = "+me.cs.getColorID(),0,0); LCD.drawString("Ultra = "+me.us.getRange(), 0,1); LCD.drawString("Touch = "+me.ts.isPressed(), 0,2); LCD.drawString("MotorA = "+me.ma.getPower(), 0,3); LCD.drawString("MotorB = "+me.ma.getPower(), 0,4); try { this.sleep(delay); } catch (Exception e) { ; }

} // end while} // end run} // end class

ProgFive.java    import lejos.nxt.*;public class ProgFive { public static void main(String [] args) throws Exception { StandardRobot me = new StandardRobot(); RobotMonitor rm = new RobotMonitor(me,400); me.ma.setPower(100); me.mb.setPower(100); rm.start(); // launch the monitor thread while(me.us.getRange() >= 30) { Thread.sleep(200); } // end while } // end main} // end ProgFive

What  ProgFive  does    

• First  creates  an  instance  of  StandardRobot,  called  “me”  

• Then  creates  an  instance  of  RobotMonitor,  called  “rm”  

• Sets  the  motors  running  

• Invokes  the  start()  method  on  the  robot  monitor  

• Loops  un<l  range  to  closest  object  is  <  30  cm  

Behaviour-­‐based  Programming  

• A  standard  programming  methodology  for  robo<c  applica<ons  is  behaviour-­‐based  programming  

• Traces  its  origins  to  work  by  Rodney  Brooks  of  MIT  in  the  mid  1980s  on  subsump'on  architecture  

Behavior-­‐based  Programming  Methodology  

1.  Programmer  conceives  all  the  task-­‐accomplishing  behaviors  that  they  want  the  robot  to  exhibit  

2.  Behaviors  are  developed  independently  3.  Behaviors  are  then  arranged  into  a  hierarchy,  

indica'ng  precedence  

4.  At  run-­‐<me,  behaviors  “compete”  for  control  of  the  robot  

• Higher  priority  behaviors  given  precedence  

Subsump$on  Architecture  Example:  Trash-­‐Collec$ng  Robot  

• Imagine  a  robot  whose  task  is  to  travel  around  an  office  environment  collec<ng  and  disposing  of  empty  soda  cans.  Behaviors  are:  

• Avoid  obstacles  • Explore  • Recognise  trash  • Pick  up  trash  • Return  to  base  • Empty  trash  can  

Subsump$on  Architecture  Example:  Trash-­‐Collec$ng  Robot  

• At  run  <me,  these  behaviors  will  be  interleaved:  

• Explore  • Explore  • Avoid  obstacle  • Explore  • Recognise  trash  • Pick  up  trash  • …  

Behaviors  in  LEJOS  

• LEJOS  provides  a  library  to  support  behavior-­‐based  development  

• Two  key  components:  

• The  Behavior  interface  • The  Arbitrator  class.  

The  Behavior  Interface  

• Each  behavior  is  implemented  in  its  own  class,  which  must  implement  the  Behavior  interface  • The  Behavior  interface  requires  a  class  to  implement  three  methods:  

• boolean takeControl()• void action()• void suppress()

boolean takeControl()

• This  method  should  

• Return  VERY  QUICKLY  –  should  not  perform  a  <me-­‐consuming  computa<on  

• Return  true  if  the  associated  behavior  should  take  control  of  the  robot  

void action()• This  method  encodes  the  actual  ac<ons  to  be  carried  out  if  the  behavior  becomes  ac<ve  

• Must  terminate  quickly  when  the  suppress()  method  is  invoked  on  the  behavior    

• On  termina<on,  must  leave  the  robot  in  a  “clean”  state  

• Typical  structure:  public void action() { supressed = false; while(!suppressed) { // do something }}

suppressed is boolean variable set in suppress() method

void suppress()

• Should:  • Terminate  the  code  running  in  the  action() method  

• Terminate  VERY  quickly  

• Typical  structure:  public void suppress() { suppressed = true;}

The action() method will quit when suppressed is set true

Arbitrators  

• To  select  between  behaviors,  we  use  the  Arbitrator  class  

• We  pass  the  Arbitrator  constructor  an  array  of  behaviors:  lowest  up  to  highest  priority  

• We  then  run  the  start()  method  on  the  arbitrator  object  we  create  

Prog06:  Move  Forward  &  Avoid  

• Our  program  will  have  2  behaviours,  which  will  be  interleaved:  

• Forward  just  moves  the  robot  forward  

• Avoid  will  intervene  when  an  obstacle  is  detected  

Prog06.java  

import lejos.nxt.*;import lejos.robotics.subsumption.*;public class Prog06 {

public static void main(String [] args) throws Exception { StandardRobot me = new StandardRobot(); RobotMonitor rm = new RobotMonitor(me,300); rm.start(); Behavior b1 = new ForwardBehavior(me); Behavior b2 = new AvoidBehavior(me); Behavior [] bArray = {b1, b2}; Arbitrator arb = new Arbitrator(bArray); arb.start();}

} // end Prog06

ForwardBehavior.java  (part  1  of  2)  

import lejos.robotics.subsumption.*;import lejos.nxt.*;public class ForwardBehavior implements Behavior {

public static boolean suppressed;

private static StandardRobot r;

public ForwardBehavior(StandardRobot r1) { r = r1; } public boolean takeControl() { return true; }

ForwardBehavior.java  (part  2  of  2)  

public void suppress() { suppressed = true; }

public void action() { suppressed = false; r.ma.forward(); r.mb.forward(); r.ma.setPower(100); r.mb.setPower(100); while(!suppressed) { try { Thread.sleep(200); } catch (Exception e) { ; } } }

} // end class

AvoidBehavior.java  (part  1  of  2)  

import lejos.robotics.subsumption.*;import lejos.nxt.*;public class AvoidBehavior implements Behavior {

public static boolean suppressed; private static StandardRobot r; public AvoidBehavior(StandardRobot r1) { r = r1; } public boolean takeControl() { return (r.ts.isPressed() || (r.us.getRange() < 10)); }

AvoidBehavior.java  (part  2  of  2)  

public void suppress() { suppressed = true; }

public void action() { suppressed = false; r.ma.backward(); r.mb.backward(); try { Thread.sleep(2000); } catch (Exception e) { ; } r.ma.stop(); r.mb.stop(); }

} // end class