当前位置:   article > 正文

运动控制入门到入土:pure persuit纯追踪算法gazebo仿真_ros插件实现纯跟踪算法

ros插件实现纯跟踪算法

本代码根据【从零开始自动驾驶】01 - 05_哔哩哔哩_bilibili 的逻辑和代码。写了一套C++代码

感谢B站up Imjusty的教学

cmdvel2gazebo.cpp

  1. #include "cmdvel2gazebo.h"
  2. int main(int argc, char** argv){
  3. ros::init(argc, argv, "cmdvel2gazebo");
  4. cmdvel2gazebo cmdvel2gazebo;
  5. cmdvel2gazebo.control();
  6. return 0;
  7. }
  8. void cmdvel2gazebo::Cmd_Vel_Callback(const geometry_msgs::Twist &twist){
  9. velocity = twist.linear.x / 0.3;
  10. // cout << "velocity:" << velocity <<endl;
  11. angle = max(-maxsteer, min(maxsteer, twist.angular.z));
  12. // cout << "angle:" << angle <<endl;
  13. last_Time = ros::Time::now();
  14. publish();
  15. }
  16. void cmdvel2gazebo::control(){
  17. ros::spin();
  18. }
  19. void cmdvel2gazebo::publish(){
  20. std_msgs::Float64 msg_vel_L, msg_vel_R, msg_ang_L, msg_ang_R;
  21. delta_Time = (ros::Time::now()- last_Time).toSec();
  22. msgs_too_old = delta_Time > timeout ? 1: 0;
  23. if(msgs_too_old){
  24. velocity = 0;
  25. angle= 0;
  26. msg_vel_L.data = velocity;
  27. msg_vel_R.data = velocity;
  28. msg_ang_L.data = angle;
  29. msg_ang_R.data = angle;
  30. pub_rearL.publish(msg_vel_L);
  31. pub_rearR.publish(msg_vel_R);
  32. pub_steerL.publish(msg_ang_L);
  33. pub_steerR.publish(msg_ang_R);
  34. }
  35. // cout << "velocity1:" << velocity <<endl;
  36. // cout << "angle1:" << angle <<endl;
  37. if(angle!= 0){
  38. radius = wheelbase/fabs(tan(angle));
  39. radius_rearL = radius- (copysign(1, angle)* (Tread/ 2.0));
  40. radius_rearR = radius+ (copysign(1, angle)* (Tread/ 2.0));
  41. radius_frontL = radius- (copysign(1, angle)* (Tread/ 2.0));
  42. radius_frontR = radius+ (copysign(1, angle)* (Tread/ 2.0));
  43. velocity_rearL = velocity* radius_rearL/ radius;
  44. velocity_rearR = velocity* radius_rearR/ radius;
  45. msg_vel_L.data = velocity_rearL;
  46. msg_vel_R.data = velocity_rearR;
  47. pub_rearL.publish(msg_vel_L);
  48. pub_rearR.publish(msg_vel_R);
  49. angle_frontL = atan2(wheelbase, radius_frontL)* copysign(1, angle);
  50. angle_frontR = atan2(wheelbase, radius_frontR)* copysign(1, angle);
  51. // cout << "angle_L:" << angle_frontL <<endl;
  52. // cout << "angle_R:" << angle_frontR <<endl;
  53. msg_ang_L.data = angle_frontL;
  54. msg_ang_R.data = angle_frontR;
  55. pub_steerL.publish(msg_ang_L);
  56. pub_steerR.publish(msg_ang_R);
  57. }
  58. else{
  59. msg_vel_L.data = velocity;
  60. msg_vel_R.data = velocity;
  61. msg_ang_L.data = angle;
  62. msg_ang_R.data = angle;
  63. pub_rearL.publish(msg_vel_L);
  64. pub_rearR.publish(msg_vel_R);
  65. pub_steerL.publish(msg_ang_L);
  66. pub_steerR.publish(msg_ang_R);
  67. }
  68. }
  69. cmdvel2gazebo::cmdvel2gazebo()
  70. {
  71. pub_steerL = n.advertise <std_msgs::Float64>("/smart/front_left_steering_position_controller/command", 10);
  72. pub_steerR = n.advertise <std_msgs::Float64>("/smart/front_right_steering_position_controller/command", 10);
  73. pub_rearL = n.advertise <std_msgs::Float64>("/smart/rear_left_velocity_controller/command",10);
  74. pub_rearR = n.advertise <std_msgs::Float64>("/smart/rear_right_velocity_controller/command",10);
  75. cmd_vel_sub = n.subscribe("/smart/cmd_vel", 100, &cmdvel2gazebo::Cmd_Vel_Callback, this);
  76. last_Time= ros::Time::now();
  77. rMax = wheelbase/ tan(maxsteerInside);
  78. rIdeal = rMax+ (Tread/ 2.0);
  79. maxsteer = atan2(wheelbase, rIdeal);
  80. }
  81. cmdvel2gazebo::~cmdvel2gazebo()
  82. {
  83. }

transform_publisher.cpp

  1. #include "transform_publisher.h"
  2. int main(int argc, char** argv){
  3. ros::init(argc, argv, "transform_publisher");
  4. transform_publisher transform_publisher;
  5. transform_publisher.control();
  6. }
  7. void transform_publisher::pose_callback(const geometry_msgs::PoseStamped &pose_msgs){
  8. auto pose = pose_msgs.pose.position;
  9. cout << pose << endl;
  10. auto orientation = pose_msgs.pose.orientation;
  11. static tf::TransformBroadcaster br;
  12. tf::Transform transform;
  13. transform.setOrigin(tf::Vector3(pose.x, pose.y, pose.z));
  14. transform.setRotation(tf::Quaternion(orientation.x, orientation.y, orientation.z, orientation.w));
  15. br.sendTransform(tf::StampedTransform(transform, ros::Time::now(), "world", "base_link"));
  16. }
  17. void transform_publisher::control(){
  18. ros::spin();
  19. }
  20. transform_publisher::transform_publisher(){
  21. center_pose_sub = n.subscribe("/smart/center_pose", 10, &transform_publisher::pose_callback, this);
  22. }
  23. transform_publisher::~transform_publisher(){
  24. }

vehicle_pose_and_velocity_updater.cpp

  1. #include "vehicle_pose_and_velocity_updater.h"
  2. int main(int argc, char** argv){
  3. ros::init(argc, argv, "vehicle_pose_and_velocity_updater");
  4. vehicle_pose_and_velocity_updater vehicle_pose_and_velocity_updater;
  5. vehicle_pose_and_velocity_updater.control();
  6. return 0;
  7. }
  8. void vehicle_pose_and_velocity_updater::model_states_callback(const gazebo_msgs::ModelStatesConstPtr &states){
  9. int modelCount = states->name.size();
  10. for(int modelInd = 0; modelInd < modelCount; ++modelInd)
  11. {
  12. if(states->name[modelInd] == "smart")
  13. {
  14. vehicle_position = states->pose[modelInd];
  15. vehicle_velocity = states->twist[modelInd];
  16. orientation = vehicle_position.orientation;
  17. tf::Quaternion quaternion1(
  18. orientation.x,
  19. orientation.y,
  20. orientation.z,
  21. orientation.w
  22. );
  23. double roll, pitch, yaw;//定义存储r\p\y的容器
  24. tf::Matrix3x3(quaternion1).getRPY(roll, pitch, yaw);//进行转换
  25. time_stamp = ros::Time::now();
  26. geometry_msgs::PoseStamped center_pose;
  27. center_pose.header.frame_id = "/world";
  28. center_pose.header.stamp = time_stamp;
  29. center_pose.pose.position = vehicle_position.position;
  30. center_pose.pose.orientation = vehicle_position.orientation;
  31. center_pose_pub.publish(center_pose);
  32. geometry_msgs::PoseStamped rear_pose;
  33. rear_pose.header.frame_id = "/world";
  34. rear_pose.header.stamp = time_stamp;
  35. double center_x = vehicle_position.position.x;
  36. double center_y = vehicle_position.position.y;
  37. double rear_x = center_x - cos(yaw) * 0.945;
  38. double rear_y = center_y - sin(yaw) * 0.945;
  39. rear_pose.pose.position.x = rear_x;
  40. rear_pose.pose.position.y = rear_y;
  41. rear_pose.pose.orientation = vehicle_position.orientation;
  42. rear_pose_pub.publish(rear_pose);
  43. geometry_msgs::TwistStamped velocity;
  44. velocity.header.frame_id ="world";
  45. velocity.header.stamp = time_stamp;
  46. velocity.twist.linear = vehicle_velocity.linear;
  47. velocity.twist.angular = vehicle_velocity.angular;
  48. vel_pub.publish(velocity);
  49. }
  50. }
  51. }
  52. void vehicle_pose_and_velocity_updater::control(){
  53. ros::spin();
  54. }
  55. vehicle_pose_and_velocity_updater::vehicle_pose_and_velocity_updater(){
  56. rear_pose_pub = n.advertise<geometry_msgs::PoseStamped>("/smart/rear_pose", 10);
  57. center_pose_pub = n.advertise<geometry_msgs::PoseStamped>("/smart/center_pose", 10);
  58. vel_pub = n.advertise<geometry_msgs::TwistStamped>("/smart/velocity",10);
  59. model_states_sub = n.subscribe("/gazebo/model_states", 10, &vehicle_pose_and_velocity_updater::model_states_callback,this);
  60. }
  61. vehicle_pose_and_velocity_updater::~vehicle_pose_and_velocity_updater(){
  62. }

waypoint_loader.cpp

  1. #include "waypoint_loader.h"
  2. double waypoint_loader::two_points_distance(const geometry_msgs::Point &current_position, const geometry_msgs::Point &last_position){
  3. double x,y,z;
  4. x = current_position.x - last_position.x;
  5. y = current_position.y - last_position.y;
  6. z = current_position.z - last_position.z;
  7. return sqrt(x*x+y*y+z*z);
  8. }
  9. vector<styx_msgs::Waypoint> waypoint_loader::decelerate(const vector<styx_msgs::Waypoint> &data){
  10. vector<styx_msgs::Waypoint> Return_data = data;
  11. styx_msgs::Waypoint last;
  12. double dist, vel;
  13. last = data[waypoint_count -1];
  14. last.twist.twist.linear.x = 0;
  15. for (int i = 0; i < data.size(); i++)
  16. {
  17. dist = two_points_distance(data[i].pose.pose.position, last.pose.pose.position);
  18. vel = sqrt(2* MAX_DECEL* dist);
  19. if(vel<1){
  20. vel=0;
  21. }
  22. Return_data[i].twist.twist.linear.x = min(vel, data[i].twist.twist.linear.x);
  23. }
  24. return Return_data;
  25. }
  26. void waypoint_loader::getPose(std::string s, double *v)
  27. {
  28. int p = 0;
  29. int q = 0;
  30. for (int i = 0; i < s.size(); i++)
  31. {
  32. if (s[i] == ',' || i == s.size() - 1)
  33. {
  34. char tab2[16];
  35. strcpy(tab2, s.substr(p, i - p).c_str());
  36. v[q] = std::strtod(tab2, NULL);
  37. p = i + 1;
  38. q++;
  39. }
  40. }
  41. }
  42. int waypoint_loader::process(){
  43. std::ifstream f(ros::package::getPath("waypoint_loader") + "/waypoints/" + "waypoints.csv");
  44. //f.open(ros::package::find(plan_pkg)+"/paths/path.csv"); //ros::package::find(plan_pkg)
  45. if (!f.is_open())
  46. {
  47. ROS_ERROR("failed to open file");
  48. return 0;
  49. }
  50. std::string line;
  51. std::vector<styx_msgs::Waypoint> waypoints;
  52. styx_msgs::Lane lane;
  53. double scale = 100;
  54. int count = -1;
  55. nav_msgs::Path ros_path_;
  56. geometry_msgs::PoseArray track;
  57. track.header.stamp = ros::Time::now();
  58. track.header.frame_id = "/world";
  59. while (std::getline(f, line))
  60. {
  61. count++;
  62. double pose[3];
  63. getPose(line, pose);
  64. tf::Quaternion q = tf::createQuaternionFromRPY(0, 0, pose[2]);
  65. geometry_msgs::Pose pose1;
  66. geometry_msgs::PoseStamped pose2;
  67. styx_msgs::Waypoint pose3;
  68. ros_path_.header.frame_id = "/world";
  69. ros_path_.header.stamp = ros::Time::now();
  70. pose2.header = ros_path_.header;
  71. pose2.pose.position.x = pose[0];
  72. pose2.pose.position.y = pose[1];
  73. pose2.pose.position.z = 0;
  74. pose1.orientation.x = q.x();
  75. pose1.orientation.y = q.y();
  76. pose1.orientation.z = q.z();
  77. pose1.orientation.w = q.w();
  78. pose1.position.x = pose[0];
  79. pose1.position.y = pose[1];
  80. pose1.position.z = 0;
  81. pose3.pose.pose.position.x = pose[0];
  82. pose3.pose.pose.position.y = pose[1];
  83. pose3.pose.pose.position.z = 0;
  84. pose3.pose.pose.orientation.x = q.x();
  85. pose3.pose.pose.orientation.y = q.y();
  86. pose3.pose.pose.orientation.z = q.z();
  87. pose3.pose.pose.orientation.w = q.w();
  88. pose3.twist.twist.linear.x = 2.78;
  89. pose3.forward = true;
  90. waypoints.push_back(pose3);
  91. track.poses.push_back(pose1);
  92. ros_path_.poses.push_back(pose2);
  93. }
  94. waypoint_count = waypoints.size();
  95. waypoints = decelerate(waypoints);
  96. lane.header.frame_id = "world";
  97. lane.header.stamp = ros::Time::now();
  98. lane.waypoints = waypoints;
  99. while (ros::ok())
  100. {
  101. path_pub.publish(track);
  102. state_pub_.publish(ros_path_);
  103. path.publish(lane);
  104. }
  105. return 0;
  106. }
  107. int main(int argc, char **argv)
  108. {
  109. setlocale(LC_ALL, "");
  110. ros::init(argc, argv, "waypoint_loader");
  111. waypoint_loader waypoint_loader;
  112. ros::AsyncSpinner spinner(1);
  113. spinner.start();
  114. sleep(1);
  115. waypoint_loader.process();
  116. }

waypoint_updater.cpp

  1. #include "waypoint_updater.h"
  2. void waypoint_updater::publish_waypoints(const int &idx, const ros::Publisher &final_waypoints_pub, const ros::Publisher &final_path_pub){
  3. styx_msgs::Lane Lane_pub;
  4. Lane_pub.header = base_waypoints.header;
  5. if(idx + LOOKAHEAD_WPS < waypoint_count){
  6. for (int i = 0; i < LOOKAHEAD_WPS; i++)
  7. {
  8. Lane_pub.waypoints.push_back(base_waypoints.waypoints[idx+i]);
  9. }
  10. }
  11. else
  12. {
  13. for (int i = 0; i < waypoint_count - idx; i++)
  14. {
  15. Lane_pub.waypoints.push_back(base_waypoints.waypoints[idx+i]);
  16. }
  17. }
  18. nav_msgs::Path path;
  19. path.header.frame_id = "/world";
  20. for(int i = 0; i < Lane_pub.waypoints.size();i++){
  21. geometry_msgs::PoseStamped path_element;
  22. path_element.pose.position.x = Lane_pub.waypoints[i].pose.pose.position.x;
  23. path_element.pose.position.y = Lane_pub.waypoints[i].pose.pose.position.y;
  24. path_element.pose.position.z = Lane_pub.waypoints[i].pose.pose.position.z;
  25. path.poses.push_back(path_element);
  26. }
  27. final_waypoints_pub.publish(Lane_pub);
  28. final_path_pub.publish(path);
  29. }
  30. int waypoint_updater::get_closest_waypoint_idx(){
  31. pcl::PointXYZ searchPoint;
  32. searchPoint.x = pose.pose.position.x;
  33. searchPoint.y = pose.pose.position.y;
  34. searchPoint.z = pose.pose.position.z;
  35. vector<int> pointIdxNKNSearch(K);
  36. vector<float> pointNKNSquaredDistance(K);
  37. if(kdtree.nearestKSearch(searchPoint, K, pointIdxNKNSearch, pointNKNSquaredDistance) > 0){
  38. for (size_t i=0; i<pointIdxNKNSearch.size (); ++i){
  39. // cout << " 点" << (*cloud)[pointIdxNKNSearch[i]].x
  40. // << " " << (*cloud)[pointIdxNKNSearch[i]].y
  41. // << " " << (*cloud)[pointIdxNKNSearch[i]].z
  42. // << " (平方距离: " << pointNKNSquaredDistance[i] << ")" << endl;
  43. // cout << "Index :" << pointIdxNKNSearch[i] << endl;
  44. }
  45. return pointIdxNKNSearch[0];
  46. }
  47. }
  48. void waypoint_updater::pose_cb(const geometry_msgs::PoseStamped &msg)
  49. {
  50. pose = msg;
  51. // cout << pose << endl;
  52. }
  53. void waypoint_updater::waypoint_cb(const styx_msgs::Lane &waypoints)
  54. {
  55. waypoint_count = waypoints.waypoints.size();
  56. base_waypoints = waypoints;
  57. if((*cloud).size() == 0 ){
  58. cloud->width = 56;
  59. cloud->height = 1;
  60. cloud->points.resize(cloud->width * cloud->height);
  61. for (int i = 0; i < waypoints.waypoints.size(); i++){
  62. (*cloud)[i].x = waypoints.waypoints[i].pose.pose.position.x;
  63. (*cloud)[i].y = waypoints.waypoints[i].pose.pose.position.y;
  64. (*cloud)[i].z = waypoints.waypoints[i].pose.pose.position.z;
  65. }
  66. kdtree.setInputCloud(cloud);
  67. }
  68. }
  69. void waypoint_updater::process(){
  70. while(ros::ok())
  71. {
  72. ros::spinOnce();
  73. if(base_waypoints.waypoints.size()!=0){
  74. int closest_waypoint_idx = get_closest_waypoint_idx();
  75. publish_waypoints(closest_waypoint_idx, final_waypoints_pub, final_path_pub);
  76. }
  77. }
  78. }
  79. int main(int argc, char** argv){
  80. ros::init(argc, argv, "waypoint_updater");
  81. waypoint_updater waypoint_updater;
  82. waypoint_updater.process();
  83. return 0;
  84. }

pure_persuit.cpp

  1. #include "pure_persuit.h"
  2. geometry_msgs::Twist pure_persuit::calculateTwistCommand(){
  3. double lad = 0.0;
  4. int targetIndex = currentWaypoints.waypoints.size() -1;
  5. for(int i = 0; i<currentWaypoints.waypoints.size(); i++){
  6. if(i+1 < currentWaypoints.waypoints.size()){
  7. double this_x = currentWaypoints.waypoints[i].pose.pose.position.x;
  8. double this_y = currentWaypoints.waypoints[i].pose.pose.position.y;
  9. double next_x = currentWaypoints.waypoints[i+1].pose.pose.position.x;
  10. double next_y = currentWaypoints.waypoints[i+1].pose.pose.position.y;
  11. lad = lad + hypot(next_x - this_x, next_y - this_y);
  12. if(lad > HORIZON){
  13. targetIndex = i+1;
  14. break;
  15. }
  16. }
  17. }
  18. geometry_msgs::Twist twistCmd;
  19. styx_msgs::Waypoint targetWaypoint;
  20. double targetSpeed, targetX, targetY, currentX, currentY;
  21. targetWaypoint = currentWaypoints.waypoints[targetIndex];
  22. targetSpeed = currentWaypoints.waypoints[0].twist.twist.linear.x;
  23. targetX = targetWaypoint.pose.pose.position.x;
  24. targetY = targetWaypoint.pose.pose.position.y;
  25. currentX = currentPose.pose.position.x;
  26. currentY = currentPose.pose.position.y;
  27. tf::Quaternion q(currentPose.pose.orientation.x, currentPose.pose.orientation.y, currentPose.pose.orientation.z, currentPose.pose.orientation.w);
  28. double roll, pitch, yaw;
  29. tf::Matrix3x3(q).getRPY(roll, pitch, yaw);
  30. auto alpha = atan2(targetY - currentY, targetX - currentX) - yaw;
  31. auto l = sqrt(pow(currentX - targetX, 2) + pow(currentY - targetY, 2));
  32. if(l > 0.5){
  33. auto theta = atan(2 * 1.868 * sin(alpha) / l);
  34. twistCmd.linear.x = targetSpeed;
  35. twistCmd.angular.z = theta;
  36. }
  37. else{
  38. twistCmd.linear.x = 0;
  39. twistCmd.angular.z = 0;
  40. }
  41. return twistCmd;
  42. }
  43. void pure_persuit::process(){
  44. while (ros::ok())
  45. {
  46. ros::spinOnce();
  47. if(currentWaypoints.waypoints.size()!=0){
  48. geometry_msgs::Twist twistCommand = calculateTwistCommand();
  49. cmd_vel.publish(twistCommand);
  50. }
  51. }
  52. }
  53. void pure_persuit::pose_cb(const geometry_msgs::PoseStamped &data1){
  54. currentPose = data1;
  55. }
  56. void pure_persuit::vel_cb(const geometry_msgs::TwistStamped &data2){
  57. currentVelocity = data2;
  58. }
  59. void pure_persuit::lane_cb(const styx_msgs::Lane &data3){
  60. currentWaypoints = data3;
  61. }
  62. int main(int argc, char** argv){
  63. ros::init(argc, argv, "pure_persuit");
  64. pure_persuit pure_persuit;
  65. pure_persuit.process();
  66. return 0;
  67. }

github:GitHub - casso1993/Pure_Persuit_Simulation

1.open gazebo

roslaunch gazebo_ros empty_world.launch

2.run the set environment

roslaunch car_model spawn_car.launch

3.run rviz

rviz

File -> open config -> "src/car_model/rviz_config/samrt.rviz"

4.run pure persuit

roslaunch pure_persuit pure_persuit.launch

偷懒,先不写原理

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/weixin_40725706/article/detail/592102
推荐阅读
相关标签
  

闽ICP备14008679号