ROS学习笔记9-创建ros消息和服务
该节内容主要来自于官方文档的两个小节:
1.使用rosed来编辑
2.创建ros消息的服务
先来看rosed:
- rosed
rosed命令是rosbash的一部分,使用rosed可以直接编辑包中的一个文件,而无需键入文件所在的全路径,用法如下:$ rosed [package_name] [filename]
例如我们想编辑roscpp包下的Logger.msg,则输入如下命令:
$ rosed roscpp Logger.msg
则会使用vim打开Logger.msg进入编辑状态。
同时,rosed支持使用tab键实现自动完成功能,用法如下:$ rosed [package_name] <tab><tab>
例如:
$ rosed roscpp <tab><tab>
注意:两个tab和包名之间有空格。
会列出roscpp包中的所有的文件:Empty.srv roscpp.cmake
genmsg_cpp.py roscppConfig.cmake
gensrv_cpp.py roscppConfig-version.cmake
GetLoggers.srv roscpp-msg-extras.cmake
Logger.msg roscpp-msg-paths.cmake
msg_gen.py SetLoggerLevel.srv
package.xml并且,rosed还可以指定编辑器,默认的采用vim编辑器,可以通过设置~/.bashrc文件中的环境变量来指定编辑器:
例如输入如下命令将编辑器设置为nano编辑器。export EDITOR='nano -w'
也可以使用如下命令设置为gedit:
export EDITOR='gedit -w'
- msg和srv文件介绍
msg文件每行包含一个类型和一个变量名:
其中,变量类型可以为如下类型:- int8, int16, int32, int64 (以及uint)
- float32, float64
- string
- time, duration
- 其他消息类型
- 变长度以及定长度的数组[]
此外还有一个特殊类型,头类型(Header),Header类型包含一个时间戳和坐标轴信息,这些信息在ROS中很常用。一个典型的ros消息定义如下:
Header header
string child_frame_id
geometry_msgs/PoseWithCovariance pose
geometry_msgs/TwistWithCovariance twistsrv文件定义与msg类似,也是由不同行组成,每行包含一个变量类型和一个变量名,不过srv包含请求(request)和响应(response)两个部分,该两部分用一行三短杠---分隔开。例如:
int64 A
int64 B
---
int64 Sum在上面的例子中:A和B是请求,Sum是响应。
- 使用msg
- 创建msg
比如使用如下命令可以在之前的示例包里创建一个新msg:$ roscd beginner_tutorials
$ mkdir msg
$ echo "int64 num" > msg/Num.msg该msg只有一行,当然也可以创建一个更复杂的msg
string first_name
string last_name
uint8 age
uint32 score然后,为了确保该msg文件能被转化为其他语言的代码,需要检查package.xml中如下两行存在且未被注释掉:(查看之后发现默认是注释掉的)
<build_depend>message_generation</build_depend>
<exec_depend>message_runtime</exec_depend>在编译期间,我们需要启用message_generation,在运行期间,我们需要启用message_runtime。
然后使用你最喜爱的编辑器打开CMakeLists.txt(可以使用rosed)
然后在find_package中添加message_generation的条目:## Find catkin macros and libraries
## if COMPONENTS list like find_package(catkin REQUIRED COMPONENTS xyz)
## is used, also find other catkin packages
find_package(catkin REQUIRED COMPONENTS
roscpp
rospy
std_msgs
message_generation
)同时,确保在运行时依赖中也添加了该消息的依赖:
catkin_package(
# INCLUDE_DIRS include
# LIBRARIES begginner_tutorials
# CATKIN_DEPENDS roscpp rospy std_msgs
# DEPENDS system_lib
CATKIN_DEPENS message_runtime
)找到添加消息文件的代码段:
# add_message_files(
# FILES
# Message1.msg
# Message2.msg
# )取消注释并添加该消息文件名:
add_message_files(
FILES
Num.msg
)确保generate_message被调用:
generate_messages(
DEPENDENCIES
std_msgs
) - 查看msg的信息
定义信息之后,可以用rosmsg命令来查看消息的信息:$ rosmsg show [message type]
例如,对于上述定义的信息,用如下命令:
$ rosmsg show beginner_tutorials/Num
可以看到返回为:
int64 num
也可以不写全路径,如果你不记得该消息在哪个包下面,可以这样写:
$ rosmsg show Num
返回为:
[beginner_tutorials/Num]:
int64 num
- 创建msg
- 使用srv
- 创建srv
类似于msg,我们先创建一个srv的文件夹:$ roscd beginner_tutorials
$ mkdir srv可以在其中手动写一个srv文件,也可以将其他地方的srv文件复制过来,在此处介绍一个ros下面复制文件的命令,roscp,该命令用法如下:
$ roscp [package_name] [file_to_copy_path] [copy_path]
然后我们将rospy_tutorials包中的srv文件复制过来:
$ roscp rospy_tutorials AddTwoInts.srv srv/AddTwoInts.srv
同时在package.xml中启用message_generation和message_runtime(该步与msg相同)。
然后在find_package的调用中增加message_generation(与msg中相同)。
不同的是在add_service_files的调用中要添加与服务对应的条目。add_service_files(
FILES
AddTwoInts.srv
) - 查看srv的信息
与rosmsg类似,ros也提供了rossrv来查看srv服务相关的信息:
例如:$ rossrv show beginner_tutorials/AddTwoInts
返回:
int64 a
int64 b
---
int64 sum也可以不加路径:
$ rossrv show AddTwoInts
[beginner_tutorials/AddTwoInts]:
int64 a
int64 b
---
int64 sum [rospy_tutorials/AddTwoInts]:
int64 a
int64 b
---
int64 sum
- 创建srv
- 通用步骤(个人感觉应该该节改名为编译步骤)
如果进行完了如上步骤,然后就可以编译这些msg和srv,取消CMakeLists.txt中以下几行的注释:generate_messages(
DEPENDENCIES
std_msgs
)然后运行catkin_make进行编译:
# In your catkin workspace
$ roscd beginner_tutorials
$ cd ../..
$ catkin_make install
$ cd -则会将msg和srv文件编译成其他语言的代码。例如,对于msg,C++的头文件会包含在~/catkin_ws/devel/include/beginner_tutorials/中;
python的源文件会包含在~/catkin_ws/devel/lib/python2.7/dist-packages/beginner_tutorials/msg中;
~/catkin_ws/devel/share/common-lisp/ros/beginner_tutorials/msg/中。
srv文件对于C++会和msg文件生成的源文件在统一文件夹中,而python和lisp的srv文件生成的文件会在单独的srv文件夹中,该文件夹与msg文件夹在同一个目录下。
看一个C++的msg头文件:// Generated by gencpp from file begginner_tutorials/Num.msg
// DO NOT EDIT! #ifndef BEGGINNER_TUTORIALS_MESSAGE_NUM_H
#define BEGGINNER_TUTORIALS_MESSAGE_NUM_H #include <string>
#include <vector>
#include <map> #include <ros/types.h>
#include <ros/serialization.h>
#include <ros/builtin_message_traits.h>
#include <ros/message_operations.h> namespace begginner_tutorials
{
template <class ContainerAllocator>
struct Num_
{
typedef Num_<ContainerAllocator> Type; Num_()
: num(0) {
}
Num_(const ContainerAllocator& _alloc)
: num(0) {
(void)_alloc;
} typedef int64_t _num_type;
_num_type num; typedef boost::shared_ptr< ::begginner_tutorials::Num_<ContainerAllocator> > Ptr;
typedef boost::shared_ptr< ::begginner_tutorials::Num_<ContainerAllocator> const> ConstPtr; }; // struct Num_ typedef ::begginner_tutorials::Num_<std::allocator<void> > Num; typedef boost::shared_ptr< ::begginner_tutorials::Num > NumPtr;
typedef boost::shared_ptr< ::begginner_tutorials::Num const> NumConstPtr; // constants requiring out of line definition template<typename ContainerAllocator>
std::ostream& operator<<(std::ostream& s, const ::begginner_tutorials::Num_<ContainerAllocator> & v)
{
ros::message_operations::Printer< ::begginner_tutorials::Num_<ContainerAllocator> >::stream(s, "", v);
return s;
} } // namespace begginner_tutorials namespace ros
{
namespace message_traits
{ // BOOLTRAITS {'IsFixedSize': True, 'IsMessage': True, 'HasHeader': False}
// {'std_msgs': ['/opt/ros/kinetic/share/std_msgs/cmake/../msg'], 'begginner_tutorials': ['/home/shao/catkin_ws/src/begginner_tutorials/msg']} // !!!!!!!!!!! ['__class__', '__delattr__', '__dict__', '__doc__', '__eq__', '__format__', '__getattribute__', '__hash__', '__init__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', '_parsed_fields', 'constants', 'fields', 'full_name', 'has_header', 'header_present', 'names', 'package', 'parsed_fields', 'short_name', 'text', 'types'] template <class ContainerAllocator>
struct IsFixedSize< ::begginner_tutorials::Num_<ContainerAllocator> >
: TrueType
{ }; template <class ContainerAllocator>
struct IsFixedSize< ::begginner_tutorials::Num_<ContainerAllocator> const>
: TrueType
{ }; template <class ContainerAllocator>
struct IsMessage< ::begginner_tutorials::Num_<ContainerAllocator> >
: TrueType
{ }; template <class ContainerAllocator>
struct IsMessage< ::begginner_tutorials::Num_<ContainerAllocator> const>
: TrueType
{ }; template <class ContainerAllocator>
struct HasHeader< ::begginner_tutorials::Num_<ContainerAllocator> >
: FalseType
{ }; template <class ContainerAllocator>
struct HasHeader< ::begginner_tutorials::Num_<ContainerAllocator> const>
: FalseType
{ }; template<class ContainerAllocator>
struct MD5Sum< ::begginner_tutorials::Num_<ContainerAllocator> >
{
static const char* value()
{
return "57d3c40ec3ac3754af76a83e6e73127a";
} static const char* value(const ::begginner_tutorials::Num_<ContainerAllocator>&) { return value(); }
static const uint64_t static_value1 = 0x57d3c40ec3ac3754ULL;
static const uint64_t static_value2 = 0xaf76a83e6e73127aULL;
}; template<class ContainerAllocator>
struct DataType< ::begginner_tutorials::Num_<ContainerAllocator> >
{
static const char* value()
{
return "begginner_tutorials/Num";
} static const char* value(const ::begginner_tutorials::Num_<ContainerAllocator>&) { return value(); }
}; template<class ContainerAllocator>
struct Definition< ::begginner_tutorials::Num_<ContainerAllocator> >
{
static const char* value()
{
return "int64 num\n\
";
} static const char* value(const ::begginner_tutorials::Num_<ContainerAllocator>&) { return value(); }
}; } // namespace message_traits
} // namespace ros namespace ros
{
namespace serialization
{ template<class ContainerAllocator> struct Serializer< ::begginner_tutorials::Num_<ContainerAllocator> >
{
template<typename Stream, typename T> inline static void allInOne(Stream& stream, T m)
{
stream.next(m.num);
} ROS_DECLARE_ALLINONE_SERIALIZER
}; // struct Num_ } // namespace serialization
} // namespace ros namespace ros
{
namespace message_operations
{ template<class ContainerAllocator>
struct Printer< ::begginner_tutorials::Num_<ContainerAllocator> >
{
template<typename Stream> static void stream(Stream& s, const std::string& indent, const ::begginner_tutorials::Num_<ContainerAllocator>& v)
{
s << indent << "num: ";
Printer<int64_t>::stream(s, indent + " ", v.num);
}
}; } // namespace message_operations
} // namespace ros #endif // BEGGINNER_TUTORIALS_MESSAGE_NUM_H还是挺复杂的。
ROS学习笔记9-创建ros消息和服务的更多相关文章
- ROS学习手记 - 7 创建ROS msg & srv
至此,我们初步学习了ROS的基本工具,接下来一步步理解ROS的各个工作部件的创建和工作原理. 本文的详细文档:http://wenku.baidu.com/view/623f41b3376baf1ff ...
- ROS学习笔记二:ROS系统架构及概念
本文主要是了解ROS的系统架构.文件夹结构以及工作所需的核心文件. ROS系统架构主要被设计和划分为三部分,每一部分代表一个层级的概念:文件系统级(The filesystem level).计算图级 ...
- ROS学习笔记一(ROS的catkin工作空间)
在安装完成ROS indigo之后,需要查看环境变量是否设置正确,并通过创建一个简单的实例来验证ROS能否正常运行. 1 查看环境变量 在ROS的安装过程中,我们执行了如下命令:(此命令就是向当前用户 ...
- ROS学习笔记一:ROS安装与测试
1 Ubuntu和ROS版本的对应关系 Ubuntu 和 ROS 都存在不同的版本,其对应关系如下: 注:如果Ubuntu版本和ROS版本不对应的话,安装就不会成功了- 笔者安装的是Ubuntu14. ...
- ROS学习笔记九:ROS工具
ROS有各种工具可以帮助用户使用ROS.应该指出,这些GUI工具是对输入型命令工具的补充.如果包括ROS用户个人发布的工具,那么ROS工具的数量很庞大.其中,本文讨论的工具是对于ROS编程非常有用的辅 ...
- [转]ROS学习笔记十一:ROS中数据的记录与重放
本节主要介绍如何记录一个正在运行的ROS系统中的数据,然后在一个运行的系统中根据记录文件重新产生和记录时类似的运动情况.本例子还是以小海龟例程为例. 记录数据(创建一个bag文件) 首先运行小海龟例程 ...
- ROS学习笔记七:在ROS中使用USB摄像头
下面是一些USB摄像头的驱动(大多数摄像头都支持uvc标准): 1 使用软件库里的uvc-camera功能包 1.1 检查摄像头 lsusb ----------------------------- ...
- ROS学习手记 - 8 编写ROS的Publisher and Subscriber
上一节我们完成了 message & srv 文件的创建和加入编译,这次我们要玩简单的Publisher 和 Subscriber 要玩 Publisher 和 Subscriber, 需要具 ...
- Java学习笔记-多线程-创建线程的方式
创建线程 创建线程的方式: 继承java.lang.Thread 实现java.lang.Runnable接口 所有的线程对象都是Thead及其子类的实例 每个线程完成一定的任务,其实就是一段顺序执行 ...
随机推荐
- PAT T1025 Keep at Most 100 Characters
删除字符的镜像问题,状态转移方程一样~ #include<bits/stdc++.h> using namespace std; ; ; string s; long long dp[ma ...
- Navicat for MySQL怎么往表中填数据
只有往表中更新数据,数据库才会起到真正的作用. 工具/原料 仔细阅读 方法/步骤 1.打开数据库,首先连接localhost,如图所示. 2.连接成功后,右侧便会显示已经建成的表,找到要修改的表, ...
- PHP序列化与反序列化(二)
题目(攻防世界): __construct和__destruct的魔术方法是默认执行的,我们可以忽视他们,__wake up执行以后会返回当前主页上,需要绕过,下面的正则匹配preg_match也需要 ...
- GO Range
Go 语言中 range 关键字用于 for 循环中迭代数组(array).切片(slice).通道(channel)或集合(map)的元素.在数组和切片中它返回元素的索引和索引对应的值,在集合中返回 ...
- maven打jar包(包括依赖jar)
<build> <plugins> <plugin> <artifactId> maven-assembly-plugin </artifactI ...
- Nexus-vPC与FHRP
去往vPC的流量,如何可能将会被本地的vPC成员端口所转发.FHRP的行为是被修改的,所有的FHRP路由器都会主动转发从vPC收到的流量.修改结果:如果可能,流量避免使用Peer link,这样创建一 ...
- 洛谷P1073最优贸易(跑两遍dij)
题目描述 CC C国有n n n个大城市和m mm 条道路,每条道路连接这 nnn个城市中的某两个城市.任意两个城市之间最多只有一条道路直接相连.这 mmm 条道路中有一部分为单向通行的道路,一部分为 ...
- Leetcode 12,452,455-贪心算法
Leetcode第12题,整数转罗马数字,难度中等 整个题目比较好理解,难度也不大,就算不过脑子,用一串if也基本上可以解决问题,比如 /** 执行用时:6ms,在所有 Java 提交中击败了52.6 ...
- 一大波新款iPhone跟安卓厂商抢夺5G市场
据外媒最新报道称,苹果已经基本完成了今年iPhone的推新阵容,其发布的多款新机中,将涵盖399美元-1149美元的售价区间,特别是5G手机,起步价可能会很亲民,其目的在于进一步占据市场. 今年苹果将 ...
- PCB设计要点
pcb要点 : 2014年8月5日 13:04 一地线设计 1.1分类模拟地.数字地.外壳地.系统大地 1.2接地方式:单点接地(f<1MHZ,避免环流),多点接地(f>10MHZ降低地线 ...