Behavior Tree Navigation
Background
Navigating through real-life terrain is full of unexpected obstacles. Things
that are hard to catch with the onboard sensor cannot be avoided with just a
local planner. In my specific case, I only had a 2D LiDAR on my robot, so any
obstacle that come below the horizontal rays of the LiDAR were not
detected. That is just one example. There are countless other ways in
which a robot can fail to avoid obstacles and come to a stop before reaching
its destination. A robust way to prevent such issue is to add a recovery
behavior. A recovery behavior is a set of predefined controls the robot
performs when it has detected a failure. For instance, if the robot stops
moving because it has hit an undetected obstacle, it can back up a short
distance then try to move forward again. In this case, the recovery behavior
is backing up.
Behavior Tree
A good C++ library to use when adding a recovery behavior to your robot is
BehaviorTreeCPP.
In practice, these nodes are like plugins, a piece of code that is compiled
into a shared library and loaded dynamically. This way, individual actions of
the robot can be compiled separately and modularized to facilitate creating
complex behavior trees.
In this project, the behavior tree will be used to add a recovery behavior.
The robot will first try to navigate to the goal pose, but when it detects a
failure (ex. the robot is not moving) it will initiate the recovery behavior
to get the robot out of whatever situation it is in.
Behavior Tree: Detailed Explanation
The behavior tree works is by sending a "tick" from the root node all the way
to the leaf node. A leaf node that receives a tick is executed. Then the leaf
node sends back its node status, which is propagated up the tree all the way
to the root node.
Figure 2: Left most subtree.
Figure 3: left half of entire behavior tree
Figure 4: Right half of entire behavior tree.
ROS-Specific Details
Figure 5: ROS integration of BehaviorTreeCPP
The BehaviorTreeCPP library is integrated into the ROS environment by making
the leaf nodes be an client (action or service). For example, the
ComputePathToPose node is a client of the ComputePathToPose action. On each
tick to the node, it sends an action request to the server to compute the path
to goal pose. The same is true for FollowPath, ClearEntireGlobalCostmap,
ClearEntireLocalCostmap, Wait, and Backup: they are all action or service
clients that send a request to the server when ticked.
Result
The behavior tree was tested on an obstacle course.
Figure 6: Map of obstacle course.
Figure 7: Actual obstacle course.
The obstacle course consisted of both mapped obstacles (red) and unmapped
obstacles (blue). The robot started at the left end of the course and was set
to navigate to the right end.
Comments
Post a Comment