Создание пакетов использующих «публикацию/подписку»
При publish/subscribe между нодами устанавливается однонаправленный канал обмена данными.
Создадим два пакета twilight и celestia, в каждом будет по исполняемому файлу с нодами twilight_sparkle и princess_celestia соответственно. Формат передаваемого сообщения будет описан в пакете letter_msgs.
twilight_sparkle будет публиковать сообщения в топик spike, а princess_celestia будет подписываться на этот топик и получать сообщения.
mkdir ~/ros/my_ws/src/pub_sub
cd ~/ros/my_ws/src/pub_sub
catkin_create_pkg letter_msgs std_msgs roscpp message_generation message_runtime
catkin_create_pkg twilight roscpp
catkin_create_pkg celestia roscpp
mkdir letter_msgs/msg
Этот файл описывает формат сообщений, которыми будут обмениваться наши ноды.
letter_msgs/msg/Letter.msg
string text
int64 num
letter_msgs/CMakeLists.txt
cmake_minimum_required(VERSION 2.8.3)
project(letter_msgs)
find_package(catkin REQUIRED COMPONENTS
message_generation
message_runtime
roscpp
std_msgs
)
add_message_files(
FILES
Letter.msg
)
generate_messages(
DEPENDENCIES
std_msgs
)
catkin_package(
# INCLUDE_DIRS include
# LIBRARIES letter_msgs
# CATKIN_DEPENDS message_generation message_runtime roscpp std_msgs
# DEPENDS system_lib
)
include_directories(
${catkin_INCLUDE_DIRS}
)
letter_msgs/package.xml
<?xml version="1.0"?>
<package>
<name>letter_msgs</name>
<version>0.0.0</version>
<description>The letter_msgs package</description>
<maintainer email="user@todo.todo">user</maintainer>
<license>TODO</license>
<buildtool_depend>catkin</buildtool_depend>
<build_depend>message_generation</build_depend>
<build_depend>roscpp</build_depend>
<build_depend>std_msgs</build_depend>
<run_depend>message_runtime</run_depend>
<run_depend>roscpp</run_depend>
<run_depend>std_msgs</run_depend>
<export>
</export>
</package>
twilight/src/twilight.cpp
#include "ros/ros.h"
// этот файл создастся автоматически из файла Letter.msg
#include "letter_msgs/Letter.h"
int main(int argc, char **argv)
{
/**
* Функция ros::init() инициализирует подсистему ROS.
* Первыми двумя параметрами передаются параметры командной строки т.к. ноды ROS
* используют свои параметры (см. http://wiki.ros.org/Nodes)
* третьим параметром задается имя ноды, четвертым могут быть переданы опции инициализации.
*/
ros::init(argc, argv, "twilight_sparkle");
/**
* При помощи NodeHandle осуществляется коммуникация с подсистемой ROS.
* Первый созданный NodeHandle полностью инициализирует ноду,
* а последний уничтоженный NodeHandle завершает ноду.
*/
ros::NodeHandle n;
/**
* При помощи функции advertise() (англ. извещать, информировать, оповещать; уведомлять;)
* можно сказать ROS, что мы хотим опубликовать сообщения в топик с определенным именем.
* Функция возвращает объект Publisher, который позволяет публиковать сообщения в топик,
* вызвая функцию publish(). Топик автоматически закроется как только все копии объекта
* Publisher будут уничтожены. Вторым параметром передается размер буфера.
*/
ros::Publisher spike_pub = n.advertise<letter_msgs::Letter>("spike", 1000);
ros::Rate loop_rate(10);
int count = 0;
while (ros::ok())
{
/**
* Это объект сообщения, мы заполняем его данными и публикуем.
*/
letter_msgs::Letter letter;
letter.text = "Dear Princess Celestia";
letter.num = count;
/**
* Функция publish() посылает сообщения. Параметром передается объект сообщения.
* Тип сообщения должен совпадать с тем, который был указан при вызове advertise().
*/
spike_pub.publish(letter);
ROS_INFO("Spike sends %lu letters to princess", letter.num);
ros::spinOnce();
loop_rate.sleep();
++count;
}
return 0;
}
twilight/CMakeLists.txt
cmake_minimum_required(VERSION 2.8.3)
project(twilight)
find_package(catkin REQUIRED COMPONENTS
roscpp
letter_msgs
)
catkin_package(
# INCLUDE_DIRS include
# LIBRARIES twilight
# CATKIN_DEPENDS roscpp
# DEPENDS system_lib
)
include_directories(
${catkin_INCLUDE_DIRS}
)
add_executable(twilight_node src/twilight.cpp)
add_dependencies(twilight_node ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})
target_link_libraries(twilight_node
${catkin_LIBRARIES}
)
twilight/package.xml
<?xml version="1.0"?>
<package>
<name>twilight</name>
<version>0.0.0</version>
<description>The twilight package</description>
<maintainer email="user@todo.todo">user</maintainer>
<license>TODO</license>
<buildtool_depend>catkin</buildtool_depend>
<build_depend>roscpp</build_depend>
<build_depend>letter_msgs</build_depend>
<run_depend>roscpp</run_depend>
<run_depend>letter_msgs</run_depend>
<export>
</export>
</package>
celestia/src/celestia.cpp
#include "ros/ros.h"
// этот файл создастся автоматически из файла Letter.msg
#include "letter_msgs/Letter.h"
void chatterCallback(const letter_msgs::Letter::ConstPtr& letter)
{
ROS_INFO("A letter from Twilight: [%s] %lu", letter->text.c_str(), letter->num);
}
int main(int argc, char **argv)
{
/**
* Функция ros::init() инициализирует подсистему ROS.
* Первыми двумя параметрами передаются параметры командной строки т.к. ноды ROS
* используют свои параметры (см. http://wiki.ros.org/Nodes)
* третим параметром задается имя ноды, четвертым могут быть переданы опции инициализации.
*/
ros::init(argc, argv, "princess_celestia");
/**
* При помощи NodeHandle осуществляется коммуникация с подсистемой ROS.
* Первый созданный NodeHandle полностью инициализирует ноду,
* а последний уничтоженный NodeHandle завершает ноду.
*/
ros::NodeHandle n;
/**
* При помощи функции subscribe() можно сказать ROS, что вы хотите получать сообщения
* из определенного топика. Сообщения будут переданы в callback функцию chatterCallback.
* Функция возвращает объект Subscriber, который нужно хранить пока вы не захотите отписаться.
* Вторым параметром передается размер буфера.
*/
ros::Subscriber spike_sub = n.subscribe("spike", 1000, chatterCallback);
/**
* Функция ros::spin() не дает программе завершиться, она инициализирует бесконечный цикл,
* при этом все callback функции будут вызваны в этом же (главном) потоке.
* Функция завершится при нажатии Ctrl-C, или если нода будет завершена из вне мастером.
*/
ros::spin();
return 0;
}
celestia/CMakeLists.txt
cmake_minimum_required(VERSION 2.8.3)
project(celestia)
find_package(catkin REQUIRED COMPONENTS
roscpp
letter_msgs
)
catkin_package(
# INCLUDE_DIRS include
# LIBRARIES celestia
# CATKIN_DEPENDS roscpp
# DEPENDS system_lib
)
include_directories(
${catkin_INCLUDE_DIRS}
)
add_executable(celestia_node src/celestia.cpp)
add_dependencies(celestia_node ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})
target_link_libraries(celestia_node
${catkin_LIBRARIES}
)
celestia/package.xml
<?xml version="1.0"?>
<package>
<name>celestia</name>
<version>0.0.0</version>
<description>The celestia package</description>
<maintainer email="user@todo.todo">user</maintainer>
<license>TODO</license>
<buildtool_depend>catkin</buildtool_depend>
<build_depend>roscpp</build_depend>
<build_depend>letter_msgs</build_depend>
<run_depend>roscpp</run_depend>
<run_depend>letter_msgs</run_depend>
<export>
</export>
</package>
src
└── pub_sub
├── celestia
│ ├── CMakeLists.txt
│ ├── include
│ │ └── celestia
│ ├── package.xml
│ └── src
│ └── celestia.cpp
├── letter_msgs
│ ├── CMakeLists.txt
│ ├── include
│ │ └── letter_msgs
│ ├── msg
│ │ └── Letter.msg
│ ├── package.xml
│ └── src
└── twilight
├── CMakeLists.txt
├── include
│ └── twilight
├── package.xml
└── src
└── twilight.cpp
Теперь можно скомпилировать воркспейс.
cd ~/ros/my_ws
catkin_make
И проверить. Запускаем каждую команду в отдельном терминале:
roscore
rosrun celestia celestia_node
rosrun twilight twilight_node
