由于ROS1 的 kinetic版本不支持了,现在改用melodic版本的ROS1,两者目前我没发现太大的区别,用法好像都是一致的,这里声明一下。
首先奉上官方教程,点击这里。
一般都会在工作空间下,新建一个专门用于存放各种消息的功能包,我这里就新建了一个与autoware消息对接的ROS1功能包,这里就举个例子,然后就新建一个test_msgs的功能包,由于我分别安装了ROS1和ROS2,分别的工作空间目录为 ~/Documents/ros1_melodic 和 ~/Documents/ros2_dashing ,所以以下都是按照我的工作空间来描述的,首先进入工作空间的src文件夹下,新建一个test_msgs功能包。
cd ~/Documents/ros1_melodic/src
catkin_create_pkg test_msgs std_msgs roscpp rospy
然后,新建自定义的msg文件,要养成一个良好的习惯,msg文件要放在msgs文件夹下面。 msg文件每一行定义一个变量,更确切的来说就是一个变量类型加上一个变量名,msg中可以使用的变量类型有:
个人认为msg文件最大的方便之处在于,可以依赖于其他的msg而生成个人需要的msg消息格式,这里举个栗子说明一下。ROS1中的std_msgs/Header.msg中的内容如下:
# Standard metadata for higher-level stamped data types.
# This is generally used to communicate timestamped data
# in a particular coordinate frame.
#
# sequence ID: consecutively increasing ID
uint32 seq
#Two-integer timestamp that is expressed as:
# * stamp.sec: seconds (stamp_secs) since epoch (in Python the variable is called 'secs')
# * stamp.nsec: nanoseconds since stamp_secs (in Python the variable is called 'nsecs')
# time-handling sugar is provided by the client library
time stamp
#Frame this data is associated with
# 0: no frame
# 1: global frame
string frame_id
简单解释一下,seq表示消息的滚动计数,stamp表示消息的时间戳,frame_id表示此消息中的数据是所基于坐标系的名称。
而ROS1中的自带的另一个消息geometry_msgs/PoseStamped.msg中的内容如下:
std_msgs/Header header
geometry_msgs/Pose pose
可以从中看到,PoseStamped.msg中就直接调用了std_msgs/Header格式的消息。这种使用方式,是很方便的,而且实际使用的大多数消息,都是第一行就是std_msgs/Header header ,这里就不多赘述了,一些ROS1常用的消息,在这里附上链接,方便后续查阅 std_msgs,common_msgs。
基本的概念就这样吧,下面继续新建msg文件,建立一个msg文件夹,放msg文件,并新建test.msg文件:
cd test_msgs/
mkdir msg
cd msg/
touch test.msg
其中test.msg中的内容如下,
std_msgs/Header header
string child_frame_id
float32[] data
geometry_msgs/Pose pose
由于srv这一块用的不是很多,就把自己理解的部分码上来,如有错误,小伙伴看到了麻烦批评指出。
首先,srv消息主要用于,需要经常调用这个服务的功能,因此,service多数都是在后台开启的,client在需要实现service功能的时候,向service发送需要处理的数据,然后再由client接收service返回的值,具体可以直接看ROS1官方的代码。
继续新建srv消息,首先在功能包test_msgs中新建一个srv文件夹,然后新建一个 AddTwoInts.srv 文件。
cd ..
mkdir srv
cd srv
touch AddTwoInts.srv
具体的 AddTwoInts.srv 内容如下,
int64 a
int64 b
---
int64 sum
其中,a和b为 request,sum为service处理完后,返回的值,注意中间的 — 符号,符号上面的为 request,下面为 return 。
打开 test_msgs 文件夹下的文件 package.xml,确保其有下面两条代码:
message_generation
message_runtime
message_generation 为把 .msg 和 .srv文件生成对应的 C++ 或者 Python 代码的工具包,此外由于新建的 test.msg 文件中,使用了 geometry_msgs ,这样就需要另外加上两行代码,
声明自定义消息的依赖,
geometry_msgs
geometry_msgs
如果还有其他的功能包依赖,则一样需要添加进去,这里没有了,所以就这么多。
CMakeList.txt 确定了编译环境的配置
find_package(catkin REQUIRED COMPONENTS
roscpp
rospy
std_msgs
geometry_msgs
message_generation
)
add_message_files(
FILES
test.msg
)
add_service_files(
FILES
AddTwoInts.srv
)
generate_messages(
DEPENDENCIES
std_msgs
geometry_msgs
)
catkin_make
编译完成后,运行
rosmsg show test_msgs/test
rossrv show test_msgs/AddTwoInts
另外在 ~/Documents/ros1_melodic/src/ 下新建一个功能包 test
catkin_create_pkg test std_msgs roscpp rospy
进入该功能包的src文件夹下,新建文件 test.cpp,内容为,
#include "ros/ros.h"
#include
#include "test_msgs/test.h"
int main(int argc, char **argv)
{
ros::init(argc, argv, "test");
ros::NodeHandle node;
ros::Publisher test_pub = node.advertise<test_msgs::test>("test_msg",1000);
ros::Rate loop_rate(10);
ROS_INFO("Test Init !!!");
while (ros::ok())
{
test_msgs::test msg;
std::cout << "msg.data.size=" << msg.data.size() << std::endl;
msg.header.frame_id = " Test ";
test_pub.publish(msg);
ros::spinOnce();
loop_rate.sleep();
}
return 0;
}
对应的 CMakeList.txt 文件中,需要在 find_package 中加入 test_msgs,catkin_package下的CATKIN_DEPENDS 同样需要加入 test_msgs,如下
cmake_minimum_required(VERSION 2.8.3)
project(test)
add_compile_options(-std=c++11)
find_package(catkin REQUIRED COMPONENTS
roscpp
rospy
std_msgs
test_msgs
)
catkin_package(
INCLUDE_DIRS include
LIBRARIES test
CATKIN_DEPENDS roscpp rospy std_msgs test_msgs
DEPENDS system_lib
)
include_directories(
include
${catkin_INCLUDE_DIRS}
)
add_executable(test_node src/test.cpp)
target_link_libraries(test_node
${catkin_LIBRARIES}
)
package.xml 文件中,需要加入
test_msgs
test_msgs
至于 srv 的参考,这里奉上官方的连接,可以参考,大致和 msg 的调用一致,只是用法有些不同而已。