ROS2 Package Architecture

The lib/ros2_ws/src directory in the ROS2 workspace contains all packages needed to develop, test and operate the Bioscara robot. Logically coherent software is combined in a package which is useful for distribution and dependecy management.

Remarks on Nomenclature

  • The robot arm (without any gripper) is refered to as the “arm” or “bioscara_arm”.

  • a custom bioscara gripper is refered to as the “gripper” or “bioscara_gripper_<type>”

  • The assembly of an arm and a gripper is a “robot” or “bioscara_<arm>_<gripper>” .

  • An environment with a robot and potentially other objects is a “scene”.

Design goals

The package architecture is designed on modularity, since it is expected future variants of hard- and software will be developed. The modular approach allows to mix and swap old the software. Modularity achieved two fold:

  • Standalone packages for arms and grippers.

  • Grippers that are simply variants but utilize the same hardware interface, just different hardware description and hardware parameters grouped in a package but with standalone description macros.

  • Packages and description macros can be swapped via command line arguments or set in scene specific bringup files.

The architecture may serve as a blueprint for the future integration of more DALSA robots (custom or commercial) into ROS2.

Additional MoveIt2 packages

Unfortunately it was necessary to build MoveIt2 from source to use features from the MoveIt Task Constructor, installing MoveIt from source adds many packages to the workspace. To build the workspace follow the compilation instructions.

Meta Packages

Packages that logically belong together are grouped in meta packages. Meta packages do not contain source code or configuration files but simplify dependency management. For example a hardware meta package may contain the hardware’s description, driver, interface, controller and bringup packages. Other packages that depend on that hardware can simply specify the meta package as a dependency and automatically inherit the remaining sub-dependencies.

The following meta packages are available:

dalsa_bioscara_arm: Contains all packages related to the custom bioscara arm hardware component

dalsa_bioscara_grippers: Contains all packages related to the custom bioscara gripper hardware component and its variants.

dalsa_controllers: Contains custom, hardware agnostic controllers.

dalsa_moveit_configurations: Contains MoveIt2 configurations.

system_test_packages: Contain different simple programs to execute system tests.

Overview

The diagram below shows a simple package architecture and dependency diagram. It does not yet include the MoveIt configuration package. The individual packages are grouped by their meta package.

        flowchart TB
 subgraph dalsa_bioscara_arm["dalsa_bioscara_arm"]
        bioscara_arm_bringup["bioscara_arm_bringup"]
        bioscara_arm_description["bioscara_arm_description"]
        bioscara_arm_hardware_interface["bioscara_arm_hardware_interface"]
        bioscara_arm_hardware_driver["bioscara_arm_hardware_driver"]
  end
 subgraph dalsa_bioscara_grippers["dalsa_bioscara_grippers"]
        bioscara_gripper_bringup["bioscara_gripper_bringup"]
        bioscara_gripper_descriptions["bioscara_gripper_descriptions"]
        bioscara_gripper_hardware_driver["bioscara_gripper_hardware_driver"]
        bioscara_gripper_hardware_interface["bioscara_gripper_hardware_interface"]
  end
 subgraph dalsa_controllers["dalsa_controllers"]
        single_trigger_controller["single_trigger_controller"]
  end
  subgraph dalsa_moveit_configurations["dalsa_moveit_configurations"]
        bioscara_arm_gripper_128_moveit_config["bioscara_arm_gripper_128_moveit_config"]
  end
    
    scene_descriptions["scene_descriptions"] --> bioscara_arm_description & bioscara_gripper_descriptions
    scene_bringup["scene_bringup"] --> scene_descriptions & dalsa_bioscara_arm & dalsa_bioscara_grippers & bioscara_rviz_plugin
    bioscara_arm_bringup --> single_trigger_controller & bioscara_arm_description
    bioscara_arm_description --> bioscara_arm_hardware_interface
    bioscara_arm_hardware_interface --> bioscara_arm_hardware_driver
    bioscara_gripper_bringup --> bioscara_gripper_descriptions
    bioscara_gripper_hardware_driver --> bioscara_arm_hardware_driver
    bioscara_gripper_descriptions --> bioscara_gripper_hardware_interface
    bioscara_gripper_hardware_interface --> bioscara_gripper_hardware_driver
    bioscara_rviz_plugin["bioscara_rviz_plugin"] --> dalsa_bioscara_arm & dalsa_bioscara_grippers
    dalsa_motion_plans["dalsa_motion_plans"] --> bioscara_arm_gripper_128_moveit_config 
    bioscara_arm_gripper_128_moveit_config --> scene_bringup
    

Hardware component package

Hardware component meta packages are structured according to the RTW Package Structure refrence, developed by dstogl, a key developer of ros2_control. Each hardware component dalsa_bioscara_grippers and dalsa_bioscara_arm, i.e. the arm and the gripper have meta package structured as follows, using gripper as an example:

dalsa_bioscara_grippers/
├── bioscara_gripper_bringup                                # The bringup package is used to launch a hardware component, either standalone or from another bringup package
│   ├── CMakeLists.txt                                      
│   ├── config                                                                                       
│   │   ├── bioscara_gripper_controller_manager.yaml        # ros2_control controller manager paramters if used stand-alone
│   │   └── bioscara_gripper_controllers.yaml               # Definition of controllers for this hardware component, gripper controller in this case
│   ├── launch                                              
│   │   └── bioscara_gripper.launch.py                      # Use this launch file used to start the component stand-alone, including GUI and ros2_control stack.
│   └── package.xml
├── bioscara_gripper_descriptions                           # The description package contains all files to assemble a component description with Xacro 
│   ├── CMakeLists.txt
│   ├── config                                              
│   │   ├── bioscara_gripper_128_parameters.yaml            # Describes static component parameters parsed in the robot description, like joint limits
│   │   └── bioscara_gripper_<variant_X>_parameters.yaml    # Parameters of another gripper variant
│   ├── launch
│   │   └── view.launch.py                                  # Use this launch file to simple view and inspect the assembled component.
│   ├── meshes                                              # Resources for the URDF file
│   ├── package.xml
│   ├── rviz
│   │   └── display.rviz                                    # Saved display configuration for the stand-alone GUIs
│   └── urdf
│       ├── bioscara_gripper_128.ros2_control               # ros2_control hardware information for the 128 mm variant
│       ├── bioscara_gripper_128.urdf                       # Base URDF file containing kinematic, visual and collision info for the 128 mm variant
│       ├── bioscara_gripper_128.xacro                      # Contains the "load_gripper" macro, combining the .urdf and .ros2control parts for the 128 mm variant
│       ├── bioscara_gripper_<variant_X>.ros2_control       
│       ├── bioscara_gripper_<variant_X>.urdf                       
│       ├── bioscara_gripper_<variant_X>.xacro              # Variants of the gripper using the same hardware interface can be added here
│       ├── materials.xacro
│       └── scene.xacro                                     # bringup/launch file uses this scene for the stand-alone start of the component.
├── bioscara_gripper_hardware_driver                        # The hardware driver contains the hardware specific implementation, like PWM generation for the gripper
│   ├── CMakeLists.txt
│   ├── include
│   │   └── bioscara_gripper_hardware_driver
│   ├── package.xml
│   └── src
│       ├── mBaseGripper.cpp                                # Base implementation
│       ├── mGripper.cpp                                    # Hardware implementation
│       └── mMockGripper.cpp                                # Mock implementation for testing
├── bioscara_gripper_hardware_interface                     # The hardware interface abstracts the hardware driver and creates a hardware componen plugin for ros2_control
│   ├── CMakeLists.txt
│   ├── bioscara_gripper_hardware_interface.xml
│   ├── include
│   │   └── bioscara_gripper_hardware_interface
│   ├── package.xml
│   └── src
│       └── gripper_hardware.cpp
└── dalsa_bioscara_grippers                                 # Meta package

The name of the gripper component package is written in plural since it can include multiple variants of the bioscara gripper which use the same hardware interface but might have differen geometries.

Bringup Packages

The bringup packages inside hardware components contain the ros2_control controller configurations for that specific hardware component, as well as a controller manager configuration if the hardware component is launched stand-alone with the launch file included in the bringup package. Stand-alone launch includes the ros2_control stack and can be used for example hardware interface testing, without having to also start higher level applications like MoveIt.

Description Packages

Description packages are a core building block of the modular principle. It contains robot description files and control configuration files. A robot description file is an integral part in many ROS2 applications. ROS2 uses an XML based format called Unified Robot Description File (URDF) which is “a format to describe the kinematics, dynamics, and geometries of robots, independently of software program[1], in detail this includes a systems:

  • Kinematic description (joints and frame definitions)

  • Visual properties for viszualization

  • Collision properties defining physical boundaries for trajectory generation

  • Mass and Inertial properties for physical simulation (not utilized in this project)

  • The URDF can be expanded for specific applications, in this project it addtionally includes:

  • ros2_contol configuration

    • hardware interface plugin

    • command and state interfaces

    • joints

    • gpios

The URDF files can be combined using Xacro, a XML macro extension. With Xacro a virtual robot assembly can be created, allowing to flexibly match and mix hardware components. A desription of the Xacro macros follows in the next section.

The description package also contains a stand-alone scene and launch file which can be used to simply display the geometry visuals and collision bodies, test joint limits using joint state broadcaster and frame transformations.

Dynamic Robot Assembly

The entire robot is assembled in the scene_descriptions package, in particular the load_robot macro defined in *scene_descriptions/robot.xacro”. The diagram below tries to viszualize the different Xacro macros that make up the robot. The robot can be modified simply either by passing diffferent arguments to the macros, loading different parameters from the paramter files or swapping entire macros. For example the scene.xacro file takes a gripper macro path as an argument, thus an entirely different gripper can be loaded as long as it supports the same input arguments. Alternatively one can decide to not mount a gripper at all to the robot by passing an empty gripper macro name.

        flowchart LR
 subgraph bioscara["bioscara"]
    direction LR
        arm_urdf_param_junction["arm_urdf_param_junction"]
        arm_urdf_origin>"origin"]
        arm_urdf_parent>"parent"]
        arm_urdf_parameters>"parameters"]
        arm_urdf_prefix>"prefix"]
  end
 subgraph bioscara_arm_ros2_control["bioscara_arm_ros2_control"]
    direction LR
        arm_ctrl_param_junction["arm_ctrl_param_junction"]
        arm_ctrl_use_mock_hardware>"use_mock_hardware"]
        arm_ctrl_parameters>"parameters"]
        arm_ctrl_prefix>"prefix"]
  end
 subgraph load_arm["load_arm"]
    direction TB
        arm_param_junction["arm_param_junction"]
        arm_param_file["**[parameters]** = bioscara_arm_parameters.yaml"]
        bioscara
        bioscara_arm_ros2_control
  end
 subgraph bioscara_gripper_128["bioscara_gripper_128"]
        grp_urdf_p[" "]
  end
 subgraph bioscara_gripper_128_ros2_control["bioscara_gripper_128_ros2_control"]
        grp_ctrl_p[" "]
  end
 subgraph load_gripper["load_gripper"]
        grp_param_junction["grp_param_junction"]
        grp_param_file["**[parameters]** = bioscara_gripper_128_parameters.yaml"]
        bioscara_gripper_128
        bioscara_gripper_128_ros2_control
  end
 subgraph load_robot["load_robot"]
    direction TB
        robot_param_junction["robot_param_junction"]
        grp_origin["**[origin]** = xyz=[0 0 0] rpy=[π 0 -π/2]"]
        grp_parent@{ label: "**[prefix]** = 'tool_flange'" }
        load_arm
        load_gripper
  end
 subgraph scene["scene"]
    direction LR
        use_mock_hardware>"**[use_mock_hardware]**"]
        prefix@{ label: "**[prefix]** = ' '" }
        parent@{ label: "**[prefix]** = 'world'" }
        origin["**[origin]** = xyz=[0 0 0] rpy=[0 0 0]"]
        load_robot
  end
 subgraph bus["symbolic multiple parameters"]
        n1["**[target]** = value "] &  n2[" "] --> legend_junction1 ==> legend_junction2 --> n3["target"]
        legend_junction1
        legend_junction2
  end
 subgraph legend["Legend"]
    direction TB
        defined["defined in macro"]
        arg>"macro argument"]
        bus
  end
    arm_ctrl_param_junction --> arm_ctrl_use_mock_hardware & arm_ctrl_parameters & arm_ctrl_prefix
    arm_urdf_param_junction --> arm_urdf_origin & arm_urdf_parent & arm_urdf_prefix & arm_urdf_parameters
    arm_param_junction ==> arm_ctrl_param_junction & arm_urdf_param_junction
    arm_param_file --> arm_urdf_param_junction & arm_ctrl_param_junction
    grp_param_junction ==> bioscara_gripper_128 & bioscara_gripper_128_ros2_control
    grp_param_file --> bioscara_gripper_128 & bioscara_gripper_128_ros2_control
    grp_origin --> grp_param_junction
    grp_parent --> grp_param_junction
    robot_param_junction ==> grp_param_junction & arm_param_junction
    use_mock_hardware --> robot_param_junction
    origin --> robot_param_junction
    prefix --> robot_param_junction
    parent --> robot_param_junction
    arm_urdf_param_junction@{ shape: sm-circ}
    arm_ctrl_param_junction@{ shape: sm-circ}
    arm_param_junction@{ shape: sm-circ}
    arm_param_file@{ shape: manual-input}
    grp_param_junction@{ shape: sm-circ}
    grp_param_file@{ shape: manual-input}
    robot_param_junction@{ shape: sm-circ}
    grp_origin@{ shape: manual-input}
    grp_parent@{ shape: manual-input}
    prefix@{ shape: manual-input}
    parent@{ shape: manual-input}
    origin@{ shape: manual-input}
    defined@{ shape: manual-input}
    legend_junction1@{ shape: sm-circ}
    legend_junction2@{ shape: sm-circ}

    style load_arm fill:#FFD600
    style load_gripper fill:#00C853
    style load_robot fill:#C8E6C9
    style scene fill:#FFE0B2
    

After assembling the bioscara robot in its default state the following kinematic chain is created:

        flowchart LR
 subgraph arm["arm"]
        base_link["base_link"]
        link_1["link_1"]
        link_2["link_2"]
        link_3["link_3"]
        link_4["link_3"]
        tool_flange["tool_flange"]
  end
 subgraph gripper["gripper"]
        grp_base_link["grp_base_link"]
        left_jaw_link["left_jaw_link"]
        right_jaw_link["right_jaw_link"]
        tool["tool"]
  end
 subgraph robot["robot"]
        arm
        gripper
  end
 subgraph scene["scene"]
        robot
        world["world"]
  end
    tool_flange -- origin --> grp_base_link
    grp_base_link --> left_jaw_link & right_jaw_link & tool
    base_link -- j2 --> link_1
    link_1 -- j2 --> link_2
    link_2 -- j3 --> link_3
    link_3 -- j4 --> link_4
    link_4 -- flange_joint --> tool_flange
    world -- origin --> base_link

    style arm fill:#FFD600
    style gripper fill:#00C853
    style robot fill:#C8E6C9
    style scene fill:#FFE0B2
    

Root Level Scene Packages

Scene Description

The main scene.xacro file describes the robot and its environment, in this case a table top. It loads the load_robot macro defined in the robot.xacro file. The resulting robot has been described in the Robot Assembly section.

Scene Bringup

Contains the launch files of a specific robot configuration.

Tip

This package contains the main launch file to start a robot configuration including the ros2_control stack using the <RobotConfiguration>.launch.py launch file. Start Bioscara with the currently mounted 128 mm gripper, execute ros2 launch scene_bringup bioscara_arm_gripper128.launch.py use_mock_hardware:=true/false gui:=true/false.

Note

This launch files might be superseeded by a single launch file that additionally launches the MoveIt move_group from a hardware specific dalsa_moveit_configurations package.