Formula Student Autonomous Systems
The code for the main driverless system
Loading...
Searching...
No Matches
pure_pursuit.cpp
Go to the documentation of this file.
2
3using namespace common_lib::structures;
4
9PurePursuit::PurePursuit(const ControlParameters& params) : LateralController(params),
10 lpf_(std::make_shared<LowPassFilter>(params.pure_pursuit_lpf_alpha_, params.pure_pursuit_lpf_initial_value_)) {}
11
12void PurePursuit::path_callback(const custom_interfaces::msg::PathPointArray& msg) {
13 this->last_path_msg_ = msg.pathpoint_array;
14 this->received_first_path_ = true;
15}
16
17void PurePursuit::vehicle_state_callback(const custom_interfaces::msg::Velocities& msg) {
18 this->last_velocity_msg_ = msg;
19 this->absolute_velocity_ = std::sqrt(msg.velocity_x * msg.velocity_x + msg.velocity_y * msg.velocity_y);
20 this->received_first_state_ = true;
21}
22
23void PurePursuit::vehicle_pose_callback(const custom_interfaces::msg::Pose& vehicle_pose_msg) {
24 this->last_pose_msg_ = vehicle_pose_msg;
25 this->received_first_pose_ = true;
26}
27
29 double steering_command = 0.0;
30
32 // Prepare inputs for the Pure Pursuit control law
33 Position vehicle_cog = Position(this->last_pose_msg_.x, this->last_pose_msg_.y);
34 Position rear_axis = ::rear_axis_position(vehicle_cog, this->last_pose_msg_.theta,
35 this->params_->car_parameters_.dist_cg_2_rear_axis);
36 auto [closest_point, closest_point_id, closest_point_velocity] =
37 ::get_closest_point(this->last_path_msg_, rear_axis);
38
39 this->closest_point_ = closest_point;
40
41 if (closest_point_id != -1) {
42 double ld = std::max(this->params_->pure_pursuit_lookahead_gain_ * this->absolute_velocity_,
43 this->params_->pure_pursuit_lookahead_minimum_);
44 auto [lookahead_point, lookahead_velocity, lookahead_error] =
45 ::get_lookahead_point(this->last_path_msg_, closest_point_id, ld, rear_axis, this->params_->first_last_max_dist_);
46
47 this->lookahead_point_ = lookahead_point;
48
49 if (!lookahead_error) {
50 steering_command = pp_steering_control_law(rear_axis, vehicle_cog,
51 lookahead_point, this->params_->car_parameters_.dist_cg_2_rear_axis);
52 }
53 }
54 }
55
56 return steering_command;
57}
58
60 Position lookahead_point, double dist_cg_2_rear_axis) {
61 double alpha = calculate_alpha(rear_axis, cg, lookahead_point, dist_cg_2_rear_axis);
62 // update lookahead distance to the actual distance
63 double ld = rear_axis.euclidean_distance(lookahead_point);
64
65 double steering_angle = std::atan(2 * this->params_->car_parameters_.wheelbase * std::sin(alpha) / ld);
66 double filtered_steering_angle = lpf_->filter(steering_angle);
67
68 return std::clamp(filtered_steering_angle, this->params_->car_parameters_.steering_parameters.minimum_steering_angle,
69 this->params_->car_parameters_.steering_parameters.maximum_steering_angle);
70}
71
72double PurePursuit::calculate_alpha(Position vehicle_rear_wheel, Position vehicle_cg,
73 Position lookahead_point, double dist_cg_2_rear_axis) {
74 double lookhead_point_2_rear_wheel = vehicle_rear_wheel.euclidean_distance(lookahead_point);
75 double lookhead_point_2_cg = lookahead_point.euclidean_distance(vehicle_cg);
76
77 // Law of cosines
78 double cos_alpha = (std::pow(lookhead_point_2_rear_wheel, 2) + std::pow(dist_cg_2_rear_axis, 2) -
79 std::pow(lookhead_point_2_cg, 2)) /
80 (2 * lookhead_point_2_rear_wheel * dist_cg_2_rear_axis);
81
82 cos_alpha = std::clamp(cos_alpha, -1.0, 1.0);
83 double alpha = std::acos(cos_alpha);
84
85 if (cross_product(vehicle_rear_wheel, vehicle_cg, lookahead_point) < 0) {
86 alpha = -alpha;
87 }
88
89 return alpha;
90}
91
92void PurePursuit::publish_solver_data(std::shared_ptr<rclcpp::Node> node, std::map<std::string, std::shared_ptr<rclcpp::PublisherBase>>& publisher_map) {
93 this->publish_closest_point(node, publisher_map);
94 this->publish_lookahead_point(node, publisher_map);
95}
96
97void PurePursuit::publish_closest_point(std::shared_ptr<rclcpp::Node> node, std::map<std::string, std::shared_ptr<rclcpp::PublisherBase>>& publisher_map) {
98 if (publisher_map.find("/pure_pursuit/closest_point") == publisher_map.end()) {
99 auto publisher = node->create_publisher<visualization_msgs::msg::Marker>("/pure_pursuit/closest_point", 10);
100 publisher_map["/pure_pursuit/closest_point"] = publisher;
101 }
102
103 auto publisher = std::static_pointer_cast<rclcpp::Publisher<visualization_msgs::msg::Marker>>(publisher_map["/pure_pursuit/closest_point"]);
104 visualization_msgs::msg::Marker closest_marker = common_lib::communication::marker_from_position(this->closest_point_,
105 "pure_pursuit", 0, "blue");
106 publisher->publish(closest_marker);
107}
108
109void PurePursuit::publish_lookahead_point(std::shared_ptr<rclcpp::Node> node, std::map<std::string, std::shared_ptr<rclcpp::PublisherBase>>& publisher_map) {
110 if (publisher_map.find("/pure_pursuit/lookahead_point") == publisher_map.end()) {
111 auto publisher = node->create_publisher<visualization_msgs::msg::Marker>("/pure_pursuit/lookahead_point", 10);
112 publisher_map["/pure_pursuit/lookahead_point"] = publisher;
113 }
114
115 auto publisher = std::static_pointer_cast<rclcpp::Publisher<visualization_msgs::msg::Marker>>(publisher_map["/pure_pursuit/lookahead_point"]);
116
117 visualization_msgs::msg::Marker lookahead_marker = common_lib::communication::marker_from_position(this->lookahead_point_,
118 "pure_pursuit", 0, "red");
119 publisher->publish(lookahead_marker);
120}
Base (abstract) class for lateral control solvers (that calculate steering command)
std::shared_ptr< ControlParameters > params_
Low Pass Filter class.
void publish_solver_data(std::shared_ptr< rclcpp::Node > node, std::map< std::string, std::shared_ptr< rclcpp::PublisherBase > > &publisher_map) override
Publishes solver specific data using the provided ControlNode.
bool received_first_state_
bool received_first_path_
void path_callback(const custom_interfaces::msg::PathPointArray &msg) override
Called when a new path is sent by Path Planning.
std::shared_ptr< Filter > lpf_
std::vector< custom_interfaces::msg::PathPoint > last_path_msg_
common_lib::structures::Position lookahead_point_
void vehicle_state_callback(const custom_interfaces::msg::Velocities &msg) override
Called when the car state (currently just velocity) is updated.
custom_interfaces::msg::Velocities last_velocity_msg_
custom_interfaces::msg::Pose last_pose_msg_
double absolute_velocity_
double get_steering_command() override
Returns the steering command calculated by the solver.
double pp_steering_control_law(common_lib::structures::Position rear_axis, common_lib::structures::Position cg, common_lib::structures::Position lookahead_point, double dist_cg_2_rear_axis)
Pure Pursuit control law.
void vehicle_pose_callback(const custom_interfaces::msg::Pose &msg) override
Called when the car pose is updated by SLAM.
double calculate_alpha(common_lib::structures::Position vehicle_rear_wheel, common_lib::structures::Position vehicle_cg, common_lib::structures::Position lookahead_point, double rear_wheel_2_c_g)
Calculate alpha (angle between the vehicle and lookahead point)
void publish_lookahead_point(std::shared_ptr< rclcpp::Node > node, std::map< std::string, std::shared_ptr< rclcpp::PublisherBase > > &publisher_map)
Function that publishes the lookahead point marker.
bool received_first_pose_
common_lib::structures::Position closest_point_
PurePursuit(const ControlParameters &params)
Construct a new Pure Pursuit object.
void publish_closest_point(std::shared_ptr< rclcpp::Node > node, std::map< std::string, std::shared_ptr< rclcpp::PublisherBase > > &publisher_map)
Function that publishes the closest point marker.
std::tuple< common_lib::structures::Position, int, double > get_closest_point(const std::vector< custom_interfaces::msg::PathPoint > &pathpoint_array, const common_lib::structures::Position &position)
Find the closest point on the path.
Definition utils.cpp:14
common_lib::structures::Position rear_axis_position(const common_lib::structures::Position &cg, double orientation, double dist_cg_2_rear_axis)
Calculate rear axis coordinates.
Definition utils.cpp:5
std::tuple< common_lib::structures::Position, double, bool > get_lookahead_point(const std::vector< custom_interfaces::msg::PathPoint > &pathpoint_array, int closest_point_id, double lookahead_distance, common_lib::structures::Position rear_axis_position, double last_to_first_max_dist)
Update Lookahead point.
Definition utils.cpp:35
visualization_msgs::msg::Marker marker_from_position(const common_lib::structures::Position &position, const std::string &name_space, const int id, const std::string &color="red", float scale=0.5, const std::string &frame_id="map", const std::string &shape="sphere", int action=visualization_msgs::msg::Marker::ADD)
Converts a position to a marker.
Definition marker.cpp:5
double cross_product(const Position &p1, const Position &p2, const Position &p3)
Calculate the cross product of two vectors.
Definition position.cpp:18
Hash function for cones.
Definition cone.hpp:36
double euclidean_distance(const Position &other) const
Definition position.cpp:10