Skip to content

Commit

Permalink
Dynamically changing polygons support (ros-navigation#3245)
Browse files Browse the repository at this point in the history
* Add Collision Monitor polygon topics subscription

* Add the support of polygons published in different frame

* Internal review

* Fix working with polygons visualization

* Update nav2_collision_monitor/README.md

Co-authored-by: Steve Macenski <[email protected]>

* Move getTransform to nav2_util

* Fix misprint

* Meet remaining review items:
* Update polygon params handling logic
* Warn if polygon shape was not set
* Publish with ownership movement

* Correct polygons_test.cpp parameters handling logic

* Adjust README for dynamic polygons logic update

Co-authored-by: Steve Macenski <[email protected]>
  • Loading branch information
2 people authored and Joshua Wallace committed Dec 14, 2022
1 parent 95c951d commit ab5dcd9
Show file tree
Hide file tree
Showing 14 changed files with 526 additions and 142 deletions.
8 changes: 4 additions & 4 deletions nav2_collision_monitor/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,9 @@ The following models of safety behaviors are employed by Collision Monitor:

The zones around the robot can take the following shapes:

* Arbitrary user-defined polygon relative to the robot base frame.
* Circle: is made for the best performance and could be used in the cases where the zone or robot could be approximated by round shape.
* Robot footprint polygon, which is used in the approach behavior model only. Will use the footprint topic to allow it to be dynamically adjusted over time.
* Arbitrary user-defined polygon relative to the robot base frame, which can be static in a configuration file or dynamically changing via a topic interface.
* Robot footprint polygon, which is used in the approach behavior model only. Will use the static user-defined polygon or the footprint topic to allow it to be dynamically adjusted over time.
* Circle: is made for the best performance and could be used in the cases where the zone or robot footprint could be approximated by round shape.

The data may be obtained from different data sources:

Expand All @@ -43,7 +43,7 @@ The Collision Monitor is designed to operate below Nav2 as an independent safety
This acts as a filter on the `cmd_vel` topic coming out of the Controller Server. If no such zone is triggered, then the Controller's `cmd_vel` is used. Else, it is scaled or set to stop as appropriate.

The following diagram is showing the high-level design of Collision Monitor module. All shapes (Polygons and Circles) are derived from base `Polygon` class, so without loss of generality we can call them as polygons. Subscribed footprint is also having the same properties as other polygons, but it is being obtained a footprint topic for the Approach Model.
![HDL.png](doc/HLD.png)
![HLD.png](doc/HLD.png)

## Configuration

Expand Down
11 changes: 10 additions & 1 deletion nav2_collision_monitor/include/nav2_collision_monitor/circle.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -66,15 +66,24 @@ class Circle : public Polygon
*/
int getPointsInside(const std::vector<Point> & points) const override;

/**
* @brief Specifies that the shape is always set for a circle object
*/
bool isShapeSet() override {return true;}

protected:
/**
* @brief Supporting routine obtaining polygon-specific ROS-parameters
* @brief polygon_sub_topic Input name of polygon subscription topic
* @param polygon_pub_topic Output name of polygon publishing topic
* @param footprint_topic Output name of footprint topic. For Circle returns empty string,
* there is no footprint subscription in this class.
* @return True if all parameters were obtained or false in failure case
*/
bool getParameters(std::string & polygon_pub_topic, std::string & footprint_topic) override;
bool getParameters(
std::string & polygon_sub_topic,
std::string & polygon_pub_topic,
std::string & footprint_topic) override;

// ----- Variables -----

Expand Down
37 changes: 31 additions & 6 deletions nav2_collision_monitor/include/nav2_collision_monitor/polygon.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@

#include "rclcpp/rclcpp.hpp"
#include "geometry_msgs/msg/polygon_stamped.hpp"
#include "geometry_msgs/msg/polygon.hpp"

#include "tf2/time.h"
#include "tf2_ros/buffer.h"
Expand Down Expand Up @@ -110,6 +109,12 @@ class Polygon
*/
virtual void getPolygon(std::vector<Point> & poly) const;

/**
* @brief Returns true if polygon points were set.
* Othewise, prints a warning and returns false.
*/
virtual bool isShapeSet();

/**
* @brief Updates polygon from footprint subscriber (if any)
*/
Expand Down Expand Up @@ -138,7 +143,7 @@ class Polygon
/**
* @brief Publishes polygon message into a its own topic
*/
void publish() const;
void publish();

protected:
/**
Expand All @@ -150,11 +155,29 @@ class Polygon

/**
* @brief Supporting routine obtaining polygon-specific ROS-parameters
* @brief polygon_sub_topic Output name of polygon subscription topic.
* Empty, if no polygon subscription.
* @param polygon_pub_topic Output name of polygon publishing topic
* @param footprint_topic Output name of footprint topic. Empty, if no footprint subscription
* @param footprint_topic Output name of footprint topic.
* Empty, if no footprint subscription.
* @return True if all parameters were obtained or false in failure case
*/
virtual bool getParameters(std::string & polygon_pub_topic, std::string & footprint_topic);
virtual bool getParameters(
std::string & polygon_sub_topic,
std::string & polygon_pub_topic,
std::string & footprint_topic);

/**
* @brief Updates polygon from geometry_msgs::msg::PolygonStamped message
* @param msg Message to update polygon from
*/
void updatePolygon(geometry_msgs::msg::PolygonStamped::ConstSharedPtr msg);

/**
* @brief Dynamic polygon callback
* @param msg Shared pointer to the polygon message
*/
void polygonCallback(geometry_msgs::msg::PolygonStamped::ConstSharedPtr msg);

/**
* @brief Checks if point is inside polygon
Expand Down Expand Up @@ -183,6 +206,8 @@ class Polygon
double time_before_collision_;
/// @brief Time step for robot movement simulation
double simulation_time_step_;
/// @brief Polygon subscription
rclcpp::Subscription<geometry_msgs::msg::PolygonStamped>::SharedPtr polygon_sub_;
/// @brief Footprint subscriber
std::unique_ptr<nav2_costmap_2d::FootprintSubscriber> footprint_sub_;

Expand All @@ -197,8 +222,8 @@ class Polygon
// Visualization
/// @brief Whether to publish the polygon
bool visualize_;
/// @brief Polygon points stored for later publishing
geometry_msgs::msg::Polygon polygon_;
/// @brief Polygon stored for later publishing
geometry_msgs::msg::PolygonStamped polygon_;
/// @brief Polygon publisher for visualization purposes
rclcpp_lifecycle::LifecyclePublisher<geometry_msgs::msg::PolygonStamped>::SharedPtr polygon_pub_;

Expand Down
15 changes: 0 additions & 15 deletions nav2_collision_monitor/include/nav2_collision_monitor/source.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -88,21 +88,6 @@ class Source
const rclcpp::Time & source_time,
const rclcpp::Time & curr_time) const;

/**
* @brief Obtains a transform from source_frame_id at source_time ->
* to base_frame_id_ at curr_time time
* @param source_frame_id Source frame ID to convert data from
* @param source_time Source timestamp to convert data from
* @param curr_time Current node time to interpolate data to
* @param tf_transform Output source->base transform
* @return True if got correct transform, otherwise false
*/
bool getTransform(
const std::string & source_frame_id,
const rclcpp::Time & source_time,
const rclcpp::Time & curr_time,
tf2::Transform & tf_transform) const;

// ----- Variables -----

/// @brief Collision Monitor node
Expand Down
8 changes: 6 additions & 2 deletions nav2_collision_monitor/src/circle.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,10 @@ int Circle::getPointsInside(const std::vector<Point> & points) const
return num;
}

bool Circle::getParameters(std::string & polygon_pub_topic, std::string & footprint_topic)
bool Circle::getParameters(
std::string & polygon_sub_topic,
std::string & polygon_pub_topic,
std::string & footprint_topic)
{
auto node = node_.lock();
if (!node) {
Expand All @@ -81,7 +84,8 @@ bool Circle::getParameters(std::string & polygon_pub_topic, std::string & footpr
return false;
}

// There is no footprint subscription for the Circle. Thus, set string as empty.
// There is no polygon or footprint subscription for the Circle. Thus, set strings as empty.
polygon_sub_topic.clear();
footprint_topic.clear();

try {
Expand Down
8 changes: 8 additions & 0 deletions nav2_collision_monitor/src/collision_monitor_node.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -389,6 +389,10 @@ bool CollisionMonitor::processStopSlowdown(
const Velocity & velocity,
Action & robot_action) const
{
if (!polygon->isShapeSet()) {
return false;
}

if (polygon->getPointsInside(collision_points) > polygon->getMaxPoints()) {
if (polygon->getActionType() == STOP) {
// Setting up zero velocity for STOP model
Expand Down Expand Up @@ -420,6 +424,10 @@ bool CollisionMonitor::processApproach(
{
polygon->updatePolygon();

if (!polygon->isShapeSet()) {
return false;
}

// Obtain time before a collision
const double collision_time = polygon->getCollisionTime(collision_points, velocity);
if (collision_time >= 0.0) {
Expand Down
8 changes: 7 additions & 1 deletion nav2_collision_monitor/src/pointcloud.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#include "sensor_msgs/point_cloud2_iterator.hpp"

#include "nav2_util/node_utils.hpp"
#include "nav2_util/robot_utils.hpp"

namespace nav2_collision_monitor
{
Expand Down Expand Up @@ -78,7 +79,12 @@ void PointCloud::getData(
// Obtaining the transform to get data from source frame and time where it was received
// to the base frame and current time
tf2::Transform tf_transform;
if (!getTransform(data_->header.frame_id, data_->header.stamp, curr_time, tf_transform)) {
if (
!nav2_util::getTransform(
data_->header.frame_id, data_->header.stamp,
base_frame_id_, curr_time, global_frame_id_,
transform_tolerance_, tf_buffer_, tf_transform))
{
return;
}

Expand Down
Loading

0 comments on commit ab5dcd9

Please sign in to comment.