Detour-API:修订间差异

来自MDCS wiki
跳到导航 跳到搜索
无编辑摘要
 
(未显示3个用户的19个中间版本)
第1行: 第1行:
== '''Detour''' ==
Detour使用HTTP方法提供API。以下为主要API的清单:


=== '''里程计暂停运行''' ===
<blockquote>'''Path:{ip}:4321/pause'''


'''Method:''' '''GET'''
= 1. 前言 =
Detour在4321端口启动Web API服务,为上层应用提供定位、配置和辅助功能。


'''接口描述:'''
= 2. 接口定义 =


'''请求(案例):'''<nowiki>http://127.0.0.1:4321/pause</nowiki>
== 2.1 定位 ==


'''返回(案例):'''<code>{"success":true,"id":0}</code></blockquote>
=== 2.1.1 读取位姿 ===
'''方法''':GET '''路径''':/getPos '''返回''':JSON


=== '''里程计恢复运行''' ===
举例:<syntaxhighlight lang="js">
<blockquote>'''Path:{ip}:4321/resume'''
GET http://127.0.0.1:4321/getPos


'''Method:''' '''GET'''
{
    "x": 190702.844, // 位置单位是毫米,使用直角坐标系
    "y": 336956.9,
    "th": 113.340424, // 角度单位是度
    "l_step": 27, // 定位步长,=2表示定位正常,=9999表示手动输入位置
      // >2表示回环失败,此时机器人位置附近的关键帧配准得分低于阈值,
      // 或关键帧计算出的位姿与当前位姿偏差过大而被过滤。l_step值
      // 越大表示回环失败时间越长。一般而言,在行驶时,可能存在
      // 短暂的激光SLAM定位不良区域,l_step<15可继续行驶,用
      // 激光里程计继续输出位姿,此时激光里程计累计误差较小。
      // l_step>15时应停车,重新定位成功后继续。
    "tick": 63855102200497 // 时间戳,系统时间的Tick
}


'''接口描述:'''
// 如果发生错误,比如激光雷达停止发送测量数据,则error属性
// 显示错误。使用位姿接口数据时,应校验error字段,如非null则位姿不可用。
{
    "x": 129163.734,
    "y": 416628.938,
    "th": 138.75148,
    "l_step": 200,
    "tick": 63855105852361,
    "error": "Timeout"
}
</syntaxhighlight>说明:


'''请求(案例):'''<nowiki>http://127.0.0.1:4321/resume</nowiki>
* 使用l_step判断建图质量。建图后遥控移动机器人沿工作路线走一圈,观察l_step值,由于不存在理想的SLAM环境,因此l_step值会短暂>2,一般<7以内可认为SLAM稳定工作。如在固定路段出现回环失败现象,则要考虑应对措施,比如用挡板改善环境轮廓、用反光棒切换到有反SLAM。
* 在运行时,可根据l_step结合运动状态判断“盲目行驶”风险,如l_step>15且在移动,应停车报警,恢复定位后继续行驶。l_step计算涉及多个因素,因此用范围来判断,如给出的<15区间,可根据实际情况调整区间使用。
* 激光SLAM以激光里程计输出位姿(x, y, theta)。激光里程计根据相邻激光雷达帧点云计算位移(距离和角度),积分以推算移动机器人航迹,激光里程计持续输出位姿。回环线程则搜索移动机器人附近的关键帧(路标),计算激光雷达帧点云与它们的配准程度,锁定配准得分高于阈值且最高的关键帧,以此修正激光里程计的累积误差,这个过程称为回环。l_step=2表示移动机器人当前位姿附近的关键帧被锁定,因而获得精确位置。l_step>2则表示回环失败,激光里程计继续输出位姿,但是关键帧锁定失败,因此累积误差不能消除,其值越大,输出位姿的误差性可能越大。l_step<15是我们给出的经验区间。


'''返回(案例):'''<code>{"success":true,"id":0}</code></blockquote>
=== 2.1.2 暂停定位 ===
'''方法''':GET '''路径''':/pause '''返回''':JSON


=== 执行Detour内部命令 ===
举例:<syntaxhighlight lang="js">
<blockquote>'''Path:{ip}:4321/call'''
GET http://127.0.0.1:4321/pause


'''Method:''' '''GET'''
{
    "success": true,
    "id": 0
}
</syntaxhighlight>说明:


'''接口描述:'''
* 与“恢复定位”接口配套使用。在Detour发布“紧耦合”特性之前,此接口用于暂停Detour定位功能(包括激光里程计和回环功能),改用目标跟随、巡线或轮里程计等其他定位手段行驶,通过特定场景后恢复定位,并用“指定位置重定位”功能重定位,以恢复激光SLAM功能。
* 暂停定位接口相当于关闭Detour,使其不再输出位姿,此时“读取位姿”接口将返回"timeout"错误。


参数:cmd,指令。类似于odometry_0.pause()。[主语].([参数列表...])
=== 2.1.3 恢复定位 ===
'''方法''':GET '''路径''':/resume '''返回''':JSON


'''请求(案例):'''http://127.0.0.1:4321/call?cmd=odometry_0.pause() 这表示调用odometry_0的pause方法(暂停指定里程计)。具体各个组件有哪些方法参考《[[Detour组件参考手册]]》
举例:<syntaxhighlight lang="js">
GET http://127.0.0.1:4321/resume


'''返回(案例):'''<code>{"result":"void"}</code></blockquote>
{
    "success": true,
    "id": 0
}
</syntaxhighlight>


=== '''获取当前车体在世界坐标系下的位姿''' ===
=== 2.1.4 全局重定位 ===
<blockquote>'''Path:{ip}:4321/getPos'''
'''方法''':GET '''路径'''/relocalize '''返回''':JSON


'''Method:''' '''GET'''
举例:<syntaxhighlight lang="js">
GET http://127.0.0.1:4321/relocalize


'''接口描述:'''
{
    "performed": true // 执行成功
}
</syntaxhighlight>说明:


'''请求:'''<nowiki>http://127.0.0.1:4321/getPos</nowiki>
* 全局重定位指令Detour搜索所有关键帧,取与当前点云配准分数最高者锁定,获得移动机器人当前位姿。如果点云与关键帧配准分数均低于阈值,则重定位失败。
* 全局重定位应用在环境轮廓稳定且有独特几何特征区域。如果环境轮廓与数个关键帧相似,且得分相差无几,则会定位到错误位置。建议在固定位置使用重定位接口,比如在干道旁设置固定的重定位站点。


'''返回(案例):'''<code>byte[] 下载成文件保存到本地</code></blockquote>
=== 2.1.5 指定位置重定位 ===
'''方法''':GET '''路径''':/setLocation '''返回''':JSON


=== 切换是否进行地图匹配 ===
举例:<syntaxhighlight lang="js">
<blockquote>'''Path:{ip}:4321/switchPosMatch'''
// 以(x, y, th)设定移动机器人当前位姿,注意它们都是float类型,值都应有小数点后1位。
// 激光里程计的航迹切到给定位姿。
// 如果给定位姿与实际位姿的距离过大,将导致回环失败(可锁定关键帧给出的观测位姿与当前位姿差
// 大于误差范围时,关键帧将被丢弃,见detour参数说明)。
GET http://127.0.0.1:4321/setLocation?x=100.0&y=100.0&th=90.0


'''Method:''' '''GET'''
{
    "x": 102.061165,
    "y": 97.67917,
    "th": 90.0271454,
    "l_step": 10000,
    "tick": 63855111242596
}
</syntaxhighlight>说明:


'''接口描述:'''
* 一般用于SLAM不良区域。比如潜伏式牵引车使用目标跟踪功能从料车缓存机构走出时(料车腿和缓存机构遮挡雷达视野而导致定位错误),指定位置使激光SLAM重新定位。


'''参数:'''
=== 2.1.6 指定关键帧回环 ===
'''方法''':GET '''路径''':/relocalize '''返回''':JSON


'''disabled:bool,是否关闭地图匹配'''
举例:<syntaxhighlight lang="js">
// 指示激光SLAM优先选用给定的关键帧。
// preferredKfId赋值为逗号分隔的关键帧Id集合。
// 给定的关键帧被列入优先选用集合,提高其匹配权重。
GET http://127.0.0.1:4321/setPreferredKFID?preferredKfiId=1130788673,1815389948


'''name:string,指定地图名称。不指定该参数则对所有图层生'''
{
    "success": true
}
</syntaxhighlight>说明:


'''请求(案例):'''<nowiki>http://127.0.0.1:4321/switchPosMatch</nowiki>
* 如果同一个站点的停准精度差异是锁定不同关键帧所致,可使用此接口指示激光SLAM选用特定的关键帧,以提高SLAM精度稳定性。在有限视野场景下(如180度激光雷达视野,或周围环境轮廓不良),可能会锁定不同关键帧(如站点前关键帧由于点云配准分数较低而未选用)而带来厘米级定位误差。此接口用于提高特定关键帧权重,以稳定锁定该关键帧,获得稳定的位姿。


'''返回(案例):'''<code>{"performed":true}</code></blockquote>
=== 2.1.7 启停回环功能 ===
'''方法''':GET '''路径''':/switchPosMatch '''返回''':JSON


=== '''使远端算法核将某指定图层当前的建图结果保存至文件''' ===
举例:<syntaxhighlight lang="js">
<blockquote>'''Path:{ip}:4321/setLocation'''
// 启用(或停用)给定图层的回环功能。
// disable=false表示启用,true表示停用。
// name是图层名称(单线激光SLAM标签的Lidar点云图层)
GET http://127.0.0.1:4321/switchPosMatch?disabled=false&name=mainmap


'''Method:''' '''GET'''
{
    "performed": true
}
</syntaxhighlight>说明:


'''接口描述:'''
* 停用给定图层的回环功能时,激光SLAM不再搜索该图层的关键帧。
* 本接口与暂停定位接口的差异在于,前者只是停用指定图层回环功能,激光里程计继续输出位姿;后者停止激光里程计和回环,输出位姿不可使用。


'''参数:'''  
=== 2.1.8 开启建图/锁定图层 ===
*'''方法''':GET '''路径''':/call?cmd=ground.SwitchMode(1) '''返回''':{"result":"void"}  举例:<syntaxhighlight lang="js">
// 开启或关闭建图
// 一般ground表示地纹图层名称,mainmap是激光图层名称
// 0是建图  1锁定图层
GET http:/call?cmd=ground.SwitchMode(1)
return
{
    "result":"void"
   
}
</syntaxhighlight>说明:
** 注意图层名称,开启建图和锁定UI界面的状态并不会变化。


x:float,x 坐标值
== 2.2 配置 ==


y:float,y 坐标值
=== 2.2.1 加载地图 ===
'''方法''':GET '''路径''':/loadMap '''返回''':JSON


th:float:角度值
举例:<syntaxhighlight lang="js">
// 指定图层加载激光地图。
// name是图层名称,fn是激光地图文件名称。
GET http://127.0.0.1:4321/loadMap?name=mainmap&fn=mainmap.2dlm


'''请求:'''<nowiki>http://127.0.0.1:4321/setLocation?x=1&y=2&th=3</nowiki>
{
    "performed": true,
    "success": false
}
</syntaxhighlight>说明:


'''返回(案例):'''<code>{"x":1.0,"y":2.0,"th":3.0,"l_step":9999,"tick":63832366282729,"error":"Timeout"}</code></blockquote>
* 可用于激光地图切换场景。比如移动机器人乘坐电梯到二楼时,把激光地图从一楼切换到二楼。


=== '''获取程序运行状态,包括里程计状态、地图状态等''' ===
=== 2.2.2 保存地图 ===
<blockquote>'''Path:{ip}:4321/getStat'''
'''方法''':GET '''路径'''/saveMap '''返回''':JSON


'''Method:''' '''GET'''
举例:<syntaxhighlight lang="js">
GET http://127.0.0.1:4321/saveMap?name=mainmap&fn=mainmap.2dlm


'''接口描述:'''
{
    "performed": true
}
</syntaxhighlight>说明:


'''请求:'''<nowiki>http://127.0.0.1:4321/getStat</nowiki>
* 图层的激光地图修改后,使用本接口将其存入激光地图文件。
2dlm地图格式可以参考该C#代码:[https://dev.lessokaji.com/index.php?topic=249.0 2dlm地图文件格式 (lessokaji.com])


'''返回(案例):'''<code><nowiki>{"layoutStat":{"w1":{},"w2":{},"frontlidar":{}},"odoStat":{},"posStat":{},"TCStat":{"fitmethod":0,"fitsource":"/","poseEstim":"/","TCVar":0.0},"GOStat":{"maxTension":0.0,"edgeN":0},"licence":"DID:40B38B8C111BD4EC","globalStat":{"paused":false,"IsSettingPosition":false}}</nowiki></code></blockquote>
=== 2.2.3 读取配置文件 ===
'''方法''':GET '''路径''':/getConf '''返回''':JSON


=== '''设置激光雷达的无效范围,在一系列点构成的闭包范围内的激光点将被忽略,这些点的坐标为车体坐标系下的值''' ===
举例:<syntaxhighlight lang="js">
<blockquote>'''Path:{ip}:4321/setLidar2DOdometryMask'''
GET http://127.0.0.1:4321/getConf


'''Method:''' '''POST'''
{
    "overrideLanguage": "/",
    "license": "",
    "initX": 15659.2,
    "initY": 2436.9,
    "initTh": 11.7,
    "recordLastPos": true,
    "layout": {
        "chassis": {
            "width": 1200.0,
            "length": 2000.0,
            "contour": [
                -445.0,
                330.0,
                445.0,
                330.0,
                445.0,
                -330.0,
                -445.0,
                -330.0
            ]
        },
        "components": [
        ]
    },
    "odometries": [
    ],
    "positioning": [
    ],
    "autoStart": true,
    "debug": true,
    "useGPU": true,
    "TCtimeWndSz": 150,
    "TCtimeWndLimit": 700,
    "useTC": true,
    "guru": {
        "SpatialIndex2StageCache": 4194304,
        "SpatialIndex1StageCache": 1048576,
        "ICPFastIterFac": 0.8,
        "ICPUseFastMode": false,
        "ICP2DMaxIter": 16,
        "RippleEnableEqualize": true,
        "Lidar2dMapMaxIter": 50,
        "phaseLockLvl": 3,
        "rotMapProjectionLength": 500.0,
        "gicp_p2pfac": 0.02,
        "extractPlaneThresE": 700.0,
        "lo3dlineWeightScale": 0.3,
        "inputScale": 1.0,
        "Lidar2DRippleDistDecay": 15000.0,
        "Lidar2DRippleScale": 1.0,
        "SI2DRectSmall": 130,
        "SI2DRectBig": 600,
        "TCVarMax": 1600.0,
        "TCMaxBadEdges": 3,
        "TCKalmanUseCurrentFac": 0.2,
        "debugReg2D": true,
        "ICP2ddebugSource": -1,
        "ICP2dReflexWeightTranslateFac": 3.0,
        "TCInterconnectType": 0,
        "TCAutoCaliberation": false,
        "dumpCriticalData": false,
        "dumpLocation": false,
        "logKeepDays": 7,
        "GOAllowSO3": false,
        "TCAllowSO3": true,
        "MaxTCIters": 1000,
        "GOStopMvmt": 1.0,
        "TCDiscardFactor": 0.4,
        "TCCouplingSigmaVXY": 0.2,
        "TCCouplingSigmaVTh": 0.5
    },
    "recordPosInterval": 500,
    "minimized": false
}
</syntaxhighlight>说明:


'''接口描述:'''
* 本接口返回Detour使用的配置文件内容,一般是detour.json。
* 可结合本接口和组件属性赋值接口实现激光雷达自动标定功能。首先读出配置,解析出要标定的激光雷达外参值(x, y, th),根据激光雷达外参标定方法实现移动机器人的标定行走功能,使用读取位姿、启停回环功能、组件属性赋值等接口计算并设置外参。


'''参数:'''
=== 2.2.4 组件属性赋值 ===
'''方法''':GET '''路径''':/set '''返回''':JSON


'''odometry:string,所设置的里程计名称字符串。'''
举例:<syntaxhighlight lang="js">
// 可设置以下组件的属性值:
//  - 车体部件。车体布局编辑器中列出的车体部件,一般是激光雷达,比如frontlidar。
//  - 里程计。里程计标签中的里程计。
//  - 地图。单线激光SLAM标签中的Lidar点云图层,比如mainmap。
// path是对象属性,本例是frontlidar.x,即激光雷达的x外参。
// val是值。
GET http://127.0.0.1:4321/set?path=frontlidar.x&val=500


'''Body:'''
{
    "success": true
}
</syntaxhighlight>说明:


'''一串 XY 坐标点构成的 json 字符串'''
* Detour使用该接口配置DetourLite参数。由于组件属性赋值不支持创建组件,因此在Detour创建激光雷达时,该雷达不会同步给DetourLite,进而触发对该雷达属性赋值时报“DetourLite参数设置错误”提示。


'''请求(案例):'''
=== 2.2.5 上传资源 ===
'''方法''':POST '''路径''':/uploadRes '''返回''':JSON


<code><nowiki>http://127.0.0.1:4321/setLidar2DOdometryMask?odometry=odometry_1</nowiki></code>
举例:<syntaxhighlight lang="js">
// fn是资源文件名。
// POST Body是上传的资源文件内容。
POST http://127.0.0.1:4321/uploadRes?fn=foo


<code>[{"X":123,"Y":456},{"X":123,"Y":456},{"X":123,"Y":456}]</code>
{
    "performed": true
}
</syntaxhighlight>说明:


'''返回(案例):'''
* 本接口可向Detour所在目录上传文件。比如激光地图文件。


<code>设置成功:{success: true}</code>
=== 2.2.6 下载资源 ===
'''方法''':GET '''路径''':/downloadRes '''返回''':字节流


<code>设置失败:{error=”No odometry named {指定里程计名称}”}</code></blockquote>
举例:<syntaxhighlight lang="js">
GET http://127.0.0.1:4321/downloadRes?fn=foo


=== '''将程序设置为debug模式运行,将输出debug日志文件''' ===
// 返回foo文件内容的字节流
<blockquote>'''Path:{ip}:4321/debug'''
</syntaxhighlight>


'''Method:''' '''GET'''
=== 2.2.7 保存导航配置 ===
'''方法''':Get'''路径''':/set '''返回''':JSON


'''接口描述:'''
举例:<syntaxhighlight lang="js">
//
// 比如保存雷达名称,就可以保存所有配置信息到本地了
Get http://127.0.0.1:4321/set?path=frontlidar.name&val=frontlidar


'''请求:'''<nowiki>http://127.0.0.1:4321/debug</nowiki>
{
    "performed": true
}
</syntaxhighlight>


'''返回(案例):'''<code>{"success":true"}</code></blockquote>


=== '''获取程序的配置参数''' ===
=== 2.2.8 外部加载二维码地图 ===
<blockquote>'''Path:{ip}:4321/getConf'''
'''方法''':Get'''路径''':/call?cmd=tagmap.load()'''返回''':JSON


'''Method:''' '''GET'''
举例:<syntaxhighlight lang="js">
// load 里面输入二维码地图路径即可
Get 127.0.0.1:4321/call?cmd=tagmap.load(d:/src/detour/build/fuck.json)


'''接口描述:'''
re
{
    "performed": true
}
</syntaxhighlight>


'''请求:'''<nowiki>http://127.0.0.1:4321/getConf</nowiki>
== 2.3 状态 ==


'''返回(案例):'''<code><nowiki>{"license":"","initX":0.0,"initY":0.0,"initTh":0.0,"recordLastPos":false,"layout":{"chassis":{"width":1200.0,"length":2000.0,"contour":[-445.0,330.0,445.0,330.0,445.0,-330.0,-445.0,-330.0]},"components":[{"type":"wheel,component,haveposition","options":{"platform":0,"scale":1.0,"radius":200.0,"id":1,"name":"w1","noMove":false,"time_bias_ms":0,"x":0.0,"y":300.0,"th":0.0,"z":0.0,"alt":0.0,"roll":0.0}},{"type":"wheel,component,haveposition","options":{"platform":6,"scale":1.0,"radius":200.0,"id":2,"name":"w2","noMove":false,"time_bias_ms":0,"x":0.0,"y":-300.0,"th":0.0,"z":0.0,"alt":0.0,"roll":0.0}},{"type":"lidar2d,component,haveposition","options":{"derr":20.0,"kerr":0.0,"isCircle":false,"angleSgn":1.0,"endAngle":0.0,"rangeStartAngle":-180.0,"rangeEndAngle":180.0,"afterImageFilterOutN":7,"afterImageFilterOutDeg":2.0,"ignoreDist":100.0,"maxDist":200000.0,"correctionType":"angle","dazzleWindow":5,"dazzleDist":80,"useNormalization":true,"useGridSelection":true,"gridSelSz":20.0,"useChassisFilter":true,"maxpoint":640,"useBilateralFilter":true,"useReflex":false,"removeReflex":false,"removeReflexDist":300.0,"minpointsN":20.0,"reflexThres":0.4,"reflexDiffThres":0.3,"reflexChunkThres":2.5,"reflexMutePadding":7,"reflexSize":100,"reflexDistRange":150.0,"invalidAngArrLen":128,"stepDebug":false,"id":1101520006,"name":"frontlidar","noMove":false,"time_bias_ms":0,"x":350.0,"y":0.0,"th":0.0,"z":0.0,"alt":0.0,"roll":0.0}}]},"odometries":[],"positioning":[],"autoStart":false,"debug":true,"useGPU":true,"TCtimeWndSz":150,"TCtimeWndLimit":700,"useTC":false,"guru":{"SpatialIndex2StageCache":4194304,"SpatialIndex1StageCache":1048576,"ICPFastIterFac":0.8,"ICPUseFastMode":false,"ICP2DMaxIter":16,"RippleEnableEqualize":true,"Lidar2dMapMaxIter":50,"TCAddIterations":50,"phaseLockLvl":3,"rotMapProjectionLength":500.0,"gicp_p2pfac":0.02,"extractPlaneThresE":700.0,"lo3dlineWeightScale":0.3,"inputScale":1.0,"Lidar2DRippleDistDecay":15000.0,"Lidar2DRippleScale":1.0,"SI2DRectSmall":130,"SI2DRectBig":600,"TCVarMax":1600.0,"TCMaxBadEdges":3,"TCKalmanUseCurrentFac":0.2,"debugReg2D":true,"ICP2ddebugSource":-1,"ICP2dReflexWeight":3.0,"ICP2dReflexWeightTranslateFac":3.0,"TCInterconnectType":0,"TCAutoCaliberation":false,"dumpCriticalData":true},"recordPosInterval":500,"preventErrorLocation":true,"minimized":false}</nowiki></code></blockquote>
=== 2.3.1 读取运行统计 ===
'''方法''':GET '''路径''':/getStat '''返回''':JSON


=== 进行一次全局匹配 ===
举例:<syntaxhighlight lang="js">
<blockquote>'''Path:{ip}:4321/relocalize'''
GET http://127.0.0.1:4321/getStat


'''Method:''' '''GET'''
{
    "runningSeconds": 878.7448942,
    "layoutStat": {
        "frontlidar": {
            "status": "等待帧",
            "lidar_tick": 2542,
            "interval": 77,
            "validPoints": 196,
            "preprocessTime": 0.0,
            "timeBudget": 81.036527022839024,
            "reflexN": 0.0,
            "selfFitting": 0.0
        },
        "cart_odometry": {
            "status": "初始化捕捉完毕",
            "use": true,
            "feedstate": "未开始捕获",
            "time": 0,
            "type": "/",
            "counter": 0,
            "pos": "/",
            "selfFitting": 0.0
        }
    },
    "odoStat": {
        "odometry_0": {
            "reg_ms": 6.0,
            "loop_ms": 136.0,
            "interval": 1,
            "reg_mode": 0,
            "kf_state": "10011/+1",
            "SeqScore": 0.950587451,
            "LOScore": 0.9299651,
            "kfreason": ".",
            "otherDebug": "",
            "status": "waitframe",
            "pause": false
        }
    },
    "posStat": {},
    "TCStat": {
        "commitId": 1394,
        "computeStat": "tcfrontlidar...tp",
        "fitmethod": 1,
        "goIters": 0,
        "discarding": "",
        "fitexplain": "frontlidar:5L/1.61",
        "poseEstim": "/",
        "TCPerf": "rigid:0.054,go:0.0622,post:0.0188",
        "CouplingScores": "frontlidar(5):1.00/1.00",
        "TCVar": 0.0,
        "err": 0.0,
        "historyLs": "frontlidar:N1/5",
        "powers": "True:(,()"
    },
    "GOStat": {
        "maxTension": 0.0,
        "edgeN": 0,
        "OPS": 8,
        "Use": true
    },
    "licence": "DID:4D222EB2BEE27897",
    "globalStat": {
        "paused": false,
        "IsSettingPosition": false
    }
}
</syntaxhighlight>说明:


'''接口描述:'''
* 返回结果与Detour上相应对象的状态一致。


'''请求:'''<nowiki>http://127.0.0.1:4321/relocalize</nowiki>
=== 2.3.2 导出工作区 ===
'''方法''':GET '''路径''':/dumpWorkspace '''返回''':JSON


'''返回(案例):'''<code>{performed: true}</code></blockquote>
举例:<syntaxhighlight lang="js">
GET http://127.0.0.1:4321/dumpWorkspace


=== '''使远端算法核加载远端已保存的某个地图''' ===
OK
<blockquote>'''Path:{ip}:4321/loadMap'''
</syntaxhighlight>说明:


'''Method:''' '''GET'''
* 在Detour的log/workspace目录下生成图像日志,包括一张PNG图片,内容为Detour主界面的地图;一个运行日志文件。


'''接口描述:'''
=== 2.3.3 读取点云 ===
'''方法''':GET '''路径''':/getSensors '''返回''':字节流


'''参数:'''
举例:<syntaxhighlight lang="js">
GET http://127.0.0.1:4321/getSensors


name:string,指定的图层名称,默认为 mainmap
// 返回字节流是点云数据,伪代码表述格式如下:
[
{ // 激光雷达
lidar.name : String; // 雷达名称,C# String类型
keyFrame.x : float; // 关键帧位姿
keyFrame.y : float;
keyFrame.th : float;
pointCloud.length : int; // 点云数组长度
[
point.x : float; // 测量点坐标
            point.y : float;
]
}
]
</syntaxhighlight>说明:


fn:string,指定加载的地图文件名称,默认为 mainmap.2dlm
* Detour使用此接口读取DetourLite点云数据。
* 调用该接口的频率应控制在2Hz以内,以免干扰Detour内核计算性能。
* 非必要不使用原则。如,在丢定位时(如l_step>15),在管控的维护功能界面显示点云,以帮助操作者识别移动机器人实际位姿,然后使用指定位置重定位接口找回定位。在这个场景中,只需在处理定位问题时读取点云,处理完毕后停止调用接口。


'''请求:'''<nowiki>http://127.0.0.1:4321/loadMap?name=mainmap&fn=</nowiki> mainmap.2dlm
=== 2.3.4 读取版本 ===
'''方法''':GET '''路径''':/getVersion '''返回''':JSON


'''返回(案例):'''<code>{performed: true}</code></blockquote>
举例:<syntaxhighlight lang="js">
GET http://127.0.0.1:4321/getVersion


=== '''使远端算法核将某指定图层当前的建图结果保存至文件''' ===
shicong-liu@2024-06-26T13:25:22+08|master_b8dc
<blockquote>'''Path:{ip}:4321/saveMap'''
</syntaxhighlight>


'''Method:''' '''GET'''
== 2.4 操作 ==


'''接口描述:'''
=== 2.4.1 调用方法 ===
'''方法''':GET '''路径''':/call '''返回''':JSON


'''参数:'''
举例:<syntaxhighlight lang="js">
// 调用对象方法。
// cmd是对象方法。本例是调用cart_odometry.capture()方法,即
// 触发外部定位源cart_odometry(轮里程计)的捕获方法。
GET http://127.0.0.1:4321/call?cmd=cart_odometry.capture()


name:string,指定的图层名称,默认为 mainmap
// 返回该方法的返回值
{
    "result": "void"
}
</syntaxhighlight>说明:


fn:string,指定加载的地图文件名称,默认为 mainmap.2dlm
* 本接口相当于RPC(Remote Procedure Call)调用。应根据代码调用。


'''请求:'''<nowiki>http://127.0.0.1:4321/saveMap?name=mainmap&fn=</nowiki> mainmap.2dlm
=== 2.4.2 设置激光雷达蒙板 ===
'''方法''':POST '''路径''':/setLidar2DOdometryMask '''返回''':JSON


'''返回(案例):'''<code>{performed: true}</code></blockquote>
举例:<syntaxhighlight lang="js">
// odometry是里程计标签中的里程计名称。本例的odometry_0是默认激光里程计名称。
// POST Body是蒙板顶点数组,用于构造出封闭多边形,落在多边形内的点云都会被过滤。
POST http://127.0.0.1:4321/setLidar2DOdometryMask?odometry=odometry_0
[
    {
        "X": 123,
        "Y": 456
    },
    {
        "X": 123,
        "Y": 456
    },
    {
        "X": 123,
        "Y": 456
    }
]


=== 以PNG格式返回激光地图 ===
{
<blockquote>'''Path:{ip}:4321/getMapPng?width=800&height=600&centerX=0&centerY=0&scale=0.01'''
    "success": true
}
</syntaxhighlight>说明:


'''Method:''' '''GET'''
* 本接口只影响内存中的配置,不会存入配置文件。
* 坐标参考车体编辑器,直角坐标系的原点在底盘几何中心。


'''接口描述:'''
= 2.4 定位 =


'''参数:'''
=== 2.4.1 外部定位源 ===
输入外部定位源前,首先要在车体编辑器里增加对应的“外部定位源”部件


width:int,PNG宽度
'''方法''':POST '''路径''':/postExternPosition '''返回''':JSON


height:int,PNG高度
举例:<syntaxhighlight lang="js">
// name是外部定位源。本例的cart_odometry是IMU轮里程计。
// POST Body是外部定位源的航迹。
POST http://127.0.0.1:4321/postExternPosition?name=cart_odometry
{
  "name": "cart_odometry", // 轮里程计+IMU对应在Detour中的部件名
  "counter": 0, // 单调+1
  "hasTranslation": true, // 可移动,(x, y)
  "hasRotation": true, // 可旋转,(th)
  "is3D": false, // 在三维平面运动,输出(x, y, z, th)
  "is2D": true, // 在二维平面运动,输出(x, y, th)
  "integrated": true, // 是否通过积分得到的位姿(轮里程计通过积分获得,gps是绝对位置)
  "startingTick": 0, // 时间戳,不变则表示这是一条航迹。程序启动时可用系统Ticks为初始值
  "x": 0.0,   // 当前位姿
  "y": 0.0,
  "z": 0.0,   // 二维平面的z总是0
  "th": 0.0,
}


centerX & centerY:int,地图中心坐标
{
    "performed": true
}
</syntaxhighlight>
说明:


scale:float,地图缩放比例
* 向Detour推送外部定位源的位姿。外部定位源一般是IMU轮里程计、GNSS RTK。Detour紧耦合功能融合多个里程计,择优输出一个位姿。
* IMU轮里程计的位姿发布频率建议20Hz(经测试获得的经验值)。
* 外部定位源的inputType="web",默认是"internal"(表示从Medulla发布)。设置错误将导致接口调用失败。
* 集成外部定位源时,应测试其发布频率,以免过快或过慢频率干扰紧耦合错误选用里程计。
* 以下是外部定位源表:
{| class="wikitable"
|+定位源类型和设置方法
!
!hasTranslation
!hasRotation
!is3D
!is2D
!integrated
!toRemap
|-
|GNSS定位
|true
|true
如果有的话
|false
|true
|false
|true
经纬度-地图位置需要标定:[[使用手册 - 卫星或基站定位标定|使用手册]]
|-
|轮编里程计(须自行融合IMU)
|true
|true
|false
|true
|true
须自行积分,直接从0开始积分即可
|
|}


'''请求:'''<nowiki>http://127.0.0.1:4321/getMapPng?width=800&height=600&centerX=0&centerY=0&scale=0.01</nowiki>
=== 2.4.2 外部二维码输入 ===
'''方法''':Get'''路径''':/call?cmd=lesstag.inputextern(id,x,y,th) '''返回''':JSON


'''返回(案例):PNG字节流'''</blockquote>
举例:<syntaxhighlight lang="js">
// id,x,y,th分别表示二维码的tag,xyth数值。
Get http://127.0.0.1:4321/call?cmd=lesstag.inputextern(id,x,y,th)
{
    "result": true
}
</syntaxhighlight>
说明:


=== 开启或关闭图优化 ===
* 配置此项功能需要把D参数中二维码配置useExtern改成true才可以生效
<blockquote>'''Path:{ip}:4321/set?path=graphoptimizer.Use&val=false'''
 
'''Method:''' '''GET'''
 
'''接口描述:'''
 
'''参数:'''
 
'''val''':bool,开启、关闭
 
'''请求:'''<nowiki>http://127.0.0.1:4321/set?path=graphoptimizer.Use&val=false</nowiki>
 
'''返回(案例):'''</blockquote>开启或关闭图优化<blockquote>'''Path:{ip}:4321/call?cmd=mainmap.haveneighborframes()'''
 
'''Method:''' '''GET'''
 
'''接口描述:'''
 
'''参数:无'''
 
'''请求:'''<nowiki>http://127.0.0.1:4321/call?cmd=mainmap.haveneighborframes()</nowiki>
 
'''返回(案例):<code>{"result":false}</code>'''</blockquote>

2025年4月28日 (一) 16:34的最新版本


1. 前言

Detour在4321端口启动Web API服务,为上层应用提供定位、配置和辅助功能。

2. 接口定义

2.1 定位

2.1.1 读取位姿

方法:GET 路径:/getPos 返回:JSON

举例:

GET http://127.0.0.1:4321/getPos

{
    "x": 190702.844,		// 位置单位是毫米,使用直角坐标系
    "y": 336956.9,
    "th": 113.340424,		// 角度单位是度
    "l_step": 27,			// 定位步长,=2表示定位正常,=9999表示手动输入位置
    					   // >2表示回环失败,此时机器人位置附近的关键帧配准得分低于阈值,
    					   // 或关键帧计算出的位姿与当前位姿偏差过大而被过滤。l_step值
    					   // 越大表示回环失败时间越长。一般而言,在行驶时,可能存在
    					   // 短暂的激光SLAM定位不良区域,l_step<15可继续行驶,用
    					   // 激光里程计继续输出位姿,此时激光里程计累计误差较小。
    					   // l_step>15时应停车,重新定位成功后继续。
    "tick": 63855102200497	// 时间戳,系统时间的Tick
}

// 如果发生错误,比如激光雷达停止发送测量数据,则error属性
// 显示错误。使用位姿接口数据时,应校验error字段,如非null则位姿不可用。
{
    "x": 129163.734,
    "y": 416628.938,
    "th": 138.75148,
    "l_step": 200,
    "tick": 63855105852361,
    "error": "Timeout"
}

说明:

  • 使用l_step判断建图质量。建图后遥控移动机器人沿工作路线走一圈,观察l_step值,由于不存在理想的SLAM环境,因此l_step值会短暂>2,一般<7以内可认为SLAM稳定工作。如在固定路段出现回环失败现象,则要考虑应对措施,比如用挡板改善环境轮廓、用反光棒切换到有反SLAM。
  • 在运行时,可根据l_step结合运动状态判断“盲目行驶”风险,如l_step>15且在移动,应停车报警,恢复定位后继续行驶。l_step计算涉及多个因素,因此用范围来判断,如给出的<15区间,可根据实际情况调整区间使用。
  • 激光SLAM以激光里程计输出位姿(x, y, theta)。激光里程计根据相邻激光雷达帧点云计算位移(距离和角度),积分以推算移动机器人航迹,激光里程计持续输出位姿。回环线程则搜索移动机器人附近的关键帧(路标),计算激光雷达帧点云与它们的配准程度,锁定配准得分高于阈值且最高的关键帧,以此修正激光里程计的累积误差,这个过程称为回环。l_step=2表示移动机器人当前位姿附近的关键帧被锁定,因而获得精确位置。l_step>2则表示回环失败,激光里程计继续输出位姿,但是关键帧锁定失败,因此累积误差不能消除,其值越大,输出位姿的误差性可能越大。l_step<15是我们给出的经验区间。

2.1.2 暂停定位

方法:GET 路径:/pause 返回:JSON

举例:

GET http://127.0.0.1:4321/pause

{
    "success": true,
    "id": 0
}

说明:

  • 与“恢复定位”接口配套使用。在Detour发布“紧耦合”特性之前,此接口用于暂停Detour定位功能(包括激光里程计和回环功能),改用目标跟随、巡线或轮里程计等其他定位手段行驶,通过特定场景后恢复定位,并用“指定位置重定位”功能重定位,以恢复激光SLAM功能。
  • 暂停定位接口相当于关闭Detour,使其不再输出位姿,此时“读取位姿”接口将返回"timeout"错误。

2.1.3 恢复定位

方法:GET 路径:/resume 返回:JSON

举例:

GET http://127.0.0.1:4321/resume

{
    "success": true,
    "id": 0
}

2.1.4 全局重定位

方法:GET 路径:/relocalize 返回:JSON

举例:

GET http://127.0.0.1:4321/relocalize

{
    "performed": true		// 执行成功
}

说明:

  • 全局重定位指令Detour搜索所有关键帧,取与当前点云配准分数最高者锁定,获得移动机器人当前位姿。如果点云与关键帧配准分数均低于阈值,则重定位失败。
  • 全局重定位应用在环境轮廓稳定且有独特几何特征区域。如果环境轮廓与数个关键帧相似,且得分相差无几,则会定位到错误位置。建议在固定位置使用重定位接口,比如在干道旁设置固定的重定位站点。

2.1.5 指定位置重定位

方法:GET 路径:/setLocation 返回:JSON

举例:

// 以(x, y, th)设定移动机器人当前位姿,注意它们都是float类型,值都应有小数点后1位。
// 激光里程计的航迹切到给定位姿。
// 如果给定位姿与实际位姿的距离过大,将导致回环失败(可锁定关键帧给出的观测位姿与当前位姿差
// 大于误差范围时,关键帧将被丢弃,见detour参数说明)。
GET http://127.0.0.1:4321/setLocation?x=100.0&y=100.0&th=90.0

{
    "x": 102.061165,
    "y": 97.67917,
    "th": 90.0271454,
    "l_step": 10000,
    "tick": 63855111242596
}

说明:

  • 一般用于SLAM不良区域。比如潜伏式牵引车使用目标跟踪功能从料车缓存机构走出时(料车腿和缓存机构遮挡雷达视野而导致定位错误),指定位置使激光SLAM重新定位。

2.1.6 指定关键帧回环

方法:GET 路径:/relocalize 返回:JSON

举例:

// 指示激光SLAM优先选用给定的关键帧。
// preferredKfId赋值为逗号分隔的关键帧Id集合。
// 给定的关键帧被列入优先选用集合,提高其匹配权重。
GET http://127.0.0.1:4321/setPreferredKFID?preferredKfiId=1130788673,1815389948

{
    "success": true
}

说明:

  • 如果同一个站点的停准精度差异是锁定不同关键帧所致,可使用此接口指示激光SLAM选用特定的关键帧,以提高SLAM精度稳定性。在有限视野场景下(如180度激光雷达视野,或周围环境轮廓不良),可能会锁定不同关键帧(如站点前关键帧由于点云配准分数较低而未选用)而带来厘米级定位误差。此接口用于提高特定关键帧权重,以稳定锁定该关键帧,获得稳定的位姿。

2.1.7 启停回环功能

方法:GET 路径:/switchPosMatch 返回:JSON

举例:

// 启用(或停用)给定图层的回环功能。
// disable=false表示启用,true表示停用。
// name是图层名称(单线激光SLAM标签的Lidar点云图层)
GET http://127.0.0.1:4321/switchPosMatch?disabled=false&name=mainmap

{
    "performed": true
}

说明:

  • 停用给定图层的回环功能时,激光SLAM不再搜索该图层的关键帧。
  • 本接口与暂停定位接口的差异在于,前者只是停用指定图层回环功能,激光里程计继续输出位姿;后者停止激光里程计和回环,输出位姿不可使用。

2.1.8 开启建图/锁定图层

  • 方法:GET 路径:/call?cmd=ground.SwitchMode(1) 返回:{"result":"void"} 举例:
    // 开启或关闭建图
    // 一般ground表示地纹图层名称,mainmap是激光图层名称
    // 0是建图  1锁定图层
    GET http:/call?cmd=ground.SwitchMode(1)
    return
    {
        "result":"void"
        
    }
    
    说明:
    • 注意图层名称,开启建图和锁定UI界面的状态并不会变化。

2.2 配置

2.2.1 加载地图

方法:GET 路径:/loadMap 返回:JSON

举例:

// 指定图层加载激光地图。
// name是图层名称,fn是激光地图文件名称。
GET http://127.0.0.1:4321/loadMap?name=mainmap&fn=mainmap.2dlm

{
    "performed": true,
    "success": false
}

说明:

  • 可用于激光地图切换场景。比如移动机器人乘坐电梯到二楼时,把激光地图从一楼切换到二楼。

2.2.2 保存地图

方法:GET 路径:/saveMap 返回:JSON

举例:

GET http://127.0.0.1:4321/saveMap?name=mainmap&fn=mainmap.2dlm

{
    "performed": true
}

说明:

  • 图层的激光地图修改后,使用本接口将其存入激光地图文件。

2dlm地图格式可以参考该C#代码:2dlm地图文件格式 (lessokaji.com)

2.2.3 读取配置文件

方法:GET 路径:/getConf 返回:JSON

举例:

GET http://127.0.0.1:4321/getConf

{
    "overrideLanguage": "/",
    "license": "",
    "initX": 15659.2,
    "initY": 2436.9,
    "initTh": 11.7,
    "recordLastPos": true,
    "layout": {
        "chassis": {
            "width": 1200.0,
            "length": 2000.0,
            "contour": [
                -445.0,
                330.0,
                445.0,
                330.0,
                445.0,
                -330.0,
                -445.0,
                -330.0
            ]
        },
        "components": [
        ]
    },
    "odometries": [
    ],
    "positioning": [
     ],
    "autoStart": true,
    "debug": true,
    "useGPU": true,
    "TCtimeWndSz": 150,
    "TCtimeWndLimit": 700,
    "useTC": true,
    "guru": {
        "SpatialIndex2StageCache": 4194304,
        "SpatialIndex1StageCache": 1048576,
        "ICPFastIterFac": 0.8,
        "ICPUseFastMode": false,
        "ICP2DMaxIter": 16,
        "RippleEnableEqualize": true,
        "Lidar2dMapMaxIter": 50,
        "phaseLockLvl": 3,
        "rotMapProjectionLength": 500.0,
        "gicp_p2pfac": 0.02,
        "extractPlaneThresE": 700.0,
        "lo3dlineWeightScale": 0.3,
        "inputScale": 1.0,
        "Lidar2DRippleDistDecay": 15000.0,
        "Lidar2DRippleScale": 1.0,
        "SI2DRectSmall": 130,
        "SI2DRectBig": 600,
        "TCVarMax": 1600.0,
        "TCMaxBadEdges": 3,
        "TCKalmanUseCurrentFac": 0.2,
        "debugReg2D": true,
        "ICP2ddebugSource": -1,
        "ICP2dReflexWeightTranslateFac": 3.0,
        "TCInterconnectType": 0,
        "TCAutoCaliberation": false,
        "dumpCriticalData": false,
        "dumpLocation": false,
        "logKeepDays": 7,
        "GOAllowSO3": false,
        "TCAllowSO3": true,
        "MaxTCIters": 1000,
        "GOStopMvmt": 1.0,
        "TCDiscardFactor": 0.4,
        "TCCouplingSigmaVXY": 0.2,
        "TCCouplingSigmaVTh": 0.5
    },
    "recordPosInterval": 500,
    "minimized": false
}

说明:

  • 本接口返回Detour使用的配置文件内容,一般是detour.json。
  • 可结合本接口和组件属性赋值接口实现激光雷达自动标定功能。首先读出配置,解析出要标定的激光雷达外参值(x, y, th),根据激光雷达外参标定方法实现移动机器人的标定行走功能,使用读取位姿、启停回环功能、组件属性赋值等接口计算并设置外参。

2.2.4 组件属性赋值

方法:GET 路径:/set 返回:JSON

举例:

// 可设置以下组件的属性值:
//   - 车体部件。车体布局编辑器中列出的车体部件,一般是激光雷达,比如frontlidar。
//   - 里程计。里程计标签中的里程计。
//   - 地图。单线激光SLAM标签中的Lidar点云图层,比如mainmap。
// path是对象属性,本例是frontlidar.x,即激光雷达的x外参。
// val是值。
GET http://127.0.0.1:4321/set?path=frontlidar.x&val=500

{
    "success": true
}

说明:

  • Detour使用该接口配置DetourLite参数。由于组件属性赋值不支持创建组件,因此在Detour创建激光雷达时,该雷达不会同步给DetourLite,进而触发对该雷达属性赋值时报“DetourLite参数设置错误”提示。

2.2.5 上传资源

方法:POST 路径:/uploadRes 返回:JSON

举例:

// fn是资源文件名。
// POST Body是上传的资源文件内容。
POST http://127.0.0.1:4321/uploadRes?fn=foo

{
    "performed": true
}

说明:

  • 本接口可向Detour所在目录上传文件。比如激光地图文件。

2.2.6 下载资源

方法:GET 路径:/downloadRes 返回:字节流

举例:

GET http://127.0.0.1:4321/downloadRes?fn=foo

// 返回foo文件内容的字节流

2.2.7 保存导航配置

方法:Get路径:/set 返回:JSON

举例:

// 
// 比如保存雷达名称,就可以保存所有配置信息到本地了
Get http://127.0.0.1:4321/set?path=frontlidar.name&val=frontlidar

{
    "performed": true
}


2.2.8 外部加载二维码地图

方法:Get路径:/call?cmd=tagmap.load()返回:JSON

举例:

// load 里面输入二维码地图路径即可
Get 127.0.0.1:4321/call?cmd=tagmap.load(d:/src/detour/build/fuck.json)

re
{
    "performed": true
}

2.3 状态

2.3.1 读取运行统计

方法:GET 路径:/getStat 返回:JSON

举例:

GET http://127.0.0.1:4321/getStat

{
    "runningSeconds": 878.7448942,
    "layoutStat": {
        "frontlidar": {
            "status": "等待帧",
            "lidar_tick": 2542,
            "interval": 77,
            "validPoints": 196,
            "preprocessTime": 0.0,
            "timeBudget": 81.036527022839024,
            "reflexN": 0.0,
            "selfFitting": 0.0
        },
        "cart_odometry": {
            "status": "初始化捕捉完毕",
            "use": true,
            "feedstate": "未开始捕获",
            "time": 0,
            "type": "/",
            "counter": 0,
            "pos": "/",
            "selfFitting": 0.0
        }
    },
    "odoStat": {
        "odometry_0": {
            "reg_ms": 6.0,
            "loop_ms": 136.0,
            "interval": 1,
            "reg_mode": 0,
            "kf_state": "10011/+1",
            "SeqScore": 0.950587451,
            "LOScore": 0.9299651,
            "kfreason": ".",
            "otherDebug": "",
            "status": "waitframe",
            "pause": false
        }
    },
    "posStat": {},
    "TCStat": {
        "commitId": 1394,
        "computeStat": "tcfrontlidar...tp",
        "fitmethod": 1,
        "goIters": 0,
        "discarding": "",
        "fitexplain": "frontlidar:5L/1.61",
        "poseEstim": "/",
        "TCPerf": "rigid:0.054,go:0.0622,post:0.0188",
        "CouplingScores": "frontlidar(5):1.00/1.00",
        "TCVar": 0.0,
        "err": 0.0,
        "historyLs": "frontlidar:N1/5",
        "powers": "True:(,()"
    },
    "GOStat": {
        "maxTension": 0.0,
        "edgeN": 0,
        "OPS": 8,
        "Use": true
    },
    "licence": "DID:4D222EB2BEE27897",
    "globalStat": {
        "paused": false,
        "IsSettingPosition": false
    }
}

说明:

  • 返回结果与Detour上相应对象的状态一致。

2.3.2 导出工作区

方法:GET 路径:/dumpWorkspace 返回:JSON

举例:

GET http://127.0.0.1:4321/dumpWorkspace

OK

说明:

  • 在Detour的log/workspace目录下生成图像日志,包括一张PNG图片,内容为Detour主界面的地图;一个运行日志文件。

2.3.3 读取点云

方法:GET 路径:/getSensors 返回:字节流

举例:

GET http://127.0.0.1:4321/getSensors

// 返回字节流是点云数据,伪代码表述格式如下:
[
	{	// 激光雷达
		lidar.name : String;	// 雷达名称,C# String类型
		keyFrame.x : float;		// 关键帧位姿
		keyFrame.y : float;
		keyFrame.th : float;
		pointCloud.length : int;	// 点云数组长度
		[
			point.x : float;	// 测量点坐标
             point.y : float;
		]
	}
]

说明:

  • Detour使用此接口读取DetourLite点云数据。
  • 调用该接口的频率应控制在2Hz以内,以免干扰Detour内核计算性能。
  • 非必要不使用原则。如,在丢定位时(如l_step>15),在管控的维护功能界面显示点云,以帮助操作者识别移动机器人实际位姿,然后使用指定位置重定位接口找回定位。在这个场景中,只需在处理定位问题时读取点云,处理完毕后停止调用接口。

2.3.4 读取版本

方法:GET 路径:/getVersion 返回:JSON

举例:

GET http://127.0.0.1:4321/getVersion

shicong-liu@2024-06-26T13:25:22+08|master_b8dc

2.4 操作

2.4.1 调用方法

方法:GET 路径:/call 返回:JSON

举例:

// 调用对象方法。
// cmd是对象方法。本例是调用cart_odometry.capture()方法,即
// 触发外部定位源cart_odometry(轮里程计)的捕获方法。
GET http://127.0.0.1:4321/call?cmd=cart_odometry.capture()

// 返回该方法的返回值
{
    "result": "void"
}

说明:

  • 本接口相当于RPC(Remote Procedure Call)调用。应根据代码调用。

2.4.2 设置激光雷达蒙板

方法:POST 路径:/setLidar2DOdometryMask 返回:JSON

举例:

// odometry是里程计标签中的里程计名称。本例的odometry_0是默认激光里程计名称。
// POST Body是蒙板顶点数组,用于构造出封闭多边形,落在多边形内的点云都会被过滤。
POST http://127.0.0.1:4321/setLidar2DOdometryMask?odometry=odometry_0
[
    {
        "X": 123,
        "Y": 456
    },
    {
        "X": 123,
        "Y": 456
    },
    {
        "X": 123,
        "Y": 456
    }
]

{
    "success": true
}

说明:

  • 本接口只影响内存中的配置,不会存入配置文件。
  • 坐标参考车体编辑器,直角坐标系的原点在底盘几何中心。

2.4 定位

2.4.1 外部定位源

输入外部定位源前,首先要在车体编辑器里增加对应的“外部定位源”部件

方法:POST 路径:/postExternPosition 返回:JSON

举例:

// name是外部定位源。本例的cart_odometry是IMU轮里程计。
// POST Body是外部定位源的航迹。
POST http://127.0.0.1:4321/postExternPosition?name=cart_odometry
{
  "name": "cart_odometry",	// 轮里程计+IMU对应在Detour中的部件名
  "counter": 0,				// 单调+1
  "hasTranslation": true,	 // 可移动,(x, y) 
  "hasRotation": true,		// 可旋转,(th)
  "is3D": false,			// 在三维平面运动,输出(x, y, z, th)
  "is2D": true,				// 在二维平面运动,输出(x, y, th)
  "integrated": true,	// 是否通过积分得到的位姿(轮里程计通过积分获得,gps是绝对位置)
  "startingTick": 0,		// 时间戳,不变则表示这是一条航迹。程序启动时可用系统Ticks为初始值
  "x": 0.0,				   // 当前位姿
  "y": 0.0,
  "z": 0.0,				   // 二维平面的z总是0
  "th": 0.0,
}

{
    "performed": true
}

说明:

  • 向Detour推送外部定位源的位姿。外部定位源一般是IMU轮里程计、GNSS RTK。Detour紧耦合功能融合多个里程计,择优输出一个位姿。
  • IMU轮里程计的位姿发布频率建议20Hz(经测试获得的经验值)。
  • 外部定位源的inputType="web",默认是"internal"(表示从Medulla发布)。设置错误将导致接口调用失败。
  • 集成外部定位源时,应测试其发布频率,以免过快或过慢频率干扰紧耦合错误选用里程计。
  • 以下是外部定位源表:
定位源类型和设置方法
hasTranslation hasRotation is3D is2D integrated toRemap
GNSS定位 true true

如果有的话

false true false true

经纬度-地图位置需要标定:使用手册

轮编里程计(须自行融合IMU) true true false true true

须自行积分,直接从0开始积分即可

2.4.2 外部二维码输入

方法:Get路径:/call?cmd=lesstag.inputextern(id,x,y,th) 返回:JSON

举例:

// id,x,y,th分别表示二维码的tag,xyth数值。
Get http://127.0.0.1:4321/call?cmd=lesstag.inputextern(id,x,y,th)
{
    "result": true
}

说明:

  • 配置此项功能需要把D参数中二维码配置useExtern改成true才可以生效