1. 程式人生 > >V-rep學習筆記:ROSInterface

V-rep學習筆記:ROSInterface

comm sim itl 幫助 ubuntu下 具體步驟 按鈕 publisher 壓縮

  • Ubuntu 14.04 上安裝V-rep 3.4.0

  進入VREP官網下載Linux版本的V-rep(註意V-rep 3.4.0只有64位的版本,因此操作系統也要與之對應,Ubuntu 32位系統就無法運行V-rep 3.4。如果想使用以前的V-rep版本,可以進入這個網址下載)

技術分享圖片

  將下載的壓縮文件解壓後放到合適的位置,進入該目錄下,執行sh腳本文件打開V-rep程序:

./vrep.sh

技術分享圖片

  VREP與ROS的連接主要有三種方法:

  1. The RosInterface: RosInterface是V-rep官方推薦的用來跟ROS通信的插件(We highly recommend you to first try your hands on the RosInterface, since this is the most flexible and natural approach)
  2. The ROS plugin skeleton: 可以讓用戶實現特定功能的ROS插件框架(This represents a skeleton project that can be used to create a new ROS plugin for V-REP / create your own specific ROS plugin for V-REP. e.g. to support ROS messages for a specific robot)
  3. ROS interfaces developed by others: 其他非V-rep官方支持的通信接口,比如V-REP ROS bridge.

RosInterface

  將VREP安裝路徑下的compiledRosPlugins文件夾中的libv_repExtRosInterface.so或libv_repExtRosSkeleton.so庫復制到上層目錄(VREP安裝目錄)中:

技術分享圖片

  然後在終端中運行roscore開啟ROS master,接著執行vrep.sh腳本打開VREP,打開過程中會導入插件。可以看到RosInterface插件已經成功加載:

技術分享圖片

  開啟一個新終端,輸入rosnode list查看運行的ros節點。可以看到除了ros master以外vrep_ros_interface也成功運行:

技術分享圖片

  如果插件沒能成功導入(我沒遇到這種情況),可能需要自己重新編譯庫文件。編譯所需的幾個package位於VREP安裝目錄的programming/ros_packages下,將其復制到自己的catkin_ws/src中,用catkin工具進行編譯。具體步驟可以參照幫助文件中的ROS tutorial - Indigo頁面或者自行百度。

技術分享圖片

  下面看一個簡單的例子。在場景中選擇一個物體添加一個non-threaded腳本,這個腳本會發布仿真時間然後自己訂閱它,並且還會發布坐標變換消息:

技術分享圖片
function subscriber_callback(msg)
    -- This is the subscriber callback function
    simAddStatusbarMessage(subscriber receiver following Float32: ..msg.data)
end

function getTransformStamped(objHandle,name,relTo,relToName)
    -- This function retrieves the stamped transform for a specific object
    t=simGetSystemTime()
    p=simGetObjectPosition(objHandle,relTo)
    o=simGetObjectQuaternion(objHandle,relTo)
    return {
        header={
            stamp=t,
            frame_id=relToName
        },
        child_frame_id=name,
        transform={
            translation={x=p[1],y=p[2],z=p[3]},
            rotation={x=o[1],y=o[2],z=o[3],w=o[4]}
        }
    }
end

if (sim_call_type==sim_childscriptcall_initialization) then
    -- The child script initialization
    objectHandle=simGetObjectAssociatedWithScript(sim_handle_self)
    objectName=simGetObjectName(objectHandle)
    -- Check if the required RosInterface is there:
    moduleName=0
    index=0
    rosInterfacePresent=false
    while moduleName do
        moduleName=simGetModuleName(index)
        if (moduleName==RosInterface) then
            rosInterfacePresent=true
        end
        index=index+1
    end

    -- Prepare the float32 publisher and subscriber (we subscribe to the topic we advertise):
    if rosInterfacePresent then
        publisher=simExtRosInterface_advertise(/simulationTime,std_msgs/Float32)
        subscriber=simExtRosInterface_subscribe(/simulationTime,std_msgs/Float32,subscriber_callback)
    end
end

if (sim_call_type==sim_childscriptcall_actuation) then
    -- Send an updated simulation time message, and send the transform of the object attached to this script:
    if rosInterfacePresent then
        simExtRosInterface_publish(publisher,{data=simGetSimulationTime()})
        simExtRosInterface_sendTransform(getTransformStamped(objectHandle,objectName,-1,world))
        -- To send several transforms at once, use simExtRosInterface_sendTransforms instead
    end
end

if (sim_call_type==sim_childscriptcall_cleanup) then
    -- Following not really needed in a simulation script (i.e. automatically shut down at simulation end):
    if rosInterfacePresent then
        simExtRosInterface_shutdownPublisher(publisher)
        simExtRosInterface_shutdownSubscriber(subscriber)
    end
end
View Code

技術分享圖片

  終端中輸入rostopic list指令查看話題:

技術分享圖片

  為了查看消息的內容,可以輸入:

$ rostopic echo /simulationTime

技術分享圖片

  腳本中主要用到下面幾個函數:

  • simExtRosInterface_advertise

技術分享圖片

  • simExtRosInterface_subscribe

技術分享圖片

  • simExtRosInterface_publish

技術分享圖片

  • simExtRosInterface_sendTransform

技術分享圖片

rosInterfaceTopicPublisherAndSubscriber

  在V-rep自帶的例子中還有一個場景模型"rosInterfaceTopicPublisherAndSubscriber.ttt",腳本代碼中會發布視覺傳感器捕獲的圖像信息到/image話題上,同時會自己訂閱這個信息並顯示出來。

技術分享圖片

技術分享圖片
-- This illustrates how to publish and subscribe to an image using the ROS Interface.
-- An alternate version using image transport can be created with following functions:
--
-- simExtRosInterface_imageTransportAdvertise
-- simExtRosInterface_imageTransportPublish
-- simExtRosInterface_imageTransportShutdownPublisher
-- simExtRosInterface_imageTransportShutdownSubscriber
-- simExtRosInterface_imageTransportSubscribe

function imageMessage_callback(msg)
    -- Apply the received image to the passive vision sensor that acts as an image container
    simSetVisionSensorCharImage(passiveVisionSensor,msg.data)
end

if (sim_call_type==sim_childscriptcall_initialization) then
    -- Get some handles:
    activeVisionSensor=simGetObjectHandle(Vision_sensor)
    passiveVisionSensor=simGetObjectHandle(PassiveVision_sensor)

    -- Enable an image publisher and subscriber:
    pub=simExtRosInterface_advertise(/image, sensor_msgs/Image)
    --After calling this function, this publisher will treat uint8 arrays as string. Using strings should be in general much faster that using int arrays in Lua.
    simExtRosInterface_publisherTreatUInt8ArrayAsString(pub) -- treat uint8 arrays as strings (much faster, tables/arrays are kind of slow in Lua)

    sub=simExtRosInterface_subscribe(/image, sensor_msgs/Image, imageMessage_callback)
    simExtRosInterface_subscriberTreatUInt8ArrayAsString(sub) -- treat uint8 arrays as strings (much faster, tables/arrays are kind of slow in Lua)
end

if (sim_call_type==sim_childscriptcall_sensing) then
    -- Publish the image of the active vision sensor:
    local data,w,h=simGetVisionSensorCharImage(activeVisionSensor)
    d={}
    d[header]={seq=0,stamp=simExtRosInterface_getTime(), frame_id="a"}
    d[height]=h
    d[width]=w
    d[encoding]=rgb8
    d[is_bigendian]=1
    d[step]=w*3
    d[data]=data
    simExtRosInterface_publish(pub,d)
end

if (sim_call_type==sim_childscriptcall_cleanup) then
    -- Shut down publisher and subscriber. Not really needed from a simulation script (automatic shutdown)
    simExtRosInterface_shutdownPublisher(pub)
    simExtRosInterface_shutdownSubscriber(sub)
end
View Code

  可以在終端中輸入下面的命令來顯示/image話題的圖像:

$ rosrun image_view image_view image:=/image

技術分享圖片

  在rviz中添加Image,將話題選為/image也可以查看圖像信息:

技術分享圖片

controlTypeExamples

  還有一個例子是controlTypeExamples.ttt,V-rep中的腳本負責發布接近傳感器的信息以及仿真時間並訂閱左右輪驅動的話題。外部的ros程序rosBubbleRob2根據接收到的傳感器信息生成左右輪速度指令,並發布出去,V-rep中訂閱後在回調函數裏控制左右輪關節轉動。

技術分享圖片

  V-rep中腳本代碼如下:

技術分享圖片
function setLeftMotorVelocity_cb(msg)

    -- Left motor speed subscriber callback

    simSetJointTargetVelocity(leftMotor,msg.data)

end



function setRightMotorVelocity_cb(msg)

    -- Right motor speed subscriber callback

    simSetJointTargetVelocity(rightMotor,msg.data)

end



function getTransformStamped(objHandle,name,relTo,relToName)

    t=simGetSystemTime()

    p=simGetObjectPosition(objHandle,relTo)

    o=simGetObjectQuaternion(objHandle,relTo)

    return {

        header={

            stamp=t,

            frame_id=relToName

        },

        child_frame_id=name,

        transform={

            translation={x=p[1],y=p[2],z=p[3]},

            rotation={x=o[1],y=o[2],z=o[3],w=o[4]}

        }

    }

end



if (sim_call_type==sim_childscriptcall_initialization) then

    robotHandle=simGetObjectAssociatedWithScript(sim_handle_self)

    leftMotor=simGetObjectHandle("rosInterfaceControlledBubbleRobLeftMotor") -- Handle of the left motor

    rightMotor=simGetObjectHandle("rosInterfaceControlledBubbleRobRightMotor") -- Handle of the right motor

    noseSensor=simGetObjectHandle("rosInterfaceControlledBubbleRobSensingNose") -- Handle of the proximity sensor



    -- Check if the required ROS plugin is there:

    moduleName=0

    moduleVersion=0

    index=0

    pluginNotFound=true

    while moduleName do

        moduleName,moduleVersion=simGetModuleName(index)

        if (moduleName==RosInterface) then

            pluginNotFound=false

        end

        index=index+1

    end



    -- Add a banner:

    if (pluginNotFound) then

        bannerText="I cannot run! (I couldn‘t find my RosInterface plugin)"

    else

        bannerText="I am controlled via a ROS node and the RosInterface! (‘rosBubbleRob2‘ controlls me)"

    end

    black={0,0,0,0,0,0,0,0,0,0,0,0}

    red={0,0,0,0,0,0,0,0,0,1,0.2,0.2}

    simAddBanner(bannerText,0,sim_banner_bitmapfont+sim_banner_overlay,nil,simGetObjectAssociatedWithScript(sim_handle_self),black,red)



    -- Ok now launch the ROS client application:

    if (not pluginNotFound) then

        local sysTime=simGetSystemTimeInMs(-1) 

        local leftMotorTopicName=leftMotorSpeed..sysTime -- we add a random component so that we can have several instances of this robot running

        local rightMotorTopicName=rightMotorSpeed..sysTime -- we add a random component so that we can have several instances of this robot running

        local sensorTopicName=sensorTrigger..sysTime -- we add a random component so that we can have several instances of this robot running

        local simulationTimeTopicName=simTime..sysTime -- we add a random component so that we can have several instances of this robot running



        -- Prepare the sensor publisher and the motor speed subscribers:

        sensorPub=simExtRosInterface_advertise(/..sensorTopicName,std_msgs/Bool)

        simTimePub=simExtRosInterface_advertise(/..simulationTimeTopicName,std_msgs/Float32)

        leftMotorSub=simExtRosInterface_subscribe(/..leftMotorTopicName,std_msgs/Float32,setLeftMotorVelocity_cb)

        rightMotorSub=simExtRosInterface_subscribe(/..rightMotorTopicName,std_msgs/Float32,setRightMotorVelocity_cb)



        -- Now we start the client application:

        result=simLaunchExecutable(rosBubbleRob2,leftMotorTopicName.." "..rightMotorTopicName.." "..sensorTopicName.." "..simulationTimeTopicName,0)

    end

end



if (sim_call_type==sim_childscriptcall_actuation) then

    -- Send an updated sensor and simulation time message, and send the transform of the robot:

    if not pluginNotFound then

        local result=simReadProximitySensor(noseSensor)

        local detectionTrigger={}

        detectionTrigger[data]=result>0

        simExtRosInterface_publish(sensorPub,detectionTrigger)

        simExtRosInterface_publish(simTimePub,{data=simGetSimulationTime()})

        -- Send the robot‘s transform:

        simExtRosInterface_sendTransform(getTransformStamped(robotHandle,rosInterfaceControlledBubbleRob,-1,world))

        -- To send several transforms at once, use simExtRosInterface_sendTransforms instead

    end

end



if (sim_call_type==sim_childscriptcall_cleanup) then

    if not pluginNotFound then

        -- Following not really needed in a simulation script (i.e. automatically shut down at simulation end):

        simExtRosInterface_shutdownPublisher(sensorPub)

        simExtRosInterface_shutdownSubscriber(leftMotorSub)

        simExtRosInterface_shutdownSubscriber(rightMotorSub)

    end

end
View Code

rosInterface helper tool

  在模型瀏覽器的tools文件夾中有一個RosInterface的幫助工具,將其拖入場景中可以方便實現一些控制功能。

技術分享圖片

  主要有下面一些功能:

  • startSimulation topic: can be used to start a simulation by publishing on this topic a std_msgs::Bool message.
  • pauseSimulation topic: can be used to pause a simulation by publishing on this topic a std_msgs::Bool message.
  • stopSimulation topic: can be used to stop a simulation by publishing on this topic a std_msgs::Bool message.
  • enableSyncMode topic: by publishing a std_msgs::Bool message on this topic, you can enable/disable the synchronous simulation mode.
  • triggerNextStep topic: by publishing a std_msgs::Bool message on this topic, you can trigger the next simulation step, while in the synchronous simulation mode.
  • simulationStepDone topic: a message of type std_msgs::Bool will be published at the end of each simulation pass.
  • simulationState topic: messages of type std_msgs::Int32 will be published on a regular basis. 0 indicates that the simulation is stopped, 1 that it is running and 2 that it is paused.
  • simulationTime topic: messages of type std_msgs::Float32 will be published on a regular basis, indicating the current simulation time.

  可以在終端中輸入下面的一些命令進行測試:

$ rostopic pub /startSimulation std_msgs/Bool true --once
$ rostopic pub
/pauseSimulation std_msgs/Bool true --once
$ rostopic pub
/stopSimulation std_msgs/Bool true --once
$ rostopic pub
/enableSyncMode std_msgs/Bool true --once $ rostopic pub /triggerNextStep std_msgs/Bool true --once

  比如在終端中輸入:rostopic pub /startSimulation std_msgs/Bool true --once, 就可以開始仿真,跟手動點擊仿真按鈕效果一樣。

技術分享圖片

參考:

vrep_ros_bridge

Ros與Vrep平臺搭建

機器人操作系統ROS(indigo)與三維仿真軟件V-Rep(3.2.1)通信接口使用筆記

從零開始的仿真之旅——在Ubuntu下配置V-Rep仿真平臺下的搭載ROS系統的機器人仿真

V-rep學習筆記:ROSInterface