.msg
,用于生成不同语言的消息源代码。/msg
文件夹中。消息文件的格式为:
<字段类型> <字段名称>
注意:<字段类型> 与 <字段名称>直接需使用
空格
而不能使用Tab
。
可用的字段类型有:
int8, int16, int32, int64 (plus uint*)
float32, float64
string
time, duration
消息文件支持嵌套,也就是说字段类型可以是其他消息的名称。
另外,字段类型还支持可变长短数组和固定长度数组:
array[] array[constant] # 使用时直接将 array 替换成类型名
除此之外,在 ROS 中也有一个特殊类型: Header
,Header
包含常用于 ROS 的时间戳和坐标帧信息。经常会在 msg 文件的第一行放置 Header
头。如在CARLA中的IMU消息的头所包含的信息:
header:
seq: 140
stamp:
secs: 96
nsecs: 355454117
frame_id: "ego_vehicle/imu/imu1"
下面是一个消息的示例:
Header header
string child_frame_id
geometry_msgs/PoseWithCovariance pose
geometry_msgs/TwistWithCovariance twist
你也可以在已有的ros pkg 中添加自定义的消息文件,我这里为了演示方便新建了一个 rospkg:
cd ~/catkin_ws/src #转到你的工作空间
catkin_create_pkg my_msg roscpp rospy std_msgs message_generation message_runtime
my_msg
是这个 rospkg 的名称;
roscpp rospy std_msgs message_generation message_runtime
依赖项,在构建时,我们需要message_generation
,而在运行时,我们只需要message_runtime
。
如果这一步操作成果会得到类似下文的输出:
Created file my_msg/package.xml
Created file my_msg/CMakeLists.txt
Created folder my_msg/include/my_msg
Created folder my_msg/src
Successfully created files in /home/jk/catkin_ws/my_msg. Please adjust the values in package.xml.
在/my_msg
中新建/msg
文件夹,在该路径下新建你的消息文件,如我创建Num.msg
文件(一般来说消息名的首字母大写),编辑其内容如下并保存。
string first_name
string last_name
uint8 age
uint32 score
打开package.xml 文件, 确保有下面两个语句,且没有被注释
<build_depend>message_generationbuild_depend>
<exec_depend>message_runtimeexec_depend>
由于我们在创建 catkin Package 的时候就声明了对message_generation message_runtim
的依赖,所以我们的 package.xml 应该已经有未注释的上面两条语句。
打开包中的 CMakeLists.txt 文件。
确保find_package
中以下字段存在且未被注释:
## 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
message_generation
roscpp
rospy
std_msgs
)
由于我们在创建 catkin Package 的时候就声明了对roscpp rospy std_msgs message_generation message_runtim
的依赖,所以我们的 CMakeLists.txt 应该已经有未注释的上面几条语句。我们可能需要删除多余的一项:message_runtime
。
确保导出消息运行时的依赖项,需要确保下面的语句中CATKIN_DEPENDS message_runtime
未被注释。
###################################
## catkin specific configuration ##
###################################
## The catkin_package macro generates cmake config files for your package
## Declare things to be passed to dependent projects
## INCLUDE_DIRS: uncomment this if your package contains header files
## LIBRARIES: libraries you create in this project that dependent projects also need
## CATKIN_DEPENDS: catkin_packages dependent projects also need
## DEPENDS: system dependencies of this project that dependent projects also need
catkin_package(
# INCLUDE_DIRS include
# LIBRARIES my_msg
CATKIN_DEPENDS message_runtime
# DEPENDS system_lib
)
然后找到下面的模块:
# add_message_files(
# FILES
# Message1.msg
# Message2.msg
# )
取消注释,并把msg 的文件名替换成你自己的:
add_message_files(
FILES
Num.msg
)
我们还要确保generate_messages()
模块未被注释:
如果消息中有用到
geometry_msgs
类型的字段,要把geometry_msgs
也添加到下面的模块中去
# Generate added messages and services with any dependencies listed here
generate_messages(
DEPENDENCIES
std_msgs
)
退回到上一级目录,使用catkin_make 进行编译:
cd ..
catkin_make
不出意外我们应该已经成功生成了消息文件的c++格式的头文件(如果报错,仔细阅读错误说明应该很容易解决)。
生成的文件在
,命名和.msg
文件一致,为Num.h
,内容如下:
// Generated by gencpp from file my_msg/Num.msg
// DO NOT EDIT!
#ifndef MY_MSG_MESSAGE_NUM_H
#define MY_MSG_MESSAGE_NUM_H
#include
#include
#include
#include
#include
#include
#include
namespace my_msg
{
template <class ContainerAllocator>
struct Num_
{
typedef Num_<ContainerAllocator> Type;
Num_()
: first_name()
, last_name()
, age(0)
, score(0) {
}
Num_(const ContainerAllocator& _alloc)
: first_name(_alloc)
, last_name(_alloc)
, age(0)
, score(0) {
(void)_alloc;
}
typedef std::basic_string<char, std::char_traits<char>, typename ContainerAllocator::template rebind<char>::other > _first_name_type;
_first_name_type first_name;
typedef std::basic_string<char, std::char_traits<char>, typename ContainerAllocator::template rebind<char>::other > _last_name_type;
_last_name_type last_name;
typedef uint8_t _age_type;
_age_type age;
typedef uint32_t _score_type;
_score_type score;
typedef boost::shared_ptr< ::my_msg::Num_<ContainerAllocator> > Ptr;
typedef boost::shared_ptr< ::my_msg::Num_<ContainerAllocator> const> ConstPtr;
}; // struct Num_
typedef ::my_msg::Num_<std::allocator<void> > Num;
typedef boost::shared_ptr< ::my_msg::Num > NumPtr;
typedef boost::shared_ptr< ::my_msg::Num const> NumConstPtr;
// constants requiring out of line definition
template<typename ContainerAllocator>
std::ostream& operator<<(std::ostream& s, const ::my_msg::Num_<ContainerAllocator> & v)
{
ros::message_operations::Printer< ::my_msg::Num_<ContainerAllocator> >::stream(s, "", v);
return s;
}
} // namespace my_msg
namespace ros
{
namespace message_traits
{
// BOOLTRAITS {'IsFixedSize': False, 'HasHeader': False, 'IsMessage': True}
// {'std_msgs': ['/opt/ros/kinetic/share/std_msgs/cmake/../msg'], 'my_msg': ['/home/jk/catkin_ws/src/my_msg/msg']}
// !!!!!!!!!!! ['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__le__', '__lt__', '__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< ::my_msg::Num_<ContainerAllocator> >
: FalseType
{ };
template <class ContainerAllocator>
struct IsFixedSize< ::my_msg::Num_<ContainerAllocator> const>
: FalseType
{ };
template <class ContainerAllocator>
struct HasHeader< ::my_msg::Num_<ContainerAllocator> >
: FalseType
{ };
template <class ContainerAllocator>
struct HasHeader< ::my_msg::Num_<ContainerAllocator> const>
: FalseType
{ };
template <class ContainerAllocator>
struct IsMessage< ::my_msg::Num_<ContainerAllocator> >
: TrueType
{ };
template <class ContainerAllocator>
struct IsMessage< ::my_msg::Num_<ContainerAllocator> const>
: TrueType
{ };
template<class ContainerAllocator>
struct MD5Sum< ::my_msg::Num_<ContainerAllocator> >
{
static const char* value()
{
return "f8bfa80ae3c7a93455596d9622ad33a9";
}
static const char* value(const ::my_msg::Num_<ContainerAllocator>&) { return value(); }
static const uint64_t static_value1 = 0xf8bfa80ae3c7a934ULL;
static const uint64_t static_value2 = 0x55596d9622ad33a9ULL;
};
template<class ContainerAllocator>
struct DataType< ::my_msg::Num_<ContainerAllocator> >
{
static const char* value()
{
return "my_msg/Num";
}
static const char* value(const ::my_msg::Num_<ContainerAllocator>&) { return value(); }
};
template<class ContainerAllocator>
struct Definition< ::my_msg::Num_<ContainerAllocator> >
{
static const char* value()
{
return "string first_name\n\
string last_name\n\
uint8 age\n\
uint32 score\n\
";
}
static const char* value(const ::my_msg::Num_<ContainerAllocator>&) { return value(); }
};
} // namespace message_traits
} // namespace ros
namespace ros
{
namespace serialization
{
template<class ContainerAllocator> struct Serializer< ::my_msg::Num_<ContainerAllocator> >
{
template<typename Stream, typename T> inline static void allInOne(Stream& stream, T m)
{
stream.next(m.first_name);
stream.next(m.last_name);
stream.next(m.age);
stream.next(m.score);
}
ROS_DECLARE_ALLINONE_SERIALIZER
}; // struct Num_
} // namespace serialization
} // namespace ros
namespace ros
{
namespace message_operations
{
template<class ContainerAllocator>
struct Printer< ::my_msg::Num_<ContainerAllocator> >
{
template<typename Stream> static void stream(Stream& s, const std::string& indent, const ::my_msg::Num_<ContainerAllocator>& v)
{
s << indent << "first_name: ";
Printer<std::basic_string<char, std::char_traits<char>, typename ContainerAllocator::template rebind<char>::other > >::stream(s, indent + " ", v.first_name);
s << indent << "last_name: ";
Printer<std::basic_string<char, std::char_traits<char>, typename ContainerAllocator::template rebind<char>::other > >::stream(s, indent + " ", v.last_name);
s << indent << "age: ";
Printer<uint8_t>::stream(s, indent + " ", v.age);
s << indent << "score: ";
Printer<uint32_t>::stream(s, indent + " ", v.score);
}
};
} // namespace message_operations
} // namespace ros
#endif // MY_MSG_MESSAGE_NUM_H