28 #define POT_HIGH 1.0e10    32 #include <tuw_multi_robot_msgs/Route.h>    34 #include <boost/functional/hash.hpp>    35 #include <boost/regex.hpp>    40 int main ( 
int argc, 
char **argv ) {
    42     ros::init ( argc, argv, 
"tuw_multi_robot_router" ); 
    65     monitor_enabled_ ( false ),
    67     attempts_successful_(0),
    68     sum_processing_time_total_(.0),
    69     sum_processing_time_successful_(.0){
    92     if ( !singleRobotName_.size() == 0 ) {
   106         std::map<std::string, double>::iterator it = 
finished_robots_.find ( robot->robot_name );
   107         if ( robot->status == tuw_multi_robot_msgs::RobotInfo::STATUS_DRIVING ) {
   111                     ROS_INFO ( 
"%10s started!", robot->robot_name.c_str() );
   120                     ROS_INFO ( 
"%10s stopped @ %6.2lf sec, %3i robots left",  robot->robot_name.c_str(), duration, nr_of_driving_robots );
   128             ROS_INFO ( 
"Execution finished after %lf sec!", duration.
toSec() );
   129             std::stringstream ss;
   131                 ss << it->second << 
", ";
   133             ROS_INFO ( 
"Duration by robot: \n [%s]", ss.str().c_str() );
   143     tuw_multi_robot_msgs::RobotGoals goal;
   145     goal.destinations.push_back ( _goal.pose );
   147     tuw_multi_robot_msgs::RobotGoalsArray goals;
   148     goals.robots.push_back ( goal );
   156         ( *it )->updateOnlineStatus ( _secs );
   161     uint32_t threads = config.nr_threads;
   162     if ( config.router_type == 1 )
   167     if ( config.collision_resolver == 0 ){
   170     } 
else if ( config.collision_resolver == 1 ) {
   178     if ( config.voronoi_graph )
   183     if ( config.goal_mode == 0 )
   185     else if ( config.goal_mode == 1 )
   200     std::vector<signed char> map = _map.data;
   202     Eigen::Vector2d origin;
   203     origin[0] = _map.info.origin.position.x;
   204     origin[1] = _map.info.origin.position.y;
   206     size_t new_hash = 
getHash ( map, origin, _map.info.resolution );
   208     ROS_INFO ( 
"map %f %f %f", origin[0], origin[1], _map.info.resolution );
   215         cv::Mat m ( _map.info.height, _map.info.width, CV_8SC1, map.data() );
   217         m.convertTo ( m, CV_8UC1 );
   218         cv::bitwise_not ( m, m );
   220         cv::threshold ( m, m, 40, 255, CV_THRESH_BINARY | CV_THRESH_OTSU );
   221         cv::distanceTransform ( m, 
distMap_, CV_DIST_L1, 3 );
   232     tuw_multi_robot_msgs::RobotInfo ri;
   233     if ( shape == ri.SHAPE_CIRCLE ) {
   234         return shape_variables[0];
   245         RobotInfoPtr robot_new = std::make_shared<RobotInfo> ( _robotInfo );
   246         robot_new->initTopics ( 
n_ );
   249         ( *robot )->updateInfo ( _robotInfo );
   260     std::vector<Segment> graph;
   262     for ( 
const tuw_multi_robot_msgs::Vertex &segment : msg.vertices ) {
   263         std::vector<Eigen::Vector2d> points;
   265         for ( 
const geometry_msgs::Point &point : segment.path ) {
   266             points.emplace_back ( point.x, point.y );
   269         std::vector<uint32_t> successors;
   271         for ( 
const auto &succ : segment.successors ) {
   272             successors.emplace_back ( succ );
   275         std::vector<uint32_t> predecessors;
   277         for ( 
const auto &pred : segment.predecessors ) {
   278             predecessors.emplace_back ( pred );
   281         if ( segment.valid ) {
   284             graph.emplace_back ( segment.id, points, successors, predecessors, 0 );
   290     size_t hash = 
getHash ( graph );
   300 bool Router_Node::preparePlanning ( std::vector<float> &_radius, std::vector<Eigen::Vector3d> &_starts, std::vector<Eigen::Vector3d> &_goals, 
const tuw_multi_robot_msgs::RobotGoalsArray &goal_msg, std::vector<std::string> &robot_names ) {
   307     for ( 
int k = 0; k < goal_msg.robots.size(); k++ ) {
   308         const tuw_multi_robot_msgs::RobotGoals &route_request = goal_msg.robots[k];
   311             ROS_INFO ( 
"No robot subsribed with the name: %s", route_request.robot_name.c_str() );
   313             if ( route_request.destinations.empty() ) {
   314                 ROS_INFO ( 
"No robot: %s has not goal defined", route_request.robot_name.c_str() );
   320                 _radius.push_back ( ( *active_robot )->radius() );
   321                 if ( route_request.destinations.size() > 1 ) {
   322                     geometry_msgs::Pose p = route_request.destinations[0];
   323                     _starts.push_back ( Eigen::Vector3d ( p.position.x, p.position.y, 
getYaw ( p.orientation ) ) );
   325                     _starts.push_back ( ( *active_robot )->getPose() );
   328                 geometry_msgs::Pose p = route_request.destinations.back();
   329                 _goals.push_back ( Eigen::Vector3d ( p.position.x, p.position.y, 
getYaw ( p.orientation ) ) );
   343     std::vector<Eigen::Vector3d> starts;
   344     std::vector<Eigen::Vector3d> goals;
   345     std::vector<float> radius;
   346     std::vector<std::string> robot_names;
   350     bool preparationSuccessful = 
preparePlanning ( radius, starts, goals, _goals, robot_names );
   355         auto t1 = std::chrono::high_resolution_clock::now();
   357         auto t2 = std::chrono::high_resolution_clock::now();
   358         int duration = std::chrono::duration_cast<std::chrono::milliseconds> ( t2 - t1 ).count();
   360         if ( preparationSuccessful ) {
   378         ROS_INFO ( 
"\nSuccess %i, %i = %4.3f, avr %4.0f ms, success: %4.0f ms, %s, %s, %s \n [%4.3f, %4.0f,  %4.0f]", 
   381               rate_success, avr_duration_total, avr_duration_successful);
   394     double roll, pitch, yaw;
   406     nav_msgs::Path msg_path;
   407     tuw_multi_robot_msgs::Route msg_route;
   408     msg_path.header.seq = 0;
   410     msg_path.header.frame_id = 
"map";
   411     msg_route.header = msg_path.header;
   414         robot->pubPaths_.publish ( msg_path );
   415         robot->pubRoute_.publish ( msg_route );
   429     nav_msgs::Path msg_path;
   430     tuw_multi_robot_msgs::Route msg_route;
   431     msg_path.header.seq = 0;
   433     msg_path.header.frame_id = 
"map";
   434     msg_route.header = msg_path.header;
   438         const std::vector<Checkpoint> &route = 
getRoute ( i );
   439         msg_path.poses.clear();
   442         geometry_msgs::PoseStamped pose_1;
   443         pose_1.header.seq = 0;
   445         pose_1.header.frame_id = 
"map";
   447         Eigen::Vector2d pos ( route[0].start[0] * 
mapResolution_, route[0].start[1] * mapResolution_ );
   448         pose_1.pose.position.x = pos[0] + 
mapOrigin_[0];
   449         pose_1.pose.position.y = pos[1] + mapOrigin_[1];
   451         pose_1.pose.orientation.w = 1;
   452         msg_path.poses.push_back ( pose_1 );
   456             geometry_msgs::PoseStamped pose;
   459             pose.header.frame_id = 
"map";
   461             Eigen::Vector2d pos ( c.end[0] * mapResolution_, c.end[1] * mapResolution_ );
   462             pose.pose.position.x = pos[0] + mapOrigin_[0];
   463             pose.pose.position.y = pos[1] + mapOrigin_[1];
   468             pose.pose.orientation.w = q.w();
   469             pose.pose.orientation.x = q.x();
   470             pose.pose.orientation.y = q.y();
   471             pose.pose.orientation.z = q.z();
   472             msg_path.poses.push_back ( pose );
   475         robot->pubPaths_.publish ( msg_path );
   478         msg_route.segments.clear();
   481             tuw_multi_robot_msgs::RouteSegment seg;
   483             Eigen::Vector2d posStart ( cp.start[0] * mapResolution_, cp.start[1] * mapResolution_ );
   485             qStart.
setEuler ( 0, 0, cp.start[2] );
   487             seg.start.position.x = posStart[0] + mapOrigin_[0];
   488             seg.start.position.y = posStart[1] + mapOrigin_[1];
   489             seg.start.orientation.w = qStart.w();
   490             seg.start.orientation.x = qStart.x();
   491             seg.start.orientation.y = qStart.y();
   492             seg.start.orientation.z = qStart.z();
   494             Eigen::Vector2d posEnd ( cp.end[0] * mapResolution_, cp.end[1] * mapResolution_ );
   498             seg.end.position.x = posEnd[0] + mapOrigin_[0];
   499             seg.end.position.y = posEnd[1] + mapOrigin_[1];
   500             seg.end.orientation.w = qEnd.w();
   501             seg.end.orientation.x = qEnd.x();
   502             seg.end.orientation.y = qEnd.y();
   503             seg.end.orientation.z = qEnd.z();
   505             seg.segment_id = cp.segId;
   508             for ( 
int j = 0; j < cp.preconditions.size(); j++ ) {
   509                 tuw_multi_robot_msgs::RoutePrecondition pc;
   510                 pc.robot_id = 
active_robots_[cp.preconditions[j].robotId]->robot_name;
   511                 pc.current_route_segment = cp.preconditions[j].stepCondition;
   512                 seg.preconditions.push_back ( pc );
   515             msg_route.segments.push_back ( seg );
   518         robot->pubRoute_.publish ( msg_route );
   521     tuw_multi_robot_msgs::RouterStatus ps;
   533 size_t Router_Node::getHash ( 
const std::vector<signed char> &_map, 
const Eigen::Vector2d &_origin, 
const float &_resolution ) {
   534     std::size_t seed = 0;
   536     boost::hash_combine ( seed, _origin[0] );
   537     boost::hash_combine ( seed, _origin[1] );
   538     boost::hash_combine ( seed, _resolution );
   540     for ( 
const signed char &val : _map ) {
   541         boost::hash_combine ( seed, val );
   548     std::size_t seed = 0;
   550     for ( 
const Segment &seg : _graph ) {
   551         boost::hash_combine ( seed, seg.width() );
   552         boost::hash_combine ( seed, seg.length() );
   553         boost::hash_combine ( seed, seg.getSegmentId() );
   555         for ( 
const int &p : seg.getPredecessors() ) {
   556             boost::hash_combine ( seed, p );
   559         for ( 
const int &
s : seg.getSuccessors() ) {
   560             boost::hash_combine ( seed, 
s );
   563         for ( 
const Eigen::Vector2d &vec : seg.getPoints() ) {
   564             boost::hash_combine ( seed, vec[0] );
   565             boost::hash_combine ( seed, vec[1] );
 void goalsCallback(const tuw_multi_robot_msgs::RobotGoalsArray &_goals)
 
static std::vector< std::shared_ptr< RobotInfo > >::iterator findObj(std::vector< std::shared_ptr< RobotInfo > > &data, const std::string &name)
 
float getYaw(const geometry_msgs::Quaternion &_rot)
 
Eigen::Vector2d mapOrigin_
 
dynamic_reconfigure::Server< tuw_multi_robot_router::routerConfig > param_server
 
float getOverallPathLength() const 
getter 
 
void parametersCallback(tuw_multi_robot_router::routerConfig &config, uint32_t level)
 
size_t current_graph_hash_
 
int main(int argc, char **argv)
 
void publish(const boost::shared_ptr< M > &message) const 
 
std::vector< RobotInfoPtr > subscribed_robots_
 
void monitorExecution()
monitors the execution 
 
Subscriber subscribe(const std::string &topic, uint32_t queue_size, void(T::*fp)(M), T *obj, const TransportHints &transport_hints=TransportHints())
 
std::string singleRobotName_
 
ros::Publisher pubPlannerStatus_
 
void setPlannerType(routerType _type, uint32_t _nr_threads)
 
ROSCPP_DECL void init(int &argc, char **argv, const std::string &name, uint32_t options=0)
 
Router_Node(ros::NodeHandle &n)
Construct a new Router_Node object. 
 
std::string singleRobotGoalTopic_
 
std::vector< std::shared_ptr< RobotInfo > >::iterator RobotInfoPtrIterator
 
ros::Subscriber subVoronoiGraph_
 
bool publish_routing_table_
 
double sum_processing_time_total_
 
std::string planner_status_topic_
 
size_t getHash(const std::vector< signed char > &_map, const Eigen::Vector2d &_origin, const float &_resolution)
 
void mapCallback(const nav_msgs::OccupancyGrid &_map)
 
void publish()
publishes a RoutingTable 
 
tuw_multi_robot_msgs::RouterStatus mrrp_status_
 
ros::Subscriber subSingleRobotGoal_
 
ros::NodeHandle n_
Node handler to the root node. 
 
ros::NodeHandle n_param_
Node handler to the current node. 
 
const std::vector< Checkpoint > & getRoute(const uint32_t _robot) const 
returns the found Routing Table 
 
float getLongestPathLength() const 
getter 
 
void robotInfoCallback(const tuw_multi_robot_msgs::RobotInfo &_robotInfo)
 
void getRPY(tfScalar &roll, tfScalar &pitch, tfScalar &yaw, unsigned int solution_number=1) const 
 
Duration expectedCycleTime() const 
 
bool param(const std::string ¶m_name, T ¶m_val, const T &default_val) const 
 
void graphCallback(const tuw_multi_robot_msgs::Graph &msg)
 
float calcRadius(const int shape, const std::vector< float > &shape_variables) const 
 
void publishEmpty()
publishes an empty RoutingTable 
 
const std::string & getNamespace() const 
 
std::map< std::string, double > finished_robots_
robots currently used by the planner 
 
bool makePlan(const std::vector< Eigen::Vector3d > &_starts, const std::vector< Eigen::Vector3d > &_goals, const std::vector< float > &_radius, const cv::Mat &_map, const float &_resolution, const Eigen::Vector2d &_origin, const std::vector< Segment > &_graph, const std::vector< std::string > &_robot_names)
generates the plan from (Vertex[odom robotPose] to Vertex[_goals] 
 
static bool sortSegments(const Segment &i, const Segment &j)
 
Publisher advertise(const std::string &topic, uint32_t queue_size, bool latch=false)
 
uint32_t getPriorityScheduleAttemps() const 
getter 
 
std::string robot_info_topic_
 
void setEuler(const tfScalar &yaw, const tfScalar &pitch, const tfScalar &roll)
 
void setCollisionResolutionType(const SegmentExpander::CollisionResolverType _cr)
sets the CollisionResolverType used 
 
ros::Time time_first_robot_started_
 
dynamic_reconfigure::Server< tuw_multi_robot_router::routerConfig >::CallbackType call_type
 
bool preparePlanning(std::vector< float > &_radius, std::vector< Eigen::Vector3d > &_starts, std::vector< Eigen::Vector3d > &_goals, const tuw_multi_robot_msgs::RobotGoalsArray &_ros_goals, std::vector< std::string > &robot_names)
 
std::string voronoi_topic_
 
bool priorityRescheduling_
 
std::vector< Segment > graph_
 
std::shared_ptr< RobotInfo > RobotInfoPtr
 
ros::Subscriber subRobotInfo_
 
uint32_t getSpeedScheduleAttemps() const 
getter 
 
void goalCallback(const geometry_msgs::PoseStamped &_goal)
 
ROSCPP_DECL void spinOnce()
 
ros::Subscriber subGoalSet_
 
double sum_processing_time_successful_
 
uint32_t getDuration_ms() const 
getter 
 
bool segmentOptimizations_
 
std::vector< RobotInfoPtr > active_robots_
robots avaliable 
 
void updateTimeout(const float _secs)
used to update the nodes timeout to latch topics