这次过一下loop中的内容
这里会先做lowBattery的处理,没电了就直接停了
- readEnvironment
- 读取当前状态
- read_IMU(), 读取IMU,应该是为了保持平衡
- read_sound(),读取用户输入的声音?目前是空的实现
- read_GPS(),目前是空的
- dealWithExceptions
- 处理exception,这里应该和其他地方有关,暂时先不关注
- tQueue->popTask
- opencat里有一个全局的任务队列,每个task里包含了token,parameters。
- popTask,这里会拉去last,记录当前的parameters到newCmd中,并记录当前的task的启动时间。每一个task还有一个dly(应该是delay),表示这个task要执行多久,在此之前是不会执行新的task的
- readSignal()
- 这里应该是从各个硬件中读取signal,比如从蓝牙中读取数据,从camera中读取等等。这里是遍历了module中的每个组件,调用对应的read函数,处理一些输入的信号
- reaction()
- 这里是做具体的任务的处理了,这里稍微有点多,先看一个简单的作为示例吧
- reaction:T_REST:
- 这个就是发送休息指令后,狗会做的动作
- 首先会设置gyroBalanceQ = false,关闭陀螺仪的balance功能
- 如果cmd length为0,这里会把newCmd设为为rest,并且当newCmd不等于lastCmd的时候,调用loadBySkillName
- skilllist->lookup(skillname),找预定义好的skill
- skill->buildSkill()。这里build skill看起来是先读取一个period的长度,然后读取每一个period的具体的cmd
- skill->transformToSkill(),这里貌似是计算需要移动的角度
- 然后每次执行的时候调用的是perform()
- 每次移动的时候要考虑IMU给的修正,以及本次目的要移动的角度
- 最后调用calibratedPWM,来把对应的关节移动到目的的angle上
- 这里calibratedPWM会计算上之前的校准的offset,然后会根据速度做一个插值,默认情况下是没有插值的,直接移动。否则就会分step,多次调用servo.Write(degree),移动舵机
- 这个直接写degree,不sleep是有用的吗?
- 有关skill的初始化,定义到了InstinctBittleESP中,里面记录了每一个舵机在每一帧需要移动到的角度。然后还有一些元数据,比如是否是repeat的skill什么的
- transform也是一个动作函数,传入的应该是当前帧下的所有舵机的angle,angle ratio,以及speed。transform内部会遍历对应的DOF,计算需要移动的角度,并调用calibratedPWM。
- 这里的transform我要看晕了,不打算看了,目前唯一怀疑的一点在没有反馈的情况下,他是怎么确保电机在这个帧下移动到了正确的位置。默认的rundelay是8ms,可能他认为是足够的?
- 然后调用shutServos()
- 如果cmd length为1,会直接调用shutServos(),然后把parameter作为PWM号传入,表示只有一个关节休息了。
- shutServos的逻辑就是调用对应的servo的write,把0作为tick写入。这里看注释是说写一个0进去他就会停止这个servo,还有另一种方法是直接detach
文章评论
请教一下,关于opencat的运动控制部分,不知道您是怎么理解的?看代码是定义了16个joint,对应一些控制器,那么针对一个抬腿或者行走的动作,他是怎么拆解成一个运动流的,还没看到相关解读。如果您看到了,希望能指点一下。
@橘皮特甜 可以加我wx 15130410553