Porting to v2.10

Version 2.10 introduces a few significant changes to the XBot2 framework, i.e.:

  • Joint device management: versions prior to v2.10 included a component named JointMaster, which would act as a centralized authority for communicating with all joint devices at once, sitting in the middle between RobotInterface objects, and the HAL. Notably, safety policies and filtering used to be integrated at the JointMaster layer. Starting from version v2.10, RobotInterface objects communicate directly with the HAL layer, therefore simplifying the information flow by removing the hidden man-in-the-middle.

  • Customizable safety system: since safety is no longer managed at the (hidden) JointMaster layer, it needs to explicitly be handler by the developer implementing the HAL interface for the robot or simulator. XBot2 now provides the XBot::Hal::JointSafety object, which takes care of enforcing safety policies as well as filtering, in a customizable way (via callbacks) which is also integrated with the rest of the framrework.

  • Safety-aware plugins: thanks to the above mentioned integration, plugins are now safety aware. By default, all plugins are aborted whenever the safety system is triggered. Users can override this behavior by providing their own implementation of XBot::ControlPlugin::on_safety_triggered.

  • Resource management system: prior to version v2.10, no check was performed to understand whether two or more plugins were commanding the same device at the same time, possibly leading to conflicts, and undesired behavior. Starting from v2.10, XBot2 provides a built-in resource management system. The simplest highest-level API is implemented inside the usual XBot::RobotInterface::setControlMode set of functions. Plugins can leverage on this API to implement simple, safe policies such as refusing to start if a resource conflict is detected.

  • Serialization support: for internal topics, services, parameters. This allows to interact with XBot2’s internal intra-process communicacion system in a YAML-based, type-free fashion.

  • Dedicated Safety API: to check if filters are enabled, their cutoff frequency, etc

What actions do I need to take?

  1. Rename safety-related parameters: in the main configuration file, inside the xbotcore_param field:
    • /jm/tx_filter_autostart: becomes /xbot/hal/joint_device/filter_autostart

    • /jm/tx_filter_cutoff: becomes /xbot/hal/joint_device/filter_cutoff_hz

    • /jm/enable_safety becomes /xbot/hal/enable_safety

    • it is possible to customize the cutoff frequency for the three profiles safe, medium, and fast, via the parameter /xbot/hal/joint_safety/filter_<PROFILE_NAME>_cutoff_hz

For example:
xbotcore_param:
  /xbot/hal/joint_safety/filter_autostart: {value: true, type: bool}
  /xbot/hal/joint_safety/filter_cutoff_hz: {value: 2.0, type: double}
  /xbot/hal/enable_safety: {value: true, type: bool}
  1. Declare joint resources: inside the on_initialize function of your control plugin, you can call setDefaultControlMode to declare what joint resources your plugin will need upon execution. If the declared resources are not available upon plugin start, the start command is discarded and an error appears on the terminal. Closing the plugin who is holding the contended resources will fix the issue.

    For example:

    bool MyPlugin::on_initialize()
    {
        // your own initialization logic
    
        // prior to version 2.10, it was customary to set the robot's
        // control mode once and for all, as follows:
        // _robot->setControlMode(ControlMode::Position());
    
        // from 2.10 onwards, we need to declare the required resources
        // with a different API, as in the following example:
    
        // all joints use position references
        setDefaultControlMode(ControlMode::Position());
    
        // override wheels
        std::map<std::string, ControlMode> wheel_ctrl_map;
        wheel_ctrl_map["wheel_1"] = ControlMode::Velocity();
        wheel_ctrl_map["wheel_2"] = ControlMode::Velocity();
        setDefaultControlMode(wheel_ctrl_map);
    
        return true;
    }
    

    If you forget to do so, calling robot->move() will not have any effect.

  2. Handling safety events: control plugins are now safety aware, and the default reaction is to abort on a safety triggered event. If you wish to change this behavior, you need to override the on_safety_triggered virtual method:

    void MyPlugin::on_safety_triggered()
    {
        // no op
        jinfo("safety triggered: ignoring");
    }
    
  3. Using the Safety API to check its status as in the following example; note that this API is currently NOT real-time safe

    #include <xbot2/hal/dev_joint_safety.h>
    
    auto safety_status = Hal::JointSafety::status();  // note: not real-time safe!
    jinfo("safety enabled: {}", safety_status.safety_enabled);
    jinfo("filter enabled: {}", safety_status.filter_enabled);
    jinfo("filter cutoff : {} Hz", safety_status.cutoff_hz);
    
  4. Update HAL drivers to use the new Hal::JointSafety component, which is the new way to enforce safety policies. Reaction to safety events can be customized via callbacks. Developers with source code access can check this (internal) example.

  5. Update signature for HAL device constructors to accept an additional parameter as follows. Note: developers only!

    /* device driver, device client */
    
    // old signature
    // MyDevice(Hal::DeviceInfo dinfo);
    
    // new signature
    MyDevice(Hal::DeviceInfo dinfo,
             const Hal::Device::CommonParams& params);
    
    /* device containers */
    
    // old signature
    // MyDeviceContainer(std::vector<Hal::DeviceInfo> dinfo);
    
    // new signature
    MyDeviceContainer(std::vector<Hal::DeviceInfo> dinfo,
                      const Hal::Device::CommonParams& params);