Robot Reflection System

This page explains the robot reflection system that automatically detects 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 performed, the module manager is started to launch all the applications. See The startup process of the robot and application management for more details.

How to re-run the robot reflection system

If you want to re-run the robot reflection system without rebooting the robot, you can use the following command:

pal module_manager restart --restart-reflection

Then 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, you can use the following command:

systemctl restart robot_reflection.service

How to check the detected hardware for the last boot

In order to check the logs of the robot reflection system, you can use the following command:

journalctl -u robot_reflection.service -b

How to disable robot reflection on boot

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 ~/.bashrc file:

export DISABLE_ROBOT_REFLECTION=1

How to re-enable robot reflection on boot

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 ~/.bashrc file or set it to 0:

export DISABLE_ROBOT_REFLECTION=0

How to run manually

For running the robot reflection system manually, you can use the following command:

ros2 launch robot_reflection detect_hardware.py

with the following optional arguments:

  • verbose: To choose if you want more verbose output. Default is True.

  • dry_run: Do 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

  1. 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 info
  1. Register the Plugin

To register the plugin, add an entry point in the setup.py file of your package:

entry_points={
   'robot_reflection.hardware': [
      'dummy_component = dummy_component_reflection.detect_dummy_component:DummyComponentReflection',
   ],
}

3. 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.