zoukankan      html  css  js  c++  java
  • 机器人平台框架Yarp

    简介

    ROS有强大和易用的特性,用的人很多,目前已经推出2.0版本,有相关的官网和论坛。然而其缺点也比较明显。

          只能基于Ubuntu系统,且一个ROS版本只能对应一个具体的Ubuntu版本
          通信效率相对较低,基于Tcp协议。据说2.0以后支持udp协议,但效率如何位置,据说2.0以后版本变化也比较大
          系统较大。ROS使用与一个系统较大的平台,包括移动机器人、机械臂、平台机器人、室外展示机器人等。对于一般的开发者而已,往往只专注与1~2个核心点,很少涉及全部功能。而ROS的升级和维护往往涉及较大的文件和相关库,开发并不轻便。

    故需要找到替代品。Yarp标榜了“Another"不知作者是否是相对ROS而言。

    Yarp是开源系统,源码在Github中可以得到,且有几个稳定版本共选择。https://github.com/robotology/yarp
    官方文档在 http://www.yarp.it/

    然而官方文档似乎由doxgen生成,并不条理,且很多文档并没有相关注释,tutorial下来也没有一个明确的理解概念,所以在此需要记录学习过程的体会和经验,希望给后来者提供需求和帮助。


    Yarp的优势:

    •        分布式,支持tcp/udp/http 协议
    •        跨平台,用c++编写,依赖库很少,Linux下只需要必备的几个三方库。Windows下需额外下载一个库编译后即可使用
    •        开源,支持修改
    •           简单,支持CMake工具


    基于以上有点,在跨平台开发时得心应手,目前没有碰到太多效率问题,比较时候当前的项目需求。

    安装


          利用Git工具获取源码或相应稳定版本 https://github.com/robotology/yarp
          Windows下尚需按照源码ACE
          利用CMake生成工程,编译,设定YARP_DIR为CMake相关目录

          Enjoy!

    简单实例

      新建CMakeLists.txt, 内容如下
      

    1 cmake_minimum_required(VERSION 2.8.12)
    2 
    3 project(yarp_demo)
    4 
    5 find_package(YARP REQUIRED)
    6 include_directories(${YARP_INCLUDE_DIRS})
    7 add_executable(simple_sender simple_sender.cpp)
    8 
    9 target_link_libraries(simple_receiver ${YARP_LIBRARIES})

      简单的CMake代码,主要包含Yarp引用的header files,以及在链接时需要加入的Yarp库。Windows和Linux下面均经过测试。其中Windows需要在环境变量中指定Yarp_dir。当然,Yarp最好是自己编译通过。

      simple_sender.cpp的源码如下:

    #include <yarp/os/Network.h>
    #include <yarp/os/Port.h>
    #include <yarp/os/Bottle.h>
    #include <yarp/os/Time.h>
    #include <stdio.h>
    #include <yarp/os/all.h>
    #include <yarp/sig/all.h>
    
    #include <opencv2/core/core.hpp>
    #include <opencv2/imgproc/imgproc.hpp>
    #include <opencv2/highgui/highgui.hpp>
    
    using namespace yarp::os;
    using namespace yarp::sig;
    using namespace yarp::sig::draw;
    using namespace yarp::os;
    
    
    int main(int argc, char **argv)
    {
        char* ipAddr = "127.0.0.1";
        const int defaultPort = 10000;
    
            Network yarp;
        
            // connect to the name server
            Contact nameServer(ipAddr, defaultPort);
            Network::setNameServerContact(nameServer);
        
    
        BufferedPort<ImageOf<PixelRgb> > port;
        port.open("/circle");
    
        cv::VideoCapture mCap;
    
        mCap = cv::VideoCapture(0);
        if (mCap.isOpened())
        {
            while (1)
            {
                cv::Mat frame;
                mCap >> frame;
    
                ImageOf<PixelRgb>& img = port.prepare(); 
                img.setExternal(frame.data, frame.cols, frame.rows);
                port.write();
    
    
                cv::imshow("image", frame);
                int val = cv::waitKey(30);
                if(val > 0) break;
            }
    
        }
        else
        {
            int ct = 0;
            int idx = 0;
            while (true)
            {
                ImageOf<PixelRgb>& img = port.prepare();
                img.resize(100, 100);
                img.zero();
    
                PixelRgb blue(0, 0, 255);
                addCircle(img, blue, ct, 50, 10);
    
                printf("send msg: %d 
    ", ++idx);
                port.write();
    
                Time::delay(1);
                ct = (ct + 6) % 100;
                if (idx > 0xffff) break;
            }
    
        }
        
        mCap.release();
            port.close();    
        return 0;
    }

      相对于Yarp Example里面的范例,本例略复杂,即将发送的数据由OpenCV采集摄像头的数据,再转化为图片格式,发送出去。如果客户端没有摄像头,则直接创建一张简单图片,画一个圆形发送出去。

      其接受代码如下simple_receiver.cpp(CMakeList可参照上面的写,非常简单):

    #include <yarp/os/Network.h>
    #include <yarp/os/Port.h>
    #include <yarp/os/Bottle.h>
    #include <stdio.h>
    
    #include <yarp/os/all.h>
    #include <yarp/sig/all.h>
    
    using namespace yarp::os;
    using namespace yarp::sig;
     
    #include <opencv2/core/core.hpp>
    #include <opencv2/highgui/highgui.hpp>
    
    #include <string>
    
    int main(int argc, char **argv)
    {
        std::string ipAddr("127.0.0.1");
        const int defaultPort = 10000;
    
        Network yarp;    
        // connect to the name server
        Contact nameServer(ipAddr, defaultPort);
        Network::setNameServerContact(nameServer);
    
        Port input;
        auto ret = input.open("/receiver");
        if (!ret)
        {
            printf("Could not connect server 
    . ## Please retry. 
    ");
            return -1;
        }
        
        Bottle bot; 
        ImageOf<PixelRgb> img;
        
        Network::connect("/circle", "/receiver", "udp");
     
        while (true)
        {
    
            input.read(img);
            auto img2 = img.getIplImage();
            IplImage *img3 = static_cast<IplImage*>(img2);
            
            cvShowImage("Image", img3);
            cvWaitKey(20);
    
    
            printf("	======================== 
    ");
            //printf("got msg: %s
    ", bot.toString().c_str());
        }
        
        
        
        input.close();
        
        return 0;
    }

      连接正常的话,可以实时收到sender发送过来的图像。

    其他几个要点:

      Network::connect函数的第三个参数可选择tpc或upd

      Yarp默认不需要选择ipAddr或者port。在多机通信时,需要指定ip或端口

      单机通信效率比较高。

    另外Yarp含有Ros的结构,同时也有类似Ros的Topic的概念,会我后面的文章中介绍。

      

  • 相关阅读:
    变量与基本数据类型的练习
    04-各数据类型的常用操作
    常用函数
    03-python流程控制
    02-Python输入输出及运算符
    02-补充:逻辑运算符
    线程
    tcp实现并发效果
    生产消费者作业
    作业4.22
  • 原文地址:https://www.cnblogs.com/zjulion/p/6700964.html
Copyright © 2011-2022 走看看