Skip to content
This repository has been archived by the owner on Jun 18, 2022. It is now read-only.

Behaviour

Ritwik Roy edited this page Jan 5, 2015 · 2 revisions

Basic Structure

Our behaviours are written in Python. At a high level, our C++ perception thread reads information from the world (through vision / sonars, etc), localises based on that information, and then calls a python function in an embedded interpreter which has to return an action to perform. This action is relayed to the relevant robot outputs (LEDs directly, or to the walk engine for physical motion).

There’s three core Classes that are important:

  • BehaviourTask: This is the superclass for any task.
  • World: Every task has a world object that gives it access to shared information about the world. It also sets a behaviour request in that world which gets read at the end of the behaviour tick.
  • TaskState: This is for Tasks that are complex enough to warrant states / state transitions / hysteresis.

Helpers

Often while writing behaviours you'll need to perform general tasks that are not unique to your behaviour (e.g calculating geometries, checking information about the team, etc). To be more efficient and have fewer places to change when we perform actions, we have utility modules that contain a lot of this information. These are listed here:

  • Constants.py: Wrapper for robot module constants and python constants. Please use these over directly accessing the robot module so that it's easier to change in one place if the C++ blackboard changes. This one will also include any other constants that aren't from C++, so it'll all be in one place.
  • Global.py: Information about the world and you (e.g canSeeBall(), myPose(), amILost(), offNetwork().
  • util (various useful utilities like timers, etc.)
    • MathUtil.py: Additional maths on top of what's in the math library
    • FieldGeometry.py - Geometry functions for common field calculations (angles, etc)
    • TeamStatus.py: Team information (things like player numbers, whether an obstacle is a teammate, etc).
    • Timer.py: A simple timer utility so you don't have to keep doing the thing where you subtract starttime from blackboard.vision.timestamp. Also provides useful stopwatch like features so you can time the total amount of something in pieces.
    • Vector2D.py: Simple class for vectors.

These modules have access to the latest blackboard on each tick, so you don't need to pass the blackboard around to them.

FAQ

Where are the tasks/skills?

Python code is found here:

image/home/nao/data/behaviours/

If you want to see how the C++ code that starts the behaviours, it's in the perception folder:

robot/perception/behaviour/

How do I sync skills to the robot?

nao_sync robot-name
# e.g: nao_sync luigi

How do I write a behaviour?

Have a look at a simple one, like Default. Create a filename with the same name as your skill, so MyNewSkill.py would have a class:

from skills.Task import BehaviourTask
import robot

class MyNewSkill(BehaviourTask):
  def init(self):
     # Any special initialisation code. Note that if you don't override __init__, it will set up the world
     # variables, etc. If you decide to override __init__ (there's valid cases to do so), see what 
     # BehaviourTask.__init__ and make sure to also do what it does.
     pass
  def transition(self):
    # Any transition code if you have taskstates.
    pass
  def _tick(self):
    # What to run in each timestep.
    # Note: use this if you want to let the system manage transitions for you. Essentially it will call
    # transition and then _tick.
    # If you want to manage that yourself, then you override tick()
    
    req =  robot.BehaviourRequest()
    request.actions = robot.All()
    # Some request stuff.
    self.world.b_request = req # This will automatically get returned to C++.

How do I get data from vision, localisation etc.?

The world object your task has access to will have a blackboard. This matches the blackboard in c++.

self.world.blackboard.vision.timestamp

How do I test my behaviour?

Sync it to the robot. Test it in isolation by running it with runswift: runswift -s YourSkillName

What Skill is run if I don’t pass a skill to runswift?

Default

I keep seeing self.world in new skills. Where does this World get created / set up?

The highest level of the architecture, behaviour.py will create a new World() object and pass it to the first skill it creates (the one you passed it with -s or GameController by default). This world object stays the same throughout, the only thing that changes is the blackboard variable within it which we set. This structure allows us to change the blackboard once and have every skill that's looking at the same world have the new blackboard. Otherwise, if each skill had a "self.blackboard" we would need to update that reference in each tick by calling an update function on each item in the tree (which adds more code complexity).