Skip to content

Commit dff3ac8

Browse files
authored
Merge pull request #44 from fmrico/adjust_processing_times_costmap
Adjust output time in costamp stack
2 parents 83a9827 + 39b2936 commit dff3ac8

13 files changed

Lines changed: 81 additions & 71 deletions

File tree

controllers/easynav_serest_controller/include/easynav_serest_controller/SerestController.hpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,7 @@ class SerestController : public ControllerMethodBase
182182
* @return double Minimum obstacle distance (m). Infinity if none is found.
183183
*/
184184
double closest_obstacle_distance(
185-
const NavState & nav_state) const;
185+
const NavState & nav_state);
186186

187187
/**
188188
* @brief Compute a safe linear speed bound from obstacle distance and slope.
@@ -226,7 +226,7 @@ class SerestController : public ControllerMethodBase
226226
void safety_limits(
227227
const NavState & nav_state,
228228
const RefKinematics & rk,
229-
double & d_closest, double & v_safe, double & v_curv) const;
229+
double & d_closest, double & v_safe, double & v_curv);
230230

231231
// Aplica corner‑guard: ajusta v_prog_ref y obtiene omega_boost + término ápice.
232232
void apply_corner_guard(
@@ -354,6 +354,8 @@ class SerestController : public ControllerMethodBase
354354
double last_vrot_{0.0};
355355
/// @brief Last update timestamp.
356356
rclcpp::Time last_update_ts_;
357+
/// @brief Last input timestamp (max of path and odom).
358+
rclcpp::Time last_input_ts_;
357359
/// @brief Output TwistStamped buffer.
358360
geometry_msgs::msg::TwistStamped twist_stamped_;
359361
};

controllers/easynav_serest_controller/src/easynav_serest_controller/SerestController.cpp

Lines changed: 26 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -287,7 +287,7 @@ SerestController::frenet_errors(
287287

288288
double
289289
SerestController::closest_obstacle_distance(
290-
const NavState & nav_state) const
290+
const NavState & nav_state)
291291
{
292292
// 1) Prefer direct measurement if it exists
293293
if (nav_state.has("closest_obstacle_distance")) {
@@ -304,14 +304,18 @@ SerestController::closest_obstacle_distance(
304304
const auto & perceptions = nav_state.get<PointPerceptions>("points");
305305
const auto & tf_info = RTTFBuffer::getInstance()->get_tf_info();
306306

307-
auto fused = PointPerceptionsOpsView(perceptions)
308-
.downsample(0.3)
309-
.fuse(tf_info.robot_footprint_frame)
310-
.filter({-dist_search_radius_, -dist_search_radius_, NAN},
311-
{dist_search_radius_, dist_search_radius_, 2.0})
312-
.collapse({NAN, NAN, 0.1})
313-
.downsample(0.3)
314-
.as_points();
307+
auto view = PointPerceptionsOpsView(perceptions);
308+
view.downsample(0.3)
309+
.fuse(tf_info.robot_footprint_frame)
310+
.filter({-dist_search_radius_, -dist_search_radius_, NAN},
311+
{dist_search_radius_, dist_search_radius_, 2.0})
312+
.collapse({NAN, NAN, 0.1})
313+
.downsample(0.3);
314+
const auto & fused = view.as_points();
315+
316+
if (last_input_ts_ < view.get_latest_stamp()) {
317+
last_input_ts_ = view.get_latest_stamp();
318+
}
315319

316320
double min_dist = std::numeric_limits<double>::infinity();
317321
for (const auto p : fused) {
@@ -377,6 +381,13 @@ SerestController::fetch_required_inputs(
377381
path = nav_state.get<nav_msgs::msg::Path>("path");
378382
odom = nav_state.get<nav_msgs::msg::Odometry>("robot_pose");
379383

384+
if (rclcpp::Time(path.header.stamp, last_input_ts_.get_clock_type()) > last_input_ts_) {
385+
last_input_ts_ = path.header.stamp;
386+
}
387+
if (rclcpp::Time(odom.header.stamp, last_input_ts_.get_clock_type()) > last_input_ts_) {
388+
last_input_ts_ = odom.header.stamp;
389+
}
390+
380391
if (path.poses.empty()) {
381392
publish_stop(nav_state, path.header.frame_id);
382393
return false;
@@ -427,7 +438,7 @@ void
427438
SerestController::safety_limits(
428439
const NavState & nav_state,
429440
const RefKinematics & rk,
430-
double & d_closest, double & v_safe, double & v_curv) const
441+
double & d_closest, double & v_safe, double & v_curv)
431442
{
432443
d_closest = closest_obstacle_distance(nav_state);
433444
v_safe = v_safe_from_distance(d_closest, /*slope_sin=*/0.0);
@@ -535,7 +546,7 @@ SerestController::maybe_final_align_and_publish(
535546

536547
// Publicación y actualización de estado
537548
twist_stamped_.header.frame_id = path.header.frame_id;
538-
twist_stamped_.header.stamp = get_node()->now();
549+
twist_stamped_.header.stamp = last_input_ts_;
539550
twist_stamped_.twist.linear.x = vlin;
540551
twist_stamped_.twist.angular.z = vrot;
541552

@@ -578,7 +589,7 @@ SerestController::publish_cmd_and_debug(
578589
int in_final_align, int arrived)
579590
{
580591
twist_stamped_.header.frame_id = path.header.frame_id;
581-
twist_stamped_.header.stamp = get_node()->now();
592+
twist_stamped_.header.stamp = last_input_ts_;
582593
twist_stamped_.twist.linear.x = vlin;
583594
twist_stamped_.twist.angular.z = vrot;
584595
nav_state.set("cmd_vel", twist_stamped_);
@@ -601,7 +612,7 @@ SerestController::publish_cmd_and_debug(
601612
void
602613
SerestController::publish_stop(NavState & nav_state, const std::string & frame_id)
603614
{
604-
auto now = get_node()->now();
615+
auto now = last_input_ts_;
605616
twist_stamped_.header.frame_id = frame_id;
606617
twist_stamped_.header.stamp = now;
607618
twist_stamped_.twist.linear.x = 0.0;
@@ -655,13 +666,12 @@ SerestController::update_rt(NavState & nav_state)
655666

656667
// 6.5) Early turn-in-place with hysteresis (start-of-path aware)
657668
{
658-
const double PI = 3.14159265358979323846;
659669
const double s_total = pd.s_acc.back();
660670
const double dist_to_end = s_total - prj.s_star;
661671

662672
// Internal angular thresholds (enter/exit)
663-
const double thr_enter = 60.0 * PI / 180.0;
664-
const double thr_exit = 35.0 * PI / 180.0;
673+
const double thr_enter = 60.0 * M_PI / 180.0;
674+
const double thr_exit = 35.0 * M_PI / 180.0;
665675
const double near_start_s = 0.30; // treat the first 30 cm as the start region
666676

667677
// Base request from the regular criterion (using the provided threshold)

localizers/easynav_costmap_localizer/src/easynav_costmap_localizer/AMCLLocalizer.cpp

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,8 @@ AMCLLocalizer::AMCLLocalizer()
177177
double roll, pitch, yaw;
178178
tf2::Matrix3x3(q).getRPY(roll, pitch, yaw);
179179

180-
ret << "Odometry with pose: (x: " << x << ", y: " << y << ", yaw: " << yaw << ")";
180+
ret << "{" << rclcpp::Time(odom.header.stamp).seconds() << " } Odometry with pose: (x: " <<
181+
x << ", y: " << y << ", yaw: " << yaw << ")";
181182
return ret.str();
182183
});
183184
}
@@ -269,6 +270,7 @@ AMCLLocalizer::on_initialize()
269270
"initialpose", 10, std::bind(&AMCLLocalizer::init_pose_callback, this, std::placeholders::_1));
270271

271272
last_reseed_ = get_node()->now();
273+
last_input_time_ = get_node()->now();
272274

273275
get_node()->get_logger().set_level(rclcpp::Logger::Level::Debug);
274276
}
@@ -583,19 +585,22 @@ AMCLLocalizer::correct(NavState & nav_state)
583585
const auto & map_static = nav_state.get<Costmap2D>("map.static");
584586

585587
const auto & tf_info = RTTFBuffer::getInstance()->get_tf_info();
586-
const auto & filtered = PointPerceptionsOpsView(perceptions)
587-
.downsample(map_static.getResolution())
588-
.fuse(tf_info.robot_footprint_frame)
589-
.filter({NAN, NAN, 0.1}, {NAN, NAN, NAN})
590-
.collapse({NAN, NAN, 0.1})
591-
.downsample(map_static.getResolution())
592-
.as_points();
588+
589+
auto view = PointPerceptionsOpsView(perceptions);
590+
view.downsample(map_static.getResolution())
591+
.fuse(tf_info.robot_footprint_frame)
592+
.filter({NAN, NAN, 0.1}, {NAN, NAN, NAN})
593+
.collapse({NAN, NAN, 0.1})
594+
.downsample(map_static.getResolution());
595+
const auto & filtered = view.as_points();
593596

594597
if (filtered.empty()) {
595598
RCLCPP_WARN(get_node()->get_logger(), "No points to correct");
596599
return;
597600
}
598601

602+
last_input_time_ = view.get_latest_stamp();
603+
599604
for (auto & particle : particles_) {
600605
int hits = 0;
601606
int possible_hits = 0;

localizers/easynav_navmap_localizer/src/easynav_navmap_localizer/AMCLLocalizer.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -357,7 +357,8 @@ AMCLLocalizer::AMCLLocalizer()
357357
tf2::Quaternion q(odom.pose.pose.orientation.x, odom.pose.pose.orientation.y,
358358
odom.pose.pose.orientation.z, odom.pose.pose.orientation.w);
359359
double r, p, y; tf2::Matrix3x3(q).getRPY(r, p, y);
360-
ret << "Odometry with pose: (x: " << odom.pose.pose.position.x
360+
ret << "{" << rclcpp::Time(odom.header.stamp).seconds() << "} Odometry with pose: (x: " <<
361+
odom.pose.pose.position.x
361362
<< ", y: " << odom.pose.pose.position.y << ", yaw: " << y << ")";
362363
return ret.str();
363364
});

localizers/easynav_simple_localizer/src/easynav_simple_localizer/AMCLLocalizer.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,8 @@ AMCLLocalizer::AMCLLocalizer()
175175
double roll, pitch, yaw;
176176
tf2::Matrix3x3(q).getRPY(roll, pitch, yaw);
177177

178-
ret << "Odometry with pose: (x: " << x << ", y: " << y << ", yaw: " << yaw << ")";
178+
ret << "{" << rclcpp::Time(odom.header.stamp).seconds() << "} Odometry with pose: (x: " <<
179+
x << ", y: " << y << ", yaw: " << yaw << ")";
179180
return ret.str();
180181
});
181182
}

maps_managers/easynav_costmap_maps_manager/src/easynav_costmap_maps_manager/CostmapMapsManager.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,10 @@ CostmapMapsManager::update(NavState & nav_state)
195195

196196
nav_state.set("map.dynamic.filtered", dynamic_map_);
197197

198+
if (!nav_state.has("map_time")) {
199+
nav_state.set("map_time", get_node()->now());
200+
}
201+
198202
for (const auto & filter : costmap_filters_) {
199203
filter->update(nav_state);
200204
}
@@ -203,9 +207,11 @@ CostmapMapsManager::update(NavState & nav_state)
203207

204208
const auto & tf_info = RTTFBuffer::getInstance()->get_tf_info();
205209

210+
rclcpp::Time map_stamp = nav_state.get<rclcpp::Time>("map_time");
211+
206212
dynamic_map_->toOccupancyGridMsg(dynamic_grid_msg_);
207213
dynamic_grid_msg_.header.frame_id = tf_info.map_frame;
208-
dynamic_grid_msg_.header.stamp = get_node()->now();
214+
dynamic_grid_msg_.header.stamp = map_stamp;
209215
dynamic_occ_pub_->publish(dynamic_grid_msg_);
210216
}
211217

maps_managers/easynav_costmap_maps_manager/src/easynav_costmap_maps_manager/filters/ObstacleFilter.cpp

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -55,11 +55,16 @@ ObstacleFilter::update(NavState & nav_state)
5555
Costmap2D & dynamic_map = *dynamic_map_ptr;
5656
const auto & tf_info = RTTFBuffer::getInstance()->get_tf_info();
5757

58-
auto fused = PointPerceptionsOpsView(perceptions)
59-
.downsample(dynamic_map.getResolution())
60-
.fuse(tf_info.map_frame)
61-
.filter({NAN, NAN, 0.1}, {NAN, NAN, NAN})
62-
.as_points();
58+
rclcpp::Time stamp;
59+
60+
auto view = PointPerceptionsOpsView(perceptions);
61+
view.downsample(dynamic_map.getResolution())
62+
.fuse(tf_info.map_frame, stamp, false)
63+
.filter({NAN, NAN, 0.1}, {NAN, NAN, NAN});
64+
65+
const auto & fused = view.as_points();
66+
67+
nav_state.set("map_time", stamp);
6368

6469
double min_x = std::numeric_limits<double>::max();
6570
double min_y = std::numeric_limits<double>::max();

maps_managers/easynav_costmap_maps_manager/tests/costmap_mapsmanager_tests.cpp

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -19,17 +19,6 @@ class CostmapMapsManagerTest : public ::testing::Test
1919
void SetUp() override
2020
{
2121
rclcpp::init(0, nullptr);
22-
easynav::NavState::register_printer<easynav::PointPerceptions>(
23-
[](const easynav::PointPerceptions & perceptions) {
24-
std::ostringstream ret;
25-
ret << "PointPerception " << perceptions.size() << " with:\n";
26-
for (const auto & perception : perceptions) {
27-
ret << "\t[" << static_cast<const void *>(perception.get()) << "] --> "
28-
<< perception->data.size() << " points in frame [" << perception->frame_id
29-
<< "] with ts " << perception->stamp.seconds() << "\n";
30-
}
31-
return ret.str();
32-
});
3322
}
3423

3524
void TearDown() override

maps_managers/easynav_navmap_maps_manager/tests/navmap_mapsmanager_tests.cpp

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -22,17 +22,6 @@ class NavMapMapsManagerTest : public ::testing::Test
2222
void SetUp() override
2323
{
2424
rclcpp::init(0, nullptr);
25-
::easynav::NavState::register_printer<easynav::PointPerceptions>(
26-
[](const easynav::PointPerceptions & perceptions) {
27-
std::ostringstream ret;
28-
ret << "PointPerception " << perceptions.size() << " with:\n";
29-
for (const auto & perception : perceptions) {
30-
ret << "\t[" << static_cast<const void *>(perception.get()) << "] --> "
31-
<< perception->data.size() << " points in frame [" << perception->frame_id
32-
<< "] with ts " << perception->stamp.seconds() << "\n";
33-
}
34-
return ret.str();
35-
});
3625
}
3726

3827
void TearDown() override

maps_managers/easynav_simple_maps_manager/tests/simple_mapsmanager_tests.cpp

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -40,18 +40,6 @@ class SimpleMapsManagerTest : public ::testing::Test
4040
void SetUp() override
4141
{
4242
rclcpp::init(0, nullptr);
43-
44-
easynav::NavState::register_printer<easynav::PointPerceptions>(
45-
[](const easynav::PointPerceptions & perceptions) {
46-
std::ostringstream ret;
47-
ret << "PointPerception " << perceptions.size() << " with:\n";
48-
for (const auto & perception : perceptions) {
49-
ret << "\t[" << static_cast<const void *>(perception.get()) << "] --> "
50-
<< perception->data.size() << " points in frame [" << perception->frame_id
51-
<< "] with ts " << perception->stamp.seconds() << "\n";
52-
}
53-
return ret.str();
54-
});
5543
}
5644

5745
void TearDown() override

0 commit comments

Comments
 (0)