下午好,亲爱的哈布尔读者!这是有关Raspberry Pi上ROS实际使用的系列文章中的第二篇。在该系列的第一篇文章中,我描述了安装必要的ROS组件并设置工作环境。在本系列的第二部分中,我们将开始在Raspberry Pi平台上实际使用ROS功能。具体来说,在本文中,我将讨论将Raspberry Pi上的Raspberry Pi摄像头板与ROS结合使用来解决计算机视觉问题。谁有兴趣,请照顾下。相机RPi相机板
为了工作,我们将需要一台Raspberry Pi相机板
相机:该相机通过板上的CSi连接器直接连接到GPU,这使您无需使用处理器时间即可记录和编码相机中的图像。ZIF电缆用于连接相机。板上的电缆连接器位于以太网和HDMI端口之间:
库安装
因此,让我们继续安装必要的库。首先,安装OpenCV:$ sudo apt-get install libopencv-dev
要使用Raspberry Pi相机,我们将需要raspicam库。从这里下载档案。接下来,安装库:$ tar xvzf raspicamxx.tgz
$ cd raspicamxx
$ mkdir build
$ cd build
$ cmake ..
$ make
$ sudo make install
$ sudo ldconfig
您需要通过raspi-config程序在Raspbian中启用相机支持:$ sudo raspi-config
选择选项5-启用摄像机,保存选择并重新启动系统。ROS入门
为方便起见,请为我们的包装创建一个新的柳絮车间:$ mkdir -p ~/driverobot_ws/src
$ cd ~/driverobot_ws/src
$ catkin_init_workspace
$ cd ~/driverobot_ws
$ catkin_make
创建一个新的ROS包:$ cd src/
$ catkin_create_pkg raspi_cam_ros image_transport cv_bridge roscpp std_msgs sensor_msgs compressed_image_transport opencv2
catkin_create_pkg命令的规范如下:catkin_create_pkg <package_name> [depend1] [depend2],您可以在其中指定库(程序包将使用的库)下的任何依赖项。此命令创建ROS项目的框架:一个空的src目录,用于存放节点脚本以及CMakeLists.txt和package.xml配置文件。我找到了一个简单的脚本,该脚本可以接收来自相机的帧并使用“发布者”(publisher)发布这些帧,并将其改编为ROS Indigo。您可以从这里下载。要使用它,您需要安装Raspberry Pi UV4L摄像机驱动程序:$ curl http://www.linux-projects.org/listing/uv4l_repo/lrkey.asc | sudo apt-key add -
将以下行添加到/etc/apt/sources.list文件中deb http://www.linux-projects.org/listing/uv4l_repo/raspbian/ wheezy main
更新软件包并安装:$ sudo apt-get update
$ sudo apt-get install uv4l uv4l-raspicam
要下载驱动程序,在每次系统引导时,我们还安装一个可选软件包:$ sudo apt-get install uv4l-raspicam-extras
让我们继续编辑包。将此处的行粘贴到CMakeLists.txt文件中。CMakeLists.txt文件中最重要的几行:link_directories(/usr/lib/uv4l/uv4lext/armv6l/)
…
target_link_libraries(capture ${catkin_LIBRARIES} uv4lext)
因此,我们向uv4l驱动程序添加了链接,这对于编译软件包是必需的。在文件末尾,我们为节点设置特殊行:add_executable(capture src/capturer.cpp)
target_link_libraries(capture ${catkin_LIBRARIES} uv4lext)
add_executable行创建用于启动的二进制文件,而target_link_lbraries链接用于捕获二进制文件的其他库。将缺少的行从此处粘贴到package.xml文件中,使其看起来像这样:<?xml version="1.0"?>
<package>
<name>raspi_cam_ros</name>
<version>0.0.0</version>
<description>The raspi_cam_ros package</description>
<maintainer email="pi@todo.todo">pi</maintainer>
<license>TODO</license>
<buildtool_depend>catkin</buildtool_depend>
<build_depend>cv_bridge</build_depend>
<build_depend>image_transport</build_depend>
<build_depend>roscpp</build_depend>
<build_depend>std_msgs</build_depend>
<build_depend>sensor_msgs</build_depend>
<build_depend>opencv2</build_depend>
<build_depend>compressed_image_transport</build_depend>
<run_depend>cv_bridge</run_depend>
<run_depend>image_transport</run_depend>
<run_depend>roscpp</run_depend>
<run_depend>std_msgs</run_depend>
<run_depend>sensor_msgs</run_depend>
<run_depend>opencv2</run_depend>
<run_depend>compressed_image_transport</run_depend>
</package>
在第一行中,设置了节点的基本参数-名称,版本,描述,有关作者的信息。build_depend行确定编译包所需的库依赖关系,run_depend行确定运行包中的代码所需的依赖关系。在src文件夹中创建一个capturer.cpp文件,然后从此处粘贴行。在main()方法中,此节点被初始化并在循环中启动:ros::init(argc, argv,"raspi_cam_ros");
ros::NodeHandle n;
UsbCamNode a(n);
a.spin();
脚本的整个逻辑是,我们使用OpenCV从摄像机获取图片,将其包装在fillImage方法中的ROS消息中,并将其发布到主题。在这里,image_transport包用于创建“发布者”图片。通过运行以下命令启动uv4l驱动程序:$ uv4l --driver raspicam --auto-video_nr --width 640 --height 480 --nopreview
什么将创建MJPEG流。编译我们的ROS节点:$ roscore
$ cd ~/driverobot_ws
$ catkin_make
检查ROS_PACKAGE_PATH变量的值:echo $ROS_PACKAGE_PATH
/opt/ros/indigo/share:/opt/ros/indigo/stacks
ROS_PACKAGE_PATH变量的值应包括工作空间的路径。在路径中添加我们的工作室空间:$ source devel/setup.bash
现在再次运行echo $ ROS_PACKAGE_PATH命令,我们应该看到类似的输出:/home/youruser/catkin_ws/src:/opt/ros/indigo/share:/opt/ros/indigo/stacks
,其中/ home / <用户名> / catkin_ws / src是工作空间的路径。这意味着ROS可以“看到”我们在catkin_ws中创建的节点,并且可以通过rosrun运行它们。运行我们的ROS节点:$ rosrun raspi_cam_ros capture
运行图形程序rqt_image_view以显示该主题的视频流:$ rosrun rqt_image_view rqt_image_view
在rqt_image_view窗口中选择image_raw主题。
启动节点时,通过ssh或“ GdkGLExt-WARNING **:窗口系统不支持OpenGL”时,可能会出现错误“ Gtk-WARNING **:无法打开显示:-1”。在VNC远程桌面模式下运行时。解决方案是使用X11转发通过SSH连接到Raspberry Pi:$ ssh -X pi@<host_pi>
您可以使用rostopic命令找出发布到主题的频率:rostopic hz image_raw
此命令计算每秒每个主题接收消息的频率,并将其显示在控制台中。对于模型B +,我有这样的结论:average rate: 7.905
min: 0.075s max: 0.249s std dev: 0.02756s
如您所见,发布频率为8 Hz。我还检查了在RPi 2模型上从摄像机发布图像的频率,这里的结果要好很多倍:average rate: 30.005
min: 0.024s max: 0.043s std dev: 0.00272s
消息已经以30 Hz的频率发布,与B +模型相比,这是一个相当不错的速度提高。使用OpenCV和ROS的基于视觉的机器人控制
现在,我们将编写一个小的ROS程序包,以便在具有Raspberry Pi的机器人上使用计算机视觉,它将执行识别算法(在我们的示例中,使用行跟随方法进行视觉定向)并将所需的机器人偏移量的值发布到主题中。另一方面,机器人运动控制节点将订阅该主题并将运动控制命令发送到Arduino。现在,我们将一个“发布者”添加到capturer.cpp脚本中,该脚本将发布shift值。首先,为移位值启用消息类型的定义-std_msgs / Int16。#include <std_msgs/Int16.h>
rosserial需要特殊的msg消息文件并为其生成源代码。使用此模板:
标准rosserial消息的源代码存储在ros_lib目录内的package_name文件夹中。
接下来,我们初始化此类型的消息:package_name/msg/Foo.msg → package_name::Foo
std_msgs::Int16 shift_msg;
创建一个“发布者”:ros::Publisher shift_pub;
在UsbCamNode构造函数中,我们为其定义:shift_pub = nh.advertise<std_msgs/Int16>(“line_shift”, 1);
在这里,我们设置消息的类型和发布主题的名称。接下来,在#ifdef OUTPUT_ENABLED行之前,添加使用OpenCV计算换行值并将其发布到take_and_send_image()方法中的line_shift主题的逻辑:
shift_msg.data = offset;
shift_pub.publish(shift_msg);
我没有现成的行跟随算法,因此读者可以在此处自由编写自己的逻辑。实际上,消息中的数据存储在数据字段中。可以使用以下命令查看消息结构:$ rosmsg show std_msgs/Int16
现在运行节点:$ rosrun raspi_cam_ros capturer
我们使用rostopic echo命令来输出发布到主题line_shift的数据:$ rostopic echo line_shift
现在,将“订户”添加到机械手控制节点。启用消息类型的定义:#include <std_msgs/UInt16.h>
然后,我们添加一个回调函数,该回调函数在从主题接收到消息时执行。void messageCb(const std_msgs::UInt16& message)
{
int shift_val = int(message.data);
char* log_msg;
if(shift_val < 0) log_msg = "Left";
else if(shift_val > 0 ) log_msg = "Right";
else log_msg = "Forward";
nh.loginfo(log_msg);
}
回调函数的类型必须为void,并将消息类型的const引用作为参数。为简单起见,我记录了有关行偏移方向的消息。在这里,您可以为自己的场景添加自己的机器人运动逻辑。为主题line_shift创建消息的订阅者。ros::Subscriber<std_msgs::UInt16> sub("line_shift", &messageCb);
在这里,我们设置主题的名称以及指向回调函数的链接。接下来是rosserial_arduino的标准素描方法:void setup()
{
nh.initNode();
nh.subscribe(sub);
Serial.begin(57600);
}
void loop()
{
nh.spinOnce();
delay(100);
}
唯一的区别是,我们添加nh.subscribe(sub)来为主题创建站点的实际“订阅”。可以从此处下载用于控制机器人的草图。小把戏!在ROS中,有一些特殊的启动文件,使您可以使用某些参数将节点作为独立的进程自动启动。启动文件以xml格式创建,其语法允许您一次运行多个节点。但是,启动文件不能保证将按照指定的确切顺序启动节点。您可以创建启动文件以使rosserial_python服务器更易于启动。$ cd <catkin_ws>/src
$ catkin_create_pkg rosserial_controller
$ cd src/rosserial_controller
$ vim rosserial_controller.launch
我们编写具有以下内容的启动文件:<launch>
<node pkg="rosserial_python" type="serial_node.py" name="arduino_serial">
<param name="port" value="/dev/ttyACM0"/>
</node>
</launch>
编译并运行它:$ cd ~/<catkin_ws>
$ catkin_make
$ source devel/setup.bash
$ roslaunch rosserial_controller rosserial_controller.launch
我们可以使用rqt_plot实用工具可视化line_shift主题中发布的值,如本文所述:$ rqt_plot line_shift
现在,您可以在方案中充分利用Raspberry Pi相机和OpenCV库,以实现机器人的视觉定向,对象识别,跟踪以及许多其他功能。释放您的想象力!下次,我们将讨论通过按键盘上的键在遥控模式下控制机器人。PS。该网络具有有用的备忘单-ROS备忘单。对于ROS Indigo版本,可以从此处下载。