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的概念,会我后面的文章中介绍。

      

  • 相关阅读:
    git常用指令 github版本回退 reset
    三门问题 概率论
    如何高效的学习高等数学
    数据库6 关系代数(relational algebra) 函数依赖(functional dependency)
    数据库5 索引 动态哈希(Dynamic Hashing)
    数据库4 3层结构(Three Level Architecture) DBA DML DDL DCL DQL
    梦想开始的地方
    java String字符串转对象实体类
    java 生成图片验证码
    java 对象之间相同属性进行赋值
  • 原文地址:https://www.cnblogs.com/zjulion/p/6700964.html
Copyright © 2011-2022 走看看