摘要:MIT Cheetah-Software是四足机器人的开源项目,理清程序流程是进一步理解和研究项目的必要条件。Cheetah-Software开源项目包含robot、common、sim和user等四个部分的源码,本文以user/MIT_Controller下的子项目来介绍Cheetah-Software的程序流程。

一、主函数

        主函数定义在main.cpp文件中,源码如下:

int main(int argc, char** argv) 
{
     main_helper(argc, argv, new MIT_Controller());
     return 0;
}

       在主函数中,先使用new生成一个MIT_Controller对象,然后调用main_helper函数,最后返回0,流程如图1所示。

 图1 主函数流程图

       注:MIT_Controller在user/MIT_Controller/MIT_Controller.hpp文件中。

二、main_helper函数

       main_helper函数定义在robot/src/main_helper.cpp,流程图见图2。

图2 main_helper函数流程图 

       上面流程图中,大部分流程用于命令参数判断,在流程图后面三个分支中的对象是我们研究的重点,即MiniCheetahHardwareBridge、CheetahHardwareBridge和SimulationBridge三个类的对象声明hw和hw.run()。

MiniCheetahHardwareBridge和CheetahHardwareBridge是HardwareBridge的子类,是两种不同类型的四足机器人对象,而SimulationBridge类是仿真模拟类,用来仿真四足机器人对象,下面分别以MiniCheetahHardwareBridge和Cheetah3HardwareBridge为例来介绍四足机器人的运行流程。

三、HardwareBridge::run()

HardwareBridge类是一个抽象类,定义了run()的接口函数,其子类在run()中实现机器人运行代码。

(一)MiniCheetahHardwareBridge::run()

MiniCheetahHardwareBridge::run()的流程图如图3所示。

图3 MiniCheetahHardwareBridge::run函数流程图

1、初始化通信模块,调用基类HardwareBridge::initCommon()函数,通过LCM通信模块订阅interface和interface_request两个主题;

2、初始化MiniCheetah机器人的spi通信和惯性导航模块(IMU);

3、初始化机器人参数和用户控制参数列表;

4、创建和配置RobotRunner对象(实际上是一个任务对象);

5、启动状态任务;

6、启动spi通信任务,spi通信负责传输控制命令和接收传感器数据;

7、启动惯性导航线程;

8、执行RobotRunner的任务;

9、启动可视化数据LCM通信任务;

10、启动遥控器指令接收任务;

11、启动惯性导航日志任务;

12、每隔1秒循环。

(二)Cheetah3HardwareBridge::run()

Cheetah3HardwareBridge::run()的流程图如图4所示。

图4 Cheetah3HardwareBridge::run函数流程图 

1、初始化通信模块,调用基类HardwareBridge::initCommon()函数;

2、初始化Cheetah3的硬件系统;

3、初始化机器人参数和用户控制参数列表;

4、创建和配置RobotRunner对象;

5、初始化RobotRunner对象;

6、启动状态任务;

7、启动工业以太网(基于ethercat协议);

8、执行RobotRunner任务;

9、启动可视化数据LCM通信任务;

10、每隔1秒,打印状态。

四、RobotRunner任务的初始化与执行

在Cheetah3HardwareBridge::run()的流程中调用了RobotRunner::init()和RobotRunner::start(),下面分析两个函数的流程和功能。

(一)RobotRunner::init()

RobotRunner::init()的流程如图5所示。

图5 RotbotRunner::init函数流程图

1、根据机器人类型创建四足机器人模型(_quadruped)和生成基础移动模型;

2、创建机器人关节位姿初始化对象;

3、创建腿控制器对象;

4、创建状态预测容器并初始化;

5、创建期望状态命令对象;

6、将生成的对象赋值给机器人控制对象;

7、初始化机器人控制对象。

(二)RobotRunner::start()

RobotRunner的基类是PeriodicTask,PeriodicTask是一个线程任务类,所以RobotRunner::start()实际调用的是PeriodicTask::start()。RobotRunner::start()的流程如图6所示。

图6 启动RobotRunner任务流程图

1、调用PeriodicTask::start();

2、PeriodicTask::start()启动线程,线程的主体函数是PeriodicTask::loopFunction();

3、在PeriodicTask::loopFunction()中循环执行PeriodicTask::run()函数,而PeriodicTask::run()是一个纯虚函数,实际调用的是RobotRunner::run()函数。

五、RobotRunner::run()

RobotRunner::run()是机器人系统每个执行周期的运行内容,其流程如图7所示。

 

图7 RobotRunner::run函数流程图

1、运行状态预测;

2、可视化数据清零;

3、将机器人数据更新到LegController对象;

4、设置LegController对象使能;

5、当遥控器控制时的rc_control.mode为0时,将LegController对象的控制命令数据清零,否则执行6;

6、如果关节位置初始对象没有初始化时,将LegController对象的各个关节的kp和kd赋值,否则执行7;

7、执行机器人控制对象(实际是MIT_Controller对象)的runController()和updateVisualization()函数。

(一)RobotRunner::setupStep()

RobotRunner::setupStep()的功能是将机器人的各关节数据更新到LegController对象,流程见图8所示。

 

图8 RobotRunner::setupStep函数流程图

(二)MIT_Controller::runController()

MIT_Controller::runController()的功能是根据机器人当前位姿、期望位姿、遥控器指令、步态等多种数据计算各关节的控制命令,流程见图9所示。

图9 MIT_Controller::runController函数流程图

(三)RobotRunner::finalizeStep()

RobotRunner::finalizeStep()的功能是将生成的控制命令数据更新到机器人各控制系统,流程见图10所示。

图10 RobotRunner::finalizeStep函数流程图

六、小结

本文从/user/MIT_Controller/main.cpp的main()函数出发,通过逐次递进的方法分析了MIT开源项目Cheetah-Software机器人系统运行的主要流程,这只是源码分析的开始,希望和四足机器人爱好者们共同进步!

 

 

 

Logo

瓜分20万奖金 获得内推名额 丰厚实物奖励 易参与易上手

更多推荐