ROS2总结(二)
1.QoS (Quality of Service)
1.1 概述
ROS2提供了一套非常丰富的服务质量QoS策略用于调整节点之间的通信。众所周知,在TCP与UDP之间存在着无数的折中设置,QoS既可以设置成像TCP一样可靠(reliable),也可以设置为像UDP一样高效(best effort)。
一套QoS策略形成了一个QoS Profile。考虑到为特定的场景选择正确QoS策略较为复杂,ROS2提供了一套预定义的QoS Profiles,用于常见场景(如传感器数据)。同时,也提供了特定的Profiles给使用者设置QoS策略。发布器、订阅器、服务端和客户端可以指定Profile,且它们的每个实例都可以单独指定Profile,但不兼容的Profiles可能导致无法通信。
1.2 QoS策略
QoS Profile提供了对以下QoS策略的设置:
(1)可靠性(Reliability) 消息传达的可靠性
- 可靠的(Reliable):反复重传以保证数据成功传输。
- 尽力的(Best effort):尝试传输数据但不保证成功传输(当网络不稳定时可能丢失数据)。
(2)历史记录(History) 消息的历史记录方式
当订阅者由于忙碌错过了消息,其仍能收到历史消息。这个参数只有在 Reliability 为 RELIABLE 时才有用。
- 保留近期记录(Keep last):缓存最多N条记录,可通过队列长度选项来配置。
- 保留所有记录(Keep all):缓存所有记录,但受限于底层中间件可配置的最大资源。
(3)深度(Depth)
- 队列深度(Size of the queue):只能与Keep last配合使用,指定需要保留的消息个数。
(4)持续性(Durability)
消息是否应该在网络中持久化,以便新加入的订阅者也能接收。这个参数只有在 Reliability 为 RELIABLE 时才有用。
- Transient local:消息在发布者端持久化,新加入的订阅者可以接收到旧消息,接收个数由History和Depth决定。
- Volatile:不保留任何数据。
rclcpp::QoS custom_qos_profile(rclcpp::QoSInitialization::from_rmw(rmw_qos_profile_default));// 设置 QoS 策略
custom_qos_profile.keep_last(10) // History: Keep last 10 条.reliable() // Reliability: Reliable.transient_local(); // Durability: Transient Local
SensorDataQoS 是 ROS2 中一个 预定义的 QoS配置,专门用于处理传感器数据(如摄像头图像、激光雷达点云等)的 发布-订阅通信。它被设计为在高频、低延迟但可容忍丢包的场景中使用。
- History: Keep last,
- Depth: 5,
- Reliability: Best effort, 不保证每条消息传达成功(适用于实时要求高的传感器数据)
- Durability: Volatile,
- Deadline: Default,
- Lifespan: Default,
- Liveliness: System default,
- Liveliness lease duration: default,
- avoid ros namespace conventions: false
ROS2学习日志:QoS要点总结 - dzyBK - 博客园
2.DDS
DDS是ROS2的一大特性,具体就不再赘述了,一般而言默认使用的是FAST DDS ,可通过 ros2 doctor --report 查看
RMW MIDDLEWARE
middleware name : rmw_fastrtps_cpp
有个需求:两个docker需要相互话题通信,需要把DDS改为cyclone dds(适合多机通信和生产环境)
export RMW_IMPLEMENTATION=rmw_cyclonedds_cpp
此外,只有设置相同 domain_id 的 ROS 节点,才能发现彼此、进行通信。
export ROS_DOMAIN_ID=3
Eclipse Cyclone DDS — ROS 2 Documentation: Jazzy documentation
3. 节点进程通信
3.1 单进程
intra-process 也叫 IPC,当多个节点合并启动时,如果开启 IPC,数据将直接通过进程内的指针传递,绕过中间件,这样可以大大降低通信开销。
demo
// LIO-SAM ros2 code
int main(int argc, char** argv)
{ rclcpp::init(argc, argv);rclcpp::NodeOptions options;options.use_intra_process_comms(true);rclcpp::executors::MultiThreadedExecutor e;auto ImuP = std::make_shared<IMUPreintegration>(options);auto TF = std::make_shared<TransformFusion>(options);e.add_node(ImuP);e.add_node(TF);RCLCPP_INFO(rclcpp::get_logger("rclcpp"), "\033[1;32m----> IMU Preintegration Started.\033[0m");e.spin();rclcpp::shutdown();return 0;
}
总结:同一个进程内的两个 ROS 节点间通信,零拷贝,减少CPU负载。
3.2 多进程
上一小节只是单进程内多个节点通信,但实际应用中是多个进程间通信,这个时候需要使用component 合并进程。
具体参考 demo 即可,注意需要把 add_library声明的动态库 install 到 lib目录下。
对比LIO-SAM代码修改为单进程的CPU负载:
①独立进程:
②合并进程: