diff --git a/README.md b/README.md index 9c843a3..132fa2f 100644 --- a/README.md +++ b/README.md @@ -87,6 +87,48 @@ The bridge can also be started via ros run, therefore use the following instruct run `cargo ament-build --install-base install/voraus-ros-bridge -- --release`. Then `ros2 run voraus-ros-bridge voraus-ros-bridge` +### How to add new voraus.core functionality to ROS + +The voraus.core has an OPC UA interface which this bridge utilizes. +Hence, the first step to expose new voraus.core functionality to the ROS 2 world is to validate that the desired functionality is available within the OPC UA interface (look here #TODO). +Then, the (OPC UA) functionality must be mapped to an adequate ROS 2 equivalent. +For OPC UA variables most of the time this is a ROS topic but could theoretically also be a getter ROS service. +OPC UA methods should be mapped to ROS services but it could also be convenient to use ROS subscriptions (see the `impedance_control/set_wrench` topic). + +We will continue with an example: +Let's assume we want to use the `move_joints` functionality of the voraus.core within our ROS 2 environment. +We already found the `move_joints` method in the voraus.core OPC UA specification and identified its namespace and node id to be `ns=1;i=100211` with the parent node at `ns=1;i=100210`. +The method has quiet a lot of arguments, so we decide it's most convenient to call it via a ROS service. + +A ROS service is specified by its input and output arguments separated by `---` in a .srv file. +Hence, we create a new file called `MoveJoints.srv` within `voraus_interfaces/srv` containing the following: + +``` +bool relative +uint32 target_reference_cs +float64[] target_coordinate +uint32 arriving_cs +float64 velocity_scaling +bool with_blending +float64 blending_parameter +int32[] config_vector +uint32 command_id +bool manual_mode +--- +``` + +After that, we add the new file to the `CMakeLists.txt` of the `voraus_interfaces` package and compile it via `colcon build`. +As a result, we are now able to use our new service type within the rust project. +The next step in our example is to add a new method to the `ROSServices` struct, which will be later used as a callback for the ROS service call. +This method defines the OPC UA object id and method id of the desired voraus.core function which we identified earlier. +It is additionally responsible to call the OPC UA method with the correct arguments provided by the service request. +Next, we create a new ROS service in the `main.rs` and register the previously created method as callback. +Now it's time to test our new method. Therefore, we add our new method in the `test_bridge_methods` module in order to assert that it is properly propagated. +Run the integration test to verify the new tests gets executed and passes. +Lastly we verify that it actually works E2E by starting a voraus.core and test the new functionality. For now this is a manual process, but could as well be automated in the future. + +For the concrete implementation of this example see this pull request: #todo (Note that the implementation details will change over time). + ### Custom message/service files Create a separate ROS message package just like you would in cpp.