Skip to content

Commit f00250f

Browse files
baumantamrivi
baumanta
authored andcommitted
smoothing: add jerk limitation
1 parent 194b77a commit f00250f

File tree

4 files changed

+54
-35
lines changed

4 files changed

+54
-35
lines changed

local_planner/cfg/local_planner_node.cfg

+2
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@ gen.add("reproj_age_", int_t, 0, "maximum age of a reprojected point", 50, 0, 10
3636
gen.add("relevance_margin_e_degree_", double_t, 0, "obstacles at more than this angle from goal direction are ignored", 25, 0, 90)
3737
gen.add("relevance_margin_z_degree_", double_t, 0, "obstacles at more than this angle from goal direction are ignored", 40, 0, 180)
3838
gen.add("velocity_sigmoid_slope_", double_t, 0, "the bigger the bigger the acceleration", 1, 0, 10)
39+
gen.add("max_jerk_limit_", double_t, 0, "max jerk for smoothing (set to 0 to disable)", 700, 0, 2000)
40+
gen.add("min_jerk_limit_", double_t, 0, "min jerk for velocity-dependent max jerk (set to 0 to disable velocity-dependence)", 200, 0, 1000)
3941

4042
gen.add("use_vel_setpoints_", bool_t, 0, "Enable velocity setpoints (if false, position setpoints are used)", False)
4143
gen.add("stop_in_front_", bool_t, 0, "Enable stop in front of the obstacle", False)

local_planner/src/nodes/local_planner_node.cpp

+2
Original file line numberDiff line numberDiff line change
@@ -878,6 +878,8 @@ void LocalPlannerNode::dynamicReconfigureCallback(
878878
avoidance::LocalPlannerNodeConfig &config, uint32_t level) {
879879
std::lock_guard<std::mutex> guard(running_mutex_);
880880
local_planner_.dynamicReconfigureSetParams(config, level);
881+
wp_generator_.setMinJerkLimit(config.min_jerk_limit_);
882+
wp_generator_.setMaxJerkLimit(config.max_jerk_limit_);
881883
}
882884

883885
void LocalPlannerNode::threadFunction() {

local_planner/src/nodes/waypoint_generator.cpp

+27-32
Original file line numberDiff line numberDiff line change
@@ -244,33 +244,31 @@ void WaypointGenerator::reachGoalAltitudeFirst() {
244244
output_.goto_position.z = pose_.pose.position.z + pose_to_wp.z;
245245
}
246246

247-
// smooth trajectory by liming the maximim accelleration possible
248-
void WaypointGenerator::smoothWaypoint() {
249-
ros::Time time = ros::Time::now();
250-
ros::Duration time_diff = time - last_t_smooth_;
251-
double dt = time_diff.toSec() > 0.0 ? time_diff.toSec() : 0.004;
252-
last_t_smooth_ = time;
247+
void WaypointGenerator::smoothWaypoint(double dt) {
253248

254-
Eigen::Vector2f vel_xy(curr_vel_.twist.linear.x, curr_vel_.twist.linear.y);
255-
Eigen::Vector2f vel_waypt_xy(
249+
Eigen::Vector2f vel_cur_xy(curr_vel_.twist.linear.x, curr_vel_.twist.linear.y);
250+
Eigen::Vector2f vel_sp_xy(
256251
(output_.adapted_goto_position.x - last_position_waypoint_.pose.position.x) / dt,
257252
(output_.adapted_goto_position.y - last_position_waypoint_.pose.position.y) / dt);
258-
Eigen::Vector2f vel_waypt_xy_prev(
259-
(last_position_waypoint_.pose.position.x -
260-
last_last_position_waypoint_.pose.position.x) /
261-
dt,
262-
(last_position_waypoint_.pose.position.y -
263-
last_last_position_waypoint_.pose.position.y) /
264-
dt);
265-
Eigen::Vector2f acc_waypt_xy((vel_waypt_xy - vel_waypt_xy_prev) / dt);
266-
267-
if (acc_waypt_xy.norm() > (acc_waypt_xy.norm() / 2.0f)) {
268-
vel_xy = (acc_waypt_xy.norm() / 2.0f) * acc_waypt_xy.normalized() * dt +
269-
vel_waypt_xy_prev;
253+
254+
Eigen::Vector2f accel_diff = (vel_sp_xy - vel_cur_xy) / dt;
255+
Eigen::Vector2f accel_cur = (vel_cur_xy - last_velocity_) / dt;
256+
Eigen::Vector2f jerk_diff = (accel_diff - accel_cur) / dt;
257+
float max_jerk = max_jerk_limit_param_;
258+
259+
// velocity-dependent max jerk
260+
if (min_jerk_limit_param_ > 0.001f) {
261+
max_jerk *= vel_cur_xy.norm();
262+
if (max_jerk < min_jerk_limit_param_) max_jerk = min_jerk_limit_param_;
263+
}
264+
265+
if (jerk_diff.squaredNorm() > max_jerk * max_jerk && max_jerk > 0.001f) {
266+
jerk_diff = max_jerk * jerk_diff.normalized();
267+
vel_sp_xy = (jerk_diff * dt + accel_cur) * dt + vel_cur_xy;
270268
}
271269

272-
output_.smoothed_goto_position.x = last_position_waypoint_.pose.position.x + vel_xy(0) * dt;
273-
output_.smoothed_goto_position.y = last_position_waypoint_.pose.position.y + vel_xy(1) * dt;
270+
output_.smoothed_goto_position.x = last_position_waypoint_.pose.position.x + vel_sp_xy(0) * dt;
271+
output_.smoothed_goto_position.y = last_position_waypoint_.pose.position.y + vel_sp_xy(1) * dt;
274272
output_.smoothed_goto_position.z = output_.adapted_goto_position.z;
275273

276274
ROS_DEBUG("[WG] Smoothed waypoint: [%f %f %f].", output_.smoothed_goto_position.x,
@@ -354,11 +352,12 @@ void WaypointGenerator::adaptSpeed() {
354352
// create the message that is sent to the UAV
355353
void WaypointGenerator::getPathMsg() {
356354
output_.path.header.frame_id = "/world";
357-
last_last_position_waypoint_ = last_position_waypoint_;
358-
last_position_waypoint_ = output_.position_waypoint;
359-
last_yaw_ = curr_yaw_;
360355
output_.adapted_goto_position = output_.goto_position;
361356

357+
const ros::Time now = ros::Time::now();
358+
ros::Duration time_diff = now - last_time_;
359+
double dt = time_diff.toSec() > 0.0 ? time_diff.toSec() : 0.004;
360+
362361
// If avoid sphere is used, project waypoint on sphere
363362
if (planner_info_.use_avoid_sphere && planner_info_.avoid_sphere_age < 100 &&
364363
planner_info_.reach_altitude && !reached_goal_) {
@@ -387,11 +386,7 @@ void WaypointGenerator::getPathMsg() {
387386
ROS_DEBUG("[WG] pose altitude func: [%f %f %f].", pose_.pose.position.x,
388387
pose_.pose.position.y, pose_.pose.position.z);
389388
} else {
390-
if (!only_yawed_ && !reached_goal_) {
391-
smoothWaypoint();
392-
new_yaw_ = nextYaw(pose_, output_.smoothed_goto_position);
393-
;
394-
}
389+
smoothWaypoint(dt);
395390
}
396391

397392
// change waypoint if drone is at goal or above
@@ -431,10 +426,10 @@ void WaypointGenerator::getPathMsg() {
431426
transformPositionToVelocityWaypoint();
432427

433428
output_.path.poses.push_back(output_.position_waypoint);
434-
curr_yaw_ = new_yaw_;
435-
last_last_position_waypoint_ = last_position_waypoint_;
436429
last_position_waypoint_ = output_.position_waypoint;
437430
last_yaw_ = curr_yaw_;
431+
last_velocity_ = Eigen::Vector2f(curr_vel_.twist.linear.x, curr_vel_.twist.linear.y);
432+
last_time_ = now;
438433
}
439434

440435
void WaypointGenerator::getWaypoints(waypointResult &output) {

local_planner/src/nodes/waypoint_generator.h

+23-3
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,10 @@ class WaypointGenerator {
4747
double curr_vel_magnitude_;
4848
ros::Time update_time_;
4949
geometry_msgs::TwistStamped curr_vel_;
50+
ros::Time last_time_{0.};
51+
52+
double max_jerk_limit_param_{500.};
53+
double min_jerk_limit_param_{200.};
5054

5155
bool reached_goal_;
5256
bool waypoint_outside_FOV_;
@@ -59,11 +63,10 @@ class WaypointGenerator {
5963

6064
geometry_msgs::Point hover_position_;
6165
geometry_msgs::PoseStamped last_position_waypoint_;
62-
geometry_msgs::PoseStamped last_last_position_waypoint_;
66+
Eigen::Vector2f last_velocity_{0.f, 0.f}; ///< last vehicle's velocity
6367

6468
ros::Time velocity_time_;
6569
std::vector<int> z_FOV_idx_;
66-
ros::Time last_t_smooth_;
6770

6871
void calculateWaypoint();
6972
void updateState();
@@ -72,17 +75,34 @@ class WaypointGenerator {
7275
void transformPositionToVelocityWaypoint();
7376
bool withinGoalRadius();
7477
void reachGoalAltitudeFirst();
75-
void smoothWaypoint();
78+
void smoothWaypoint(double dt);
7679
void adaptSpeed();
7780
void getPathMsg();
7881

7982
public:
83+
8084
void getWaypoints(waypointResult &output);
8185
void setPlannerInfo(avoidanceOutput input);
8286
void updateState(geometry_msgs::PoseStamped act_pose,
8387
geometry_msgs::PoseStamped goal,
8488
geometry_msgs::TwistStamped vel, bool stay, ros::Time t);
8589

90+
/**
91+
* Set maximum jerk limitation. Set to 0 to disable.
92+
*/
93+
void setMaxJerkLimit(double max_jerk_limit) {
94+
max_jerk_limit_param_ = max_jerk_limit;
95+
}
96+
97+
/**
98+
* Set minimum jerk limitation for velocity-depdendent jerk limit.
99+
* Set to 0 to disable velocity-dependent jerk limit, and use a fixed
100+
* limit instead.
101+
*/
102+
void setMinJerkLimit(double min_jerk_limit) {
103+
min_jerk_limit_param_ = min_jerk_limit;
104+
}
105+
86106
WaypointGenerator();
87107
~WaypointGenerator();
88108
};

0 commit comments

Comments
 (0)