El estudio ROS señala siete
Modelo de tema
La siguiente imagen es de las "21 conferencias sobre la introducción de ROS" de Gu Yue.
Los mensajes de tema utilizados en las dos secciones anteriores están todos definidos en ROS. Esta vez personalizaremos un nuevo tipo de mensaje para la comunicación del tema. ROS Master gestiona dos nodos, suscriptores y editores Creamos un nuevo mensaje de tipo learning_topic :: Person y nos comunicamos entre los dos nodos a través de topic / person_info.
Mensaje de tema personalizado
Definir archivo msg
Person.msg
string name
uint8 sex
uint8 age
uint8 unknown = 0
uint8 male = 1
uint8 female = 2
msg es independiente del idioma y se convertirá dinámicamente al tipo de datos correspondiente al compilar, por lo que es necesario agregar opciones de compilación.
Agregue opciones de compilación en CMakeLists.txt
find_package(... message_generation)
add_message_files(FILES Person.msg)
generate_messages(DEPENDENCIES std_msgs)
catkin_package(...cmessage_runtime)
Agregue la dependencia del paquete de funciones en package.xml
<build_depend>message_generation</build_depend>
<exec_depend>message_runtime</exec_depend>
Compilar y ejecutar dependencias
Compile y genere archivos relacionados con el idioma
Crear código de 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;
}
Crear código de suscriptor (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 reglas de compilación de código
- Configure el código que se compilará y el archivo ejecutable generado
- Configurar la biblioteca de enlaces
- Agregar dependencias
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)
Compilar y ejecutar editores y suscriptores
$ cd~/catkin_ws
$ catkin_make
$ source devel/setup.bash
$ roscore
$ rosrun learning_topic person_publisher
$ rosrun learning_topic person_subscriber
El resultado es el siguiente:
en este momento, roscore está cerrado y la comunicación puede continuar normalmente porque los dos han establecido un enlace.
Implementación de código de publicador y suscriptor (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
abonado
#!/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 del código de este artículo proviene de Gu Yue "21 conferencias sobre la introducción de ROS"
Enlace anterior
Notas de estudio ROS 6 (implementación de programación de suscriptores)
Notas de estudio de ROS 5 (implementación de programación de editores)
Notas de estudio de ROS 4 (creación de espacios de trabajo y paquetes funcionales)
Notas de estudio de ROS 3 (uso de herramientas de línea de comandos de
ROS ) Notas de estudio de ROS 2 (Conceptos básicos de ROS )
Notas de estudio ROS 1 (Operación básica del sistema Linux)