ViSP library allows to grab images from cameras using specific classes depending on the underlaying camera drivers. Thus it allows to grab images from firewire or usb cameras using either vp1394TwoGrabber or vpV4l2Grabber classes.
In the next section Image grabbing using ViSP, we recall how ViSP can be used to grab images. Then in section ros we introduce vpROSGrabber that can be used to grab images published by a ROS camera node.
Let us consider the following classical ViSP example provided in tutorial-visp-grabber-1394.cpp and given here after. Thanks to the vp1394TwoGrabber class provided in ViSP library we are able to grab images from a firewire camera.
#include <visp/vp1394TwoGrabber.h> #include <visp/vpDisplayX.h> #include <visp/vpImage.h> int main() { #ifdef VISP_HAVE_DC1394_2 try { vpImage<unsigned char> I; // Create a gray level image container bool reset = true; // Enable bus reset during construction (default) vp1394TwoGrabber g(reset); // Create a grabber based on libdc1394-2.x third party lib g.setVideoMode(vp1394TwoGrabber::vpVIDEO_MODE_640x480_MONO8); g.setFramerate(vp1394TwoGrabber::vpFRAMERATE_60); g.open(I); std::cout << "Image size: " << I.getWidth() << " " << I.getHeight() << std::endl; #ifdef VISP_HAVE_X11 vpDisplayX d(I); #else std::cout << "No image viewer is available..." << std::endl; #endif while(1) { g.acquire(I); vpDisplay::display(I); vpDisplay::flush(I); if (vpDisplay::getClick(I, false)) break; } } catch(vpException e) { std::cout << "Catch an exception: " << e << std::endl; } #endif }
This example is described in ViSP image frame grabbing tutorial pages.
To build this example ViSP should be installed. If not, depending on your ROS distro it could be done like:
sudo apt-get install ros-<distro>-visp
ViSP could also be installed from Debian package:
sudo apt-get install libvisp-dev
Now to build this example, just run the following commands in a terminal:
cd ~/catkin_ws/src/visp_ros/tutorial/grabber/visp cmake . make
To run this example, connect a firewire camera hit in the same terminal:
./tutorial-visp-grabber-1394
Let us consider this other ViSP example provided in tutorial-visp-grabber-v4l2.cpp and given here after. Thanks to the vpV4l2Grabber class we are able this time to grab images from an usb camera.
#include <visp/vpV4l2Grabber.h> #include <visp/vpDisplayX.h> #include <visp/vpImage.h> int main() { #ifdef VISP_HAVE_V4L2 try { vpImage<unsigned char> I; vpV4l2Grabber g; g.open(I); std::cout << "Image size: " << I.getWidth() << " " << I.getHeight() << std::endl; #ifdef VISP_HAVE_X11 vpDisplayX d(I); #else std::cout << "No image viewer is available..." << std::endl; #endif while(1) { g.acquire(I); vpDisplay::display(I); vpDisplay::flush(I); if (vpDisplay::getClick(I, false)) break; } } catch(vpException e) { std::cout << "Catch an exception: " << e << std::endl; } #endif }
To run this example, connect an usb camera and hit in the same terminal:
./tutorial-visp-grabber-v4l2
Depending on the camera that is used, you may adapt your code to use the right camera driver. This may be fastidious. That is why, in the next section we show how to use a more generic grabber class based on ROS and called vpROSGrabber. It just subscribes to a camera topic.
visp_ros package provides vpROSGrabber class that is able to handle any images published on a ROS topic. This class is interesting since it can be used as a classical ViSP class without knowing ROS very well since it makes ROS transparent for the user.
To be able to grab images published by a ROS camera node and display these images, the previous example need to be modified as in tutorial-ros-grabber.cpp given below:
#include <visp/vpDisplayX.h> #include <visp/vpImage.h> #include <visp_ros/vpROSGrabber.h> int main(int argc, const char** argv) { try { bool opt_use_camera_info = false; for (int i=0; i<argc; i++) { if (std::string(argv[i]) == "--use-camera-info") opt_use_camera_info = true; else if (std::string(argv[i]) == "--help") { std::cout << "Usage: " << argv[0] << " [--use-camera-info] [--help]" << std::endl; return 0; } } std::cout << "Use camera info: " << ((opt_use_camera_info == true) ? "yes" : "no") << std::endl; //vpImage<unsigned char> I; // Create a gray level image container vpImage<vpRGBa> I; // Create a color image container vpROSGrabber g; // Create a grabber based on ROS g.setImageTopic("/camera/image_raw"); if (opt_use_camera_info) { g.setCameraInfoTopic("/camera/camera_info"); g.setRectify(true); } g.open(I); std::cout << "Image size: " << I.getWidth() << " " << I.getHeight() << std::endl; #ifdef VISP_HAVE_X11 vpDisplayX d(I); #else std::cout << "No image viewer is available..." << std::endl; #endif while(1) { g.acquire(I); vpDisplay::display(I); vpDisplay::displayText(I, 20, 20, "A click to quit...", vpColor::red); vpDisplay::flush(I); if (vpDisplay::getClick(I, false)) break; } } catch(vpException e) { std::cout << "Catch an exception: " << e << std::endl; } }
Compared to the example based fully on ViSP and given in the Image grabbing using ViSP, once declared :
vpROSGrabber g; // Create a grabber based on ROS
we simply indicate which is the image topic name:
g.setImageTopic("/camera/image_raw");
If camera_info parameters are provided including distorsion, the image is rectified:
if (opt_use_camera_info) { g.setCameraInfoTopic("/camera/camera_info"); g.setRectify(true); }
Next as usual with ViSP, the device is opened
g.open(I);
and a new image is acquired using:
g.acquire(I);
Now to build this example, install visp_ros catkin package and setup the environment as described in the tutorial: Howto build and install visp_ros.
source ~/catkin_ws/install/setup.bash
Build the example by entering the following commands in a terminal:
cd ~/catkin_ws/src/visp_ros/tutorial/grabber/ros cmake . make
The previous example can work with images published by camera1394 node. To this end let us consider the following launch file named "camera-firewire.launch" where images are published on topic /camera/image_raw and camera parameters on topic /camera/camera_info.
<launch> <!-- Launch the firewire camera acquisition node --> <node pkg="camera1394" type="camera1394_node" name="my_camera1394_node" args="_video_mode:=640x480_rgb8" > <param name="camera_info_url" value="package://visp_ros/tutorial/grabber/ros/cam_parameters.yml" /> </node> </launch>
When launched, you will see the images:
cd ~/catkin_ws/src/visp_ros/tutorial/grabber/ros roslaunch camera-firewire.launch ./tutorial-ros-grabber --use-camera-info
The previous example can also work with images published by usb_cam node. To this end let us consider the following launch file named "camera-usb.launch" where images are published on topic /camera/image_raw and camera parameters on topic /camera/camera_info.
<launch> <!-- % rosrun usb_cam usb_cam_node _video_device:="/dev/video0" _pixel_format:="yuyv" _io_method:="mmap" _image_height:=640 _image_height:=480 --> <node pkg="usb_cam" type="usb_cam_node" name="camera" output="screen" > <param name="video_device" value="/dev/video0" /> <param name="image_width" value="640" /> <param name="image_height" value="480" /> <param name="pixel_format" value="yuyv" /> <param name="io_method" value="mmap"/> <param name="camera_info_url" value="package://visp_ros/tutorial/grabber/ros/cam_parameters.yml" /> </node> </launch>
When launched, you will see the images:
cd ~/catkin_ws/src/visp_ros/tutorial/grabber/ros roslaunch camera-usb.launch --use-camera-info ./tutorial-ros-grabber