Video Tutorial at https://youtu.be/iueRUQCvJXw
In this tutorial I will be showing you how to write a ROS subscriber. A ROS subscriber allows you to use data being published on a ROS topic in your own C++ ROS node.
in iq_gnc/src
create a new file and call it sub.cpp
Next open up the CMakeLists.txt
in iq_gnc
and add the following lines to the bottom of the file
add_executable(sub src/sub.cpp)
target_link_libraries(sub ${catkin_LIBRARIES})
these will allow catkin to build our program when we next run catkin build
in every ros program we make, we will need to add the ros include as follows
#include <ros/ros.h>
then below, we will add our main function.
int main(int argc, char **argv)
{
//rest of code will go here
return 0;
}
ros::init(argc, argv, "detection_sub");
ros::NodeHandle n;
subscribers are declared in the form
ros::Subscriber sub = <nodehandle>.subscribe("<topic>", <# of msg buffered>, <name of callback function>);
We want to subscribe to the detection data coming from darknet, so lets see which topics might have the data we need. run
roslaunch darknet_ros darknet_ros.launch
then
rostopic list
we see the following topics
/darknet_ros/bounding_boxes
/darknet_ros/check_for_objects/cancel
/darknet_ros/check_for_objects/feedback
/darknet_ros/check_for_objects/goal
/darknet_ros/check_for_objects/result
/darknet_ros/check_for_objects/status
/darknet_ros/detection_image
/darknet_ros/found_object
Lets subscribe to /darknet_ros/bounding_boxes
, but fist we need to see what type of ROS message this is.
run
rostopic list -v /darknet_ros/bounding_boxes
we see
Published topics:
* /darknet_ros/bounding_boxes [darknet_ros_msgs/BoundingBoxes] 1 publisher
Subscribed topics:
this means that the topic is publishing data in the form of darknet_ros_msgs/BoundingBoxes
Now we should have enough info to declare our subscriber. write
ros::Subscriber sub = n.subscribe("/darknet_ros/bounding_boxes", 1, detection_cb);
then add ros::spin();
this way the subscriber continues to get the latest data as it becomes available.
ros::spin();
we will also need to include the ros message to our include section. At the top of the program add
#include <darknet_ros_msgs/BoundingBoxes.h>
we are going to call our call back function detection_cb
. go ahead and add the following code
void detection_cb(const darknet_ros_msgs::BoundingBoxes::ConstPtr& msg)
{
//rest of callback function code
}
now we want to get the name of the object we are seeing out of the message, so lets learn more about the structure of this message. run the following
rosmsg show darknet_ros_msgs/BoundingBoxes
you will see
std_msgs/Header header
uint32 seq
time stamp
string frame_id
std_msgs/Header image_header
uint32 seq
time stamp
string frame_id
darknet_ros_msgs/BoundingBox[] bounding_boxes
string Class <---- the information we want
float64 probability
int64 xmin
int64 ymin
int64 xmax
int64 ymax
we can access the above information by dereferencing the ROS message as follows msg->bounding_boxes[i].Class
. add the following code to the callback function to print out all the objects detected.
for( int i=0; i < msg->bounding_boxes.size(); i++)
{
ROS_INFO("%s detected", msg->bounding_boxes[i].Class.c_str());
}
build
catkin build
then run our simulation and takeoff the drone
we can run our new program by running
rosrun iq_gnc sub
we should see the objects seen by the drone being printed in the console
http://wiki.ros.org/ROS/Tutorials/WritingPublisherSubscriber%28c%2B%2B%29