古月居 ROS 21 讲
古月居 ROS 21 讲
5、话题消息的订阅与使用
1)完成数据接口的定义:在learning topic中创建msg,打开终端设置
string name
uint8 sex
uint8 age
uint8 unknown = 0
uint8 male = 1
uint8 female = 2
2)根据数据接口定义设置编译规则
➢ 在package.xml中添加功能包依赖
<build_depend>message_generation</build_depend>编译依赖
<exec_depend>message_runtime</exec_depend>运行依赖
➢ 在CMakeLists.txt添加编译选项
• message_generation
• add_message_files(FILES Person.msg)接口
generate_messages(DEPENDENCIES std_msgs) ROS已经有的库
• message_runtime
由.msg编译生成的代码文件.h
// Generated by gencpp from file learning_topic/Person.msg
// DO NOT EDIT!
#ifndef LEARNING_TOPIC_MESSAGE_PERSON_H
#define LEARNING_TOPIC_MESSAGE_PERSON_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 learning_topic
{
template <class ContainerAllocator>
struct Person_
{
typedef Person_<ContainerAllocator> Type;
Person_()
: name()
, sex(0)
, age(0) {
}
Person_(const ContainerAllocator& _alloc)
: name(_alloc)
, sex(0)
, age(0) {
(void)_alloc;
}
typedef std::basic_string<char, std::char_traits<char>, typename ContainerAllocator::template rebind<char>::other > _name_type;
_name_type name;
typedef uint8_t _sex_type;
_sex_type sex;
typedef uint8_t _age_type;
_age_type age;
enum {
unknown = 0u,
male = 1u,
female = 2u,
};
typedef boost::shared_ptr< ::learning_topic::Person_<ContainerAllocator> > Ptr;
typedef boost::shared_ptr< ::learning_topic::Person_<ContainerAllocator> const> ConstPtr;
}; // struct Person_
typedef ::learning_topic::Person_<std::allocator<void> > Person;
typedef boost::shared_ptr< ::learning_topic::Person > PersonPtr;
typedef boost::shared_ptr< ::learning_topic::Person const> PersonConstPtr;
// constants requiring out of line definition
template<typename ContainerAllocator>
std::ostream& operator<<(std::ostream& s, const ::learning_topic::Person_<ContainerAllocator> & v)
{
ros::message_operations::Printer< ::learning_topic::Person_<ContainerAllocator> >::stream(s, "", v);
return s;
}
} // namespace learning_topic
namespace ros
{
namespace message_traits
{
// BOOLTRAITS {'IsFixedSize': False, 'IsMessage': True, 'HasHeader': False}
// {'learning_topic': ['/home/ubuntu/catkin_ws/src/learning_topic/msg'], 'std_msgs': ['/opt/ros/kinetic/share/std_msgs/cmake/../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< ::learning_topic::Person_<ContainerAllocator> >
: FalseType
{ };
template <class ContainerAllocator>
struct IsFixedSize< ::learning_topic::Person_<ContainerAllocator> const>
: FalseType
{ };
template <class ContainerAllocator>
struct IsMessage< ::learning_topic::Person_<ContainerAllocator> >
: TrueType
{ };
template <class ContainerAllocator>
struct IsMessage< ::learning_topic::Person_<ContainerAllocator> const>
: TrueType
{ };
template <class ContainerAllocator>
struct HasHeader< ::learning_topic::Person_<ContainerAllocator> >
: FalseType
{ };
template <class ContainerAllocator>
struct HasHeader< ::learning_topic::Person_<ContainerAllocator> const>
: FalseType
{ };
template<class ContainerAllocator>
struct MD5Sum< ::learning_topic::Person_<ContainerAllocator> >
{
static const char* value()
{
return "8361f88618d6779bd872f0ba928ced56";
}
static const char* value(const ::learning_topic::Person_<ContainerAllocator>&) { return value(); }
static const uint64_t static_value1 = 0x8361f88618d6779bULL;
static const uint64_t static_value2 = 0xd872f0ba928ced56ULL;
};
template<class ContainerAllocator>
struct DataType< ::learning_topic::Person_<ContainerAllocator> >
{
static const char* value()
{
return "learning_topic/Person";
}
static const char* value(const ::learning_topic::Person_<ContainerAllocator>&) { return value(); }
};
template<class ContainerAllocator>
struct Definition< ::learning_topic::Person_<ContainerAllocator> >
{
static const char* value()
{
return "string name\n\
uint8 sex\n\
uint8 age\n\
uint8 unknown = 0\n\
uint8 male = 1\n\
uint8 female = 2\n\
";
}
static const char* value(const ::learning_topic::Person_<ContainerAllocator>&) { return value(); }
};
} // namespace message_traits
} // namespace ros
namespace ros
{
namespace serialization
{
template<class ContainerAllocator> struct Serializer< ::learning_topic::Person_<ContainerAllocator> >
{
template<typename Stream, typename T> inline static void allInOne(Stream& stream, T m)
{
stream.next(m.name);
stream.next(m.sex);
stream.next(m.age);
}
ROS_DECLARE_ALLINONE_SERIALIZER
}; // struct Person_
} // namespace serialization
} // namespace ros
namespace ros
{
namespace message_operations
{
template<class ContainerAllocator>
struct Printer< ::learning_topic::Person_<ContainerAllocator> >
{
template<typename Stream> static void stream(Stream& s, const std::string& indent, const ::learning_topic::Person_<ContainerAllocator>& v)
{
s << indent << "name: ";
Printer<std::basic_string<char, std::char_traits<char>, typename ContainerAllocator::template rebind<char>::other > >::stream(s, indent + " ", v.name);
s << indent << "sex: ";
Printer<uint8_t>::stream(s, indent + " ", v.sex);
s << indent << "age: ";
Printer<uint8_t>::stream(s, indent + " ", v.age);
}
};
} // namespace message_operations
} // namespace ros
#endif // LEARNING_TOPIC_MESSAGE_PERSON_H
创建person_publisher与person_subscriber
Publisher
/**
* 该例程将发布/person_info话题,自定义消息类型learning_topic::Person
*/
#include <ros/ros.h>
#include "learning_topic/Person.h"
int main(int argc, char **argv)
{
// ROS节点初始化
ros::init(argc, argv, "person_publisher");
// 创建节点句柄
ros::NodeHandle n;
// 创建一个Publisher,发布名为/person_info的topic,消息类型为learning_topic::Person,队列长度10
ros::Publisher person_info_pub = n.advertise<learning_topic::Person>("/person_info", 10);
// 设置循环的频率
ros::Rate loop_rate(1);
int count = 0;
while (ros::ok())
{
// 初始化learning_topic::Person类型的消息
learning_topic::Person person_msg;
person_msg.name = "Tom";
person_msg.age = 18;
person_msg.sex = learning_topic::Person::male;
// 发布消息
person_info_pub.publish(person_msg);
ROS_INFO("Publish Person Info: name:%s age:%d sex:%d",
person_msg.name.c_str(), person_msg.age, person_msg.sex);
// 按照循环频率延时
loop_rate.sleep();
}
return 0;
}
Subscriber
/**
* 该例程将订阅/person_info话题,自定义消息类型learning_topic::Person
*/
#include <ros/ros.h>
#include "learning_topic/Person.h"
// 接收到订阅的消息后,会进入消息回调函数
void personInfoCallback(const learning_topic::Person::ConstPtr& msg)
{
// 将接收到的消息打印出来
ROS_INFO("Subcribe Person Info: name:%s age:%d sex:%d",
msg->name.c_str(), msg->age, msg->sex);
}
int main(int argc, char **argv)
{
// 初始化ROS节点
ros::init(argc, argv, "person_subscriber");
// 创建节点句柄
ros::NodeHandle n;
// 创建一个Subscriber,订阅名为/person_info的topic,注册回调函数personInfoCallback
ros::Subscriber person_info_sub = n.subscribe("/person_info", 10, personInfoCallback);
// 循环等待回调函数
ros::spin();
return 0;
}
3)编译代码
如何配置CMakeLists.txt中的编译规则
• 设置需要编译的代码和生成的可执行文件;
• 设置链接库;
• 添加依赖项。
add_executable(person_publisher src/person_publisher.cpp)
target_link_libraries(person_publisher ${catkin_LIBRARIES})
add_dependencies(person_publisher ${PROJECT_NAME}_generate_messages_cpp)
add_executable(person_subscriber src/person_subscriber.cpp)
target_link_libraries(person_subscriber ${catkin_LIBRARIES})
add_dependencies(person_subscriber ${PROJECT_NAME}_generate_messages_cpp)
拷贝到CMakeLists.txt
$ cd ~/catkin_ws
$ catkin_make
$ source devel/setup.bash
$ roscore
$ rosrun learning_topic person_subscriber
$ rosrun learning_topic person_publisher
关掉ROSMaster也不会影响发送与接受
上一篇: 我想和你好好的,我要的爱情其实很简单
下一篇: 我喜欢你是寂静的