A-A+

WowWee Rovio API for ROS Groovy

2013年07月12日 robotics, ROS 评论 1 条 阅读 62,886 次

玩WowWee Rovio小车有段时间了,整理了一下之前写的代码,在ROS Groovy里面,对WowWee Rovio的CGI接口进行了封装,这次封装的主要是控制接口(三个全向轮,摄像头),图像接口(为了节约流量没有采取视频流的方式获取图像,而是采用request来response实时图像),MCU Report接口(包含红外传感,编码盘信息,电池信息等)。

Environment: Ubuntu 12.10 + Ros groovy (catkin workspace)

科普

WowWee Rovio是WowWee的早些年的一款WIFI小车,对于机器人爱好者来说,它的强大在于不错的硬件配置:

  1. 三个全向轮,附带三个编码传感器
  2. WIFI功能+摄像头
  3. 双向语音
  4. 一个红外障碍传感器
Rovio img

WowWee Rovio

而对于普通玩家来说,它的亮点还在于北极星导航系统,内置的WEB控制页面易于访问控制,外观高端。只可惜国内流行的都是洋垃圾,电池老化,内置部件质量差,电路设计早已过时,不合理效率低,以至于大部分产品都是随时可能坏掉崩溃的产品,对普通玩家来说没有实用价值。但是对于机器人爱好者,做一些改装也能变废为宝。

ROS (Robot Operating System),无需多言,做机器人研究的不用ROS,永远都会比别人落后一步(夸张了点,但是ROS有望成为机器人界的软件架构标准)。

How to use rovio_base package to develop with Rovio API

1. Download rovio_base package into your catkin workspace (here is ros_ws)

$ cd ~/ros_ws/src
$ git clone https://github.com/yuanboshe/rovio_base.git

2. Edit rovioServer.launch

$ roscd rovio_base
$ gedit launch/rovioServer.launch

Change the parameter values to yours

3. Create rovio_test package

$ cd ~/ros_ws/src
$ catkin_create_pkg rovio_test std_msgs roscpp cv_bridge

4. Create rovioTest.cpp

$ roscd rovio_test
$ gedit src/rovioTest.cpp

Paste the following code in to rovioTest.cpp and save.

#include "ros/ros.h"
#include "rovio_base/manDrv.h"
#include "rovio_base/image.h"
#include "rovio_base/report.h"
#include <cv_bridge/cv_bridge.h>
#include <sensor_msgs/image_encodings.h>
#include <opencv2/opencv.hpp

int main(int argc, char **argv)
{
  ros::init(argc, argv, "rovioTest");
  ros::NodeHandle n;
  ros::ServiceClient imageClient = n.serviceClient<rovio_base::image>("rovioImage");
  ros::ServiceClient controlClient = n.serviceClient<rovio_base::manDrv>("rovioControl");
  ros::ServiceClient reportClient = n.serviceClient<rovio_base::report>("rovioReport");
  rovio_base::image imageSrv;
  rovio_base::manDrv controlSrv;
  rovio_base::report reportSrv;

// Head middle control
  controlSrv.request.drive = 13;
  controlSrv.request.speed = 9;
  if (controlClient.call(controlSrv))
  {
    ROS_INFO("Control response code: %d", (int )controlSrv.response.code);
  }
  else
  {
    ROS_ERROR("Failed to call service rovioControl");
    return 1;
  }

// Get report info
  if (reportClient.call(reportSrv))
  {
    int length = reportSrv.response.length;
    int lDirection = reportSrv.response.lDirection;
    int lNum = reportSrv.response.lNum;
    int rDirection = reportSrv.response.rDirection;
    int rNum = reportSrv.response.rNum;
    int rearDirection = reportSrv.response.rearDirection;
    int rearNum = reportSrv.response.rearNum;
    int headPosition = reportSrv.response.headPosition;
    bool isLedOn = reportSrv.response.isLedOn;
    bool isIrOn = reportSrv.response.isIrOn;
    bool isDetectedBarrier = reportSrv.response.isDetectedBarrier;
    ROS_INFO("MCU Report:\nlength=%d", length);
    ROS_INFO("Left direction:num=%d:%d", lDirection, lNum);
    ROS_INFO("Right direction:num=%d:%d", rDirection, rNum);
    ROS_INFO("Rear direction:num=%d:%d", rearDirection, rearNum);
    ROS_INFO("headPosition=%d", headPosition);
    ROS_INFO("isLedOn=%d,isIrOn=%d,isDetectedBarrier=%d", isLedOn, isIrOn, isDetectedBarrier);
  }
  else
  {
    ROS_ERROR("Failed to call service rovioReport");
    return 1;
  }

// Show images from camera
  for (int i = 0; i < 20; i++) { 
    if (imageClient.call(imageSrv)) {
      ROS_INFO("Image size: %dx%d", (int )imageSrv.response.img.width, (int )imageSrv.response.img.height); 
      cv_bridge::CvImagePtr cvImgPtr; 
      try { 
        cvImgPtr = cv_bridge::toCvCopy(imageSrv.response.img, sensor_msgs::image_encodings::BGR8);
        cv::imshow("", cvImgPtr->image);
        cv::waitKey(100);
      }
      catch (cv_bridge::Exception& e){
        ROS_ERROR("cv_bridge exception: %s", e.what());
        return 1;
      }
    }
    else{
      ROS_ERROR("Failed to call service rovioImage");
      return 1;
    }
  }

// Head down control
  controlSrv.request.drive = 12;
  controlSrv.request.speed = 9;
  if (controlClient.call(controlSrv))
  {
    ROS_INFO("Control response code: %d", (int )controlSrv.response.code);
  }
  else
  {
    ROS_ERROR("Failed to call service rovioControl");
    return 1;
  }

  return 0;
}

About how to use the API, you can refer to Rovio API document. The above test program shows that three services you can use: "rovioControl", "rovioImage" and "rovioReport". You can find them as ManualDrive(), GetImage, GetMCUReport () in the above document.
Also, you may prefer to use the rovioParser class directly, that avoids using ROS's service and client frame.

5. Edit the rovio_test CMakeLists.txt located at ~/row_ws/src/rovio_test/CMakeLists.txt and change the related regions as follows(or just add at the end)

add_executable(rovioTest src/rovioTest.cpp)
target_link_libraries(rovioTest ${catkin_LIBRARIES})

6. Build the packages

$ cd ~/ros_ws/
$ catkin_make

7. Run them to test

Run the follow commands in three terminals respectively

$ roscore
$ roslaunch rovio_base rovioServer.launch
$ rosrun rovio_test rovioTest

After you executed the last command, your WowWee Rovio would head middle and head down, and you would view the images from camera 2 seconds.

在测试程序rovioTest node的terminal中,Control response code为0,MCU Report length > 0,Image size 显示正确值,则三个services调用返回了正确数据。

第一次用WP,排版有点乱,美化版可参见:http://yuanboshe.github.io/blog/2013/06/rovio_base_for_ros_groovy.html 。本打算把视觉避障的文章写好了再发的,后来发现事情太多,遥遥无期了,喜欢Rovio + ROS编程的童鞋可以一起来合作玩玩(ExBot官方群:109434898),本文当做抛砖引玉吧。
简陋的Rovio避障视频

标签:

1 条留言  访客:1 条  博主:0 条

  1. 我的名字叫麒

    你这个太专业了,顶一下

给我留言

Copyright © ExBot易科机器人实验室 保留所有权利.   Theme   Robin modified by poyoten

用户登录

分享到: