Integrating with Your ROS 2 System
This tutorial shows how to integrate ros2_medkit with your existing ROS 2 application.
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:
# 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:
# 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:
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:
<depend>ros2_medkit_fault_reporter</depend>
Report faults in your node:
#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<FaultReporter>(
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<FaultReporter> 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 requiredFault::SEVERITY_WARN- Warning, may need attentionFault::SEVERITY_ERROR- Error, requires attentionFault::SEVERITY_CRITICAL- Critical, immediate action required
Exposing Custom Data
Any topic under your node’s namespace is automatically exposed via the Data API:
// 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<MyStatus>("status", 10);
pub_diagnostics_ = create_publisher<DiagnosticArray>("diagnostics", 10);
Best practices for data exposure:
Use meaningful topic names
Publish regularly for real-time monitoring
Include timestamps in messages
Use standard message types when possible
Exposing Services and Actions
Services and actions under your namespace become Operations:
// Service: POST /api/v1/apps/{app_id}/operations/reset/executions
srv_reset_ = create_service<std_srvs::srv::Trigger>(
"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<Calibrate>(
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:
// 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:
auto param_callback = [this](const std::vector<rclcpp::Parameter>& 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:
# 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:
☐ |
Enable TLS (Configuring HTTPS/TLS) |
☐ |
Configure authentication (Configuring 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
Customizing the Entity Hierarchy - Advanced area customization
Docker Deployment - Docker deployment
Configuring Authentication - Security configuration