Skip to content

Commit 3a20e7e

Browse files
TranHuuNhatHuypre-commit-ci[bot]takam5f2
authored
feat: [codecov/refactoring] [simple_pure_pursuit] isolation of core logics, and full revamp of unit tests (#1182)
* init simpupu core logics module with Apache license * init simpupu core logics module with Apache license * init simpupu core logics header with Apache license * defined simpupu params struct * define public funcs * defined private funcs and entities for core logics * implement simple pure pursuit constructor and param setter * isolate create_control_command's core logics from the mess of ROS2+core logics in original node module * isolatecalc_longitudinal_control the same way * isolate calc_lateral_coltrol the same way * modified calc_lateral_control as for now completely immitates the original func (after discussing with the team) * refactored the simpupu main header - removing all core logics, leaving only ROS-related * refactored the simpupu main module - same way as headers - only ROS2 related + core logics inference * quick fixes based for clang compiler suggests * adapt cmakelists, package xml and header of core logics, thus wrapping up step 2 * test_simple_pure_pursuit.cpp - first make it work on build * removed the old test cases in unit test module because the old ones are bundled and obsoleted with new architecture * added test 1 of perfectly normal case ahppy tracking * added test 2 of strong terminal brake at trajectory goal * added test 3 of strong terminal brake when trajectory is wayyyyyyyy too short * added test 4 of overriding with external target velocity * adeed test 5 of lateral offset correcting * added test 6 of lookahead distance clamping (the current calc logic is weird so I had to resort to infinity check) * added final branch coverage case of lookahead point search exceeding trajectory length case * some final touchups, all good I guess * style(pre-commit): autofix * deal with spell-check-differential * fixed that cpplink precommit test of you dont need a ; after a } thingy * style(pre-commit): autofix * fixed that cpplint precommit of Add #include <memory> for make_unique<> [build/include_what_you_use] * change all to (yeah lol right, tbf I've used English for too long to the point of not thinking twice about plural single forms of these words * style(pre-commit): autofix * refactoring the file/class names as Ishikawa-san suggested * style(pre-commit): autofix * bring trajectory fallback to core logics * prevent node to return early upon false validation * dropping set_params() for ummitability * successful build * rebased, gonna add the precommit lint locally later * style(pre-commit): autofix * rebase * style(pre-commit): autofix * fixed spellcheck differentials * unified namespaces * Update control/autoware_simple_pure_pursuit/src/simple_pure_pursuit.hpp Co-authored-by: Takayuki AKAMINE <38586589+takam5f2@users.noreply.github.com> * [akamine] redundant function set_params() at header * [akamine] remove branch redundancy in clongitudinal control command core logic * [akamine] name the magic number -10.0 as terminal_brake_accel at simple_pure_pursuit logic header and apply it to whole node * [akamine] fix typo EXCEPT=>EXPECT * [akamine] fix class name in docstring * [akamine] node name inconsistency fix --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Takayuki AKAMINE <38586589+takam5f2@users.noreply.github.com>
1 parent 883f77c commit 3a20e7e

9 files changed

Lines changed: 417 additions & 213 deletions

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,3 +16,5 @@ log/
1616

1717
#prettier
1818
node_modules/
19+
.cache/
20+
lcov/

control/autoware_simple_pure_pursuit/CMakeLists.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@ rclcpp_components_register_node(${PROJECT_NAME}_lib
1515

1616
if(BUILD_TESTING)
1717
find_package(ament_cmake_gtest REQUIRED)
18+
find_package(autoware_testing REQUIRED)
19+
find_package(autoware_test_utils REQUIRED)
20+
1821
ament_add_ros_isolated_gtest(test_simple_pure_pursuit_integration
1922
test/test_simple_pure_pursuit_integration.cpp
2023
)

control/autoware_simple_pure_pursuit/package.xml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@
2727
<test_depend>ament_index_cpp</test_depend>
2828
<test_depend>ament_lint_auto</test_depend>
2929
<test_depend>autoware_lint_common</test_depend>
30+
<test_depend>autoware_test_utils</test_depend>
31+
<test_depend>autoware_testing</test_depend>
3032

3133
<export>
3234
<build_type>ament_cmake</build_type>

control/autoware_simple_pure_pursuit/src/simple_pure_pursuit.cpp

Lines changed: 41 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -21,53 +21,20 @@
2121

2222
namespace autoware::control::simple_pure_pursuit
2323
{
24-
using autoware::motion_utils::findNearestIndex;
2524

26-
SimplePurePursuitNode::SimplePurePursuitNode(const rclcpp::NodeOptions & node_options)
27-
: Node("simple_pure_pursuit", node_options),
28-
pub_control_command_(
29-
create_publisher<autoware_control_msgs::msg::Control>(
30-
"~/output/control_command", rclcpp::QoS(1).transient_local())),
31-
vehicle_info_(autoware::vehicle_info_utils::VehicleInfoUtils(*this).getVehicleInfo()),
32-
lookahead_gain_(declare_parameter<float>("lookahead_gain")),
33-
lookahead_min_distance_(declare_parameter<float>("lookahead_min_distance")),
34-
speed_proportional_gain_(declare_parameter<float>("speed_proportional_gain")),
35-
use_external_target_vel_(declare_parameter<bool>("use_external_target_vel")),
36-
external_target_vel_(declare_parameter<float>("external_target_vel"))
37-
{
38-
using namespace std::literals::chrono_literals;
39-
timer_ = rclcpp::create_timer(
40-
this, get_clock(), 30ms, std::bind(&SimplePurePursuitNode::on_timer, this));
41-
}
25+
using autoware::motion_utils::findNearestIndex;
4226

43-
void SimplePurePursuitNode::on_timer()
27+
// Constructor
28+
SimplePurePursuit::SimplePurePursuit(const SimplePurePursuitParameters & params) : params_(params)
4429
{
45-
// 1. subscribe data
46-
const auto odom_ptr = odom_sub_.take_data();
47-
const auto traj_ptr = traj_sub_.take_data();
48-
if (!odom_ptr || !traj_ptr) {
49-
return;
50-
}
51-
52-
// 2. extract subscribed data
53-
const auto odom = *odom_ptr;
54-
const auto traj = *traj_ptr;
55-
56-
// 3. create control command
57-
const auto control_command = create_control_command(odom, traj);
58-
59-
// 4. publish control command
60-
pub_control_command_->publish(control_command);
6130
}
6231

63-
autoware_control_msgs::msg::Control SimplePurePursuitNode::create_control_command(
64-
const Odometry & odom, const Trajectory & traj)
32+
// Core logic for creating control command based on current odom and traj
33+
autoware_control_msgs::msg::Control SimplePurePursuit::create_control_command(
34+
const nav_msgs::msg::Odometry & odom, const autoware_planning_msgs::msg::Trajectory & traj) const
6535
{
66-
// Check for empty trajectory
36+
// Trajectory fallback now at core logic too
6737
if (traj.points.empty()) {
68-
RCLCPP_WARN_THROTTLE(
69-
get_logger(), *get_clock(), 5000,
70-
"Received empty trajectory, returning zero velocity command.");
7138
autoware_control_msgs::msg::Control cmd;
7239
cmd.stamp = odom.header.stamp;
7340
cmd.longitudinal.velocity = 0.0;
@@ -77,83 +44,87 @@ autoware_control_msgs::msg::Control SimplePurePursuitNode::create_control_comman
7744

7845
const size_t closest_traj_point_idx = findNearestIndex(traj.points, odom.pose.pose.position);
7946

80-
// when the ego reaches the goal
81-
if (closest_traj_point_idx == traj.points.size() - 1 || traj.points.size() <= 5) {
47+
// When ego reaches goal or traj is too short, stop vehicle
48+
if ((closest_traj_point_idx == traj.points.size() - 1) || (traj.points.size() <= 5)) {
8249
autoware_control_msgs::msg::Control control_command;
8350
control_command.stamp = odom.header.stamp;
8451
control_command.longitudinal.velocity = 0.0;
85-
control_command.longitudinal.acceleration = -10.0;
52+
control_command.longitudinal.acceleration = terminal_brake_accel;
8653
control_command.longitudinal.is_defined_acceleration = true;
87-
RCLCPP_DEBUG_THROTTLE(get_logger(), *get_clock(), 5000, "reached to the goal");
54+
8855
return control_command;
8956
}
9057

91-
// calculate target longitudinal velocity
58+
// Calculate target longitudinal velocity
9259
const double target_longitudinal_vel =
93-
use_external_target_vel_ ? external_target_vel_
94-
: traj.points.at(closest_traj_point_idx).longitudinal_velocity_mps;
60+
params_.use_external_target_vel
61+
? params_.external_target_vel
62+
: traj.points.at(closest_traj_point_idx).longitudinal_velocity_mps;
9563

96-
// calculate control command
64+
// Calculate control command
9765
autoware_control_msgs::msg::Control control_command;
9866
control_command.stamp = odom.header.stamp;
9967
control_command.longitudinal = calc_longitudinal_control(odom, target_longitudinal_vel);
10068
control_command.lateral =
10169
calc_lateral_control(odom, traj, target_longitudinal_vel, closest_traj_point_idx);
10270

10371
return control_command;
104-
}
72+
};
10573

106-
autoware_control_msgs::msg::Longitudinal SimplePurePursuitNode::calc_longitudinal_control(
107-
const Odometry & odom, const double target_longitudinal_vel) const
74+
// Core logic for calculating longitudinal control command
75+
autoware_control_msgs::msg::Longitudinal SimplePurePursuit::calc_longitudinal_control(
76+
const nav_msgs::msg::Odometry & odom, const double target_longitudinal_vel) const
10877
{
109-
const double current_longitudinal_vel = odom.twist.twist.linear.x;
110-
11178
autoware_control_msgs::msg::Longitudinal longitudinal_control_command;
79+
const double current_velocity = odom.twist.twist.linear.x;
80+
11281
longitudinal_control_command.velocity = static_cast<float>(target_longitudinal_vel);
11382
longitudinal_control_command.acceleration = static_cast<float>(
114-
speed_proportional_gain_ * (target_longitudinal_vel - current_longitudinal_vel));
83+
(target_longitudinal_vel - current_velocity) * params_.speed_proportional_gain);
11584

11685
return longitudinal_control_command;
117-
}
86+
};
11887

119-
autoware_control_msgs::msg::Lateral SimplePurePursuitNode::calc_lateral_control(
120-
const Odometry & odom, const Trajectory & traj, const double target_longitudinal_vel,
121-
const size_t closest_traj_point_idx) const
88+
// Core logic for calculating lateral control command
89+
autoware_control_msgs::msg::Lateral SimplePurePursuit::calc_lateral_control(
90+
const nav_msgs::msg::Odometry & odom, const autoware_planning_msgs::msg::Trajectory & traj,
91+
const double target_longitudinal_vel, const size_t closest_traj_point_idx) const
12292
{
123-
// calculate lookahead distance
93+
// Calculate lookahead distance
12494
const double lookahead_distance =
125-
lookahead_gain_ * target_longitudinal_vel + lookahead_min_distance_;
95+
params_.lookahead_gain * target_longitudinal_vel + params_.lookahead_min_distance;
12696

127-
// calculate center coordinate of rear wheel
97+
// Calculate center coordinate of rear wheel
12898
const double vehicle_heading = tf2::getYaw(odom.pose.pose.orientation);
12999
const double rear_x =
130-
odom.pose.pose.position.x - vehicle_info_.wheel_base_m / 2.0 * std::cos(vehicle_heading);
100+
odom.pose.pose.position.x - params_.wheel_base_m / 2.0 * std::cos(vehicle_heading);
131101
const double rear_y =
132-
odom.pose.pose.position.y - vehicle_info_.wheel_base_m / 2.0 * std::sin(vehicle_heading);
102+
odom.pose.pose.position.y - params_.wheel_base_m / 2.0 * std::sin(vehicle_heading);
133103

134-
// search lookahead point
104+
// Search for the lookahead point on the trajectory
135105
auto lookahead_point_itr = std::find_if(
136106
traj.points.begin() + static_cast<std::ptrdiff_t>(closest_traj_point_idx), traj.points.end(),
137-
[&](const TrajectoryPoint & point) {
107+
[&](const autoware_planning_msgs::msg::TrajectoryPoint & point) {
138108
return std::hypot(point.pose.position.x - rear_x, point.pose.position.y - rear_y) >=
139109
lookahead_distance;
140110
});
111+
141112
if (lookahead_point_itr == traj.points.end()) {
142113
lookahead_point_itr = traj.points.end() - 1;
143114
}
115+
144116
const double lookahead_point_x = lookahead_point_itr->pose.position.x;
145117
const double lookahead_point_y = lookahead_point_itr->pose.position.y;
146118

147-
// calculate steering angle
119+
// Calculate pure pursuit steering angle
148120
autoware_control_msgs::msg::Lateral lateral_control_command;
149121
const double alpha = std::atan2(lookahead_point_y - rear_y, lookahead_point_x - rear_x) -
150122
tf2::getYaw(odom.pose.pose.orientation);
123+
151124
lateral_control_command.steering_tire_angle = static_cast<float>(
152-
std::atan2(2.0 * vehicle_info_.wheel_base_m * std::sin(alpha), lookahead_distance));
125+
std::atan2(2.0 * params_.wheel_base_m * std::sin(alpha), lookahead_distance));
153126

154127
return lateral_control_command;
155128
}
156-
} // namespace autoware::control::simple_pure_pursuit
157129

158-
#include <rclcpp_components/register_node_macro.hpp>
159-
RCLCPP_COMPONENTS_REGISTER_NODE(autoware::control::simple_pure_pursuit::SimplePurePursuitNode)
130+
}; // namespace autoware::control::simple_pure_pursuit

control/autoware_simple_pure_pursuit/src/simple_pure_pursuit.hpp

Lines changed: 62 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -15,63 +15,83 @@
1515
#ifndef SIMPLE_PURE_PURSUIT_HPP_
1616
#define SIMPLE_PURE_PURSUIT_HPP_
1717

18-
#include <autoware_utils_rclcpp/polling_subscriber.hpp>
19-
#include <autoware_vehicle_info_utils/vehicle_info_utils.hpp>
20-
#include <rclcpp/rclcpp.hpp>
21-
2218
#include <autoware_control_msgs/msg/control.hpp>
2319
#include <autoware_planning_msgs/msg/trajectory.hpp>
24-
#include <autoware_planning_msgs/msg/trajectory_point.hpp>
2520
#include <nav_msgs/msg/odometry.hpp>
2621

2722
namespace autoware::control::simple_pure_pursuit
2823
{
29-
using autoware_planning_msgs::msg::Trajectory;
30-
using autoware_planning_msgs::msg::TrajectoryPoint;
31-
using nav_msgs::msg::Odometry;
3224

33-
class SimplePurePursuitNode : public rclcpp::Node
25+
/**
26+
@ brief Params for SimplePurePursuit class
27+
*
28+
* @param lookahead_gain Gain for calculating lookahead distance
29+
* @param lookahead_min_distance Minimum lookahead distance
30+
* @param speed_proportional_gain Proportional gain for longitudinal control
31+
* @param use_external_target_vel Whether to use external target velocity or not
32+
* @param external_target_vel External target velocity to use when use_external_target_vel is true
33+
* @param wheel_base_m Wheel base of vehicle in meters
34+
*/
35+
struct SimplePurePursuitParameters
3436
{
35-
public:
36-
explicit SimplePurePursuitNode(const rclcpp::NodeOptions & node_options);
37-
38-
private:
39-
// subscribers
40-
autoware_utils_rclcpp::InterProcessPollingSubscriber<Odometry> odom_sub_{
41-
this, "~/input/odometry"};
42-
autoware_utils_rclcpp::InterProcessPollingSubscriber<Trajectory> traj_sub_{
43-
this, "~/input/trajectory"};
37+
double lookahead_gain;
38+
double lookahead_min_distance;
39+
double speed_proportional_gain;
40+
bool use_external_target_vel;
41+
double external_target_vel;
42+
double wheel_base_m;
43+
};
4444

45-
// publishers
46-
rclcpp::Publisher<autoware_control_msgs::msg::Control>::SharedPtr pub_control_command_;
45+
class SimplePurePursuit
46+
{
47+
public:
48+
// Constructor
49+
explicit SimplePurePursuit(const SimplePurePursuitParameters & params);
4750

48-
// timer
49-
rclcpp::TimerBase::SharedPtr timer_;
51+
/**
52+
* @brief Create control command based on current odom and traj
53+
*
54+
* @param odom Current odometry of vehicle
55+
* @param traj Current trajectory to follow
56+
*
57+
* @return Control command to be published
58+
*/
59+
[[nodiscard]] autoware_control_msgs::msg::Control create_control_command(
60+
const nav_msgs::msg::Odometry & odom,
61+
const autoware_planning_msgs::msg::Trajectory & traj) const;
5062

51-
// vehicle info
52-
const autoware::vehicle_info_utils::VehicleInfo vehicle_info_;
63+
// Hard-coded acceleration for terminal brake
64+
static constexpr double terminal_brake_accel = -10.0;
5365

54-
// pure pursuit parameters
55-
const double lookahead_gain_;
56-
const double lookahead_min_distance_;
57-
const double speed_proportional_gain_;
58-
const bool use_external_target_vel_;
59-
const double external_target_vel_;
66+
private:
67+
const SimplePurePursuitParameters params_;
6068

61-
// functions
62-
void on_timer();
63-
autoware_control_msgs::msg::Control create_control_command(
64-
const Odometry & odom, const Trajectory & traj);
65-
autoware_control_msgs::msg::Longitudinal calc_longitudinal_control(
66-
const Odometry & odom, const double target_longitudinal_vel) const;
67-
autoware_control_msgs::msg::Lateral calc_lateral_control(
68-
const Odometry & odom, const Trajectory & traj, const double target_longitudinal_vel,
69-
const size_t closest_traj_point_idx) const;
69+
/**
70+
* @brief Calculate longitudinal control command
71+
*
72+
* @param odom Current odometry of vehicle
73+
* @param target_longitudinal_vel Target longitudinal velocity to achieve
74+
*
75+
* @return Longitudinal control command
76+
*/
77+
[[nodiscard]] autoware_control_msgs::msg::Longitudinal calc_longitudinal_control(
78+
const nav_msgs::msg::Odometry & odom, const double target_longitudinal_vel) const;
7079

71-
public:
72-
friend class SimplePurePursuitNodeTest;
80+
/**
81+
* @brief Calculate lateral control command
82+
*
83+
* @param odom Current odometry of vehicle
84+
* @param traj Current trajectory to follow
85+
* @param target_longitudinal_vel Target longitudinal velocity to achieve
86+
* @param closest_traj_point_idx Index of closest trajectory point to current vehicle position
87+
*
88+
* @return Lateral control command
89+
*/
90+
[[nodiscard]] autoware_control_msgs::msg::Lateral calc_lateral_control(
91+
const nav_msgs::msg::Odometry & odom, const autoware_planning_msgs::msg::Trajectory & traj,
92+
const double target_longitudinal_vel, const size_t closest_traj_point_idx) const;
7393
};
7494

75-
} // namespace autoware::control::simple_pure_pursuit
95+
}; // namespace autoware::control::simple_pure_pursuit
7696

7797
#endif // SIMPLE_PURE_PURSUIT_HPP_

0 commit comments

Comments
 (0)