什么是 rosidl_runtime_c__double__Sequence 类型?

What is rosidl_runtime_c__double__Sequence type?

由于 micro-ros(arduino 版本),我正在尝试使用 teensy 4.1 作为编码器和 ROS 之间的接口。

我想用 teensy 将轮子的位置发布到 /jointState 主题,但 micro-ros arduino Github repo.

上没有示例

我试过检查 sensormsgs/msg/jointState message struct 但一切都有些模糊,我不明白如何让它工作。我不明白什么是 rosidl_runtime_c__double__Sequence 类型。

我已经尝试了几种方法,但总是遇到有关操作数类型的错误

no match for 'operator=' (operand types are 'rosidl_runtime_c__String' and 'const char [18]')
 msg.name.data[0] = "drivewhl_1g_joint";

这是我的arduino代码

#include <micro_ros_arduino.h>

#include <stdio.h>
#include <rcl/rcl.h>
#include <rcl/error_handling.h>
#include <rclc/rclc.h>
#include <rclc/executor.h>

#include <sensor_msgs/msg/joint_state.h>

rcl_publisher_t publisher;
sensor_msgs__msg__JointState msg;
rclc_executor_t executor;
rclc_support_t support;
rcl_allocator_t allocator;
rcl_node_t node;
rcl_timer_t timer;

#define LED_PIN 13

#define RCCHECK(fn) { rcl_ret_t temp_rc = fn; if((temp_rc != RCL_RET_OK)){error_loop();}}
#define RCSOFTCHECK(fn) { rcl_ret_t temp_rc = fn; if((temp_rc != RCL_RET_OK)){}}


void error_loop(){
  while(1){
    digitalWrite(LED_PIN, !digitalRead(LED_PIN));
    delay(100);
  }
}

void timer_callback(rcl_timer_t * timer, int64_t last_call_time)
{  
  RCLC_UNUSED(last_call_time);
  if (timer != NULL) {
    RCSOFTCHECK(rcl_publish(&publisher, &msg, NULL));
    
    //

    //Do not work
    //msg.name=["drivewhl_1g_joint","drivewhl_1d_joint","drivewhl_2g_joint","drivewhl_2d_joint"];
    //msg.position=["1.3","0.2", "0","0"];
    msg.name.size = 1;
    msg.name.data[0] = "drivewhl_1g_joint";
    msg.position.size = 1;
    msg.position.data[0] = 1.85;
    
  
  }
}

void setup() {
  set_microros_transports();
  
  pinMode(LED_PIN, OUTPUT);
  digitalWrite(LED_PIN, HIGH);  
  
  delay(2000);

  allocator = rcl_get_default_allocator();

  //create init_options
  RCCHECK(rclc_support_init(&support, 0, NULL, &allocator));

  // create node
  RCCHECK(rclc_node_init_default(&node, "micro_ros_arduino_node", "", &support));

  // create publisher
  RCCHECK(rclc_publisher_init_default(
    &publisher,
    &node,
    ROSIDL_GET_MSG_TYPE_SUPPORT(sensor_msgs, msg, JointState),
    "JointState"));

  // create timer,
  const unsigned int timer_timeout = 1000;
  RCCHECK(rclc_timer_init_default(
    &timer,
    &support,
    RCL_MS_TO_NS(timer_timeout),
    timer_callback));

  // create executor
  RCCHECK(rclc_executor_init(&executor, &support.context, 1, &allocator));
  RCCHECK(rclc_executor_add_timer(&executor, &timer));

}

void loop() {
  delay(100);
  RCSOFTCHECK(rclc_executor_spin_some(&executor, RCL_MS_TO_NS(100)));
}

我是Ros和C的初学者,这可能是一个非常愚蠢的问题,但我不知道如何解决。感谢您的帮助!

rosidl_runtime_c__String__Sequence是一个结构,用于传输旧字符串数据。具体来说,它是 rosidl_runtime_c__String 数据的 序列 。您 运行 出错了,因为 rosidl_runtime_c__String 本身也是一个没有定义自定义运算符的结构。因此,您的分配失败,因为类型不能直接转换。您需要做的是使用 rosidl_runtime_c__String.data 字段。您可以看到更多信息 here

void timer_callback(rcl_timer_t * timer, int64_t last_call_time)
{  
  RCLC_UNUSED(last_call_time);
  if (timer != NULL) {
    //msg.name=["drivewhl_1g_joint","drivewhl_1d_joint","drivewhl_2g_joint","drivewhl_2d_joint"];
    //msg.position=["1.3","0.2", "0","0"];
    msg.name.size = 1;
    msg.name.data[0].data = "drivewhl_1g_joint";
    msg.name.data[0].size = 17; //Size in bytes excluding null terminator
    msg.position.size = 1;
    msg.position.data[0] = 1.85;
    
    RCSOFTCHECK(rcl_publish(&publisher, &msg, NULL));
  }
}

我也花了很多时间尝试从我的 esp32 运行 microros 发布 JointState 消息,但也找不到工作示例。终于,我成功了,也许它会对某人有所帮助。

简单来说:

  • .capacity 包含最大数量的元素
  • .size 包含元素的实际数量(strlen 在字符串的情况下)
  • .data 应该分配为使用 malloc 作为 .capacity * sizeof()
  • 序列中的每个字符串应该单独分配

这是我为12个关节分配内存的代码,命名为j0-j11。祝你好运!

...
// Declarations
rcl_publisher_t pub_joint;
sensor_msgs__msg__JointState joint_state_msg;
...
// Create publisher
RCCHECK(rclc_publisher_init_default(&pub_joint, &node,
    ROSIDL_GET_MSG_TYPE_SUPPORT(sensor_msgs, msg, JointState), 
    "/hexapod/joint_state"));

//Allocate memory
    joint_state_msg.name.capacity = 12;
    joint_state_msg.name.size = 12;
    joint_state_msg.name.data = (std_msgs__msg__String*) malloc(joint_state_msg.name.capacity*sizeof(std_msgs__msg__String));

    for(int i=0;i<12;i++) {
        joint_state_msg.name.data[i].data = malloc(5);
        joint_state_msg.name.data[i].capacity = 5;
        sprintf(joint_state_msg.name.data[i].data,"j%d",i);
        joint_state_msg.name.data[i].size = strlen(joint_state_msg.name.data[i].data);
    }

    joint_state_msg.position.size=12;
    joint_state_msg.position.capacity=12;
    joint_state_msg.position.data = malloc(joint_state_msg.position.capacity*sizeof(double));
    joint_state_msg.velocity.size=12;
    joint_state_msg.velocity.capacity=12;
    joint_state_msg.velocity.data = malloc(joint_state_msg.velocity.capacity*sizeof(double));
    joint_state_msg.effort.size=12;
    joint_state_msg.effort.capacity=12;
    joint_state_msg.effort.data = malloc(joint_state_msg.effort.capacity*sizeof(double));

    for(int i=0;i<12;i++) {
        joint_state_msg.position.data[i]=0.0;
        joint_state_msg.velocity.data[i]=0.0;
        joint_state_msg.effort.data[i]=0.0;
    }

....
//Publish
RCSOFTCHECK(rcl_publish(&pub_joint, &joint_state_msg, NULL));