Skip to content

Commit 00b96cc

Browse files
committed
feat(pid_longitudinal_controller): fix some bugs and improve delay compensation #4712
Signed-off-by: Berkay Karaman <brkay54@gmail.com>
1 parent be626b7 commit 00b96cc

File tree

5 files changed

+467
-384
lines changed

5 files changed

+467
-384
lines changed

control/pid_longitudinal_controller/include/pid_longitudinal_controller/longitudinal_controller_utils.hpp

+18-10
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,7 @@
2929
#include <cmath>
3030
#include <limits>
3131

32-
namespace autoware::motion::control::pid_longitudinal_controller
33-
{
34-
namespace longitudinal_utils
32+
namespace autoware::motion::control::pid_longitudinal_controller::longitudinal_utils
3533
{
3634

3735
using autoware_auto_planning_msgs::msg::Trajectory;
@@ -75,9 +73,8 @@ double calcElevationAngle(const TrajectoryPoint & p_from, const TrajectoryPoint
7573
* @brief calculate vehicle pose after time delay by moving the vehicle at current velocity and
7674
* acceleration for delayed time
7775
*/
78-
Pose calcPoseAfterTimeDelay(
79-
const Pose & current_pose, const double delay_time, const double current_vel,
80-
const double current_acc);
76+
std::pair<double, double> calcDistAndVelAfterTimeDelay(
77+
const double delay_time, const double current_vel, const double current_acc);
8178

8279
/**
8380
* @brief apply linear interpolation to orientation
@@ -93,7 +90,7 @@ Quaternion lerpOrientation(const Quaternion & o_from, const Quaternion & o_to, c
9390
* @param [in] point Interpolated point is nearest to this point.
9491
*/
9592
template <class T>
96-
TrajectoryPoint lerpTrajectoryPoint(
93+
std::pair<TrajectoryPoint, size_t> lerpTrajectoryPoint(
9794
const T & points, const Pose & pose, const double max_dist, const double max_yaw)
9895
{
9996
TrajectoryPoint interpolated_point;
@@ -112,6 +109,8 @@ TrajectoryPoint lerpTrajectoryPoint(
112109
points.at(i).pose.position.x, points.at(i + 1).pose.position.x, interpolate_ratio);
113110
interpolated_point.pose.position.y = interpolation::lerp(
114111
points.at(i).pose.position.y, points.at(i + 1).pose.position.y, interpolate_ratio);
112+
interpolated_point.pose.position.z = interpolation::lerp(
113+
points.at(i).pose.position.z, points.at(i + 1).pose.position.z, interpolate_ratio);
115114
interpolated_point.pose.orientation = lerpOrientation(
116115
points.at(i).pose.orientation, points.at(i + 1).pose.orientation, interpolate_ratio);
117116
interpolated_point.longitudinal_velocity_mps = interpolation::lerp(
@@ -125,7 +124,7 @@ TrajectoryPoint lerpTrajectoryPoint(
125124
points.at(i).heading_rate_rps, points.at(i + 1).heading_rate_rps, interpolate_ratio);
126125
}
127126

128-
return interpolated_point;
127+
return std::make_pair(interpolated_point, seg_idx);
129128
}
130129

131130
/**
@@ -149,7 +148,16 @@ double applyDiffLimitFilter(
149148
double applyDiffLimitFilter(
150149
const double input_val, const double prev_val, const double dt, const double max_val,
151150
const double min_val);
152-
} // namespace longitudinal_utils
153-
} // namespace autoware::motion::control::pid_longitudinal_controller
151+
152+
/**
153+
* @brief calculate the projected pose after distance from the current index
154+
* @param [in] src_idx current index
155+
* @param [in] distance distance to project
156+
* @param [in] trajectory reference trajectory
157+
*/
158+
geometry_msgs::msg::Pose findTrajectoryPoseAfterDistance(
159+
const size_t src_idx, const double distance,
160+
const autoware_auto_planning_msgs::msg::Trajectory & trajectory);
161+
} // namespace autoware::motion::control::pid_longitudinal_controller::longitudinal_utils
154162

155163
#endif // PID_LONGITUDINAL_CONTROLLER__LONGITUDINAL_CONTROLLER_UTILS_HPP_

control/pid_longitudinal_controller/include/pid_longitudinal_controller/pid_longitudinal_controller.hpp

+21-17
Original file line numberDiff line numberDiff line change
@@ -64,13 +64,25 @@ class PidLongitudinalController : public trajectory_follower::LongitudinalContro
6464
double vel{0.0};
6565
double acc{0.0};
6666
};
67-
67+
struct StateAfterDelay
68+
{
69+
StateAfterDelay(const double velocity, const double acceleration, const double distance)
70+
: vel(velocity), acc(acceleration), running_distance(distance)
71+
{
72+
}
73+
double vel{0.0};
74+
double acc{0.0};
75+
double running_distance{0.0};
76+
};
6877
enum class Shift { Forward = 0, Reverse };
6978

7079
struct ControlData
7180
{
7281
bool is_far_from_trajectory{false};
82+
autoware_auto_planning_msgs::msg::Trajectory interpolated_traj{};
7383
size_t nearest_idx{0}; // nearest_idx = 0 when nearest_idx is not found with findNearestIdx
84+
size_t target_idx{0};
85+
StateAfterDelay state_after_delay{0.0, 0.0, 0.0};
7486
Motion current_motion{};
7587
Shift shift{Shift::Forward}; // shift is used only to calculate the sign of pitch compensation
7688
double stop_dist{0.0}; // signed distance that is positive when car is before the stopline
@@ -268,11 +280,9 @@ class PidLongitudinalController : public trajectory_follower::LongitudinalContro
268280

269281
/**
270282
* @brief calculate control command based on the current control state
271-
* @param [in] current_pose current ego pose
272283
* @param [in] control_data control data
273284
*/
274-
Motion calcCtrlCmd(
275-
const geometry_msgs::msg::Pose & current_pose, const ControlData & control_data);
285+
Motion calcCtrlCmd(const ControlData & control_data);
276286

277287
/**
278288
* @brief publish control command
@@ -303,7 +313,7 @@ class PidLongitudinalController : public trajectory_follower::LongitudinalContro
303313
* @brief calculate direction (forward or backward) that vehicle moves
304314
* @param [in] nearest_idx nearest index on trajectory to vehicle
305315
*/
306-
enum Shift getCurrentShift(const size_t nearest_idx) const;
316+
enum Shift getCurrentShift(const ControlData & control_data) const;
307317

308318
/**
309319
* @brief filter acceleration command with limitation of acceleration and jerk, and slope
@@ -342,7 +352,8 @@ class PidLongitudinalController : public trajectory_follower::LongitudinalContro
342352
* @param [in] point vehicle position
343353
* @param [in] nearest_idx index of the trajectory point nearest to the vehicle position
344354
*/
345-
autoware_auto_planning_msgs::msg::TrajectoryPoint calcInterpolatedTargetValue(
355+
std::pair<autoware_auto_planning_msgs::msg::TrajectoryPoint, size_t>
356+
calcInterpolatedTrajPointAndSegment(
346357
const autoware_auto_planning_msgs::msg::Trajectory & traj,
347358
const geometry_msgs::msg::Pose & pose) const;
348359

@@ -351,18 +362,14 @@ class PidLongitudinalController : public trajectory_follower::LongitudinalContro
351362
* @param [in] current_motion current velocity and acceleration of the vehicle
352363
* @param [in] delay_compensation_time predicted time delay
353364
*/
354-
double predictedVelocityInTargetPoint(
365+
StateAfterDelay predictedStateAfterDelay(
355366
const Motion current_motion, const double delay_compensation_time) const;
356367

357368
/**
358369
* @brief calculate velocity feedback with feed forward and pid controller
359-
* @param [in] target_motion reference velocity and acceleration. This acceleration will be used
360-
* as feed forward.
361-
* @param [in] dt time step to use
362-
* @param [in] current_vel current velocity of the vehicle
370+
* @param [in] control_data data for control calculation
363371
*/
364-
double applyVelocityFeedback(
365-
const Motion target_motion, const double dt, const double current_vel);
372+
double applyVelocityFeedback(const ControlData & control_data);
366373

367374
/**
368375
* @brief update variables for debugging about pitch
@@ -375,12 +382,9 @@ class PidLongitudinalController : public trajectory_follower::LongitudinalContro
375382
/**
376383
* @brief update variables for velocity and acceleration
377384
* @param [in] ctrl_cmd latest calculated control command
378-
* @param [in] current_pose current pose of the vehicle
379385
* @param [in] control_data data for control calculation
380386
*/
381-
void updateDebugVelAcc(
382-
const Motion & ctrl_cmd, const geometry_msgs::msg::Pose & current_pose,
383-
const ControlData & control_data);
387+
void updateDebugVelAcc(const Motion & ctrl_cmd, const ControlData & control_data);
384388
};
385389
} // namespace autoware::motion::control::pid_longitudinal_controller
386390

control/pid_longitudinal_controller/src/longitudinal_controller_utils.cpp

+44-26
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,6 @@
1717
#include "tf2/LinearMath/Matrix3x3.h"
1818
#include "tf2/LinearMath/Quaternion.h"
1919

20-
#include <experimental/optional> // NOLINT
21-
2220
#ifdef ROS_DISTRO_GALACTIC
2321
#include "tf2_geometry_msgs/tf2_geometry_msgs.h"
2422
#else
@@ -28,9 +26,7 @@
2826
#include <algorithm>
2927
#include <limits>
3028

31-
namespace autoware::motion::control::pid_longitudinal_controller
32-
{
33-
namespace longitudinal_utils
29+
namespace autoware::motion::control::pid_longitudinal_controller::longitudinal_utils
3430
{
3531

3632
bool isValidTrajectory(const Trajectory & traj)
@@ -48,11 +44,7 @@ bool isValidTrajectory(const Trajectory & traj)
4844
}
4945

5046
// when trajectory is empty
51-
if (traj.points.empty()) {
52-
return false;
53-
}
54-
55-
return true;
47+
return !traj.points.empty();
5648
}
5749

5850
double calcStopDistance(
@@ -75,7 +67,9 @@ double calcStopDistance(
7567

7668
double getPitchByPose(const Quaternion & quaternion_msg)
7769
{
78-
double roll, pitch, yaw;
70+
double roll{0.0};
71+
double pitch{0.0};
72+
double yaw{0.0};
7973
tf2::Quaternion quaternion;
8074
tf2::fromMsg(quaternion_msg, quaternion);
8175
tf2::Matrix3x3{quaternion}.getRPY(roll, pitch, yaw);
@@ -128,12 +122,11 @@ double calcElevationAngle(const TrajectoryPoint & p_from, const TrajectoryPoint
128122
return pitch;
129123
}
130124

131-
Pose calcPoseAfterTimeDelay(
132-
const Pose & current_pose, const double delay_time, const double current_vel,
133-
const double current_acc)
125+
std::pair<double, double> calcDistAndVelAfterTimeDelay(
126+
const double delay_time, const double current_vel, const double current_acc)
134127
{
135128
if (delay_time <= 0.0) {
136-
return current_pose;
129+
return std::make_pair(0.0, 0.0);
137130
}
138131

139132
// check time to stop
@@ -142,17 +135,11 @@ Pose calcPoseAfterTimeDelay(
142135
const double delay_time_calculation =
143136
time_to_stop > 0.0 && time_to_stop < delay_time ? time_to_stop : delay_time;
144137
// simple linear prediction
145-
const double yaw = tf2::getYaw(current_pose.orientation);
138+
const double vel_after_delay = current_vel + current_acc * delay_time_calculation;
146139
const double running_distance = delay_time_calculation * current_vel + 0.5 * current_acc *
147140
delay_time_calculation *
148141
delay_time_calculation;
149-
const double dx = running_distance * std::cos(yaw);
150-
const double dy = running_distance * std::sin(yaw);
151-
152-
auto pred_pose = current_pose;
153-
pred_pose.position.x += dx;
154-
pred_pose.position.y += dy;
155-
return pred_pose;
142+
return std::make_pair(running_distance, vel_after_delay);
156143
}
157144

158145
double lerp(const double v_from, const double v_to, const double ratio)
@@ -162,7 +149,8 @@ double lerp(const double v_from, const double v_to, const double ratio)
162149

163150
Quaternion lerpOrientation(const Quaternion & o_from, const Quaternion & o_to, const double ratio)
164151
{
165-
tf2::Quaternion q_from, q_to;
152+
tf2::Quaternion q_from;
153+
tf2::Quaternion q_to;
166154
tf2::fromMsg(o_from, q_from);
167155
tf2::fromMsg(o_to, q_to);
168156

@@ -187,5 +175,35 @@ double applyDiffLimitFilter(
187175
const double min_val = -max_val;
188176
return applyDiffLimitFilter(input_val, prev_val, dt, max_val, min_val);
189177
}
190-
} // namespace longitudinal_utils
191-
} // namespace autoware::motion::control::pid_longitudinal_controller
178+
179+
geometry_msgs::msg::Pose findTrajectoryPoseAfterDistance(
180+
const size_t src_idx, const double distance,
181+
const autoware_auto_planning_msgs::msg::Trajectory & trajectory)
182+
{
183+
double remain_dist = distance;
184+
geometry_msgs::msg::Pose p = trajectory.points.back().pose;
185+
for (size_t i = src_idx; i < trajectory.points.size() - 1; ++i) {
186+
const double dist = tier4_autoware_utils::calcDistance3d(
187+
trajectory.points.at(i).pose, trajectory.points.at(i + 1).pose);
188+
if (remain_dist < dist) {
189+
if (remain_dist <= 0.0) {
190+
return trajectory.points.at(i).pose;
191+
}
192+
double ratio = remain_dist / dist;
193+
p = trajectory.points.at(i).pose;
194+
p.position.x = trajectory.points.at(i).pose.position.x +
195+
ratio * (trajectory.points.at(i + 1).pose.position.x -
196+
trajectory.points.at(i).pose.position.x);
197+
p.position.y = trajectory.points.at(i).pose.position.y +
198+
ratio * (trajectory.points.at(i + 1).pose.position.y -
199+
trajectory.points.at(i).pose.position.y);
200+
p.position.z = trajectory.points.at(i).pose.position.z +
201+
ratio * (trajectory.points.at(i + 1).pose.position.z -
202+
trajectory.points.at(i).pose.position.z);
203+
break;
204+
}
205+
remain_dist -= dist;
206+
}
207+
return p;
208+
}
209+
} // namespace autoware::motion::control::pid_longitudinal_controller::longitudinal_utils

0 commit comments

Comments
 (0)