Integrating with Your ROS 2 System =================================== This tutorial shows how to integrate ros2_medkit with your existing ROS 2 application. .. contents:: Table of Contents :local: :depth: 2 Overview -------- ros2_medkit works with any ROS 2 system out of the box through automatic discovery. This tutorial covers: - Basic integration (zero configuration) - Organizing nodes with namespaces - Reporting custom faults - Best practices for production Zero-Configuration Integration ------------------------------ The simplest integration requires no changes to your existing code. Just run the gateway alongside your nodes: .. code-block:: bash # Terminal 1: Your existing ROS 2 application ros2 launch my_robot robot.launch.py # Terminal 2: ros2_medkit gateway ros2 launch ros2_medkit_gateway gateway.launch.py The gateway will automatically discover: - All running nodes → Apps - Top-level namespaces → Areas - Namespace groupings → Synthetic Components - Topics, services, actions → Data, Operations - Parameters → Configurations Organizing with Namespaces -------------------------- ros2_medkit maps ROS 2 namespaces to Areas. To create a logical hierarchy, use namespaces in your launch files: .. code-block:: python # my_robot.launch.py from launch import LaunchDescription from launch_ros.actions import Node def generate_launch_description(): return LaunchDescription([ # Perception nodes → /perception area Node( package='camera_driver', executable='camera_node', namespace='/perception/cameras', name='front_camera' ), Node( package='lidar_driver', executable='lidar_node', namespace='/perception/lidar', name='velodyne' ), # Navigation nodes → /navigation area Node( package='nav2_controller', executable='controller_server', namespace='/navigation', name='controller' ), # Manipulation nodes → /manipulation area Node( package='moveit2', executable='move_group', namespace='/manipulation', name='move_group' ), ]) This creates the hierarchy: .. code-block:: text Areas: ├── perception │ ├── Component: front_camera │ └── Component: velodyne ├── navigation │ └── Component: controller └── manipulation └── Component: move_group Reporting Custom Faults ----------------------- To report faults from your nodes, use the ``ros2_medkit_fault_reporter`` package: **Add dependency to package.xml:** .. code-block:: xml ros2_medkit_fault_reporter **Report faults in your node:** .. code-block:: cpp #include "ros2_medkit_fault_reporter/fault_reporter.hpp" #include "ros2_medkit_msgs/msg/fault.hpp" using ros2_medkit_fault_reporter::FaultReporter; using ros2_medkit_msgs::msg::Fault; class MyNode : public rclcpp::Node { public: MyNode() : Node("my_node") { // FaultReporter requires shared_from_this() and a source identifier fault_reporter_ = std::make_shared( this->shared_from_this(), this->get_fully_qualified_name()); } void check_sensor() { if (!sensor_ok_) { fault_reporter_->report( "SENSOR_DISCONNECTED", Fault::SEVERITY_ERROR, "Front camera not responding" ); } } private: std::shared_ptr fault_reporter_; }; .. note:: Faults are cleared through the FaultManager service, not the reporter. Use ``ros2 service call /fault_manager/clear_fault`` or the REST API ``DELETE /api/v1/components/{id}/faults/{fault_code}``. **Fault severity levels:** - ``Fault::SEVERITY_INFO`` - Informational, no action required - ``Fault::SEVERITY_WARN`` - Warning, may need attention - ``Fault::SEVERITY_ERROR`` - Error, requires attention - ``Fault::SEVERITY_CRITICAL`` - Critical, immediate action required Exposing Custom Data -------------------- Any topic under your node's namespace is automatically exposed via the Data API: .. code-block:: cpp // These topics will be accessible via: // GET /api/v1/apps/{app_id}/data // (or /api/v1/components/{component_id}/data in synthetic mode) pub_status_ = create_publisher("status", 10); pub_diagnostics_ = create_publisher("diagnostics", 10); **Best practices for data exposure:** 1. Use meaningful topic names 2. Publish regularly for real-time monitoring 3. Include timestamps in messages 4. Use standard message types when possible Exposing Services and Actions ----------------------------- Services and actions under your namespace become Operations: .. code-block:: cpp // Service: POST /api/v1/apps/{app_id}/operations/reset/executions srv_reset_ = create_service( "reset", std::bind(&MyNode::handle_reset, this, _1, _2)); // Action: POST /api/v1/apps/{app_id}/operations/calibrate/executions action_calibrate_ = rclcpp_action::create_server( this, "calibrate", std::bind(&MyNode::handle_goal, this, _1, _2), std::bind(&MyNode::handle_cancel, this, _1), std::bind(&MyNode::handle_accepted, this, _1)); Exposing Parameters ------------------- ROS 2 parameters become Configurations automatically: .. code-block:: cpp // These parameters will be accessible via: // GET/PUT /api/v1/apps/{app_id}/configurations/{param_name} declare_parameter("update_rate", 10.0); declare_parameter("enabled", true); declare_parameter("mode", "auto"); **Make parameters dynamically reconfigurable:** .. code-block:: cpp auto param_callback = [this](const std::vector& params) { for (const auto& param : params) { if (param.get_name() == "update_rate") { update_rate_ = param.as_double(); } } return rcl_interfaces::msg::SetParametersResult{.successful = true}; }; param_callback_handle_ = add_on_set_parameters_callback(param_callback); Launch File Integration ----------------------- Example launch file combining your robot with ros2_medkit: .. code-block:: python # robot_with_diagnostics.launch.py from launch import LaunchDescription from launch.actions import IncludeLaunchDescription from launch.launch_description_sources import PythonLaunchDescriptionSource from launch_ros.actions import Node from ament_index_python.packages import get_package_share_directory import os def generate_launch_description(): medkit_share = get_package_share_directory('ros2_medkit_gateway') return LaunchDescription([ # Your robot launch IncludeLaunchDescription( PythonLaunchDescriptionSource([ get_package_share_directory('my_robot'), '/launch/robot.launch.py' ]) ), # Fault manager for fault tracking Node( package='ros2_medkit_fault_manager', executable='fault_manager_node', name='fault_manager' ), # Gateway with custom config IncludeLaunchDescription( PythonLaunchDescriptionSource([ medkit_share, '/launch/gateway.launch.py' ]), launch_arguments={ 'server_host': '0.0.0.0', 'server_port': '8080' }.items() ), ]) Production Checklist -------------------- Before deploying to production: .. list-table:: :widths: 10 90 :header-rows: 0 * - ☐ - Enable TLS (:doc:`https`) * - ☐ - Configure authentication (:doc:`authentication`) * - ☐ - Set appropriate CORS origins * - ☐ - Use namespaces for logical organization * - ☐ - Implement fault reporting for critical components * - ☐ - Test with expected load * - ☐ - Set up monitoring and alerting * - ☐ - Document your Area/Component hierarchy See Also -------- - :doc:`custom_areas` - Advanced area customization - :doc:`docker` - Docker deployment - :doc:`authentication` - Security configuration