ROS中make_plan服务的使用

void fillPathRequest(nav_msgs::GetPlan::Request &request, float start_x, float start_y, float goal_x, float goal_y)
{
    request.start.header.frame_id ="map";
    request.start.pose.position.x = start_x;//初始位置x坐标
    request.start.pose.position.y = start_y;//初始位置y坐标
    request.start.pose.orientation.w = 1.0;//方向
    request.goal.header.frame_id = "map";
    request.goal.pose.position.x = goal_x;//终点坐标
    request.goal.pose.position.y = goal_y;
    request.goal.pose.orientation.w = 1.0;
    request.tolerance = 0.0;//如果不能到达目标,最近可到的约束
}

void myfunction(geometry_msgs::PoseStamped p)
{
    std::cout << "X = " << p.pose.position.x << "   Y = " << p.pose.position.y << std::endl;
}

//路线规划结果回调
void callPlanningService(ros::ServiceClient &serviceClient, nav_msgs::GetPlan &srv)
{
    // Perform the actual path planner call
    //执行实际路径规划器
    if (serviceClient.call(srv)) {
        //srv.response.plan.poses 为保存结果的容器,遍历取出
        if (!srv.response.plan.poses.empty()) {
//            std::for_each(srv.response.plan.poses.begin(),srv.response.plan.poses.end(),myfunction);
            ROS_INFO("make_plan success!");
        }
    }
    else {
        ROS_WARN("Got empty plan");
    }
}

int main(int argc, char **argv)
{
    ros::init(argc, argv, "system_manager_node");
    ros::NodeHandle nh("~");
    ros::NodeHandle nhandle;

    ros::Publisher markers_pub_ = nhandle.advertise<visualization_msgs::Marker>("visualization_marker", 20);

    ros::ServiceClient make_plan_client = nhandle.serviceClient<nav_msgs::GetPlan>("move_base/make_plan",true);
    if (!make_plan_client) {
        ROS_FATAL("Could not initialize get plan service from %s",
        make_plan_client.getService().c_str());
        return -1;
    }

    nav_msgs::GetPlan srv;
    fillPathRequest(srv.request,-7,-3.0,11.338,-5.8852);
    callPlanningService(make_plan_client,srv);

    visualization_msgs::Marker mk1;
    mk1.header.stamp = ros::Time::now();
    mk1.header.frame_id = "/map";
    mk1.id = 0;
    mk1.type = visualization_msgs::Marker::LINE_STRIP;
    mk1.scale.x = 0.05; mk1.scale.y = 0.05; mk1.scale.z = 0.05;
    mk1.color.r = 1.0; mk1.color.a = 1.0;
    for(int i = 100; i < srv.response.plan.poses.size(); i++)
    {
        mk1.points.push_back(srv.response.plan.poses[i].pose.position);
    }
    markers_pub_.publish(mk1);
}

  • 1
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
给下列程序添加注释:void DWAPlannerROS::initialize( std::string name, tf2_ros::Buffer* tf, costmap_2d::Costmap2DROS* costmap_ros) { if (! isInitialized()) { ros::NodeHandle private_nh("~/" + name); g_plan_pub_ = private_nh.advertise<nav_msgs::Path>("global_plan", 1); l_plan_pub_ = private_nh.advertise<nav_msgs::Path>("local_plan", 1); tf_ = tf; costmap_ros_ = costmap_ros; costmap_ros_->getRobotPose(current_pose_); // make sure to update the costmap we'll use for this cycle costmap_2d::Costmap2D* costmap = costmap_ros_->getCostmap(); planner_util_.initialize(tf, costmap, costmap_ros_->getGlobalFrameID()); //create the actual planner that we'll use.. it'll configure itself from the parameter server dp_ = boost::shared_ptr<DWAPlanner>(new DWAPlanner(name, &planner_util_)); if( private_nh.getParam( "odom_topic", odom_topic_ )) { odom_helper_.setOdomTopic( odom_topic_ ); } initialized_ = true; // Warn about deprecated parameters -- remove this block in N-turtle nav_core::warnRenamedParameter(private_nh, "max_vel_trans", "max_trans_vel"); nav_core::warnRenamedParameter(private_nh, "min_vel_trans", "min_trans_vel"); nav_core::warnRenamedParameter(private_nh, "max_vel_theta", "max_rot_vel"); nav_core::warnRenamedParameter(private_nh, "min_vel_theta", "min_rot_vel"); nav_core::warnRenamedParameter(private_nh, "acc_lim_trans", "acc_limit_trans"); nav_core::warnRenamedParameter(private_nh, "theta_stopped_vel", "rot_stopped_vel"); dsrv_ = new dynamic_reconfigure::Server<DWAPlannerConfig>(private_nh); dynamic_reconfigure::Server<DWAPlannerConfig>::CallbackType cb = boost::bind(&DWAPlannerROS::reconfigureCB, this, _1, 2); dsrv->setCallback(cb); } else{ ROS_WARN("This planner has already been initialized, doing nothing."); } }
06-12
项目背景和目标: 本项目旨在使用ROS2框架开发一个机器人导航系统,实现机器人的定位导航、路径规划、避障和导航控制等功能。具体目标如下: 1. 机器人能够通过激光雷达等传感器进行定位,并能够实时更新自身位置信息。 2. 机器人能够通过地图构建和路径规划算法,规划可行路径,并能够自主避开障碍物。 3. 机器人能够通过控制接口控制自身运动,实现导航目标的到达和停车等功能。 4. 代码要求使用ROS2的功能库、通信机制、控制接口等来编写节点和实现特定的机器人行为或算法。 步骤一:创建ROS2工作空间 首先,在终端输入以下命令以创建ROS2工作空间: ``` mkdir -p ~/ros2_ws/src cd ~/ros2_ws colcon build --symlink-install ``` 步骤二:创建导航包和节点 在ROS2工作空间的src目录下,创建一个名为navigation的包,并在该包下创建名为navigation的节点: ``` cd ~/ros2_ws/src ros2 pkg create --build-type ament_cmake navigation cd navigation mkdir src touch src/navigation.cpp ``` 在navigation.cpp编写导航节点的代码,包括机器人位置的订阅、路径规划的实现、控制指令的发布等功能。以下是节点代码示例: ``` #include "rclcpp/rclcpp.hpp" #include "geometry_msgs/msg/pose_stamped.hpp" #include "nav_msgs/msg/path.hpp" #include "nav_msgs/srv/get_plan.hpp" #include "nav_msgs/srv/set_map.hpp" #include "tf2_ros/transform_listener.h" using namespace std::chrono_literals; class Navigation : public rclcpp::Node { public: Navigation() : Node("navigation") { // 定义订阅机器人位置信息的话题 subscriber_ = this->create_subscription<geometry_msgs::msg::PoseStamped>( "robot_pose", 10, std::bind(&Navigation::robotPoseCallback, this, std::placeholders::_1)); // 定义发布控制指令的话题 publisher_ = this->create_publisher<geometry_msgs::msg::Twist>("cmd_vel", 10); // 定义调用路径规划服务的客户端 client_ = this->create_client<nav_msgs::srv::GetPlan>("get_plan"); // 定义调用地图设置服务的客户端 set_map_client_ = this->create_client<nav_msgs::srv::SetMap>("set_map"); // 定义定时器,定时执行导航任务 timer_ = this->create_wall_timer(1s, std::bind(&Navigation::navigate, this)); } private: // 机器人位置信息的回调函数 void robotPoseCallback(const geometry_msgs::msg::PoseStamped::SharedPtr msg) { robot_pose_ = *msg; } // 路径规划函数 nav_msgs::msg::Path planPath() { nav_msgs::srv::GetPlan::Request request; nav_msgs::srv::GetPlan::Response response; // 构建请求消息 request.start = robot_pose_; request.goal = goal_pose_; // 调用路径规划服务,获取响应消息 auto result = client_->call(request, response); if (!result) { RCLCPP_ERROR(this->get_logger(), "Failed to call service get_plan"); return nav_msgs::msg::Path(); } return response.plan.poses; } // 发布控制指令的函数 void publishCommand(geometry_msgs::msg::Twist command) { publisher_->publish(command); } // 导航函数 void navigate() { if (robot_pose_.header.frame_id.empty()) { RCLCPP_WARN(this->get_logger(), "Robot pose is not available yet"); return; } // 执行路径规划 nav_msgs::msg::Path path = planPath(); // 发布路径信息 path_publisher_->publish(path); // 控制机器人运动 controlRobot(path); } // 机器人控制函数 void controlRobot(nav_msgs::msg::Path path) { tf2_ros::Buffer tf_buffer; tf2_ros::TransformListener tf_listener(tf_buffer); geometry_msgs::msg::TransformStamped transformStamped; // 获取机器人当前姿态 try { transformStamped = tf_buffer.lookupTransform("map", "base_link", rclcpp::Time(0)); } catch (tf2::TransformException &ex) { RCLCPP_ERROR(this->get_logger(), "%s", ex.what()); return; } // 判断机器人是否到达目标点 double distance_to_goal = sqrt(pow(goal_pose_.pose.position.x - robot_pose_.pose.position.x, 2) + pow(goal_pose_.pose.position.y - robot_pose_.pose.position.y, 2)); if (distance_to_goal < 0.1) { RCLCPP_INFO(this->get_logger(), "Navigation goal reached"); return; } // 判断机器人距离路径的最近点 double min_distance = std::numeric_limits<double>::infinity(); int min_index = -1; for (int i = 0; i < path.poses.size(); i++) { double distance_to_path = sqrt(pow(transformStamped.transform.translation.x - path.poses[i].pose.position.x, 2) + pow(transformStamped.transform.translation.y - path.poses[i].pose.position.y, 2)); if (distance_to_path < min_distance) { min_distance = distance_to_path; min_index = i; } } // 判断机器人是否需要避障 bool need_avoidance = false; for (int i = min_index; i < path.poses.size(); i++) { double distance_to_obstacle = getDistanceToObstacle(path.poses[i].pose.position); if (distance_to_obstacle < 0.5) { need_avoidance = true; break; } } // 控制机器人运动 if (need_avoidance) { // 避障控制 geometry_msgs::msg::Twist command; command.linear.x = 0.0; command.angular.z = 0.5; publishCommand(command); } else { // 直线控制 geometry_msgs::msg::Twist command; command.linear.x = 0.5; command.angular.z = 0.0; publishCommand(command); } } // 获取机器人到障碍物的距离 double getDistanceToObstacle(geometry_msgs::msg::Point point) { // TODO: 实现障碍物检测算法 return 0.0; } private: rclcpp::Subscription<geometry_msgs::msg::PoseStamped>::SharedPtr subscriber_; rclcpp::Publisher<geometry_msgs::msg::Twist>::SharedPtr publisher_; rclcpp::Client<nav_msgs::srv::GetPlan>::SharedPtr client_; rclcpp::Client<nav_msgs::srv::SetMap>::SharedPtr set_map_client_; rclcpp::TimerBase::SharedPtr timer_; rclcpp::Publisher<nav_msgs::msg::Path>::SharedPtr path_publisher_; geometry_msgs::msg::PoseStamped robot_pose_; geometry_msgs::msg::PoseStamped goal_pose_; }; int main(int argc, char *argv[]) { rclcpp::init(argc, argv); auto node = std::make_shared<Navigation>(); rclcpp::spin(node); rclcpp::shutdown(); return 0; } ``` 在同一目录下创建CMakeLists.txt和package.xml文件,分别用于构建和描述导航包。CMakeLists.txt示例代码如下: ``` cmake_minimum_required(VERSION 3.5) project(navigation) # Default to C++14 if(NOT CMAKE_CXX_STANDARD) set(CMAKE_CXX_STANDARD 14) endif() # Find packages find_package(ament_cmake REQUIRED) find_package(rclcpp REQUIRED) find_package(geometry_msgs REQUIRED) find_package(nav_msgs REQUIRED) find_package(tf2 REQUIRED) find_package(tf2_ros REQUIRED) # Add include directories include_directories(include) # Create executable add_executable(navigation src/navigation.cpp) ament_target_dependencies(navigation rclcpp geometry_msgs nav_msgs tf2 tf2_ros) # Install executable install(TARGETS navigation DESTINATION lib/${PROJECT_NAME}) # Install launch files install(DIRECTORY launch DESTINATION share/${PROJECT_NAME}/ ) # Install config files install(DIRECTORY config DESTINATION share/${PROJECT_NAME}/ ) # Install package.xml ament_package() ``` package.xml示例代码如下: ``` <?xml version="1.0"?> <package format="2"> <name>navigation</name> <version>0.0.0</version> <description>ROS2 Navigation Package</description> <maintainer email="you@example.com">Your Name</maintainer> <license>Apache License 2.0</license> <buildtool_depend>ament_cmake</buildtool_depend> <build_depend>rclcpp</build_depend> <build_depend>geometry_msgs</build_depend> <build_depend>nav_msgs</build_depend> <build_depend>tf2</build_depend> <build_depend>tf2_ros</build_depend> <exec_depend>rclcpp</exec_depend> <exec_depend>geometry_msgs</exec_depend> <exec_depend>nav_msgs</exec_depend> <exec_depend>tf2</exec_depend> <exec_depend>tf2_ros</exec_depend> </package> ``` 步骤三:构建和运行导航节点 在终端,输入以下命令构建导航包: ``` cd ~/ros2_ws colcon build --symlink-install --packages-select navigation ``` 构建完成后,在终端输入以下命令运行导航节点: ``` source ~/ros2_ws/install/setup.bash ros2 run navigation navigation ``` 此时,机器人将开始执行导航任务,包括定位导航、路径规划、避障和导航控制等功能。 可能遇到的问题和解决方案: 1. 编译时找不到依赖包 解决方案:确保已正确安装所有依赖包,并在CMakeLists.txt和package.xml文件正确声明依赖关系。 2. 运行节点时出现错误 解决方案:检查节点代码的错误或异常,确保代码逻辑正确,传感器正常工作,机器人能够正确响应控制指令等。 3. 机器人无法定位或导航失败 解决方案:检查机器人传感器是否正常工作,地图是否正确构建,路径规划算法是否正确实现等。可以通过ROS2提供的可视化工具(如rviz)进行调试和测试。 结果分析和总结: 本项目使用ROS2框架开发了一个机器人导航系统,实现了机器人的定位导航、路径规划、避障和导航控制等功能。通过使用ROS2的功能库、通信机制、控制接口等,可以更方便地实现机器人相关的算法和应用程序。此外,ROS2还提供了丰富的可视化工具,如rviz等,可以帮助用户更直观地观察和调试机器人导航系统。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值