技术标签: ROS
首先创建一个空的package单独存放msg类型(当然也可以在任意的package中自定义msg类型)
这里为便于说明,建立一个名为test_msgs的包,用于对自定义msg类型的用法举例
$ cd catkin_ws/src
$ catkin_create_pkg test_msgs
然后在test_msgs中创建msg文件夹,在msg文件夹其中新建一个名为Test.msg
消息类型文件
$ cd test_msgs
$ mkdir msg
Test.msg
的内容如下,
基本类型可参考: std_msgs、common_msgs
float32[] data
float32 vel
geometry_msgs/Pose pose
string name
接下来需要message_generation生成C++或Python能使用的代码,需要message_runtime提供运行时的支持,所以package.xml中添加以下两句
<build_depend>message_generation</build_depend>
<run_depend>message_runtime</run_depend>
CMakeLists.txt
要注意四个地方
(1)首先调用find_package
查找依赖的包,必备的有roscpp rospy message_generation
,其他根据具体类型添加,比如上面的msg文件中用到了geometry_msgs/Pose pose
类型,那么必须查找geometry_msgs
find_package(catkin REQUIRED COMPONENTS roscpp rospy message_generation std_msgs geometry_msgs)
(2)然后是add_message_files
,指定msg文件
add_message_files(
FILES
Test.msg
# Message2.msg
)
(3)然后是generate_messages
,指定生成消息文件时的依赖项,比如上面嵌套了其他消息类型geometry_msgs
,那么必须注明
#generate_messages必须在catkin_package前面
generate_messages(
DEPENDENCIES
geometry_msgs
)
(4)然后是catkin_package
设置运行依赖
catkin_package(
CATKIN_DEPENDS message_runtime
)
到这里新的msg类型test_msgs/Test
就可以使用了,下面编译这个包,然后利用rosmsg show
指令查看
$ cd catkin_ws
$ catkin_make
$ rosmsg show test_msgs/Test
float32[] data
float32 vel
geometry_msgs/Pose pose
geometry_msgs/Point position
float64 x
float64 y
float64 z
geometry_msgs/Quaternion orientation
float64 x
float64 y
float64 z
float64 w
string name
要使用自定义的消息类型必须source自定义消息所在的工作空间,否则rosmsg show test_msgs/Test
和rostopic echo /test_msg
(/test_msg
是节点中使用自定义消息类型test_msgs/Test
的topic)都会报错,因为没有source的情况下自定义消息类型是不可见的,被认为是未定义类型
参考:
DefiningCustomMessages
如果是在test_msgs包内的节点中调用test_msgs/Test
类型,只需要在.cpp文件中如下调用即可
#include <test_msgs/Test.h>
test_msgs::Test msg;
test_msgs/Test
类型则需要修改package.xml和CMakeLists.txt,比如同样在工作空间catkin_ws内有一个名为test的包,我们可以在这个包内写一个节点,使用我们刚才自定义的消息类型test_msgs/Test
,如下:(1)修改package.xml
养成好习惯,维护软件包清单的更新,以便于别人使用你的软件前安装各种依赖项,当然这个文件不影响程序编译
<build_depend>roscpp</build_depend>
<run_depend>roscpp</run_depend>
<build_depend>test_msgs</build_depend>
<run_depend>test_msgs</run_depend>
(2)修改CMakeLists.txt
调用自定义消息类型主要修改两个地方,以下是重点:
一是find_package
中需要声明查找包含该消息类型的包;
二是add_dependencies
要注明该消息的依赖,其他地方和普通节点一样
find_package(catkin REQUIRED COMPONENTS
roscpp
geometry_msgs
test_msgs
)
add_dependencies(test1 test_msgs_gencpp)#调用同一工作空间的自定义消息类型时注明依赖关系,防止发生头文件找不到的报错
如果缺少add_dependencies
中对test_msgs_gencpp
的依赖声明,在编译的时候如果先编译test包再编译test_msgs包则会出现如下报错(ROS工作空间各个软件包的编译顺序是随机的),因为头文件test_msgs/Test.h
还未生成
fatal error: test_msgs/Test.h: 没有那个文件或目录
#include "test_msgs/Test.h"
需要说明的是std_msgs中有些数组用法和C++标准库中不一样
比如Float32MultiArray,其定义如下:
std_msgs/MultiArrayLayout layout
float32[] data
其中data
是一个浮点数组,但是方括号只是一个用来表明它是数组的符号,我们不能在定义的时候在方括号中给定数组长度,实际上ROS中类似float32[]
,int8[]
这样的数组类型都是std::vector
,使用方法也和std::vector
一样
测试代码可以从这里下载
下面是一个消息订阅节点,用于测试
/************************
* @Author: Jinglin Zhang
* @DateTime: 2017-06-07 19:57:30
* @Description: 节点test1,订阅了test_msgs包下talker节点发布的"test_msg"话题,用于测试test_msgs::Test消息类型
************************/
#include <ros/ros.h>
#include <test_msgs/Test.h>
void msgCallback(const test_msgs::Test::ConstPtr &msg)
{
//test_msgs::Test类型里的float32[]数据传到vector
std::vector<float> array = msg->data;
std::cout << "msg->data[0]=" << msg->data[0] << std::endl;
std::cout << "msg->data.size=" << msg->data.size() << std::endl;
std::cout << "msg->data=" << msg->data[0] << ", " << msg->data[1] << ", " << msg->data[2] << ", " << msg->data[3] << ", " << msg->data[4] << ", " << msg->data[5] << std::endl;
}
int main(int argc,char ** argv)
{
ros::init(argc,argv,"test1");
ros::NodeHandle n;
ros::Subscriber msg_sub = n.subscribe("test_msg", 100, msgCallback);
ros::spin();
return 0;
}
下面是一个消息发布节点,用于测试
/************************
* @Author: Jinglin Zhang
* @DateTime: 2017-06-07 20:03:35
* @Description: 节点talker,发布"test_msg"话题,用于测试test_msgs::Test消息类型
************************/
#include <ros/ros.h>
#include <test_msgs/Test.h>
int main(int argc, char **argv)
{
ros::init(argc, argv, "msg_talker");
ros::NodeHandle n;
ros::Publisher msg_pub = n.advertise<test_msgs::Test>("test_msg", 1000);
ros::Rate loop_rate(10);
int count = 0;
while (ros::ok())
{
test_msgs::Test msg;
std::cout << "msg.data.size=" << msg.data.size() << std::endl;
//用vector给float32[]数组赋值
float array[3] = {1.1,1.2,0.3};
std::vector<float> array1(array,array+3);
msg.data = array1;
std::cout << "msg.data3[0]=" << msg.data[0] << std::endl;
std::cout << "msg.data3.size=" << msg.data.size() << std::endl;
//下标访问float32[]数组
msg.data[0] = 0.1;
std::cout << "msg.data3[0]=" << msg.data[0] << std::endl;
float array4[4] = {1.0,2.0,0.3,6.6};
std::vector<float> array41(array4,array4+4);
msg.data = array41;
std::cout << "msg.data4.size=" << msg.data.size() << std::endl;
std::cout << "msg.data4=" << msg.data[0] << " " << msg.data[1] << " " << msg.data[2] << " " << msg.data[3] << std::endl;
msg.data.push_back(5.5);
std::cout << "msg.data[5]=" << msg.data[4] << std::endl;
//使用迭代器
msg.data.resize(6);
std::cout << "msg.data6.size=" << msg.data.size() << std::endl;
std::cout << "msg.data6=" ;
for(std::vector<float>::iterator it = msg.data.begin(); it != msg.data.end(); ++it)
{
*it = 0.6;
std::cout << *it << " ";
}
std::cout << std::endl;
msg_pub.publish(msg);
ros::spinOnce();
loop_rate.sleep();
++count;
}
return 0;
}
文章浏览阅读2.4k次,点赞3次,收藏9次。在写qt网口通信的过程中,遇到中文就乱码。解决方法如下:1.接收端处理中文乱码代码如下 QByteArray-> QString 中文乱码解决: #include <QTextCodec>QByteArray data= tcpSocket->readAll(); QTextCodec *tc = QTextCodec::codecForName("GBK"); QString str = tc->toUnicode(data);//str如果是中文则是中文字符_qbytearray中文乱码
文章浏览阅读2.5k次,点赞2次,收藏15次。什么是 DOM?文档对象模型(Document Object Model,简称 DOM),是 W3C 组织推荐的处理可扩展标记语言(HTML或者XML)的标准编程接口。W3C 已经定义了一系列的 DOM 接口,通过这些 DOM 接口可以改变网页的内容、结构和样式DOM 树文档:一个页面就是一个文档,DOM 中使用 document 表示元素:页面中的所有标签都是元素,DOM 中使用 element 表示节点:网页中的所有内容都是节点(标签、属性、文本、注释等),DOM 中使用 node._元素事件
文章浏览阅读1.4k次,点赞3次,收藏7次。关于服务的一些基本知识,包括活动对接口的方法调用,接口实现,服务生命周期等知识。_安卓服务
文章浏览阅读7.9k次,点赞5次,收藏8次。小白式数据库连接池使用,看完拿捏数据库连接池。_采用连接池方式连接数据库
文章浏览阅读4.9k次,点赞5次,收藏36次。摘要:本文介绍了C++11中如何开启新线程,并详细讲解了线程的基础同步原语:mutex, lock_guard, unique_lock, condition variable和semaphore等。如何采用async, packaged_task和promise实现future同步机制?怎样处理spurious wakeup?本文以质数判定服务为例为大家分享C++多线程同步措施!1. C++线程和基础同步原语Thread mutex, lock_guard, unique_lock con._c++线程同步
文章浏览阅读3.3k次,点赞4次,收藏9次。STM32 GPIOx通用输入输出I/O端口的BSRR寄存器与BRR功能简述_gpiob->brr
文章浏览阅读590次。IMP-00019: row rejected due to ORACLE error 12899IMP-00003: ORACLE error 12899 encounteredORA-12899: value too large for column "CRM"."BK_ECS_ORDER_INFO_00413"."POSTSCRIPT" (actual: 895, maximum..._row rejected due to oracle
文章浏览阅读918次。目前很多Web的项目在部署的时候会采用Nginx做为前端的反向代理服务器,后端会部署很多业务处理服务器,通常情况下Nginx代理服务器部署的还是比较少,而且其以高效性能著称,几万的并发连接处理速度都不在话下。然而去年的时候,我们的线上系统也采用类似的部署结构,同时由于我们的业务需求,Nginx的部署环境在虚拟机上面,复用了其他虚拟机的整体磁盘,在高IO消耗的场景中,我们发现Nginx的磁盘_nginx tcp转发 硬盘io
文章浏览阅读645次。Activiti 开发环境的搭建非常简单,主要分为 Activiti runtime 的安装以及 Eclipse 开发环境的配置。本文以 Windows 平台为例介绍 Activiti 5.8 版的开发环境的搭建配置过程。Activiti 的运行时程序可以从http://www.activiti.org/download.html 下载,目前最新版本为 5.8。为了配置使用 Activ_antdev activity
文章浏览阅读2.3k次。1. Vuex 是什么?Vuex 是专门为Vue 组件化思想带来的组件间通信问题提供的解决方案,主要解决以下两个问题:多个视图依赖于同一状态 来自不同视图的行为需要变更同一状态2. 核心概念State: 可以简单理解为Vue 维持的全局变量(状态)。 Getter: 获取State 中的状态的方法,可以在取出前对数据进行二次处理。 Mutation: 是改变State 中的状态..._vuex的组件同级通信
文章浏览阅读8.4k次,点赞31次,收藏33次。逆向中常常出现一些加密算法,如果我们能对这些加密算法进行快速识别则会大大减少我们逆向的难度,虽然IDA已有密码分析神器Findcrypt,但掌握手动分析方法能帮助我们应对更多的情况。这篇文章将介绍逆向中常见的单项散列算法和对称加密算法的识别方法。0xFF. 前言在很长一段时间里我经常发现自己面对复杂的加密算法无从下手,可能是因为还没有系统学过密码学吧orz,总之这个问题困扰了我很久。于是最近我花了一些时间来解决自己在密码学这块的薄弱点,写下这篇文章的目的之一也是为了巩固所学知识。加密算法的部分没有_findcrypt3 支持哪些算法
文章浏览阅读5.3k次。smplayerThere are lots of video players out there, but one that we think gets overlooked is SMPlayer. It can do anything other video players can do and even more – like remembering where you left off ..._sm69影视