先看nav2_bt_navigator的cmakelists文件会生成一个名为bt_navigator的可执行文件,这个是在我们导航的launch.py文件中启动的。
首先看bt_navigator.cpp
构造函数主要是一些参数的declared
const std::vector<std::string> plugin_libs = {
"nav2_compute_path_to_pose_action_bt_node",
"nav2_compute_path_through_poses_action_bt_node",
"nav2_smooth_path_action_bt_node",
"nav2_follow_path_action_bt_node",
"nav2_spin_action_bt_node",
"nav2_wait_action_bt_node",
"nav2_assisted_teleop_action_bt_node",
"nav2_back_up_action_bt_node",
"nav2_drive_on_heading_bt_node",
"nav2_clear_costmap_service_bt_node",
"nav2_is_stuck_condition_bt_node",
"nav2_goal_reached_condition_bt_node",
"nav2_initial_pose_received_condition_bt_node",
"nav2_goal_updated_condition_bt_node",
"nav2_globally_updated_goal_condition_bt_node",
"nav2_is_path_valid_condition_bt_node",
"nav2_reinitialize_global_localization_service_bt_node",
"nav2_rate_controller_bt_node",
"nav2_distance_controller_bt_node",
"nav2_speed_controller_bt_node",
"nav2_truncate_path_action_bt_node",
"nav2_truncate_path_local_action_bt_node",
"nav2_goal_updater_node_bt_node",
"nav2_recovery_node_bt_node",
"nav2_pipeline_sequence_bt_node",
"nav2_round_robin_node_bt_node",
"nav2_transform_available_condition_bt_node",
"nav2_time_expired_condition_bt_node",
"nav2_path_expiring_timer_condition",
"nav2_distance_traveled_condition_bt_node",
"nav2_single_trigger_bt_node",
"nav2_goal_updated_controller_bt_node",
"nav2_is_battery_low_condition_bt_node",
"nav2_navigate_through_poses_action_bt_node",
"nav2_navigate_to_pose_action_bt_node",
"nav2_remove_passed_goals_action_bt_node",
"nav2_planner_selector_bt_node",
"nav2_controller_selector_bt_node",
"nav2_goal_checker_selector_bt_node",
"nav2_controller_cancel_bt_node",
"nav2_path_longer_on_approach_bt_node",
"nav2_wait_cancel_bt_node",
"nav2_spin_cancel_bt_node",
"nav2_assisted_teleop_cancel_bt_node",
"nav2_back_up_cancel_bt_node",
"nav2_drive_on_heading_cancel_bt_node",
"nav2_is_battery_charging_condition_bt_node"
};
declare_parameter_if_not_declared(
this, "plugin_lib_names", rclcpp::ParameterValue(plugin_libs));
declare_parameter_if_not_declared(
this, "transform_tolerance", rclcpp::ParameterValue(0.1));
declare_parameter_if_not_declared(
this, "global_frame", rclcpp::ParameterValue(std::string("map")));
declare_parameter_if_not_declared(
this, "robot_base_frame", rclcpp::ParameterValue(std::string("base_link")));
declare_parameter_if_not_declared(
this, "odom_topic", rclcpp::ParameterValue(std::string("odom")));
首先是on_configure函数
- 从plugin_lib_names参数获取BT nodes的libraries
- Odometry smoother object for getting current speed
- 初始化pose_navigator_和poses_navigator_这个后面再分析navigate_to_pose.cpp和navigate_through_poses.cpp
其次是on_activate函数
主要就是激活poses_navigator_和pose_navigator_
if (!poses_navigator_->on_activate() || !pose_navigator_->on_activate()) {
return nav2_util::CallbackReturn::FAILURE;
}
接下来分析navigate_to_pose.cpp
class NavigateToPoseNavigator
: public nav2_bt_navigator::Navigator<nav2_msgs::action::NavigateToPose>
他继承了Navigator类,直接看navigator.hpp
具体的on_configure函数如下
auto node = parent_node.lock();
logger_ = node->get_logger();
clock_ = node->get_clock();
feedback_utils_ = feedback_utils;
plugin_muxer_ = plugin_muxer;
// get the default behavior tree for this navigator
std::string default_bt_xml_filename = getDefaultBTFilepath(parent_node);
// Create the Behavior Tree Action Server for this navigator
bt_action_server_ = std::make_unique<nav2_behavior_tree::BtActionServer<ActionT>>(
node,
getName(),
plugin_lib_names,
default_bt_xml_filename,
std::bind(&Navigator::onGoalReceived, this, std::placeholders::_1),
std::bind(&Navigator::onLoop, this),
std::bind(&Navigator::onPreempt, this, std::placeholders::_1),
std::bind(&Navigator::onCompletion, this, std::placeholders::_1, std::placeholders::_2));
bool ok = true;
if (!bt_action_server_->on_configure()) {
ok = false;
}
BT::Blackboard::Ptr blackboard = bt_action_server_->getBlackboard();
blackboard->set<std::shared_ptr<tf2_ros::Buffer>>("tf_buffer", feedback_utils.tf); // NOLINT
blackboard->set<bool>("initial_pose_received", false); // NOLINT
blackboard->set<int>("number_recoveries", 0); // NOLINT
blackboard->set<std::shared_ptr<nav2_util::OdomSmoother>>("odom_smoother", odom_smoother); // NOLINT
return configure(parent_node, odom_smoother) && ok;
getDefaultBTFilepath函数(get the default behavior tree for this navigator),默认使用的是nav2_bt_navigator/navigate_to_pose_w_replanning_and_recovery.xml
然后初始化bt_action_server_(Create the Behavior Tree Action Server for this navigator)此处的
ActionT = nav2_msgs::action::NavigateToPose;
然后是bt_action_server_->on_configure()
最后调用configure函数,其具体实现在navigate_to_pose.cpp中如下
start_time_ = rclcpp::Time(0);
auto node = parent_node.lock();
if (!node->has_parameter("goal_blackboard_id")) {
node->declare_parameter("goal_blackboard_id", std::string("goal"));
}
goal_blackboard_id_ = node->get_parameter("goal_blackboard_id").as_string();
if (!node->has_parameter("path_blackboard_id")) {
node->declare_parameter("path_blackboard_id", std::string("path"));
}
path_blackboard_id_ = node->get_parameter("path_blackboard_id").as_string();
// Odometry smoother object for getting current speed
odom_smoother_ = odom_smoother;
self_client_ = rclcpp_action::create_client<ActionT>(node, getName());
goal_sub_ = node->create_subscription<geometry_msgs::msg::PoseStamped>(
"goal_pose",
rclcpp::SystemDefaultsQoS(),
std::bind(&NavigateToPoseNavigator::onGoalPoseReceived, this, std::placeholders::_1));
return true;
主要是一些参数还有self_client_和goal_sub_,猜测goal_sub_通过订阅rviz2中的goal_pose topic然后
self_client_->async_send_goal(goal);
所以navigator.hpp中是ros2中的action server,那么action 的client在哪里呢?就是这个self_client_。
总体来说就是加载行为树订阅goal_pose的topic,然后使用加载的行为树做导航。
水平有限,错误之处望批评指出