====== Process Modules ======
Process modules are PyCRAMs way of executing code to control the robot. The idea behind this is that there is a process module for every physical resource of the robot and can choose the process module depending on the robot you want to execute your plan on.
The advantage of this is that the high-level plan can stay the same, independent of the robot it is executed on and new robots can be added by simply creating new process modules.
There are two types of process modules one executes code on the real robot and the other one executes code in the simulated Bullet World.
==== Creating a process module =====
Creating a new process module is fairly simple, all you have to do is create a new class which extends the ProcessModule class of the process_module.py file. This new class then needs a '_execute' method which takes a designator as parameter. This method then executes the code to control the robot.
==== Registering a process module ====
In order for the process module to be chosen for the right robot you have to register your process module. For this firstly a dictionary which has the cmd property of the designator as the key and the corresponding process module is needed. Secondly you need a method which returns the process module depending on the robot and if the robot is simulated or not.
This can look something like this:
def available_process_modules(desig):
robot_name = robot_description.i.name
robot_type = ProcessModule.robot_type
type = desig.prop_value('cmd')
if robot_name == 'pr2':
if robot_type == 'simulated':
return PR2ProcessModulesSimulated[type]
elif robot_type == 'real':
return PR2ProcessModulesReal[type]
elif robot_type == "":
logerr(f"No robot_type is set, did you use the with_simulated_robot or with_real_robot decorator?")
else:
logerr(f"No Process Module could be found for robot {robot_name}")
The robot name is the name of the currently loaded robot extracted from the robot description.
The robot type is a class attribute of the ProcessModule class which is set in the high-level plan with either the decorator 'with_real_robot' or the with statement.
Lastly, the type is the cmd property of the motion designator for which the process module is being chosen.
Too differentiate between the process modules for the real and simulated robot, two dictionary's need to be created. For choosing the process module simply the type can be used after evaluating if the process module should be for the real or simulated robot.
This method for choosing a process module then needs to be registered as a resolver, this is done by appending the method to the list of resolvers in the ProcessModule class atribute. An example of this can be seen below
ProcessModule.resolvers.append(available_process_modules)
==== Importing in the final plan ====
For the registration to take effect the files, which cointains the 'available_process_modules' method, has to be imported in the final plan. This is because the code for appending the method to the list of resolvers has to be executed before the plan.