Skip to content

Commit 3b7f4e4

Browse files
author
asarazin
committed
optimization
Signed-off-by: asarazin <[email protected]>
1 parent 8264866 commit 3b7f4e4

File tree

5 files changed

+141
-108
lines changed

5 files changed

+141
-108
lines changed

nav2_collision_monitor/include/nav2_collision_monitor/collision_monitor_node.hpp

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include <string>
1919
#include <vector>
2020
#include <memory>
21+
#include <unordered_map>
2122

2223
#include "rclcpp/rclcpp.hpp"
2324
#include "geometry_msgs/msg/twist.hpp"
@@ -159,28 +160,30 @@ class CollisionMonitor : public nav2_util::LifecycleNode
159160
/**
160161
* @brief Processes the polygon of STOP, SLOWDOWN and LIMIT action type
161162
* @param polygon Polygon to process
162-
* @param collision_points Array of 2D obstacle points
163+
* @param sources_collision_points_map Map containing source name as key and
164+
* array of source's 2D obstacle points as value
163165
* @param velocity Desired robot velocity
164166
* @param robot_action Output processed robot action
165167
* @return True if returned action is caused by current polygon, otherwise false
166168
*/
167169
bool processStopSlowdownLimit(
168170
const std::shared_ptr<Polygon> polygon,
169-
const std::vector<Point> & collision_points,
171+
const std::unordered_map<std::string, std::vector<Point>> & sources_collision_points_map,
170172
const Velocity & velocity,
171173
Action & robot_action) const;
172174

173175
/**
174176
* @brief Processes APPROACH action type
175177
* @param polygon Polygon to process
176-
* @param collision_points Array of 2D obstacle points
178+
* @param sources_collision_points_map Map containing source name as key and
179+
* array of source's 2D obstacle points as value
177180
* @param velocity Desired robot velocity
178181
* @param robot_action Output processed robot action
179182
* @return True if returned action is caused by current polygon, otherwise false
180183
*/
181184
bool processApproach(
182185
const std::shared_ptr<Polygon> polygon,
183-
const std::vector<Point> & collision_points,
186+
const std::unordered_map<std::string, std::vector<Point>> & sources_collision_points_map,
184187
const Velocity & velocity,
185188
Action & robot_action) const;
186189

nav2_collision_monitor/include/nav2_collision_monitor/polygon.hpp

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include <memory>
1919
#include <string>
2020
#include <vector>
21+
#include <unordered_map>
2122

2223
#include "rclcpp/rclcpp.hpp"
2324
#include "geometry_msgs/msg/polygon_stamped.hpp"
@@ -151,16 +152,28 @@ class Polygon
151152
*/
152153
virtual int getPointsInside(const std::vector<Point> & points) const;
153154

155+
/**
156+
* @brief Gets number of points inside given polygon
157+
* @param sources_collision_points_map Map containing source name as key,
158+
* and input array of source's points to be checked as value
159+
* @return Number of points inside polygon,
160+
* for sources in map that are associated with current polygon.
161+
* If there are no points, returns zero value.
162+
*/
163+
virtual int getPointsInside(
164+
const std::unordered_map<std::string, std::vector<Point>> & sources_collision_points_map) const;
165+
154166
/**
155167
* @brief Obtains estimated (simulated) time before a collision.
156168
* Applicable for APPROACH model.
157-
* @param collision_points Array of 2D obstacle points
169+
* @param sources_collision_points_map Map containing source name as key,
170+
* and input array of source's 2D obstacle points as value
158171
* @param velocity Simulated robot velocity
159172
* @return Estimated time before a collision. If there is no collision,
160173
* return value will be negative.
161174
*/
162175
double getCollisionTime(
163-
const std::vector<Point> & collision_points,
176+
const std::unordered_map<std::string, std::vector<Point>> & sources_collision_points_map,
164177
const Velocity & velocity) const;
165178

166179
/**

nav2_collision_monitor/src/collision_monitor_node.cpp

Lines changed: 40 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -414,24 +414,19 @@ void CollisionMonitor::process(const Velocity & cmd_vel_in, const std_msgs::msg:
414414
// Points array collected from different data sources in a robot base frame
415415
std::unordered_map<std::string, std::vector<Point>> sources_collision_points_map;
416416

417-
// Fill collision_points array from different data sources
418-
for (std::shared_ptr<Source> source : sources_) {
419-
std::vector<Point> collision_points;
420-
source->getData(curr_time, collision_points);
421-
sources_collision_points_map.insert({source->getSourceName(), collision_points});
422-
}
423-
424417
// By default - there is no action
425418
Action robot_action{DO_NOTHING, cmd_vel_in, ""};
426419
// Polygon causing robot action (if any)
427420
std::shared_ptr<Polygon> action_polygon;
428421

429-
// Fill collision_points array from different data sources
422+
// Fill collision points array from different data sources
430423
for (std::shared_ptr<Source> source : sources_) {
424+
std::vector<Point> collision_points;
425+
auto iter = sources_collision_points_map.insert({source->getSourceName(), collision_points});
426+
bool is_source_valid = source->getData(curr_time, iter.first->second);
427+
431428
if (source->getEnabled()) {
432-
if (!source->getData(curr_time, collision_points) &&
433-
source->getSourceTimeout().seconds() != 0.0)
434-
{
429+
if (!is_source_valid && source->getSourceTimeout().seconds() != 0.0) {
435430
action_polygon = nullptr;
436431
robot_action.polygon_name = "invalid source";
437432
robot_action.action_type = STOP;
@@ -441,34 +436,34 @@ void CollisionMonitor::process(const Velocity & cmd_vel_in, const std_msgs::msg:
441436
break;
442437
}
443438
}
444-
}
445439

446-
if (collision_points_marker_pub_->get_subscription_count() > 0) {
447-
// visualize collision points with markers
448-
auto marker_array = std::make_unique<visualization_msgs::msg::MarkerArray>();
449-
visualization_msgs::msg::Marker marker;
450-
marker.header.frame_id = get_parameter("base_frame_id").as_string();
451-
marker.header.stamp = rclcpp::Time(0, 0);
452-
marker.ns = "collision_points";
453-
marker.id = 0;
454-
marker.type = visualization_msgs::msg::Marker::POINTS;
455-
marker.action = visualization_msgs::msg::Marker::ADD;
456-
marker.scale.x = 0.02;
457-
marker.scale.y = 0.02;
458-
marker.color.r = 1.0;
459-
marker.color.a = 1.0;
460-
marker.lifetime = rclcpp::Duration(0, 0);
461-
marker.frame_locked = true;
462-
463-
for (const auto & point : collision_points) {
464-
geometry_msgs::msg::Point p;
465-
p.x = point.x;
466-
p.y = point.y;
467-
p.z = 0.0;
468-
marker.points.push_back(p);
440+
if (collision_points_marker_pub_->get_subscription_count() > 0) {
441+
// visualize collision points with markers
442+
auto marker_array = std::make_unique<visualization_msgs::msg::MarkerArray>();
443+
visualization_msgs::msg::Marker marker;
444+
marker.header.frame_id = get_parameter("base_frame_id").as_string();
445+
marker.header.stamp = rclcpp::Time(0, 0);
446+
marker.ns = "collision_points";
447+
marker.id = 0;
448+
marker.type = visualization_msgs::msg::Marker::POINTS;
449+
marker.action = visualization_msgs::msg::Marker::ADD;
450+
marker.scale.x = 0.02;
451+
marker.scale.y = 0.02;
452+
marker.color.r = 1.0;
453+
marker.color.a = 1.0;
454+
marker.lifetime = rclcpp::Duration(0, 0);
455+
marker.frame_locked = true;
456+
457+
for (const auto & point : iter.first->second) {
458+
geometry_msgs::msg::Point p;
459+
p.x = point.x;
460+
p.y = point.y;
461+
p.z = 0.0;
462+
marker.points.push_back(p);
463+
}
464+
marker_array->markers.push_back(marker);
465+
collision_points_marker_pub_->publish(std::move(marker_array));
469466
}
470-
marker_array->markers.push_back(marker);
471-
collision_points_marker_pub_->publish(std::move(marker_array));
472467
}
473468

474469
for (std::shared_ptr<Polygon> polygon : polygons_) {
@@ -483,37 +478,17 @@ void CollisionMonitor::process(const Velocity & cmd_vel_in, const std_msgs::msg:
483478
// Update polygon coordinates
484479
polygon->updatePolygon(cmd_vel_in);
485480

486-
// Get collision points for sources associated to polygon
487-
std::vector<std::string> sources_names = polygon->getSourcesNames();
488-
std::vector<Point> collision_points;
489-
for (auto source_name : sources_names) {
490-
try {
491-
// Get vector for source
492-
auto source_collision_points = sources_collision_points_map.at(source_name);
493-
// Concatenate vectors
494-
collision_points.insert(
495-
collision_points.end(),
496-
source_collision_points.begin(),
497-
source_collision_points.end());
498-
} catch (std::exception & e) {
499-
RCLCPP_ERROR_STREAM_THROTTLE(
500-
get_logger(),
501-
*get_clock(),
502-
1000,
503-
"Observation source [" << source_name <<
504-
"] configured for polygon [" << polygon->getName() << "] is not defined!");
505-
}
506-
}
507-
508481
const ActionType at = polygon->getActionType();
509482
if (at == STOP || at == SLOWDOWN || at == LIMIT) {
510483
// Process STOP/SLOWDOWN for the selected polygon
511-
if (processStopSlowdownLimit(polygon, collision_points, cmd_vel_in, robot_action)) {
484+
if (processStopSlowdownLimit(
485+
polygon, sources_collision_points_map, cmd_vel_in, robot_action))
486+
{
512487
action_polygon = polygon;
513488
}
514489
} else if (at == APPROACH) {
515490
// Process APPROACH for the selected polygon
516-
if (processApproach(polygon, collision_points, cmd_vel_in, robot_action)) {
491+
if (processApproach(polygon, sources_collision_points_map, cmd_vel_in, robot_action)) {
517492
action_polygon = polygon;
518493
}
519494
}
@@ -535,15 +510,15 @@ void CollisionMonitor::process(const Velocity & cmd_vel_in, const std_msgs::msg:
535510

536511
bool CollisionMonitor::processStopSlowdownLimit(
537512
const std::shared_ptr<Polygon> polygon,
538-
const std::vector<Point> & collision_points,
513+
const std::unordered_map<std::string, std::vector<Point>> & sources_collision_points_map,
539514
const Velocity & velocity,
540515
Action & robot_action) const
541516
{
542517
if (!polygon->isShapeSet()) {
543518
return false;
544519
}
545520

546-
if (polygon->getPointsInside(collision_points) >= polygon->getMinPoints()) {
521+
if (polygon->getPointsInside(sources_collision_points_map) >= polygon->getMinPoints()) {
547522
if (polygon->getActionType() == STOP) {
548523
// Setting up zero velocity for STOP model
549524
robot_action.polygon_name = polygon->getName();
@@ -590,7 +565,7 @@ bool CollisionMonitor::processStopSlowdownLimit(
590565

591566
bool CollisionMonitor::processApproach(
592567
const std::shared_ptr<Polygon> polygon,
593-
const std::vector<Point> & collision_points,
568+
const std::unordered_map<std::string, std::vector<Point>> & sources_collision_points_map,
594569
const Velocity & velocity,
595570
Action & robot_action) const
596571
{
@@ -599,7 +574,7 @@ bool CollisionMonitor::processApproach(
599574
}
600575

601576
// Obtain time before a collision
602-
const double collision_time = polygon->getCollisionTime(collision_points, velocity);
577+
const double collision_time = polygon->getCollisionTime(sources_collision_points_map, velocity);
603578
if (collision_time >= 0.0) {
604579
// If collision will occurr, reduce robot speed
605580
const double change_ratio = collision_time / polygon->getTimeBeforeCollision();

nav2_collision_monitor/src/polygon.cpp

Lines changed: 61 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -234,39 +234,80 @@ int Polygon::getPointsInside(const std::vector<Point> & points) const
234234
return num;
235235
}
236236

237+
int Polygon::getPointsInside(
238+
const std::unordered_map<std::string,
239+
std::vector<Point>> & sources_collision_points_map) const
240+
{
241+
int num = 0;
242+
std::vector<std::string> polygon_sources_names = getSourcesNames();
243+
244+
for (const auto & iter : sources_collision_points_map) {
245+
// Check the points only if the source is associated with current polygon
246+
if (std::find(
247+
polygon_sources_names.begin(), polygon_sources_names.end(), iter.first) ==
248+
polygon_sources_names.end())
249+
{
250+
continue;
251+
}
252+
253+
// Sum the number of points from all sources associated with polygon
254+
num += getPointsInside(iter.second);
255+
}
256+
return num;
257+
}
258+
237259
double Polygon::getCollisionTime(
238-
const std::vector<Point> & collision_points,
260+
const std::unordered_map<std::string, std::vector<Point>> & sources_collision_points_map,
239261
const Velocity & velocity) const
240262
{
241263
// Initial robot pose is {0,0} in base_footprint coordinates
242264
Pose pose = {0.0, 0.0, 0.0};
243265
Velocity vel = velocity;
244266

245-
// Array of points transformed to the frame concerned with pose on each simulation step
246-
std::vector<Point> points_transformed = collision_points;
267+
double collision_time = -1.0; // initialize collision time as if there is no collision
268+
std::vector<std::string> polygon_sources_names = getSourcesNames();
247269

248-
// Check static polygon
249-
if (getPointsInside(points_transformed) >= min_points_) {
250-
return 0.0;
251-
}
270+
for (const auto & iter : sources_collision_points_map) {
271+
// Check the points only if the source is associated with current polygon
272+
if (std::find(
273+
polygon_sources_names.begin(), polygon_sources_names.end(), iter.first) ==
274+
polygon_sources_names.end())
275+
{
276+
continue;
277+
}
252278

253-
// Robot movement simulation
254-
for (double time = 0.0; time <= time_before_collision_; time += simulation_time_step_) {
255-
// Shift the robot pose towards to the vel during simulation_time_step_ time interval
256-
// NOTE: vel is changing during the simulation
257-
projectState(simulation_time_step_, pose, vel);
258-
// Transform collision_points to the frame concerned with current robot pose
259-
points_transformed = collision_points;
260-
transformPoints(pose, points_transformed);
261-
// If the collision occurred on this stage, return the actual time before a collision
262-
// as if robot was moved with given velocity
263-
if (getPointsInside(points_transformed) >= min_points_) {
264-
return time;
279+
// Array of points transformed to the frame concerned with pose on each simulation step
280+
std::vector<Point> points_transformed = iter.second;
281+
282+
// Check static polygon
283+
if (getPointsInside(iter.second) >= min_points_) {
284+
return 0.0; // immediate collision, other sources don't need to be checked
285+
}
286+
287+
// Robot movement simulation
288+
for (double time = 0.0; time <= time_before_collision_; time += simulation_time_step_) {
289+
// Shift the robot pose towards to the vel during simulation_time_step_ time interval
290+
// NOTE: vel is changing during the simulation
291+
projectState(simulation_time_step_, pose, vel);
292+
// Transform collision_points to the frame concerned with current robot pose
293+
points_transformed = iter.second;
294+
transformPoints(pose, points_transformed);
295+
// If the collision occurred on this stage, return the actual time before a collision
296+
// as if robot was moved with given velocity
297+
if (getPointsInside(points_transformed) >= min_points_) {
298+
if (collision_time == -1.0) {
299+
// If first collision detected, keep collision time value
300+
collision_time = time;
301+
} else if (time < collision_time) {
302+
// Keep the smallest collision time value from all sources
303+
collision_time = time;
304+
}
305+
}
265306
}
266307
}
267308

268309
// There is no collision
269-
return -1.0;
310+
return collision_time;
270311
}
271312

272313
void Polygon::publish()

0 commit comments

Comments
 (0)