MDCS引擎适配机器人入门教学

来自MDCS wiki
跳到导航 跳到搜索

//todo...

MDCS分别为4个AGV主要组件,分别为

  • Medulla,硬件适配软件。提供通信抽象,通过插件对接各类硬件。开发者适配车型后,应使用遥控器应用进行遥控车体、试验IO等操作,来验证适配结果,确保硬件适配层不会故障或崩溃。 工作内容:网络或串口编程、适配CAN卡驱动、报文适配、编写遥控逻辑、上下位信号设计、基础动作逻辑
  • Detour,定位软件这部分只需要配置。SLAM导航、二维码、UWB定位相关程序。主要给出车体位姿。开发者应通过Detour对车体各传感器进行标定。若使用激光SLAM导航则应建图。 工作内容:配置传感器、建图、传感器位置标定:óó
  • Clumsy,自动驾驶系统。定义AGV所有可用的动作,如差速行走、舵轮行走、侧移行走、自动找工位或托盘、调姿取放货等。开发者应通过Clumsy插件实现适配AGV的所有动作,并通过测试类验证动作实现。 工作内容:车体定义、基础动作编程和参数定义、动作测试编程、智能动作编程
  • Simple,AGV调度系统。Simple是个完备的静态调度系统,即小车路径一旦下发无需更改,调度系统保证小车运行到终点。开发者需要开发业务插件,定义车型、针对车型的路径搜索约束器(限制车型的行走路线,如不可直角拐弯等)、针对车型的路径编程器(将路径转为具体的AGV动作序列)、路径搜索的约束条件、并实现场景所需的业务逻辑;还需要在Clumsy插件编写动作对接函数,使得Simple可以调用Clumsy中定义的动作。开发者的场景实现应具有模拟功能,从而可以上线前模拟验证调度业务的正确性,然后再在实际场景中上线实际业务功能。 工作内容:路径图绘制、路径搜索其发器、路径编程器、业务逻辑的正确编写(对接按钮盒、派发任务、维护任务状态等)

工程组织方法介绍

约定1:首先应命名车型名称。解决方案中存在一个称为CartAdapters的文件夹,应创建一个以该车型命名的文件夹,并把ClumsyPilot(自动驾驶工程)和MedullaAdapter(硬件适配工程)放入文件夹中。如图下所示:

约定2:源代码目录结构必须符合规范:所有的车型需要放到CartAdapters中,每个车型一个目录,并且把所有车型资料放到对应的文件夹中。(如车型图片、对接协议、文档等)。

约定3:编译结果目录结构必须符合规范:编译结果一律放到build文件夹中,每个车型一个文件夹。场景均放到AGVScene目录中,每个场景(项目)设立一个文件夹。

指南1:如何在解决方案中新建车型。以车型FY2104001为例。

首先要复制MedullaAdapter和ClumsyPilot两个工程:即从已有工程或模板中复制到CartAdapters/FY2104001目录里。然后解决方案里新建一个解决方案文件夹,命名为FY2104001,然后分别导入MedullaAdapter和ClumsyPilot两个工程。最后在build目录里新建一个名为“FY2104001“的文件夹。

随后进行改名:ClumsyPilot工程的程序集名称/默认命名空间改名为”FY2104001_c”,MedullaAdapter工程的程序集/默认命名空间名称改为“FY2104001_m”。

然后将这两个工程的生成事件中的“生成后事件命令行”修改正确:这个命令行将输出文件导出到build/FY2104002目录中,方便管理。

Medulla开发方法介绍

约定3:MedullaAdapter工程需要实现全部硬件通信、IO读取和处理、和基础运动指令下发功能。以下是一些例子:

向某个电机驱动器发送1000rpm的转速、向某个舵轮发送转到45度角并以3000rpm速度行走、货叉向上举升、如果近距离避障雷达触发了则向所有电机下发0速度,左转弯时亮起转向灯。

MedullaAdapter适配完成后,应得到可通过NetRemote应用该程序或AGV遥控器App,人工遥控执行所有AGV动作的程序。


约定4:MedullaAdapter工程中命名要规范。以某型号为BL21001的车型为例:

其中,设备定义类为BL21001Cart。

BL21001有三种轮询,分别控制IO、电机、音乐和电池。命名为IORoutine,MotorRoutine和MusicRoutine和BatteryRoutine。

BL21001的遥控逻辑为BL21001Remote


定义1:上位IO(UpperIO)指人工或自动驾驶自动下发的字段,如下发速度、下发方向盘角度、下发的避障选择区域等。


定义2:下位IO(LowerIO)指从硬件读取的字段,如实际轮速、实际转角、障碍物信号、电池电量等。


指南5:如何MedullaAdapter中定义设备。以FY2104002Cart为例:

应指定上位IO和下位IO。使用AsUpperIO标记字段来指定字段是上位IO,若改字段无上位遥控信号达到300ms,且设置了timeOutReset=true,则会自动恢复为设定的默认值。下位IO使用AsLowerIO标记。这些字段需要设为public。

可以指定一些监控量,需要使用IOObjectMonitor进行标记。这些字段需要设为public。

设备可以指定一些UI调试按钮方法,使用IOObjectUtility进行标记。这些方法需要设为public。

设备应该指定“梯形图逻辑”,即周期性执行的代码。使用UseLadderLogic来指定。UseLadderLogic需要指定logic类型和scanInterval扫描周期。Logic所指定的梯形图类型需要继承LadderLogic<FY2104002Cart>,并实现Operation方法。

设备应指定一个遥控器程序。使用UseManualController来指定,其中manualController类型为遥控逻辑类,它需要继承ManualController<FY2104002Cart>,并实现Operation方法。

可以指定初始化变量,使用AsInitParam进行标记。这些变量可以在Medulla的启动脚本startup.iocmd中设置,从而在调用Init时可以使用。

设备应实现初始化方法Init()。可以做各个设备的初始化操作。

可以映射一些空方法到UI界面上,使用IOObjectUtility标记。这些方法会出现在Medulla的界面中,用户可点击调用,一般用来测试。

以下展示了一个设备的定义案例

指南6:如何编写“梯形图逻辑”,应编写什么功能?梯形图逻辑是间隔若干ms执行的逻辑程序。需要实现Operation方法,方法里可以使用cart变量来访问设备定义类的成员变量。Operation里应处理报文。如设备初始化方法中启动了一个串口,开发者应在Operation里对串口进行读操作,来解析设备报文,存入下位IO变量(LowerIO);并根据上位IO变量(UpperIO)组织报文,并对串口进行写操作。


指南7:遥控逻辑是什么?如何编写遥控逻辑?Medulla支持多种不同的控件,如按钮、开关等,可以映射为NetRemote程序的虚拟控件、AGV遥控App的虚拟控件、或Xbox手柄上的物理按钮盒摇杆。遥控逻辑可以访问到这些控件的按键情况和数值,从而可向UpperIO写入数据,进而遥控车体运动。

以某型号为BL21001的包夹式AGV为例。

遥控逻辑类名为BL21001MRemote,继承ManualController<BL21001Cart>。

遥控逻辑类可以定义多个遥控控件,包括Button(按钮),Switch(开关),Knob(旋钮),Stick(摇杆),DPad(四向键),Throttle(推杆),DThrottle(双向推杆)。定义的遥控控件需要增加AsControlItem标记。

以下是个例子:

遥控逻辑类需要实现Operation方法。需要读取定义的控件值,并向一些UpperIO赋值(如,根据direction摇杆的方向对“下发舵轮角度”进行赋值)。

控件的值会在执行Operation方法前自动更新。


指南9:如何上机验证:以FY2104001_m为例

1.将Medulla程序放入指定目录:如桌面startup文件夹。将Medulla的全部核心程序复制入目录,将生成的Medulla适配程序(FY2104001_m.dll)放入plugins文件夹,如果适配程序还引用了其它的库,也一并放入plugins文件夹。

2.编写Medulla启动配置脚本:startup.iocmd文件。基础的例子如下

loader = io load plugins\CartActivator.dll

loader setp com COM1

cart = loader load plugins\FY2104001_m.dll

ui=io load plugins\WinMedulla.dll

ui Show

解析:

使Medulla加载车体加载器插件:loader = io load plugins\CartActivator.dll

设置初始化变量:loader setp com COM1,这里com是FY2104001_m中定义的初始化变量(标记为AsParamInit)

加载FY2104001_m中的车体定义,并把车体记为cart对象。

加载Medulla自带的UI界面库:ui=io load plugins\WinMedulla.dll

显示UI:ui Show


说明2:Medulla使用方法和启动配置脚本进一步说明

Medulla主程序启动后,逐行地执行脚本,有三种语法:

调用语句:如cart reset,使cart对象调用reset方法。

创建对象语句:如cart = loader load plugins\FY2104001_m.dll,使loader调用load方法,参数为plugins\FY2104001_m.dll,结果对象名称记为cart。

变量赋值语句:如cart.thOffset=1.2,使cart对象的thOffset成员变量赋值为1.2

Medulla的命令语句可以在UI界面的命令执行选项卡直接执行。

加载ui对象后,ui Show方法会弹出硬件控制台界面,会将控制台关闭。如果需要再打开,可以选择ui对象,并点击ShowConsole按钮。

一般AGV可能还有其它传感器要接入Medulla,如激光雷达、3D相机等。以下列举一些常用的代码配置:

加载激光雷达插件:

lidar = io load plugins\LidarController.dll

定义一个名为frontlidar的倍加福R2000雷达对象:

frontlidar = lidar init PnFR2kLidar 192.168.1.11

定义一个名为backlidar的山东科力雷达对象:

backlidar = lidar init sdkeli 192.168.1.11

定义一个名为forklidar的西克Nano Scan雷达对象

forklidar= lidar init sicknano

定义一个名为frontlidar3d的速腾聚创RS16多线雷达对象

frontlidar3d = lidar init RSLidar16 192.168.1.2


指南10:遥控验证方法:

遥控验证用于检测Medulla的硬件对接程序是否正常工作。开发者应尝试使用遥控器指挥小车做各类动作,检查动作的流畅性,并检查基础动作逻辑是否正确(如拍急停应当停车等)

注意Medulla在遥控时,就不再响应自动驾驶程序Clumsy所下发的信号了。

1.  打开Medulla硬件对接程序,截图如下。

其中红框中标出的cart即为开发的Medulla适配对象。中间的列表列举了所有开发者定义的变量(包括上位变量、下位变量和监控变量),并实时更新显示。用户还可以通过打开监视窗口来图形化地检测变量中的数值变量。


2.  使用NetRemote桌面版遥控器进行遥控验证。应用截图如下:

点击激活遥控后,AMR遥控器开始向Medulla输出遥控数据。如该遥控器是一个潜伏顶升可旋转托盘的AGV遥控画面。用户首先设定速度(即speed控件),点击上下左右键可以控制小车前进、后退、左转、右转。按住up顶升、按住down下降。滑动rot可控制转盘。

另外,可以绑定键盘按键以方便控制。点击“编辑“,右键弹出菜单即可绑定按键。


3.可使用手机遥控器App进行遥控验证,并作为AGV遥控的主要方式。

其截图如下:

类似的,用户可以激活遥控器,或点击编辑模式编辑遥控器面板。遥控器面板编辑完成后可导出为二维码并建议粘贴在车体上,供后续扫码识别使用。

手机遥控器具备两种连接模式,一种是Wifi连接,另一种是蓝牙连接。推荐使用蓝牙连接方式,连接较为简单方便。手机App中点击连接按钮,即显示以下画面:

查看Medulla界面,cart对象中属性页的BTName项,此项的值为该工控机的蓝牙名称(可自行在操作系统设置里更改)。App中选中正确的设备,等待连接完成后即可遥控。连接设定也可以导出为二维码并建议贴在车体上,供后续连接使用。


指南11:其它外设定义

说明2中已列举了激光雷达插件的使用方法。Medulla还支持以下种类的传感器输入:

USB摄像头,使用方法:

1.  进入命令执行窗口,输入camera = io load plugins\USBCamera.dll

2.  回到对象窗口,可看到当前检查到的摄像头列表。

3.  进入命令执行窗口,输入camera detail Chicony_USB2.0_Camera,查看所有支持的模式。

4.  我们选择模式2(640*480分辨率),并指定彩色输出。在startup.iocmd中配置

camera = io load plugins\USBCamera.dll

usbcam = camera init Chicony_USB2.0_Camera 2 true

即可创建一个名为usbcam的摄像头对象。


工业摄像头驱动,支持海康威视、大华、Basler等工业相机,使用方法:

在startup.iocmd中配置:

mv = io load plugins\MVCamera.dll

maincam=mv initMono CA013

其中CA013是摄像头型号,initMono为以单色方式启动。若相机是彩色相机,则使用initColor方法。

Clumsy开发介绍

Clumsy是小车的运动控制组件。开发者需要做的是:定义运动控制的输入输出变量、定义参数表、定义动作、定义动作测试例程,并提供调度接口。


约定1:车型参数表命名规范:以某背负式差速小车BSD10LS为例,命名为BSD10LSConfigs.cs,包含若干个由[FieldMember]标记的参数,为该小车可配置的参数。任何参数都可以放到该类中,Clumsy自动识别、提供默认调参程序并存储参数至clumsy.json配置文件中。支持的参数类型为string/int/float/double,即字符串和数值类。


指南1:车型定义文件如何编写?以某背负式差速小车BSD10LS为例:

1.     车型定义文件,命名为BSD10LSDef.cs,包含类BSD10LSDef,继承自PilotDefinition<BSD10LSConfigs>。该文件从MedullaAdapter工程中设备定义类BSD10LSCart.cs中摘抄标记了AsUpperIO和AsLowerIO的字段。这些字段中,AsLowerIO字段会自动更新,AsUpperIO字段会自动下发。

2.     车型定义文件还需要重写Init方法,这个方法会在Clumsy启动时调用。此外还需要重写DriveStop方法,在小车静息或遇故障停车时,写入的下位变量。常用的初始化操作包括:

a)      在BSD10LSDef中设定一个静态变量self,并在启动时设置self=this,使得其它类可以访问BSD10LSDef的实例。

b)      调用ClumsyLib.Capture();从而启动Clumsy的传感器采集功能。

c)       启动前台UI或者创建线程后台上报数据等。

3.     需要给车型定位文件增加欲使用的控制方法标记。支持三种控制方法:

a)      CanDifferentialDrive,即差速驱动方法。使用该标记,需要指定type为一个继承了DifferentialWriterClass的差速速度下发类。如:

开发者需要实现WriteLR方法,向驱动器中写入速度。

b)      CanSteeringDrive,即单舵轮驱动方法,类似的,使用该标记需要指定type为一个继承了SteeringWriterClass的舵轮速度下发类。该类除了写入舵轮速度外,还应反馈舵轮角度和速度(角度是必须的,若无速度则可以用刚刚下发的速度代替)。角度单位是度,速度无单位。如:

c)       CanOmniDrive,即全向驱动方法。使用该标记需要指定type为一个继承了OmniWriterClass的全向速度下发类。下发的速度会指定X速度、Y速度和旋转方向(旋转方向为逆时针旋转角度)。须开发者判断如何具体分解速度和旋转至各个舵轮或麦克纳姆轮上,若遇到奇点或限位问题(如舵轮角度已打满,须反向灯),也需要开发者自行计算。


指南2:如何定义动作并测试动作?动作将参数打包好并返回动作序列(为一个Generator函数),使得可以通过Clumsy的DriveTask进行管理。

1.     如使用内置的一些算法,如LeftRightWheelTracking(差速追踪模型),一个例子如下:

上述代码打包了在BSD10LSConfigs中定义的部分参数,随后可以继续对返回的LeftRightWheelTracking对象进行设置路径点操作,从而完成整套动作。

2.     可以设置一个UI按钮来测试定义的动作。如以下代码所示:

以上代码定义会在Clumsy界面中产生一个测试UI按钮:

接下来用户可在界面上拖拽来查看行走效果,从而进行调参。

3.     如果定义一些更简单的方法,如顶升等,则使用MovementDefinition来定义。该类的Get方法应是一个Generator函数,通过yield return true来表示动作计算完毕待下发,释放CPU资源并等到下一个周期再继续计算动作。这种方法可以使得动作编排足够紧凑,不需要复杂的状态机设计即可完成复杂的动作序列。如:

通过Get()方法返回一个IEnumerable<bool>对象后,可产生一个DriveTask类进行动作执行。例子如下:

4.     Clumsy使用了Nancy作为内置的HTTP服务器。若需要Clumsy额外提供接口给上下位应用,则可以编写一个WebAPIContainer类,并继承NancyModule,从而增加API。

5.     Clumsy若使用Simple作为调度系统,则需要实现AGV.cs类。类中包含所有调度能够使用的动作命令,一般至少包括一个行走命令(如可命名为Go)。

内置运动控制方法介绍见MDCS参考手册。

Simple开发介绍(待续)