Skip to content

Commit

Permalink
optimization
Browse files Browse the repository at this point in the history
Signed-off-by: asarazin <anaelle.sarazin@robocc.com>
  • Loading branch information
asarazin committed Aug 28, 2024
1 parent bc24238 commit 2d55ca7
Show file tree
Hide file tree
Showing 5 changed files with 117 additions and 90 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#include <string>
#include <vector>
#include <memory>
#include <unordered_map>

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

/**
* @brief Processes APPROACH action type
* @param polygon Polygon to process
* @param collision_points Array of 2D obstacle points
* @param sources_collision_points_map Map containing source name as key and
* array of source's 2D obstacle points as value
* @param velocity Desired robot velocity
* @param robot_action Output processed robot action
* @return True if returned action is caused by current polygon, otherwise false
*/
bool processApproach(
const std::shared_ptr<Polygon> polygon,
const std::vector<Point> & collision_points,
const std::unordered_map<std::string, std::vector<Point>> & sources_collision_points_map,
const Velocity & velocity,
Action & robot_action) const;

Expand Down
17 changes: 15 additions & 2 deletions nav2_collision_monitor/include/nav2_collision_monitor/polygon.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#include <memory>
#include <string>
#include <vector>
#include <unordered_map>

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

/**
* @brief Gets number of points inside given polygon
* @param sources_collision_points_map Map containing source name as key,
* and input array of source's points to be checked as value
* @return Number of points inside polygon,
* for sources in map that are associated with current polygon.
* If there are no points, returns zero value.
*/
virtual int getPointsInside(
const std::unordered_map<std::string, std::vector<Point>> & sources_collision_points_map) const;

/**
* @brief Obtains estimated (simulated) time before a collision.
* Applicable for APPROACH model.
* @param collision_points Array of 2D obstacle points
* @param sources_collision_points_map Map containing source name as key,
* and input array of source's 2D obstacle points as value
* @param velocity Simulated robot velocity
* @return Estimated time before a collision. If there is no collision,
* return value will be negative.
*/
double getCollisionTime(
const std::vector<Point> & collision_points,
const std::unordered_map<std::string, std::vector<Point>> & sources_collision_points_map,
const Velocity & velocity) const;

/**
Expand Down
101 changes: 40 additions & 61 deletions nav2_collision_monitor/src/collision_monitor_node.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -414,22 +414,19 @@ void CollisionMonitor::process(const Velocity & cmd_vel_in, const std_msgs::msg:
// Points array collected from different data sources in a robot base frame
std::unordered_map<std::string, std::vector<Point>> sources_collision_points_map;

// Fill collision_points array from different data sources
for (std::shared_ptr<Source> source : sources_) {
std::vector<Point> collision_points;
source->getData(curr_time, collision_points);
sources_collision_points_map.insert({source->getSourceName(), collision_points});
}

// By default - there is no action
Action robot_action{DO_NOTHING, cmd_vel_in, ""};
// Polygon causing robot action (if any)
std::shared_ptr<Polygon> action_polygon;

// Fill collision_points array from different data sources
// Fill collision points array from different data sources
auto marker_array = std::make_unique<visualization_msgs::msg::MarkerArray>();
for (std::shared_ptr<Source> source : sources_) {
auto iter = sources_collision_points_map.insert(
{source->getSourceName(), std::vector<Point>()});

if (source->getEnabled()) {
if (!source->getData(curr_time, collision_points) &&
if (!source->getData(curr_time, iter.first->second) &&
source->getSourceTimeout().seconds() != 0.0)
{
action_polygon = nullptr;
Expand All @@ -441,33 +438,35 @@ void CollisionMonitor::process(const Velocity & cmd_vel_in, const std_msgs::msg:
break;
}
}

if (collision_points_marker_pub_->get_subscription_count() > 0) {
// visualize collision points with markers
visualization_msgs::msg::Marker marker;
marker.header.frame_id = get_parameter("base_frame_id").as_string();
marker.header.stamp = rclcpp::Time(0, 0);
marker.ns = "collision_points_" + source->getSourceName();
marker.id = 0;
marker.type = visualization_msgs::msg::Marker::POINTS;
marker.action = visualization_msgs::msg::Marker::ADD;
marker.scale.x = 0.02;
marker.scale.y = 0.02;
marker.color.r = 1.0;
marker.color.a = 1.0;
marker.lifetime = rclcpp::Duration(0, 0);
marker.frame_locked = true;

for (const auto & point : iter.first->second) {
geometry_msgs::msg::Point p;
p.x = point.x;
p.y = point.y;
p.z = 0.0;
marker.points.push_back(p);
}
marker_array->markers.push_back(marker);
}
}

if (collision_points_marker_pub_->get_subscription_count() > 0) {
// visualize collision points with markers
auto marker_array = std::make_unique<visualization_msgs::msg::MarkerArray>();
visualization_msgs::msg::Marker marker;
marker.header.frame_id = get_parameter("base_frame_id").as_string();
marker.header.stamp = rclcpp::Time(0, 0);
marker.ns = "collision_points";
marker.id = 0;
marker.type = visualization_msgs::msg::Marker::POINTS;
marker.action = visualization_msgs::msg::Marker::ADD;
marker.scale.x = 0.02;
marker.scale.y = 0.02;
marker.color.r = 1.0;
marker.color.a = 1.0;
marker.lifetime = rclcpp::Duration(0, 0);
marker.frame_locked = true;

for (const auto & point : collision_points) {
geometry_msgs::msg::Point p;
p.x = point.x;
p.y = point.y;
p.z = 0.0;
marker.points.push_back(p);
}
marker_array->markers.push_back(marker);
collision_points_marker_pub_->publish(std::move(marker_array));
}

Expand All @@ -483,37 +482,17 @@ void CollisionMonitor::process(const Velocity & cmd_vel_in, const std_msgs::msg:
// Update polygon coordinates
polygon->updatePolygon(cmd_vel_in);

// Get collision points for sources associated to polygon
std::vector<std::string> sources_names = polygon->getSourcesNames();
std::vector<Point> collision_points;
for (auto source_name : sources_names) {
try {
// Get vector for source
auto source_collision_points = sources_collision_points_map.at(source_name);
// Concatenate vectors
collision_points.insert(
collision_points.end(),
source_collision_points.begin(),
source_collision_points.end());
} catch (std::exception & e) {
RCLCPP_ERROR_STREAM_THROTTLE(
get_logger(),
*get_clock(),
1000,
"Observation source [" << source_name <<
"] configured for polygon [" << polygon->getName() << "] is not defined!");
}
}

const ActionType at = polygon->getActionType();
if (at == STOP || at == SLOWDOWN || at == LIMIT) {
// Process STOP/SLOWDOWN for the selected polygon
if (processStopSlowdownLimit(polygon, collision_points, cmd_vel_in, robot_action)) {
if (processStopSlowdownLimit(
polygon, sources_collision_points_map, cmd_vel_in, robot_action))
{
action_polygon = polygon;
}
} else if (at == APPROACH) {
// Process APPROACH for the selected polygon
if (processApproach(polygon, collision_points, cmd_vel_in, robot_action)) {
if (processApproach(polygon, sources_collision_points_map, cmd_vel_in, robot_action)) {
action_polygon = polygon;
}
}
Expand All @@ -535,15 +514,15 @@ void CollisionMonitor::process(const Velocity & cmd_vel_in, const std_msgs::msg:

bool CollisionMonitor::processStopSlowdownLimit(
const std::shared_ptr<Polygon> polygon,
const std::vector<Point> & collision_points,
const std::unordered_map<std::string, std::vector<Point>> & sources_collision_points_map,
const Velocity & velocity,
Action & robot_action) const
{
if (!polygon->isShapeSet()) {
return false;
}

if (polygon->getPointsInside(collision_points) >= polygon->getMinPoints()) {
if (polygon->getPointsInside(sources_collision_points_map) >= polygon->getMinPoints()) {
if (polygon->getActionType() == STOP) {
// Setting up zero velocity for STOP model
robot_action.polygon_name = polygon->getName();
Expand Down Expand Up @@ -590,7 +569,7 @@ bool CollisionMonitor::processStopSlowdownLimit(

bool CollisionMonitor::processApproach(
const std::shared_ptr<Polygon> polygon,
const std::vector<Point> & collision_points,
const std::unordered_map<std::string, std::vector<Point>> & sources_collision_points_map,
const Velocity & velocity,
Action & robot_action) const
{
Expand All @@ -599,7 +578,7 @@ bool CollisionMonitor::processApproach(
}

// Obtain time before a collision
const double collision_time = polygon->getCollisionTime(collision_points, velocity);
const double collision_time = polygon->getCollisionTime(sources_collision_points_map, velocity);
if (collision_time >= 0.0) {
// If collision will occurr, reduce robot speed
const double change_ratio = collision_time / polygon->getTimeBeforeCollision();
Expand Down
43 changes: 37 additions & 6 deletions nav2_collision_monitor/src/polygon.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -234,19 +234,48 @@ int Polygon::getPointsInside(const std::vector<Point> & points) const
return num;
}

int Polygon::getPointsInside(
const std::unordered_map<std::string,
std::vector<Point>> & sources_collision_points_map) const
{
int num = 0;
std::vector<std::string> polygon_sources_names = getSourcesNames();

// Sum the number of points from all sources associated with current polygon
for (const auto & source_name : polygon_sources_names) {
const auto & iter = sources_collision_points_map.find(source_name);
if (iter != sources_collision_points_map.end()) {
num += getPointsInside(iter->second);
}
}

return num;
}

double Polygon::getCollisionTime(
const std::vector<Point> & collision_points,
const std::unordered_map<std::string, std::vector<Point>> & sources_collision_points_map,
const Velocity & velocity) const
{
// Initial robot pose is {0,0} in base_footprint coordinates
Pose pose = {0.0, 0.0, 0.0};
Velocity vel = velocity;

std::vector<std::string> polygon_sources_names = getSourcesNames();
std::vector<Point> collision_points;

// Save all points coming from the sources associated with current polygon
for (const auto & source_name : polygon_sources_names) {
const auto & iter = sources_collision_points_map.find(source_name);
if (iter != sources_collision_points_map.end()) {
collision_points.insert(collision_points.end(), iter->second.begin(), iter->second.end());
}
}

// Array of points transformed to the frame concerned with pose on each simulation step
std::vector<Point> points_transformed = collision_points;

// Check static polygon
if (getPointsInside(points_transformed) >= min_points_) {
if (getPointsInside(collision_points) >= min_points_) {
return 0.0;
}

Expand Down Expand Up @@ -401,20 +430,22 @@ bool Polygon::getCommonParameters(
// By default, use all observation sources for polygon
nav2_util::declare_parameter_if_not_declared(
node, "observation_sources", rclcpp::PARAMETER_STRING_ARRAY);
std::vector<std::string> source_names =
const std::vector<std::string> observation_sources =
node->get_parameter("observation_sources").as_string_array();
nav2_util::declare_parameter_if_not_declared(
node, polygon_name_ + ".sources_names", rclcpp::ParameterValue(source_names));
node, polygon_name_ + ".sources_names", rclcpp::ParameterValue(observation_sources));
sources_names_ = node->get_parameter(polygon_name_ + ".sources_names").as_string_array();

// Check the observation sources configured for polygon are defined
for (auto source_name : sources_names_) {
if (std::find(source_names.begin(), source_names.end(), source_name) == source_names.end()) {
if (std::find(observation_sources.begin(), observation_sources.end(), source_name) ==
observation_sources.end())
{
RCLCPP_ERROR_STREAM(
logger_,
"Observation source [" << source_name <<
"] configured for polygon [" << getName() <<
"] is not defined!");
"] is not defined as one of the node's observation_source!");
return false;
}
}
Expand Down
35 changes: 18 additions & 17 deletions nav2_collision_monitor/test/polygons_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -862,25 +862,26 @@ TEST_F(Tester, testPolygonGetCollisionTime)
// Forward movement check
nav2_collision_monitor::Velocity vel{0.5, 0.0, 0.0}; // 0.5 m/s forward movement
// Two points 0.2 m ahead the footprint (0.5 m)
std::vector<nav2_collision_monitor::Point> points{{0.7, -0.01}, {0.7, 0.01}};
std::unordered_map<std::string, std::vector<nav2_collision_monitor::Point>> points_map;
points_map.insert({"source", {{0.7, -0.01}, {0.7, 0.01}}});
// Collision is expected to be ~= 0.2 m / 0.5 m/s seconds
EXPECT_NEAR(polygon_->getCollisionTime(points, vel), 0.4, SIMULATION_TIME_STEP);
EXPECT_NEAR(polygon_->getCollisionTime(points_map, vel), 0.4, SIMULATION_TIME_STEP);

// Backward movement check
vel = {-0.5, 0.0, 0.0}; // 0.5 m/s backward movement
// Two points 0.2 m behind the footprint (0.5 m)
points.clear();
points = {{-0.7, -0.01}, {-0.7, 0.01}};
points_map.clear();
points_map.insert({"source", {{-0.7, -0.01}, {-0.7, 0.01}}});
// Collision is expected to be in ~= 0.2 m / 0.5 m/s seconds
EXPECT_NEAR(polygon_->getCollisionTime(points, vel), 0.4, SIMULATION_TIME_STEP);
EXPECT_NEAR(polygon_->getCollisionTime(points_map, vel), 0.4, SIMULATION_TIME_STEP);

// Sideway movement check
vel = {0.0, 0.5, 0.0}; // 0.5 m/s sideway movement
// Two points 0.1 m ahead the footprint (0.5 m)
points.clear();
points = {{-0.01, 0.6}, {0.01, 0.6}};
points_map.clear();
points_map.insert({"source", {{-0.01, 0.6}, {0.01, 0.6}}});
// Collision is expected to be in ~= 0.1 m / 0.5 m/s seconds
EXPECT_NEAR(polygon_->getCollisionTime(points, vel), 0.2, SIMULATION_TIME_STEP);
EXPECT_NEAR(polygon_->getCollisionTime(points_map, vel), 0.2, SIMULATION_TIME_STEP);

// Rotation check
vel = {0.0, 0.0, 1.0}; // 1.0 rad/s rotation
Expand All @@ -894,27 +895,27 @@ TEST_F(Tester, testPolygonGetCollisionTime)
// | ' |
// -----------
// '
points.clear();
points = {{0.49, -0.01}, {0.49, 0.01}};
points_map.clear();
points_map.insert({"source", {{0.49, -0.01}, {0.49, 0.01}}});
// Collision is expected to be in ~= 45 degrees * M_PI / (180 degrees * 1.0 rad/s) seconds
double exp_res = 45 / 180 * M_PI;
EXPECT_NEAR(polygon_->getCollisionTime(points, vel), exp_res, EPSILON);
EXPECT_NEAR(polygon_->getCollisionTime(points_map, vel), exp_res, EPSILON);

// Two points are already inside footprint
vel = {0.5, 0.0, 0.0}; // 0.5 m/s forward movement
// Two points inside
points.clear();
points = {{0.1, -0.01}, {0.1, 0.01}};
points_map.clear();
points_map.insert({"source", {{0.1, -0.01}, {0.1, 0.01}}});
// Collision already appeared: collision time should be 0
EXPECT_NEAR(polygon_->getCollisionTime(points, vel), 0.0, EPSILON);
EXPECT_NEAR(polygon_->getCollisionTime(points_map, vel), 0.0, EPSILON);

// All points are out of simulation prediction
vel = {0.5, 0.0, 0.0}; // 0.5 m/s forward movement
// Two points 0.6 m ahead the footprint (0.5 m)
points.clear();
points = {{1.1, -0.01}, {1.1, 0.01}};
points_map.clear();
points_map.insert({"source", {{1.1, -0.01}, {1.1, 0.01}}});
// There is no collision: return value should be negative
EXPECT_LT(polygon_->getCollisionTime(points, vel), 0.0);
EXPECT_LT(polygon_->getCollisionTime(points_map, vel), 0.0);
}

TEST_F(Tester, testPolygonPublish)
Expand Down

0 comments on commit 2d55ca7

Please sign in to comment.