使用V-rep仿真(结合pythonAPI)实现机器人视觉巡线+pid调速

542
2
2020年7月13日 12时34分

1.背景介绍

因为疫情原因,在家上网课。因为放假前完全没有想到会放如此长的‘假’,所以我把所有学习用的开发板、硬件、开发教程书籍都放在了学校实验室里,从而现在不但不能在家做实物,也不能去学校做实物的尴尬情形。随后因为一门课(计算机控制技术)改变了这种尴尬的情形。

 

张老师推荐我们使用Vrep进行机器人仿真,并且实现pid控制,于是乎我马上利用空闲时间研究了这款软件,做了机器人视觉巡线+pid调速。

 

在实现视觉巡线之前我提交了多次作业,从简单的灰度巡线到视觉巡线。

 

使用V-rep仿真(结合pythonAPI)实现机器人视觉巡线+pid调速插图

作业提交图

 

1.1实现效果:

 

使用V-rep仿真实现机器人视觉巡线+pid调速

 

2.V-REP仿真介绍

V-REP 是机器人仿真器里的“瑞士军刀”:你不会发现一个比它拥有更多功能,特色或是更详尽应用编程接口的机器人仿真器:
• 跨平台 (Windows、MacOS、Linux)
• 六种编程方法 (嵌入式脚本、插件、附加组件、ROS节点、远程客户端应用编程接口、或自定义的解决方案)
• 七种编程语言 (C/C++、Python、Java、Lua、Matlab、Octave、和 Urbi)
• 超过400种不同的应用编程接口函数
• 100项ROS服务、30个发布类型、25个ROS订户类型、可拓展
• 4个物理引擎 (ODE, Bullet, Vortex, Newton)
• Integrated ray-tracer (POV-Ray)
• 完整的运动学解算器 (对于任何机构的逆运动学和正运动学)
• Mesh, octree, point cloud-网孔干扰检测
• Mesh, octree, point cloud-网孔最短距离计算
• 路径规划 (在2到6维中的完整约束、对于车式车辆的非完整约束)
• 嵌入图像处理的视觉传感器 (完全可拓展)
• 现实的接近传感器 (在检测区域中的最短距离计算)
• 嵌入式的定制用户接口、包括编辑器
• 完全集成的第四类Reflexxes运动库 + RRS-1 interface specifications
• 表面切削仿真
• 数据记录与可视化 (时距图、X/Y图或三维曲线)
• 整合图形编辑模式
• 支持水/气体喷射的动态颗粒仿真
• 带有拖放功能的模型浏览器 (在仿真中依旧可行)
• 多层 取消/重做、影像记录、油漆的仿真、详尽的文档等

 

接下来由我给大家一步步实现视觉检测和pid调速

 

3.实现

3.1选取机器人

  • 我在这里为了方便选择的是V-rep仿真软件里自带的Khepera3机器人,如果大家想自己做一个机器人也是可以的。

 

使用V-rep仿真(结合pythonAPI)实现机器人视觉巡线+pid调速插图(1)

Khepera3

 

  • 这个机器人可以直接点击File/Open Scene找到C:\Program Files (x86)\V-REP3\V-REP_PRO_EDU\scenes路径下的Khepera3.ttt。

 

使用V-rep仿真(结合pythonAPI)实现机器人视觉巡线+pid调速插图(2)

 

  • 也可以直接在现有的地图中从侧边的模型浏览器里找到robots/mobile下的Khepera3.

 

使用V-rep仿真(结合pythonAPI)实现机器人视觉巡线+pid调速插图(3)

 

我在下面会提供我的地图供大家下载使用。

 

3.2更改线形状操作

  1. 选好合适的角度,点击黑线,会显示蓝色的点:使用V-rep仿真(结合pythonAPI)实现机器人视觉巡线+pid调速插图(4)
  2. 按住Ctrl,并且点击蓝色的点,蓝色的点会变白使用V-rep仿真(结合pythonAPI)实现机器人视觉巡线+pid调速插图(5)
  3. 使用标签栏里的使用V-rep仿真(结合pythonAPI)实现机器人视觉巡线+pid调速插图(6),对白点拖动,到这就完成了半
  4. 双击使用V-rep仿真(结合pythonAPI)实现机器人视觉巡线+pid调速插图(7),弹出Scene Object Properties,并且选中使用V-rep仿真(结合pythonAPI)实现机器人视觉巡线+pid调速插图(8)
  5. 点击,弹出的框内容改成,随后确定就完成了改变线的形状。

 

3.3视觉传感器

3.3.1视觉传感器选择

  1. 右键场景使用V-rep仿真(结合pythonAPI)实现机器人视觉巡线+pid调速插图(9),找到Add/Vision Sensor/perspective Type添加即可。

 

3.3.2视觉传感器介绍

Vision sensors, which can detect renderable entities(Renderable objects are objects that can be seen or detected by vision sensors), should be used over proximity sensors mainly when color, light or structure plays a role in the detection process. However, depending on the graphic card the application is running on, or on the complexity of the scene objects, vision sensors might be a little bit slower than proximity sensors. Following illustrates applications using vision sensors:

 

 

使用V-rep仿真(结合pythonAPI)实现机器人视觉巡线+pid调速插图(10)

[(1) industrial robot observed by 2 vision sensors, (2) Line tracer vehicle equipped with 3 vision sensors]

 

视觉传感器与摄像机都能显示场景中的图像但是也存在着区别(一个侧重视觉检测和处理,一个侧重场景显示):

 

  • A vision sensor has a fixed resolution. A camera has no specific resolution (i.e. it adjusts automatically to the view size).
  • A vision sensor’s image content can be accessed via the API, and image processing filters are available. A camera’s image content is not directly available via the API (but via a callback mechanism), and image processing not directly supported.
  • A vision sensor generally requires more CPU time and operates slower than cameras.
  • A vision sensor can only display renderable objects. A camera can display all object types.(只有设置了Renderable属性的物体才能被视觉传感器检测处理)
  • Vision sensors can only operate while a simulation is running; this means that a vision sensor’s image content is only visible during simulation.

 

视觉传感器可分为正交投影型和透视投影型,它们的视场形状不一样:

 

使用V-rep仿真(结合pythonAPI)实现机器人视觉巡线+pid调速插图(11)

[Orthogonal projection-type and perspective projection-type vision sensors]

 

视觉传感器有近端剪切平面(near clipping plane)和远端剪切平面,使用剪切平面可以排除场景的一些几何体,只查看或渲染场景的某些部分。比近端剪切平面近或比远端剪切平面远的对象是不可视的。可以通过传感器属性对话框中的”Near / far clipping plane”设置剪切平面的位置。

 

使用V-rep仿真(结合pythonAPI)实现机器人视觉巡线+pid调速插图(12)

 

透视模式下传感器的视场角(FOV)可以通过”Perspective angle [deg] / Orthographic size”来设置。Perspective angle: the maximum opening angle of the detection volume when the sensor is in perspective mode. 如下图所示设置视场角为60°,当X/Y分辨率一样时水平视场角和垂直视场角的大小相同。

 

使用V-rep仿真(结合pythonAPI)实现机器人视觉巡线+pid调速插图(13)

 

正交模式下传感器的视场大小可以通过”Perspective angle [deg] / Orthographic size”来设置。Orthographic size: the maximum size (along x or y) of the detection volume when the sensor is not in perspective mode. 设置为Orthographic size为1m,X/Y方向分辨率为64/32,则X方向视场为1m,Y方向为0.5m,如下图所示:

 

使用V-rep仿真(结合pythonAPI)实现机器人视觉巡线+pid调速插图(14)

 

  • Vision sensor filter composition

 

使用视觉传感器的目的就是进行图像检测与处理,VREP中的视觉传感器在仿真过程中可以产生两种数据流:彩色图像(color image )和深度图(depth map)。我们可以通过API函数获取数据,然后遍历图像的每个像素进行处理,这样做灵活性很大,但是使用起来比较麻烦而且处理速度不够快。VREP提供了一种内部的filter来对图像进行处理(It is much more convenient (and fast!) to use the built-in filtering and triggering capabilities)。最简单的图像处理流程由3部分组成:输入→滤波→输出:

 

使用V-rep仿真(结合pythonAPI)实现机器人视觉巡线+pid调速插图(15)

[Vision sensor filter with 3 components]

 

在Image processing and triggering对话框中可以添加30多种filter对图像进行快速处理,比如:

 

  • Selective color on work image:根据RGB/HSL值和公差选取图中指定颜色,进行保留或移除等操作
  • Rotate work image:对图像进行旋转
  • Resize work image:对图像进行缩放
  • Flip work image horizontally/vertically:对图像进行水平/竖直翻转
  • Edge detection on work image:对图像进行边缘检测
  • Sharpen work image:图像锐化
  • Binary work image and trigger:对图像进行二值化处理
  • 3×3 / 5×5 filter on work image:使用3×3或5×5的模板对图像进行滤波

 

下面以均值滤波为例进行说明,3×3矩阵中各个分量设为1/9,则滤波器将会对原始图像每个像素周围的9个像素点取平均,对图像进行平滑,减小噪声:

 

使用V-rep仿真(结合pythonAPI)实现机器人视觉巡线+pid调速插图(16)

使用V-rep仿真(结合pythonAPI)实现机器人视觉巡线+pid调速插图(17)

 

复杂的图像处理流程可由多个部分组成,处理环节能完成4种基本的操作:

 

  • Transfer data from one buffer to another (e.g. transfer input image to work image)——传输数据
  • Perform operations on one or more buffers (e.g. invert work image) ——对数据进行操作
  • Activate a trigger (e.g. if average image intensity > 0.3 then activate trigger)——激活触发
  • Return specific values that can be accessed through an API call (e.g. return the position of the center of mass of a binary image)——返回特定值

 

下图显示了图像处理流程中的各种缓存和相互之间的操作:

 

使用V-rep仿真(结合pythonAPI)实现机器人视觉巡线+pid调速插图(18)

 

[Vision sensor buffers and operations between buffers]

 

The input image and input depth image are volatile buffers (易变缓存 i.e. normally automatically overwritten with new data at each simulation pass);The work image, buffer1 image and buffer2 image are persistent buffers (i.e. their content is not modified unless a component operates on them)

 

下面看一个比之前复杂点的例子,将原始图像边缘提取后旋转90°再叠加到原始图像上进行输出:先将要进行操作的work image保存到buffer 1中,然后对work image进行图像处理操作,接着将buffer 1叠加到work image上,最后将合成的图像进行输出。

 

使用V-rep仿真(结合pythonAPI)实现机器人视觉巡线+pid调速插图(19)

使用V-rep仿真(结合pythonAPI)实现机器人视觉巡线+pid调速插图(20)

 

3.4PythonAPI调用

3.4.1V-rep端通信配置

  1. 双击打开使用V-rep仿真(结合pythonAPI)实现机器人视觉巡线+pid调速插图(21)中的使用V-rep仿真(结合pythonAPI)实现机器人视觉巡线+pid调速插图(22)
  2. 在function()下添加函数simExtRemoteApiStart(19999)

 

使用V-rep仿真(结合pythonAPI)实现机器人视觉巡线+pid调速插图(23)

 

我们来介绍一下这个函数:simExtRemoteApiStart,

 

使用V-rep仿真(结合pythonAPI)实现机器人视觉巡线+pid调速插图(24)

 

功能描述:在指定端口上启动临时远程API服务器服务。当从模拟脚本启动时,服务将在模拟完成时自动结束
输入:
portNumber:安装服务器服务的端口。20000以上端口优先。为了使用共享内存,可以指定负端口号,而不是套接字通信。
maxPacketSize:套接字发送包的最大大小。确保将值保持在1300,除非客户端有不同的设置。
debug:如果为真,窗口将显示该端口上的数据流量。
preEnableTrigger:如果为真,将对来自客户机的同步触发信号预启用服务器服务。
输出:
num result:-1如果操作不成功。在未来的版本中,可能会有一个更差异化的回报价值

 

[有道词典翻译,服务于头疼英语的朋友]大致可以理解一下,这个函数通常输入一些端口等配置,来实现远程API与V-rep的临时通信(V-rep运行时才能通信!!!切记,划重点,要考)

 

以上完成了V-rep端的配置,下面介绍如何配置Python端。

 

3.4.2Python的配置

笔者用的是Python 3.6,编译器是VS Studio

 

3.4.3 函数库的导入

使用V-rep仿真(结合pythonAPI)实现机器人视觉巡线+pid调速插图(25)

 

这些文件可以在Vrep的安装文件夹中找到,包括:

 

vrep.py
vrepConst.py
remoteApi.dll(win) remoteApi.dylib(mac) remoteApi.so(linux)

 

Vrep安装文件夹->programming->remoteApiBindings->
(1)->python->python–>vrep.py&vrepConst.py
(1)->lib->lib->(32/64 Bit)–>remoteApi.dll

 

将这些文件复制到VS定义的Project文件夹中,这样也省事,如图所示。

 

使用V-rep仿真(结合pythonAPI)实现机器人视觉巡线+pid调速插图(26)

 

3.5 Python程序编写

3.5.1 仿真的步骤

1.引入头文件

 

import vrep

import time

import numpy as np

import cv2

 

2.连接vrep

 

# 连接vrep

def connection(num):

    print('program start')

    vrep.simxFinish(-1) # 关掉之前的连接

    while True:

        clientId = vrep.simxStart("127.0.0.1", 19999, True, True, 5000, 5)#建立和服务器的连接

        if clientId != -1:  #连接成功

            print('connect successfully')

            Get_Image(clientId)#获取传输的图像

            break

        else:

            time.sleep(0.2)

            print('connect failed')

    vrep.simxFinish(clientId)# 结束连接     

    print('program ended')    

 

3.获取服务端发来的图像

 

def Get_Image(clientId):

    errorCode,visionSensorHandle = vrep.simxGetObjectHandle(clientId,'VS3',vrep.simx_opmode_oneshot_wait)#获取VS3的handle

    # 第一次获取数据无效

    errprCode,resolution,image = vrep.simxGetVisionSensorImage(clientId,visionSensorHandle,0,vrep.simx_opmode_streaming)

    time.sleep(0.1)

    #获取有效数据

    while True:

        errprCode,resolution,image = vrep.simxGetVisionSensorImage(clientId,visionSensorHandle,0,vrep.simx_opmode_buffer)

        sensorImage = np.array(image,dtype = np.uint8)

        sensorImage.resize([resolution[0],resolution[1],3])#整理矩阵

        cv2.imshow('sensorImage',sensorImage)#显示图像

        if cv2.waitKey(1)==27:

                break

 

4.首先运行Vrep(!!!)

5.再运行python文件(!!!)

6.运行结果

 

使用V-rep仿真(结合pythonAPI)实现机器人视觉巡线+pid调速插图(27)

使用V-rep仿真(结合pythonAPI)实现机器人视觉巡线+pid调速插图(28)

左边是vrep中的图像,右边是获取到的图像

 

3.6视觉处理

3.6.1算法解析

使用V-rep仿真(结合pythonAPI)实现机器人视觉巡线+pid调速插图(29)

将整个画面分割为若干的检测区域,并给每个区域设定一个权值。

很容易理解, 距离越远的,重要性越高/越小, 根据自己的需求来设定不同的权值

最后算出来的偏移量带入pid进行计算,pid的教程网上有很多,就不再赘述了。

一文读懂PID控制算法(抛弃公式,从原理上真正理解PID控制)

 

PID代码

pid.py

 

import time

class PositionalPID:

    def __init__(self, P, I, D):

        self.Kp = P

        self.Ki = I

        self.Kd = D

 

        self.SystemOutput = 0.0#系统输出值

        self.ResultValueBack = 0.0

        self.PidOutput = 0.0#PID控制器输出

        self.PIDErrADD = 0.0

        self.ErrBack = 0.0

    #设置一阶惯性环节系统  其中InertiaTime为惯性时间常数

    def SetInertiaTime(self, InertiaTime,SampleTime):

       self.SystemOutput = (InertiaTime * self.ResultValueBack + SampleTime * self.PidOutput) / (SampleTime + InertiaTime)

       self.ResultValueBack = self.SystemOutput

    #设置PID控制器参数

    def SetStepSignal(self,StepSignal):

        Err = StepSignal - self.SystemOutput

        KpWork = self.Kp * Err

        KiWork = self.Ki * self.PIDErrADD

        KdWork = self.Kd * (Err - self.ErrBack)

        self.PidOutput = KpWork + KiWork + KdWork

        self.PIDErrADD += Err

        self.ErrBack = Err

 

use_pid()

 

def use_pid(P, I, D,signal1):

    PositionalPid = PID.PositionalPID(P, I, D)

    PositionalPid.SetStepSignal(signal1)

    return PositionalPid.PidOutput

 

使用V-rep仿真(结合pythonAPI)实现机器人视觉巡线+pid调速插图(30)

pid效果

 

算法不足分析

只适用于单条线, 如果是多条线,就不能识别

如何识别直角?

问题其实还有很多, 这个算法比较简单, 但是适用的情景比较局限。

Reference

[1].https://blog.csdn.net/weixin_41754912/article/details/82353012#2-v-rep%E9%85%8D%E7%BD%AE

[2].https://www.cnblogs.com/21207-iHome/p/7115487.html

发表评论

后才能评论

评论列表(2条)

  • u3oey_0531 2020年7月23日 上午10:56

    请问学些VREP,一定要学习LUA语言吗?能不能将一些自己做的机器人是怎么打入VREP,并且怎么使用C++,PYthon或MATLAB进行控制的,感觉这样和真实的机器人之间才是很相似。求一些教程,谢谢。

    • 锡城筱凯 回复 u3oey_0531 2020年7月23日 下午1:13

      1.不一定要学习LUA语言,不过需要有编程基础,能看懂他的意思即可
      2.VREP可以搭建自己的机器人,和三维建模一致,方法具体可以参考http://www.360doc.com/content/19/0630/20/32181961_845820949.shtml
      3.可以通过IP发送指令控制VREP
      4.教程目前国内还不是很成熟,得靠自己摸索