Ubuntu16 基于qt C++与vrep/coppeliasim通讯

1.系统环境和软件

  • 系统:ubuntu16.04
  • IDE: QT Creator
  • vrep(现在称作coppeliasim):CoppeliaSim\_Edu\_V4\_2\_0\_Ubuntu16\_04

2.安装支撑库

  • Linux下C++是通过一个叫BlueZero的接口和vrep建立通讯的,而BlueZero自身依赖于一些库才能运行。首先需要安装这些库:
$ wget -O boost_1_65_1.tar.gz https://sourceforge.net/projects/boost/files/boost/1.65.1/boost_1_65_1.tar.gz/download
$ tar xzvf boost_1_65_1.tar.gz
$ cd boost_1_65_1/
$ ./bootstrap.sh --prefix=/usr/
$ ./b2
$ sudo ./b2 install
$ sudo apt-get install build-essential libgl1-mesa-dev
$ sudo apt-get install libzmq3-dev

3.将支撑文件和库添加到工程

  • 在项目工程里新建一个文件夹用以存放支撑文件和库,例如建立一个Simulator文件夹并在其内建立子文件夹include、src、和dependents
    在这里插入图片描述
  • 在vrep(coppeliasim)的安装位置目录中找到如下文件(夹),拷贝到上一步建立的include
    CoppeliaSim/programming/b0RemoteApiBindings/cpp/b0RemoteApi.h
    CoppeliaSim/programming/b0RemoteApiBindings/cpp/msgpack-c/include
    CoppeliaSim/programming/bluezero/include/b0/bindings
    注:可能不同版本的vrep,这些文件所处的位置不同。
  • 在vrep(coppeliasim)的安装位置目录中找到如下文件,拷贝到上一步建立的src中
    CoppeliaSim/programming/b0RemoteApiBindings/cpp/b0RemoteApi.cpp
  • 在vrep(coppeliasim)的安装位置目录中找到如下库,拷贝到上一步建立的dependents中
    CoppeliaSim/libb0.so

4.将支撑文件和库引用到工程中

  • 打开工程的pro文件,在其中添加:
INCLUDEPATH += $$PWD/FPR_Simulator/include
INCLUDEPATH += $$PWD/FPR_Simulator/include/bindings
INCLUDEPATH += $$PWD/FPR_Simulator/include/include
LIBS += -L$$PWD/FPR_Simulator/dependents/ -lb0
SOURCES += FPR_Simulator/src/b0RemoteApi.cpp

5.打开vrep端的scene

  • 使用vrep自带的一个scene
    CoppeliaSim/scenes/messaging/synchronousImageTransmissionViaRemoteApi.ttt
    在这里插入图片描述

6.测试通讯

使用如下代码替换工程的主函数进行测试:

#include "b0RemoteApi.h"

bool doNextStep=true;
bool runInSynchronousMode=true;
int sens1,sens2;
b0RemoteApi* cl=NULL;

void simulationStepStarted_CB(std::vector<msgpack::object>* msg)
{
    float simTime=0.0;
    std::map<std::string,msgpack::object> data=msg->at(1).as<std::map<std::string,msgpack::object>>();
    std::map<std::string,msgpack::object>::iterator it=data.find("simulationTime");
    if (it!=data.end())
        simTime=it->second.as<float>();
    std::cout << "Simulation step started. Simulation time: " << simTime << std::endl;
}

void simulationStepDone_CB(std::vector<msgpack::object>* msg)
{
    float simTime=0.0;
    std::map<std::string,msgpack::object> data=msg->at(1).as<std::map<std::string,msgpack::object>>();
    std::map<std::string,msgpack::object>::iterator it=data.find("simulationTime");
    if (it!=data.end())
        simTime=it->second.as<float>();
    std::cout << "Simulation step done. Simulation time: " << simTime << std::endl;
    doNextStep=true;
}

void image_CB(std::vector<msgpack::object>* msg)
{
    std::cout << "Received image." << std::endl;
    std::string img(b0RemoteApi::readByteArray(msg,2));
    cl->simxSetVisionSensorImage(sens2,false,img.c_str(),img.size(),cl->simxDefaultPublisher());
}

void stepSimulation()
{
    if (runInSynchronousMode)
    {
        while (!doNextStep)
            cl->simxSpinOnce();
        doNextStep=false;
        cl->simxSynchronousTrigger();
    }
    else
        cl->simxSpinOnce();
}

int main(int argc,char* argv[])
{
    b0RemoteApi client("b0RemoteApi_c++Client","b0RemoteApi");
    cl=&client;

    client.simxAddStatusbarMessage("Hello world!",client.simxDefaultPublisher());
    std::vector<msgpack::object>* reply=client.simxGetObjectHandle("VisionSensor",client.simxServiceCall());
    sens1=b0RemoteApi::readInt(reply,1);
    reply=client.simxGetObjectHandle("PassiveVisionSensor",client.simxServiceCall());
    sens2=b0RemoteApi::readInt(reply,1);

    if (runInSynchronousMode)
        client.simxSynchronous(true);

    client.simxGetSimulationStepStarted(client.simxDefaultSubscriber(simulationStepStarted_CB));
    client.simxGetSimulationStepDone(client.simxDefaultSubscriber(simulationStepDone_CB));
    client.simxGetVisionSensorImage(sens1,false,client.simxDefaultSubscriber(image_CB));
//    client.simxGetVisionSensorImage(sens1,false,client.simxCreateSubscriber(image_CB,1,true));
    client.simxStartSimulation(client.simxDefaultPublisher());

    unsigned long st=client.simxGetTimeInMs();
    while (client.simxGetTimeInMs()<st+5000)
        stepSimulation();

    client.simxStopSimulation(client.simxDefaultPublisher());
    std::cout << "Ended!" << std::endl;
    return(0);
}

运行成功会看到vrep端自动开启了仿真,并且两个框内出现了图像。此时代表C++端和vrep的通讯建立成功,可以利用其他api去获取handle,然后控制自己的模型,进而达到仿真的目的。

7.自己的vrep模型

8.参考

[1] https://www.coppeliarobotics.com/helpFiles/en/b0RemoteApiOverview.htm
[2] https://www.youtube.com/watch?v=9lOLyM5siTw


标签: C++, qt, include, client, std, b0RemoteApi, vrep, CoppeliaSim

相关文章推荐

添加新评论,含*的栏目为必填