Ros2 qos自定义策略实现方式(c c++ python)

Ros2 qos简介

用于节点之前的数据通信,为了保证数据能够可靠和高校的传输。ROS2提供了一套非常丰富的服务质量(Quality of Service, QoS)策略

Ros2 qos 注意事项

发布器、订阅器、服务端和客户端可以指定Profile,且它们的每个实例都可以单独指定Profile,但不兼容的Profiles可能导致无法通信。

Qos策略

当前,QoS Profile提供了对以下QoS策略的设置:

(1)历史记录(History)

保留近期记录(Keep last):缓存最多N条记录,可通过队列长度选项来配置。

保留所有记录(Keep all):缓存所有记录,但受限于底层中间件可配置的最大资源。

(2)深度(Depth)

队列深度(Size of the queue):只能与Keep last配合使用。

(3)可靠性(Reliability)

尽力的(Best effort):尝试传输数据但不保证成功传输(当网络不稳定时可能丢失数据)。

可靠的(Reliable):反复重传以保证数据成功传输。

(4)持续性(Durability)

局部瞬态(Transient local):发布器为晚连接(late-joining)的订阅器保留数据。

易变态(Volatile):不保留任何数据。

以上每个策略都有系统默认值。这个默认值就是底层中间件的默认值,由DDS供应商工具(如XML配置文件)定义。DDS本身提供了许多可配置的策略。这些策略与ROS1的特征相似,所以在ROS1中是可见的。之后可能会有更多的策略在ROS2中可见。

自定义Ros2 qos 策略

  • c版

  • 首先创建一个default_qos.h,添加自定义的策略


#ifndef RCL_ACTION__DEFAULT_QOS_H_
#define RCL_ACTION__DEFAULT_QOS_H_

#ifdef __cplusplus
extern "C"
{
#endif

#include "rmw/types.h"


static const rmw_qos_profile_t rcl_msg_qos_profile_status_default =
{
  RMW_QOS_POLICY_HISTORY_KEEP_LAST,
  10,
  RMW_QOS_POLICY_RELIABILITY_RELIABLE,
  RMW_QOS_POLICY_DURABILITY_TRANSIENT_LOCAL,
  RMW_QOS_DEADLINE_DEFAULT,
  RMW_QOS_LIFESPAN_DEFAULT,
  RMW_QOS_POLICY_LIVELINESS_SYSTEM_DEFAULT,
  RMW_QOS_LIVELINESS_LEASE_DURATION_DEFAULT,
  false
};

#ifdef __cplusplus
}
#endif

#endif

  • 第二步把定义好策略赋值到qos的结构体中

int start_msg(rcl_node_t* node, rclc_support_t* support)
{
  rcl_node_options_t node_ops = rcl_node_get_default_options();
  RCCHECK(rcl_node_init(node, "char_long_sequence_subscriber_rcl", "", &support->context, &node_ops))
  rcl_subscription_options_t subscription_ops = rcl_subscription_get_default_options();
  rcl_subscription_t subscription = rcl_get_zero_initialized_subscription();
  //设置配置好的qos策略
  subscription_ops.qos = rcl_msg_qos_profile_status_default;
  RCCHECK(rcl_subscription_init(&subscription, node, ROSIDL_GET_MSG_TYPE_SUPPORT(std_msgs, msg, String), "string data", &subscription_ops))
  rcl_wait_set_t wait_set = rcl_get_zero_initialized_wait_set();
  RCCHECK(rcl_wait_set_init(&wait_set, 1, 0, 0, 0, 0, 0, &support->context, rcl_get_default_allocator()))
  std_msgs__msg__String msg;
  msg.data.data = (char * ) malloc(ARRAY_LEN * sizeof(char));
  msg.data.size = 0;
  msg.data.capacity = ARRAY_LEN;
  char test_array[ARRAY_LEN];
  memset(test_array,'z',ARRAY_LEN);
  do {
    RCSOFTCHECK(rcl_wait_set_clear(&wait_set))
    size_t index;
    RCSOFTCHECK(rcl_wait_set_add_subscription(&wait_set, &subscription, &index))
    RCSOFTCHECK(rcl_wait(&wait_set, RCL_MS_TO_NS(1)))
    if (wait_set.subscriptions[index]) {
      rcl_ret_t rc = rcl_take(wait_set.subscriptions[index], &msg, NULL, NULL);
      if (RCL_RET_OK == rc) {
        
        // Check if sequence items matches the know pattern
        bool pass_test = strncmp(test_array, msg.data.data, msg.data.size) == 0;

        printf("I received an %ld array. Test: [%s]\n", msg.data.size, (pass_test) ? "OK" : "FAIL");
      }
    }
  } while ( true );
  RCCHECK(rcl_subscription_fini(&subscription, node))
  RCCHECK(rcl_node_fini(node))
  return 0;
}

  • python 版自定义qos策略添加
import rclpy
from rclpy.node import Node
from rclpy.qos import DurabilityPolicy
from rclpy.qos import QoSProfile
from rclpy.qos_event import SubscriptionEventCallbacks

from std_msgs.msg import String


class MinimalSubscriber(Node):

    def __init__(self):
        #创建qos对象
        qos = QoSProfile(depth=10)
        #设置不同的qos策略
        qos.durability = DurabilityPolicy.RMW_QOS_POLICY_DURABILITY_TRANSIENT_LOCAL

        custom_callback = lambda event: print("Custom Incompatible Callback!")
        callbacks = SubscriptionEventCallbacks()
        callbacks.incompatible_qos = custom_callback

        super().__init__('minimal_subscriber')
        #qos策略传入
        self.subscription = self.create_subscription(
            String,
            'string data',
            self.listener_callback,
            qos,
            event_callbacks=callbacks)

    def listener_callback(self, msg):
        self.get_logger().info('I heard: "%s"' % msg.data)


def main(args=None):
    rclpy.init(args=args)

    minimal_subscriber = MinimalSubscriber()

    rclpy.spin(minimal_subscriber)

    minimal_subscriber.destroy_node()
    rclpy.shutdown()


if __name__ == '__main__':
    main()
  • c++版 自定义Qos策略添加


#include <iostream>
#include <functional>
#include "rclcpp/rclcpp.hpp"
#include "std_msgs/msg/string.hpp"

int main(int argc, char ** argv)
{
  rclcpp::init(argc, argv);

  auto node = std::make_shared<rclcpp::Node>("qos_callback_listener");
  rclcpp::SubscriptionOptions options;

  rclcpp::QoS qos(0);
  qos.reliable();
  qos.durability(RMW_QOS_POLICY_DURABILITY_TRANSIENT_LOCAL);

  options.use_default_callbacks = false;
  options.event_callbacks.incompatible_qos_callback = [](rclcpp::QOSOfferedIncompatibleQoSInfo & event) {
    std::cout << "Custom Incompatible Callback!" << std::endl;
  };

  auto subscriber = node->create_subscription<std_msgs::msg::String>(
    "/string data",
    qos,
    [](const std_msgs::msg::String::SharedPtr) {
      std::cout << "Heard a message" << std::endl;
    },
    options);

  rclcpp::spin(node);
  return 0;
}

  • 2
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
当然,这是一个使用QoS 1级别的MQ发送端C++代码示: ```cpp #includeiostream> #include <mqtt/async_client.h> std::string SERVER_ADDRESStcp://mqtt.eclipse.org:1883"); std::string CLIENT_ID("mqtt_cpp"); class mqtt_callback : public virtual mqtt:: { void connection_lost(const std::stringcause) override { std::cout << "\nConnection lost: " << cause << std::endl; } void delivery_complete(mqtt::delivery_token_ptr token) override { std::cout << "Delivery complete for token: " << token->get_message_id() << std::endl; } void message_arrived(const mqtt::const_message_ptr &msg) override {} }; int main(int argc, char *argv[]) { mqtt::async_client client(SERVER_ADDRESS, CLIENT_ID); mqtt_callback cb; client.set_callback(cb); mqtt::connect_options connOpts; connOpts.set_keep_alive_interval(20); connOpts.set_clean_session(true); try { client.connect(connOpts); std::string topic = "your/topic"; std::string payload = "Hello, MQTT!"; int qos = 1; bool retained = false; mqtt::message_ptr pubmsg = mqtt::make_message(topic, payload, qos, retained); client.publish(pubmsg)->wait_for(std::chrono::seconds(5)); client.disconnect(); } catch (const mqtt::exception &exc) { std::cerr << "Error: " << exc.what() << std::endl; return 1; } return 0; } ``` 在这个例子中,我们使用了相同的MQTT C++库来创建一个MQTT发送端。我们连接到了公共的MQTT代理服务器(mqtt.eclipse.org)并发布了一个消息到指定的主题。消息的QoS级别设置为1,表示需要确认传递。 请注意,这只是一个基本的示例,你可以根据需要修改和扩展它来满足你的实际需求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值