-
Notifications
You must be signed in to change notification settings - Fork 12
Home
An Executive is a software module that acts as the highest level behaviour planner. This means that it contains an overall plan and issues orders such as: "navigate to position (2, 4.5)", "move the arm to this position", "learn person name", among others. This page holds information on how to use and create executives.
One key thing to keep in mind is that every action can fail, either occasionally or frequently. States should return a transition such as "failed" when they do, and an executive should handle this correctly, and have a back-up plan.
Although you can create an Executive that doesn't interact with the Using_the_reasoner, it is highly unlikely you won't do any information exchange, such as getting a position, saving the name of a person, etc, so it is a good idea to first read the tutorial on Using_the_reasoner.
An Executive is a general name to the type of software module you are about to develop. You can use different languages and libraries to do this, in this example we will use Python and ROS Smach.
It is advisable to have some experience with both of these tools, therefore you should start by reading a simple tutorial on Python and the official tutorials from ROS Smach Tutorials (sections 1 and 2 should be enough to start with).
In your user folder, create a new package called challenge_ and add robot_skills, robot_smach_states and optionally psi to the dependencies. For example:
roscreate-pkg <NAME OF PACKAGE> robot_skills robot_smach_states
In the package, create the following folders:
- src: this will hold the Python files
- launch: this will hold the launch files to start the executive
- knowledge: this will hold executive-specific knowledge that will be used by the executive
cd <NAME OF PACKAGE>
mkdir src launch knowledge
An overview of the knowledge used in different environments for the various challenges can be found in Knowledge.
Then, in the src folder, create a Python file with the name of the challenge, e.g.:
cd src
echo "" >> <NAME OF EXECUTIVE>.py
and make the file executable:
chmod +x <NAME OF EXECUTIVE>.py
In order to sucessfuly run an Executive you first need to have a basic strucute that imports all necessary information and prepares the main state machine.
It is advisable that you use a good editor, such as Sublime, to edit your Executioner, this will make it more readable and prevent confusions between spaces and tabs.
The following code snipet shows the essential things you will need to declare and prepare in order to create an Executive for Amigo. Most of the code shown bellow is not necessary on pure ROS Smach, but it is necessary in order to properly communicate with Amigo.
#! /usr/bin/env python
# General Imports
import roslib; roslib.load_manifest('NameOfPackage')
import rospy
import os
import roslib.packages as p
import smach_ros
import smach
from speech_interpreter.srv import AskUser
from robot_skills.amigo import Amigo
from std_msgs.msg import Empty
from robot_smach_states import *
from psi import Compound, Sequence, Conjunction, Term
from pein_srvs.srv import SetObjects
import robot_skills.util.msg_constructors as msgs
import robot_smach_states.util.transformations as transformations
#--------------------------------
# Other classes you might need
#--------------------------------
# Class for the main State Machine
class NameOfExecutive(smach.StateMachine):
def __init__(self, robot):
# Create a SMACH state machine with three possible outcomes
sm = smach.StateMachine.__init__(self, outcomes=['Done', 'Aborted', 'Failed'])
with self:
smach.StateMachine.add("NAME_OF_STATE",
states.Say(robot, "Hello world"),
transitions={'spoken': 'Done'})
#--------------------------------------------
# Add states to the main state machine here
#--------------------------------------------
# main entry point of the script##
if __name__ '__main__':
rospy.init_node('executive_NameOfExecutive')
amigo = Amigo(wait_services=True)
machine = NameOfChallenge(amigo)
initial_state = None
machine.set_initial_state([initial_state])
# introspection server needed to be able to use ROS Smach Viewer
introserver = smach_ros.IntrospectionServer('SM_TOP', machine, '/SM_ROOT_PRIMARY')
introserver.start()
#---------------------------------
# Initialize some variables here
#---------------------------------
# Execute the executive in a try-catch block
try:
outcome = machine.execute()
except Exception, e:
amigo.speech.speak(e)
finally:
introserver.stop()
This snipet of code shows the three main parts in which the skeleton of a Executive should be divided: the imports and global variable definition (avoid globals...), the classes that will make up the state machine, and finnally the main entry point where you define things like the amigo variable which you will need later as a parameter in many functions that interact with AMIGO, and the actual machine thats going to be executed.
Another way you could do it is the following:
#! /usr/bin/env python
import roslib; roslib.load_manifest('challenge_cocktail_party')
import rospy
import robot_smach_states as states
from robot_smach_states.util.startup import startup #gives you speech-exception reading-out-loud and smach_viewer server
from psi import Conjunction, Compound
class NameOfTheChallenge(smach.StateMachine):
def __init__(self, robot):
smach.StateMachine.__init__(self, outcomes=["Done", "Aborted", "Failed"])
# load the knowledge file to the reasoner. The first predicate of load_database/2 is the ROS package in
# which the file is located, the second argument is the relative path
robot.reasoner.query(Compound("load_database", "challenge_NameOfTheChallenge", 'knowledge/NameOfTheChallenge.pl'))
# assert to the reasoner which challenge will be run
robot.reasoner.assertz(Compound("challenge", "NameOfTheChallenge"))
with self:
smach.StateMachine.add("NAME_OF_STATE",
states.Say(robot, "Hello world"), #maybe import states separately
transitions={'spoken', 'Done'})
##
if __name__ '__main__':
rospy.init_node('executioner')
util.startup(NameOfTheChallenge)
- Do not forget to add an initial pose to your executive! Amigo needs an initial pose to know exactly where it is, e.g. in front of the door of the environment or arena. To set this, you can use the Set_initial_pose-state: Set_initial_pose(robot, ). It is included in the high-level state StartChallengeRobust
- Remember that almost every state should have a fallback in case of failure, otherwise you will get unexpected behaviour
- Avoid using global variables, its makes it much harder to debugg
- Avoid using the reasoner as storage for smaller variables, such as counters. Querying the Reasoner takes more time than just reading a local variable
- You can exchange information between states in two ways: ** Use the reasoner as a database, so you assert something and then query it back ** Pass User Data between states (recommended)
- Use SMACH Containers properly, since there are several types, and whenever possible encapsulate smaller machines inside bigger machines with the StateMachine container, this will make the code more readable and the visualization in ROS Smach Viewer more explicit
- The def init(...) in a class will only be executed once, while the def execute(...) will be executed everytime the class is called. So whenever possible declare queries and other variables that won't change over time in the def init(...)
- Avoid using sleeps (rospy.sleep()), whenever possible let the Executive run as fast as it can since the timming of actions, like moving or grasping, might change after improvements in outside code
- Always assume Amigo is in his default posture. If you change Amigo's posture, such as the spindle height, head pan and tilt or arm position, don't forget to reset them into place.
- Re-use state machines already available. For example, to learn the name of a person (which includes asking for the name, listening and requesting confirmation):
self.response = self.ask_user_service_get_learn_person_name('name', 3, rospy.Duration(60))
- It is preferable to have more states with less complexity than less states that execute several actions, makes debugging easier
- In order to make Amigo more empathic make him talk when taking some decisions (in moderation), it will help debugging whitout looking at the console and it will make him more predictable to the people watching.
- Avoid using blocking sentences when speaking:
self.robot.speech.speak("Going to the last place where I saw people.", block=False)
- Use standart names for the most common outcomes of states, e.g. Done, Aborted, Failed
- As in other programming languages it is necessary to initialize some variables before you use them. If you querie the reasoner for a specific variable that has never been asserted or rectracted it will generate an exception. You can initialize variables in the Reasoner simply by retracting them in the begginging of your state machine:
amigo.reasoner.query(Compound('retractall', Compound('goal', 'X')))
You can start an Executive in two ways, that are basically the same. You can execute it like you would any other ROS package:
rosrun challenge_<NAME OF PACKAGE> <NAME OF EXECUTIVE>
ex: rosrun challenge_cocktail_party cocktail_party.py
Or you can directly execute the Python script (make sure that you either provide the complete path to the file or that you are in the src folder :
./challenge_<NAME OF EXECUTIVE>
Amigo Console is a powerfull tool that allows you to issue commands to Amigo and querie the Reasoner even while running a challenge. It depends on Amigo's Middleware (amiddle), so make sure it is running before starting it with:
amigo-console
Amigo Console is actually a Python interpreter, with some objects and functions already set up for you. This means so you can run queries live and see their output in the command window but also use any other Python stuff you'd like.
When starting the executive, Amigo says it can't see (or something similar):
This means that there is currently no perception module running, or that at least the service /start_perception is not available. Make sure you run pein_supervisor or at least blob_clustering, ? or another perception module before starting the executive.