ROS2 IMU 消息发布

news/2024/11/14 9:17:53/

ROS2 IMU 消息发布 仅做为笔记 学习用

本文源地址:

【ROS2】获取imu数据并可视化保姆级教程(C++)_imu可视化-CSDN博客

/*
* transform.hpp
*/
#include <string>
#include <ctype.h>
#include <float.h>
#include <math.h>
class transform_imu
{
private:char *stcTime;char *stcAcc;char *stcGyro;char *stcAngle;public:struct Acc{double x;double y;double z;} acc{0, 0, 0};struct Gyro{double x;double y;double z;} gyro{0, 0, 0};struct Angle{double r;double p;double y;} angle{0, 0, 0};/*public:transform_imu(double,double,double);//构造函数,也可尝试用初始化列表方式*/void FetchData(auto &data, int usLength){int index = 0;// char *pData_head = data;// printf("count%xn",*pData_head);printf("%xn", data[index]);printf("count%dn", usLength);while (usLength >= 11) // 一个完整数据帧11字节{printf("%xn", data[index + 1]);if (data[index] != 0x55) // 0x55是协议头{index++; // 指针(/索引)后移,继续找协议头usLength--;continue;}// for(int i = 0;i < 1000;i++){printf("oncen");}if (data[index + 1] == 0x50) // time{stcTime = &data[index + 2];// memcpy(&stcTime, &data[index + 2], 8);}else if (data[index + 1] == 0x51) // 加速度{stcAcc = &data[index + 2];// memcpy(&stcAcc, &pData_head[index + 2], 8);acc.x = ((short)((short)stcAcc[1] << 8 | stcAcc[0])) / 32768.00 * 16 * 9.8;acc.y = ((short)((short)stcAcc[3] << 8 | stcAcc[2])) / 32768.00 * 16 * 9.8;acc.z = ((short)((short)stcAcc[5] << 8 | stcAcc[4])) / 32768.00 * 16 * 9.8;}else if (data[index + 1] == 0x52){stcGyro = &data[index + 2];// memcpy(&stcGyro, &pData_head[index + 2], 8);gyro.x = ((short)((short)stcGyro[1] << 8 | stcGyro[0])) / 32768.00 * 2000 / 180 * M_PI; // 弧度制gyro.y = ((short)((short)stcGyro[3] << 8 | stcGyro[2])) / 32768.00 * 2000 / 180 * M_PI;gyro.z = ((short)((short)stcGyro[5] << 8 | stcGyro[4])) / 32768.00 * 2000 / 180 * M_PI;}else if (data[index + 1] == 0x53){stcAngle = &data[index + 2];// memcpy(&stcAngle, &pData_head[index + 2], 8);angle.r = ((short)((short)stcAngle[1] << 8 | stcGyro[0])) / 32768.00 * M_PI;angle.p = ((short)((short)stcAngle[3] << 8 | stcGyro[2])) / 32768.00 * M_PI;angle.y = ((short)((short)stcAngle[5] << 8 | stcGyro[4])) / 32768.00 * M_PI;}/*case 0x54: //磁力计memcpy(&stcMag, &pData_head[2], 8);mag.x = stcMag[0];mag.y = stcMag[1];mag.z = stcMag[2];*/// 这里我一开始用switch case的写法/*case 0x59: //四元数memcpy(&stcQuat, &pData_head[2], 8);quat.w = stcQuat[0] / 32768.00;quat.x = stcQuat[1] / 32768.00;quat.y = stcQuat[2] / 32768.00;quat.z = stcQuat[3] / 32768.00;*/// 这个型号imu传感器6轴,暂时不启用这些读取// default:printf("overn");printf("overn");usLength = usLength - 11;index += 11;}}
};/*
* publisher_imu.cpp
*/
#include <chrono>
#include <math.h>
#include "serial/serial.h" //前面安装的ROS2内置串口包
#include <memory.h>
#include "std_msgs/msg/string.hpp"
#include "sensor_msgs/msg/magnetic_field.hpp"
//#include "geometry_msgs/msg/detail/vector3__struct.hpp"
#include "sensor_msgs/msg/imu.hpp"
#include "tf2/LinearMath/Quaternion.h"
#include "tf2_ros/transform_broadcaster.h"
#include "tf2_ros/static_transform_broadcaster.h"
#include "nav_msgs/msg/odometry.hpp"
#include <string>
#include "rclcpp/rclcpp.hpp"#include "transform.hpp"serial::Serial ser;using namespace std::chrono_literals;class publisher_imu_node : public rclcpp::Node// 节点命名与类最好一致
{
public:std::string port;int baudrate;std::string imu_topic;std::string imu_offline_topic;transform_imu imu_fetch; // 初始值设为0
public:publisher_imu_node(): Node("publisher_imu_node"){int output_hz = 20; // 频率,看传感器说明书// timer_ms = millisecond(output_hz);std::chrono::milliseconds timer_ms{output_hz}; // 换算成msport = "/dev/ttyUSB0";                         // 串口号,主机可查看baudrate = 9600;                               // 波特率,imu在波特率115200返回数据时间大概是1ms,9600下大概是10ms,看imu参数设置try{ser.setPort(port);ser.setBaudrate(baudrate);serial::Timeout to = serial::Timeout::simpleTimeout(500);ser.setTimeout(to);ser.open();}catch (serial::IOException &e){RCLCPP_INFO(this->get_logger(), "Unable to open port ");return;}if (ser.isOpen()){RCLCPP_INFO(this->get_logger(), "Serial Port initialized");}else{RCLCPP_INFO(this->get_logger(), "Serial Port ???");return;}pub_imu = this->create_publisher<sensor_msgs::msg::Imu>("/imu_data", 20);//<sensor_msgs::msg::Imu>消息数据类型可自行查看对应文件,消息队列长度设20pub_imu_offline = this->create_publisher<sensor_msgs::msg::Imu>("/imu_offline_data", 20);// 这里创建了两个话题,一个是/imu_data,一个是/imu_offline_data// imu = transform_imu();//初始化对象// ser.flush();// int size;printf("Process working_1n");timer_ = this->create_wall_timer(500ms, std::bind(&publisher_imu_node::timer_callback, this));//std::chrono::milliseconds timer_ms{output_hz}; // 换算成msprintf("Process working_2n");   }public:void timer_callback(){int count = ser.available(); // 读取到缓存区数据的字节数if (count != 0){// ROS_INFO_ONCE("Data received from serial port.");int num;rclcpp::Time now = this->get_clock()->now(); // 获取时间戳std::vector<unsigned char> read_buf(count);//这里定义无符号,是应为read函数的形参是无符号//unsigned char read_buf[count]; // 开辟数据缓冲区,注意这里是无符号类型num = ser.read(&read_buf[0], count); // 读出缓存区缓存的数据,返回值为读到的数据字节数std::vector<char> read_buf_char(count);//vector转char类型for(int i = 0;i < count;i++){read_buf_char[i] = (char)read_buf[i];}imu_fetch.FetchData(read_buf_char, num);sensor_msgs::msg::Imu imu_data;         //sensor_msgs::msg::Imu imu_offline_data; ////------------------imu data----------------imu_data.header.stamp = now;imu_data.header.frame_id = "imu_frame";imu_data.linear_acceleration.x = imu_fetch.acc.x;imu_data.linear_acceleration.y = imu_fetch.acc.y;imu_data.linear_acceleration.z = imu_fetch.acc.z;imu_data.angular_velocity.x = imu_fetch.angle.r * 180.0 / M_PI;imu_data.angular_velocity.y = imu_fetch.angle.p * 180.0 / M_PI;imu_data.angular_velocity.z = imu_fetch.angle.y * 180.0 / M_PI;//数据结构里没有储存欧拉角的变量名称,用angular_velocity.z凑合tf2::Quaternion curr_quater;curr_quater.setRPY(imu_fetch.angle.r, imu_fetch.angle.p, imu_fetch.angle.y);// 欧拉角换算四元数RCLCPP_INFO(this->get_logger(), "Publishing: '");//RCLCPP_INFO(this->get_logger(), "angle: x=%f, y=%f, z=%f",imu.angle.r, imu.angle.p, imu.angle.y);imu_data.orientation.x = curr_quater.x();imu_data.orientation.y = curr_quater.y();imu_data.orientation.z = curr_quater.z();imu_data.orientation.w = curr_quater.w();// RCLCPP_INFO(this->get_logger(), "Quaternion: x=%f, y=%f, z=%f, w=%f",// imu_data.orientation.x, imu_data.orientation.y, imu_data.orientation.z, imu_data.orientation.w);//---------------imu offline data--------------imu_offline_data.header.stamp = now;// imu_offline_data.header.frame_id = imu_frame;imu_offline_data.linear_acceleration.x = imu_fetch.acc.x;imu_offline_data.linear_acceleration.y = imu_fetch.acc.y;imu_offline_data.linear_acceleration.z = imu_fetch.acc.z;imu_offline_data.angular_velocity.x = imu_fetch.gyro.x;imu_offline_data.angular_velocity.y = imu_fetch.gyro.y;imu_offline_data.angular_velocity.z = imu_fetch.gyro.z;imu_offline_data.orientation.x = curr_quater.x();imu_offline_data.orientation.y = curr_quater.y();imu_offline_data.orientation.z = curr_quater.z();imu_offline_data.orientation.w = curr_quater.w();pub_imu->publish(imu_data);pub_imu_offline->publish(imu_offline_data); // 发布话题,往两个话题放数据}}rclcpp::TimerBase::SharedPtr timer_;rclcpp::Publisher<sensor_msgs::msg::Imu>::SharedPtr pub_imu;rclcpp::Publisher<sensor_msgs::msg::Imu>::SharedPtr pub_imu_offline;
};int main(int argc, char *argv[])
{rclcpp::init(argc, argv);rclcpp::spin(std::make_shared<publisher_imu_node>()); // 单线程,调用所有可触发的回调函数,将进入循环,不会返回printf("Process exitn");rclcpp::shutdown();return 0;
}


http://www.ppmy.cn/news/1508736.html

相关文章

揭开中药神秘面纱:华盈生物的中药/复方有效成分鉴定技术

中药自古以来在中华文明中占据着重要的地位&#xff0c;其独特的疗效和复杂的成分组合令人叹为观止。然而&#xff0c;随着现代医学的发展和科学技术的进步&#xff0c;对中药及其复方的研究逐渐从经验性的应用转向科学的探索和验证。为了更好地理解中药的作用机制&#xff0c;…

软考学习笔记(0):软考准备

文章目录 前言软考的优点软考项目的选择资料选择 前言 最近因为某些原因&#xff0c;我又开始上班了。新工作是纯内网开发&#xff0c;那以后发博客的频率我估计就会很少了。 软考的优点 简单来说&#xff0c;软考考上了&#xff0c;大概一个月的薪资可以涨1000-3000&#x…

【QT 5 QT 6 构建工具qmake-cmake-和-软件编译器MSVCxxxvs MinGWxxx说明】

【QT 5报错&#xff1a;/xxx/: error: ‘class Ui::frmMain’ has no member named ‘xxx’-和-软件编译器MSVCxxxvs MinGWxxx说明】 1、前言2 、qt 中 Qmake CMake 和 QBS1-qmake2-Cmake3-QBS4-官网一些说法5-各自特点 3、软件编译套件1-Desktop Qt 6.7.2 llvm-mingw 64-bit2-…

在复制 PowerPoint (PPT) 文件时,其中嵌入或者链接的 Excel 文件能够自动创建一个新的实例,而不是继续引用原始的 Excel 文件。

问题&#xff1a; 在复制 PowerPoint (PPT) 文件时&#xff0c;其中嵌入或者链接的 Excel 文件能够自动创建一个新的实例&#xff0c;而不是继续引用原始的 Excel 文件。 解答&#xff1a; 导入已有的excel实测是不行的

后端接口返回base64编码图片前端如何接收(图形验证码)

前端请求该接口的时候可能会出现请求的结果为null&#xff0c;但是查看网络&#xff0c;显示已经获取该数据了&#xff0c;导致这个的原因可能是同步请求。但是为了更方便的去使用&#xff0c;我们可以直接在前端img图片中去使用这个接口&#xff0c;来进行展示 <img srcht…

【文件IO】文件系统操作

文章目录 基本操作概述1. 文件属性2. 文件构造方法3. 文件方法1. 文件创建2. 文件删除3. 查看目录下所有的文件名4. 遍历目录5. 创建目录5. 目录重命名 基本操作概述 创建文件删除文件创建目录重命名文件判定文件存在… Java 中&#xff0c;提供了一个 File 类&#xff0c;进…

postman常用的使用方法

1.将get请求的参数变为环境参数 添加“pre-request Script” var id pm.request.url.query.get("id") pm.environment.set("id", id); 2.将接口响应结果放置全局参数 添加“Tests” var data pm.response.json() var id data.id; pm.globals.…

Unity射击游戏开发教程:(31)制造一定追踪行为的敌人

在本文中,我们将介绍如何在两种敌人行为之间切换。本文是前两篇文章的延续,分别介绍了敌人躲避玩家射击以及敌人不断旋转并向玩家射击的情况。我只是介绍如何在这两种行为之间进行转换。 这种新的敌人行为的目标: 当不开火时,敌人可以躲避玩家的射击。射击时,敌人无法躲避…