機器人平台框架Yarp - Yet another robot platform


簡介

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 \n", ++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 \n. ## Please retry. \n");
        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("\t======================== \n");
        //printf("got msg: %s\n", bot.toString().c_str());
    }
    
    
    
    input.close();
    
    return 0;
}

  連接正常的話,可以實時收到sender發送過來的圖像。

 

其他幾個要點:

  Network::connect函數的第三個參數可選擇tpc或upd

  Yarp默認不需要選擇ipAddr或者port。在多機通信時,需要指定ip或端口

  單機通信效率比較高。

 

另外Yarp含有Ros的結構,同時也有類似Ros的Topic的概念,會我后面的文章中介紹。

  

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM