States
This page contains all you need to know about states in GRIP, i.e. how to create new states and how to use the provided ones.
Constant states
The source code of the following states can be found here. You should always be able to see them, regardless of the configuration of your robot.
Counter
ReinitialiseManagers
Select
WaitFor
Commander states
The source code of the following states can be found here. These states will become available if and only if your robot uses MoveIt to operate a part of your robot.
Note
For these states to appear at least one MoveIt motion planner must be defined in the robot integration tab.
If more than one planner is defined, a configuration slot named
group_name will appear for all these states. It allows you to choose which part of the robot you wish to configure.AllowCollisions
ComputePlan
ExecuteTrajectory
Move
Generated states
When you are interfacing an external component or a sensor, GRIP will automatically generate the code of the corresponding states.
ExternalComponent
Sensor
How to create a new state
You can create new states and integrate them to GRIP. Although most of the time it is advised to create and integrate an external component, which will generate a state for you, you might want to create your own set of states. We are going to review the required process below.
Warning
All the interactive functionalities such as dropdown menu and automatic refresh of possible values for slots are not supported for external states.
For GRIP to directly account for your states, you can decide to add the source code of your state in
/home/user/projects/shadow_robot/base/src/grip/grip_core/src/grip_core/states.Warning
Make sure to add your states here and not in the commander folder! Otherwise GRIP may not run properly.
The content of any state you want to create should follow this template:
#!/usr/bin/env python
import smach
# Import other packages if required
# The name of the state MUST be the CamelCase version of the filename! For instance for this state the filename should
# be name_of_state
class NameOfState(smach.State):
"""
Small description of what the state does
"""
# Change the argument_to_set by the name of the variable you want to be able to configure in the task editor
# You can also set default values, such as argument_to_set=10
# The remaining arguments from outcomes onward MUST NOT BE REMOVED
# You can add more outcomes if you want in he signature
def __init__(self, argument_to_set1, argument_to_set2, outcomes=["success", "finished"], input_keys=[], output_keys=[], io_keys=[]):
"""
@param outcomes: Possible outcomes of the state. Default "success" and "failure"
@param input_keys: List enumerating all the inputs that a state needs to run
@param output_keys: List enumerating all the outputs that a state provides
@param io_keys: List enumerating all objects to be used as input and output data
"""
# Initialise the state, THIS LINE MUST NOT BE REMOVED
smach.State.__init__(self, outcomes=outcomes, io_keys=io_keys, input_keys=input_keys, output_keys=output_keys)
# Do whatever you want here
# ...
# Outcomes of the state. THIS LINE MUST NOT BE REMOVED
self.outcomes = outcomes
# Do NOT change the name or the signature of this function
def execute(self, userdata):
"""
@param userdata: Input and output data that can be communicated to other states
@return: - outcomes[-1] depending on your implementation
- outcomes[0] otherwise
"""
# The code here is executed everytime that the state is run
# So write what you need
# ...
# But don't forget to at least return one outcome!
# Can be self.outcomes[-1] or self.outcomes[2] if you have more than two outcomes. If you do have more than 2,
# make sure to have them defined in outcomes in the class signature!!!
return self.outcomes[0]
Important
Regardless of where you are storing the file, make sure to name the file following the underscore naming rule!
For instance if your state is named
ComputeJointState, the name of the file must be compute_joint_state.py.You can find a concrete example of how to create a new state, here.