Robot Reflection System#
This page explains the Robot Reflection System. This is a system that gives the robot self-awareness, meaning that it detects automatically the connected hardware components and configures the robot accordingly.
!!! Note The robot reflection system will not detect hardware components if the emergency stop is pressed during boot because the power cut prevents the components from being detected.
The boot process#
When the robot is powered on, the robot reflection system is run as a systemd service. It scans the connected hardware components for which plugins are installed, and configures the robot accordingly.
After the reflection process is done, the module manager is started to launch all the applications. See the startup process for more details.
Interacting with the robot reflection system#
Re-run#
If you want to re-run the robot reflection system without rebooting the robot, do:
pal module_manager restart --restart-reflection
After this the robot reflection system will be executed again, detecting the connected hardware and applying the necessary configurations. After that, the module manager will be restarted to relaunch all the applications with the new configuration.
If you just want to restart the robot reflection system without restarting the module manager, do
systemctl restart robot_reflection.service
Retrieve hardware of last boot#
The logs of the robot reflection system can be obtained by doing
journalctl -u robot_reflection.service -b
Disable#
If you donโt want the robot reflection system to run on boot, you can disable the service by running the following command:
systemctl disable robot_reflection.service
Or you can export the following environment variable in the /usr/bin/init-pal-env file:
export DISABLE_ROBOT_REFLECTION=1
Re-enable#
If you have previously disabled the robot reflection system service, you can re-enable it by running the following command:
systemctl enable robot_reflection.service
In case you have disabled it via the environment variable, just unset it by removing the line from your /usr/bin/init-pal-env file or set it to 0:
export DISABLE_ROBOT_REFLECTION=0
Manually run#
To run the robot reflection system manually do
ros2 launch robot_reflection detect_hardware.py
with the following optional arguments:
verbose: To get a more verbose output. Default is True.dry_run: To not apply changes, only simulate. Default is False.plugin: To specify a particular plugin to run. Default is to run all available plugins.
Example:
ros2 launch robot_reflection detect_hardware.py verbose:=True dry_run:=True plugin:=pal_pro_gripper
How to create new plugins#
For integrating new hardware components into the Robot Reflection framework, you must create a custom plugin.
A plugin must be a valid Python package containing a class that inherits from the
HardwareReflection base class.
The framework provides two base classes in robot_reflection.hardware_reflection:
HardwareReflection: Base class for all hardware reflection plugins.run(): Executes detection logic.get_robot_info(): Returns a dictionary of the detected info.get_default_robot_info(): Returns a dictionary of default info if hardware is not detected.detect_hardware(): Orchestrates the run/get cycle and handles errors.
HardwareReflectionCmd: An extension for plugins that rely on shell commands.run_cmd(...): Safely execute shell commands with timeouts.
Implementation step-by-step#
Create a class that implements the required methods. Below is an example of a component named
dummy_component.from typing import Dict from robot_reflection.hardware_reflection import HardwareReflectionCmd KEY = 'dummy_component' class DummyComponentReflection(HardwareReflectionCmd): def __init__(self): super().__init__() self.result = None def run(self) -> None: # execute logic or run shell commands cmd_result = self.run_cmd('echo "Dummy component detected"') self.result = cmd_result.stdout.strip() def get_robot_info(self) -> Dict: if self.result is None: raise RuntimeError('run() must be called before get_robot_info()') info = {} # Parse result and update dictionary if self.result == 'Dummy component detected': info[KEY] = True else: info[KEY] = False return info def get_default_robot_info(self) -> Dict: if self.result is None: raise RuntimeError('run() must be called before get_robot_info()') info = {} # Parse result and update dictionary if self.result == 'Dummy component detected': info[KEY] = True else: info[KEY] = False return infoRegister the Plugin
To register the plugin, add an entry point in the
setup.pyfile of your package:entry_points={ 'robot_reflection.hardware': [ 'dummy_component = dummy_component_reflection.detect_dummy_component:DummyComponentReflection', ], }Compile and source your package, and the robot reflection system will automatically detect and use your new plugin during its execution. You can test your plugin by running the robot reflection system manually as described above, specifying your plugin name if desired.