Estudo ROS notas sete
Modelo de tópico
A imagem abaixo é do livro "21 Lectures on ROS Introduction" de Gu Yue
As mensagens de tópico usadas nas duas seções acima são todas definidas no ROS. Desta vez, iremos personalizar um novo tipo de mensagem para comunicação de tópico. ROS Master gerencia dois nós, assinantes e editores, criamos uma nova mensagem do tipo learning_topic :: Person e nos comunicamos entre os dois nós por meio de topic / person_info.
Mensagem de tópico personalizado
Definir arquivo msg
Person.msg
string name
uint8 sex
uint8 age
uint8 unknown = 0
uint8 male = 1
uint8 female = 2
msg é independente do idioma e será convertido dinamicamente para o tipo de dados correspondente durante a compilação, portanto, opções de compilação precisam ser adicionadas.
Adicione opções de compilação em CMakeLists.txt
find_package(... message_generation)
add_message_files(FILES Person.msg)
generate_messages(DEPENDENCIES std_msgs)
catkin_package(...cmessage_runtime)
Adicionar dependência de pacote de funções em package.xml
<build_depend>message_generation</build_depend>
<exec_depend>message_runtime</exec_depend>
Compilar e executar dependências
Compilar e gerar arquivos relacionados ao idioma
Criar código do editor (C ++)
/**
* 该例程将发布/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;
}
Criar código de assinante (C ++)
/**
* 该例程将订阅/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;
}
Configurar regras de compilação de código
- Defina o código a ser compilado e o arquivo executável gerado
- Configure a biblioteca de links
- Adicionar dependências
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)
Compile e execute editores e assinantes
$ cd~/catkin_ws
$ catkin_make
$ source devel/setup.bash
$ roscore
$ rosrun learning_topic person_publisher
$ rosrun learning_topic person_subscriber
O resultado é o seguinte:
neste momento, o roscore está fechado e a comunicação pode continuar normalmente porque os dois estabeleceram um link.
Implementação de código de editor e assinante (Python)
locutor
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# 该例程将发布/person_info话题,自定义消息类型learning_topic::Person
import rospy
from learning_topic.msg import Person
def velocity_publisher():
# ROS节点初始化
rospy.init_node('person_publisher', anonymous=True)
# 创建一个Publisher,发布名为/person_info的topic,消息类型为learning_topic::Person,队列长度10
person_info_pub = rospy.Publisher('/person_info', Person, queue_size=10)
#设置循环的频率
rate = rospy.Rate(10)
while not rospy.is_shutdown():
# 初始化learning_topic::Person类型的消息
person_msg = Person()
person_msg.name = "Tom";
person_msg.age = 18;
person_msg.sex = Person.male;
# 发布消息
person_info_pub.publish(person_msg)
rospy.loginfo("Publsh person message[%s, %d, %d]",
person_msg.name, person_msg.age, person_msg.sex)
# 按照循环频率延时
rate.sleep()
if __name__ == '__main__':
try:
velocity_publisher()
except rospy.ROSInterruptException:
pass
assinante
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# 该例程将订阅/person_info话题,自定义消息类型learning_topic::Person
import rospy
from learning_topic.msg import Person
def personInfoCallback(msg):
rospy.loginfo("Subcribe Person Info: name:%s age:%d sex:%d",
msg.name, msg.age, msg.sex)
def person_subscriber():
# ROS节点初始化
rospy.init_node('person_subscriber', anonymous=True)
# 创建一个Subscriber,订阅名为/person_info的topic,注册回调函数personInfoCallback
rospy.Subscriber("/person_info", Person, personInfoCallback)
# 循环等待回调函数
rospy.spin()
if __name__ == '__main__':
person_subscriber()
Parte do código neste artigo vem de Gu Yue "21 Lectures on ROS Introduction"
Link anterior
Notas de estudo ROS 6 (implementação de programação de assinantes)
Notas de estudo ROS 5 (implementação de programação de editores)
Notas de estudo ROS 4 (criando espaços de trabalho e pacotes funcionais)
Notas de estudo ROS 3 (uso de ferramentas de linha de comando
ROS ) Notas de estudo ROS 2 (conceitos básicos de ROS )
Notas de estudo ROS 1 (Operação básica do sistema Linux)