debug engine 调试引擎

调试界面

Client 分为三个展示的界面分别有不同的用途:

  • Origin 显示基本信息:车号+球
  • Filtered B 显示蓝队信息:蓝队车目标点+行驶到目标点的轨迹
  • Filtered Y 显示黄队信息:黄队车目标点+行驶到目标点的轨迹

Origin 还会显示边界线和摄影机的位置,Filtered 还会显示当前 Medusa 执行的 play 文件、state 状态以及运行模式

Client 会将 Medusa 接收到的信息进行绘制

为了方便调试 Client 会将 Medusa 实时计算的相关信息在界面上绘制出来

  • 绘制的类型包括

    • 文字——比如 state 和文件名
    • 点——用 × 表示
    • 线段——连接机器人和目标点
    • 圆环
    • 机器人 Shadow
  • 绘制的颜色:

    • 简易:0~9,默认为 1(红色),其他如 0 (白色)
    • 复杂:RGB 显示
  • 设置文件位置:/rocos/Medusa/share/proto 下装在了与通讯相关的 proto 文件,上述内容均定义在 /rocos/Medusa/share/proto/zss_debug.proto

debug 演示

  1. Config.lua 中修改当前 gTestPlayTestDribbleAndKick (找到球并射门)
  2. 先在 Client 第四栏参数配置中修改 DeviceMsg 为 true
  3. 再在 Client 设置蓝队一辆小车并打开 Medusa 执行
  4. 运行时将 Client 第三栏中的录制按钮打开录制一段 log
  5. 运行结束后先关闭 Client 第一栏参数配置中 Vision 的连接再回放查看日志

DeviceMsg 输出说明

每一列展示的是某辆小车的信息,由于日志文件可以一帧一帧的查看所以每个小车分为的五个信息也是对应每一帧:

  • Fraredoff:连续未接受红外的帧数

  • Fraredon:连续触发红外的帧数

  • Chipkick:挑射,1 表示执行该动作,0 表示不执行

  • Flatkick:平射,1 表示执行该动作,0 表示不执行

  • Infrared:红外触发,1表示已触发,0表示未触发

调试方法

调试策略

一般最理想的调试方法是对于不同的状态设置在界面绘制一个点或者打印一个字符串,我们可以借助 debugEngine 的函数设置不同信息的绘制

调试介绍

Lua 和 C++ 的交互文件:global.pkg,这个文件对 C++ 可用的接口定义了在 lua 中的变量名,这里可以看到有 debugEngine 对应的是 C++ 中的 CGDebugEngine 类型

dubug 工作原理:Medusa 层使用 upd+protobuf 获取数据并压缩传送给 Client 层,Client 层使用 field.cpp 进行解包(drawDebugMessages 函数:各种 case 的处理)

调试使用

输出变量、play、state、target 或者 role 的值

调试调用的函数接口可以在 gdebugengine.pkg 文件中查询

调用位置:由于 switch 的逻辑是逐帧调用,所以一般在 swich 语句中调用调试函数的接口或者定义一个调试函数然后放在 switch 语句中

输出视觉信息

可查询相关视觉信息的函数接口:

  • player.lua 我方机器人信息
  • enemy.lua 对方机器人信息
  • ball.lua 球的信息

输出路径规划和染色图

涉及底层代码的修改,以目前学习水平了解即可

路径规划使用的简单的 RT 框架(Client 可显示的数据结构),可以满足当前简单的壁障

调试 play

  • 当有多个机器人信息需要调试的时候,可以借助日志回放的录制 Rec 进行分析

  • 判断是否书写正确推荐仿照已经写好的可用的代码

    参考文件 用途
    Test/RunMilitaryBoxing 多车规划参考代码
    Test/TestDribbleAndKick 吸球/踢球参考代码
  • 了解 task 层以及 skill 层(lua框架下)的逻辑

    TestDribbleAndKick.lua 中最后调用了 task.lua 中的 shoot() 函数

    追溯至 task.lua 会发现在 skill 层都调用了 goCmuRush() 函数,说明结果上 skill 的不同实际上是 task 封装的不同

综合示例

在上次作业的基础上设置一个调试开关,开关打开时在球处于进攻侧位置时显示以下信息:

  • (1000,1000) (2000,1000) (3000,1000) 位置绘制叉号
  • (1000,1000) 位置显示 PI 值并输出其类型
  • 显示对方 0 号车的位置并显示 ENEMY 字符串
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
local testPos={     --confirm the positions of three state
CGeoPoint:new_local(0,0), -- position of outside
CGeoPoint:new_local(3400,0), -- position of forward
CGeoPoint:new_local(-3400,0), -- position of backward
}

local DEBUG_SWITCH=true --调试开关
local str = 3.1415926 --设置输出的字符串信息
local DEBUG_FINC = function()
-- 画叉号函数
debugEngine:gui_debug_x(CGeoPoint:new_local(1000,1000))
debugEngine:gui_debug_x(CGeoPoint:new_local(2000,1000))
debugEngine:gui_debug_x(CGeoPoint:new_local(3000,1000))
-- 输出字符串函数
debugEngine:gui_debug_msg(CGeoPoint:new_local(1000,1000),str..' '..type(str),2) --在指定位置打印number值和number类型
debugEngine:gui_debug_x(enemy.pos(0)) --enemy.pos(0)获取对方0号车的坐标
debugEngine:gui_debug_msg(enemy.pos(0),'ENEMY!')
end

function check() -- help to check if a ball in yard
if (ball.posY()>3000 or ball.posY()<-3000 or ball.posX()>4500 or ball.posX()<-4500) then
return true;
else
return false;
end
end

gPlayTable.CreatePlay{

firstState="outside", --first put the ball at outside of yard

["outside"]={ --the state of middle
switch=function()
if bufcnt(check()==false and ball.posX()<0,10) then -- get the ball position to help judge machine next position
return "backward"
elseif bufcnt(check()==false and ball.posX()>0,10) then
return "forward"
end
end,
Kicker=task.goCmuRush(testPos[1],0),
match="{K}"
},

["forward"]={ -- the state of forward
switch=function() --设置成只有在forward状态且DEBUG_SWITCH为true时输出调试函数
if DEBUG_SWITCH then
DEBUG_FINC()
end
if bufcnt(check()==true,10) then
return "outside"
elseif bufcnt(check()==false and ball.posX()<0,10) then
return "backward"
end
end,
Kicker=task.goCmuRush(testPos[2],0),
match="{K}"
},

["backward"]={ -- the state of backward
switch=function()
if bufcnt(check()==true,10) then
return "outside"
elseif bufcnt(check()==false and ball.posX()>0,10) then
return "forward"
end
end,
Kicker=task.goCmuRush(testPos[3],0),
match="{K}"
},

name="MyTestRun",
applicable={
exp="a",
a=true
},
attribute = "attack",
timeout = 99999
}

在 check() 函数上方定义了一个调试函数 DEBUG_FINC(),并且在 forward 状态内部的 switch 判断语句中添加该调试函数