自动驾驶框架Autoware代码阅读---decision_maker
Autoware代码下载:
https://gitlab.com/autowarefoundation/autoware.ai/autoware/-/wikis/Source-Build
Autoware的decsion_maker是使用状态机实现的。
在1.13.0版本中,decision的代码在autoware/core_planning/decision_maker中
有四个状态机,分别是Vehicle_state,Mission_state,Behavior_state和Motion_state
Vehicle_state
Mission_state
Behaviour
Motion_state
状态机代码
上面的四个状态机都是使用同一个数据类型实现的(state_machine::StateContext),
代码在:autoware/core_planning/state_machine_lib里面
状态机的初始化
状态机的初始化是通过yaml文件加载进去的,具体代码在StateContext::createStateMap中。Decision_maker的yaml文件是存放在autoware/core_planning/decision_maker/的目录下,stateName是状态名称,key的转移边上的关键字,Target是连接的状态的名称,值得注意的是每一个state有一个parent的属性,表示这个状态是parent的子状态,parent更加抽象,child更加具体。根据上面的图可以看出,最外面的一层是一个图,含有子状态的状态内部是一棵树。
状态机的状态转移
状态转移代码在StateContext::nextState(const std::string& transition_key)中,根据key的值找到下一个状态。
当前状态是在用一条链进行表示,链头是root_state_,通过getChild函数找到下一个点。因为每个state的child_state_的变量只有一个值而不是数组,所以这是一条链(从根沿着树走的链)。
状态转移的过程是从链头开始找,直到找到一个有transition_key的边的状态,这个要连出去的状态记为transition_state,在链上找到transition_state的上一个节点记为in_state,修改该节点的child的值为target_state,调用transition_state的onExit和target_state的onEntry函数。
每一个state有一些比较重要的函数。onEntry表示进入这个状态时的操作,onExit表示退出这个状态时的操作,onUpdate是状态机走到当前状态时,每隔一段时间执行一遍的操作(整条链都会执行,因为当前状态是用一条链表示)。这些函数都在DecisionMakerNode::setupStateCallback中设置了不同的函数
状态的说明在src/autoware/core_planning/decision_maker/README.md有介绍
状态的代码在
autoware/core_planning/decision_maker/nodes/decision_maker/目录下的
decision_maker_node_state_vehicle.cpp
decision_maker_node_state_behavior.cpp
decision_maker_node_state_motion.cpp
decision_maker_node_state_mission.cpp
值得注意的地方,在一些状态机的代码里面,tryNextState的参数可能不是用于本状态机,而是用于其他的状态机的。例如:在mission_state里面,有一些地方tryNextState中调用"operation_start"“operation_end”"mission_reloaded”,但是没有处理,是因为在其他状态机里处理了,退出当前的任务,还有motion_state调用了 tryNextState(“arrived_goal”)会影响mission_state
总结
autoware 的decision_maker感觉是一个比较粗略的决策(甚至有一些比较关键的函数没有实现,例如左右切车道的安全性判断之类的,可能是放在下层规划器中了)。输入是一维的节点的序列,切车道或停止线之类的属性写在节点上(和我们现阶段的地图相似),输出是一个字符串,表示决策的结果。从代码设计上,用yaml初始化状态机的方法虽然很简便,但是在使用的时候如果key的字母写错了,很容易错,而且很难排查,个人不建议这么写,用一个key控制多个状态机这一点我感觉很厉害,可以改成用对象表示key就可以避免写错的问题。