diff --git a/include/publisher_graph.h b/include/publisher_graph.h index 285dd4f79659ea85b40dba835dd9d41d68f47cbd..7b1ceb04dc469452307c9d49e15a26334e37e782 100644 --- a/include/publisher_graph.h +++ b/include/publisher_graph.h @@ -68,7 +68,7 @@ class PublisherGraph: public Publisher std::string map_frame_id_; bool viz_overlapped_factors_; double viz_scale_, text_scale_, factors_width_, factors_absolute_height_, landmark_text_z_offset_, landmark_width_, landmark_length_, frame_width_, frame_length_; - std_msgs::ColorRGBA frame_color_, factor_abs_color_, factor_motion_color_, factor_loop_color_, factor_lmk_color_, factor_geom_color_; + std_msgs::ColorRGBA frame_color_, factor_abs_color_, factor_motion_color_, factor_loop_color_, factor_lmk_color_, factor_geom_color_, factor_other_color_; // auxiliar variables unsigned int landmark_max_hits_; diff --git a/include/publisher_tf.h b/include/publisher_tf.h index 64740385df04674c289e06cc6940a6bb4fc04b26..d9f01bc452f0155fdbf2f5c11d847f1e21de7a6f 100644 --- a/include/publisher_tf.h +++ b/include/publisher_tf.h @@ -18,6 +18,22 @@ namespace wolf { +tf::Transform stateToTfTransform(VectorComposite state, int dim) +{ + // 2D + if (dim == 2) + { + return tf::Transform (tf::createQuaternionFromYaw(state['O'](0)), + tf::Vector3(state['P'](0), state['P'](1), 0) ); + } + // 3D + else + { + return tf::Transform (tf::Quaternion(state['O'](0), state['O'](1), state['O'](2), state['O'](3)), + tf::Vector3(state['P'](0), state['P'](1), state['P'](2)) ); + } +} + class PublisherTf: public Publisher { protected: @@ -25,6 +41,9 @@ class PublisherTf: public Publisher tf::TransformBroadcaster tfb_; tf::TransformListener tfl_; + tf::StampedTransform T_odom2base_, T_map2odom_; + + bool publish_odom_tf_; bool state_available_; // used to not repeat warnings regarding availability of state public: diff --git a/src/publisher_graph.cpp b/src/publisher_graph.cpp index 04bc5540116b6c2fe6fdff50cec384d53aaa6b78..e81628f1aa134a7619104983e0ea966fde2c5b27 100644 --- a/src/publisher_graph.cpp +++ b/src/publisher_graph.cpp @@ -33,26 +33,30 @@ PublisherGraph::PublisherGraph(const std::string& _unique_name, // factors factors_width_ = getParamWithDefault<double> (_server, prefix_ + "/factors_width", 0.02); factors_absolute_height_= getParamWithDefault<double> (_server, prefix_ + "/factors_absolute_height", 2); - factor_abs_color_.r = getParamWithDefault<double> (_server, prefix_ + "/factor_abs_color_r", 0.9); - factor_abs_color_.g = getParamWithDefault<double> (_server, prefix_ + "/factor_abs_color_g", 0.2); - factor_abs_color_.b = getParamWithDefault<double> (_server, prefix_ + "/factor_abs_color_b", 0.6); + factor_abs_color_.r = getParamWithDefault<double> (_server, prefix_ + "/factor_abs_color_r", 1); //red + factor_abs_color_.g = getParamWithDefault<double> (_server, prefix_ + "/factor_abs_color_g", 0); + factor_abs_color_.b = getParamWithDefault<double> (_server, prefix_ + "/factor_abs_color_b", 0); factor_abs_color_.a = getParamWithDefault<double> (_server, prefix_ + "/factor_abs_color_a", 1); - factor_motion_color_.r = getParamWithDefault<double> (_server, prefix_ + "/factor_motion_color_r", 1); + factor_motion_color_.r = getParamWithDefault<double> (_server, prefix_ + "/factor_motion_color_r", 1);//yellow factor_motion_color_.g = getParamWithDefault<double> (_server, prefix_ + "/factor_motion_color_g", 1); factor_motion_color_.b = getParamWithDefault<double> (_server, prefix_ + "/factor_motion_color_b", 0); factor_motion_color_.a = getParamWithDefault<double> (_server, prefix_ + "/factor_motion_color_a", 1); - factor_loop_color_.r = getParamWithDefault<double> (_server, prefix_ + "/factor_loop_color_r", 1); - factor_loop_color_.g = getParamWithDefault<double> (_server, prefix_ + "/factor_loop_color_g", 0); + factor_loop_color_.r = getParamWithDefault<double> (_server, prefix_ + "/factor_loop_color_r", 0); //green + factor_loop_color_.g = getParamWithDefault<double> (_server, prefix_ + "/factor_loop_color_g", 1); factor_loop_color_.b = getParamWithDefault<double> (_server, prefix_ + "/factor_loop_color_b", 0); factor_loop_color_.a = getParamWithDefault<double> (_server, prefix_ + "/factor_loop_color_a", 1); - factor_lmk_color_.r = getParamWithDefault<double> (_server, prefix_ + "/factor_lmk_color_r", 0); - factor_lmk_color_.g = getParamWithDefault<double> (_server, prefix_ + "/factor_lmk_color_g", 0); + factor_lmk_color_.r = getParamWithDefault<double> (_server, prefix_ + "/factor_lmk_color_r", 0); //cyan + factor_lmk_color_.g = getParamWithDefault<double> (_server, prefix_ + "/factor_lmk_color_g", 1); factor_lmk_color_.b = getParamWithDefault<double> (_server, prefix_ + "/factor_lmk_color_b", 1); factor_lmk_color_.a = getParamWithDefault<double> (_server, prefix_ + "/factor_lmk_color_a", 1); - factor_geom_color_.r = getParamWithDefault<double> (_server, prefix_ + "/factor_geom_color_r", 0); - factor_geom_color_.g = getParamWithDefault<double> (_server, prefix_ + "/factor_geom_color_g", 1); + factor_geom_color_.r = getParamWithDefault<double> (_server, prefix_ + "/factor_geom_color_r", 0); //blue + factor_geom_color_.g = getParamWithDefault<double> (_server, prefix_ + "/factor_geom_color_g", 0); factor_geom_color_.b = getParamWithDefault<double> (_server, prefix_ + "/factor_geom_color_b", 1); factor_geom_color_.a = getParamWithDefault<double> (_server, prefix_ + "/factor_geom_color_a", 1); + factor_other_color_.r = getParamWithDefault<double> (_server, prefix_ + "/factor_other_color_r", 1); //white + factor_other_color_.g = getParamWithDefault<double> (_server, prefix_ + "/factor_other_color_g", 1); + factor_other_color_.b = getParamWithDefault<double> (_server, prefix_ + "/factor_other_color_b", 1); + factor_other_color_.a = getParamWithDefault<double> (_server, prefix_ + "/factor_other_color_a", 1); // INIT MARKERS --------------------------------------------------- // factor markers message @@ -478,16 +482,18 @@ void PublisherGraph::fillFactorMarker(FactorBaseConstPtr fac, // colors ------------------------------------------------------ auto color = frame_color_; - if (fac->getTopology() == "ABS") + if (fac->getTopology() == TOP_ABS) color = factor_abs_color_; - if (fac->getTopology() == "MOTION") + if (fac->getTopology() == TOP_MOTION) color = factor_motion_color_; - if (fac->getTopology() == "LOOP") + if (fac->getTopology() == TOP_LOOP) color = factor_loop_color_; - if (fac->getTopology() == "LMK") + if (fac->getTopology() == TOP_LMK) color = factor_lmk_color_; - if (fac->getTopology() == "GEOM") + if (fac->getTopology() == TOP_GEOM) color = factor_geom_color_; + if (fac->getTopology() == TOP_OTHER) + color = factor_other_color_; // more transparent if inactive if (fac->getStatus() == FAC_INACTIVE) diff --git a/src/publisher_tf.cpp b/src/publisher_tf.cpp index 59e4606a50f685a22192cc3667db316a92d22584..331147eecc147b93590a398a24f96e16e73e8e7b 100644 --- a/src/publisher_tf.cpp +++ b/src/publisher_tf.cpp @@ -16,9 +16,20 @@ PublisherTf::PublisherTf(const std::string& _unique_name, Publisher(_unique_name, _server, _problem), state_available_(true) { - map_frame_id_ = _server.getParam<std::string>(prefix_ + "/map_frame_id"); - odom_frame_id_ = _server.getParam<std::string>(prefix_ + "/odom_frame_id"); - base_frame_id_ = _server.getParam<std::string>(prefix_ + "/base_frame_id"); + map_frame_id_ = _server.getParam<std::string>(prefix_ + "/map_frame_id"); + odom_frame_id_ = _server.getParam<std::string>(prefix_ + "/odom_frame_id"); + base_frame_id_ = _server.getParam<std::string>(prefix_ + "/base_frame_id"); + publish_odom_tf_ = _server.getParam<bool>(prefix_ + "/publish_odom_tf"); + + // initialize TF transforms + T_odom2base_.setIdentity(); + T_odom2base_.frame_id_ = odom_frame_id_; + T_odom2base_.child_frame_id_ = base_frame_id_; + T_odom2base_.stamp_ = ros::Time::now(); + T_map2odom_.setIdentity(); + T_map2odom_.frame_id_ = map_frame_id_; + T_map2odom_.child_frame_id_ = odom_frame_id_; + T_map2odom_.stamp_ = ros::Time::now(); } void PublisherTf::initialize(ros::NodeHandle& nh, const std::string& topic) @@ -31,6 +42,7 @@ void PublisherTf::publishDerived() auto current_state = problem_->getState("PO"); auto current_ts = problem_->getTimeStamp(); + // MAP - BASE //Get map2base from wolf result, and builds base2map pose tf::Transform T_map2base; if (current_state.count('P') == 0 or @@ -51,50 +63,59 @@ void PublisherTf::publishDerived() ROS_INFO("PublisherTf: State available!"); state_available_ = true; // warning won't be displayed again } - // 2D - if (problem_->getDim() == 2) + T_map2base = stateToTfTransform(current_state, problem_->getDim()); + } + + // MAP - ODOM + // Wolf odometry + if (publish_odom_tf_) + { + ros::Time transform_time; + std::string error_msg; + if (tfl_.getLatestCommonTime(odom_frame_id_, base_frame_id_, transform_time, &error_msg) == tf::ErrorValues::NO_ERROR and + transform_time != T_odom2base_.stamp_) { - T_map2base = tf::Transform (tf::createQuaternionFromYaw(current_state['O'](0)), - tf::Vector3(current_state['P'](0), - current_state['P'](1), - 0) ); + WOLF_ERROR("PublisherTf: option 'publish_odom_tf' enabled but a transform between ", + base_frame_id_, " and ", odom_frame_id_, + " was found published by a third party. Not publishing this transformation."); } - // 3D else { - T_map2base = tf::Transform (tf::Quaternion(current_state['O'](0), - current_state['O'](1), - current_state['O'](2), - current_state['O'](3)), - tf::Vector3(current_state['P'](0), - current_state['P'](1), - current_state['P'](2)) ); - } - } + VectorComposite odom; + for(auto pm : problem_->getProcessorIsMotionList()) + { + /*auto p = std::dynamic_pointer_cast<ProcessorBase>(pm); + if(p != nullptr) + WOLF_TRACE("Getting odometry of processor ", p->getName(), ":\n", pm->getOdometry());//*/ + odom = pm->getOdometry(); + } - //gets T_map2odom_ (odom wrt map), by using tf listener, and assuming an odometry node is broadcasting odom2base - tf::StampedTransform T_base2odom; - if ( tfl_.waitForTransform(base_frame_id_, odom_frame_id_, ros::Time(0), ros::Duration(0.1)) ) - { - tfl_.lookupTransform(base_frame_id_, odom_frame_id_, ros::Time(0), T_base2odom); - //std::cout << ros::Time::now().sec << " Odometry: " << T_base2odom.inverse().getOrigin().getX() << " " << T_base2odom.inverse().getOrigin().getY() << " " << T_base2odom.inverse().getRotation().getAngle() << std::endl; + T_odom2base_.setData(stateToTfTransform(odom, problem_->getDim())); + T_odom2base_.stamp_ = ros::Time::now(); + tfb_.sendTransform(T_odom2base_); + } } + // TF odometry else { - ROS_WARN("No %s to %s frame received", base_frame_id_.c_str(), odom_frame_id_.c_str()); - T_base2odom.setIdentity(); - T_base2odom.frame_id_ = base_frame_id_; - T_base2odom.child_frame_id_ = odom_frame_id_; - T_base2odom.stamp_ = ros::Time::now(); + try + { + tfl_.lookupTransform(odom_frame_id_, base_frame_id_, ros::Time(0), T_odom2base_); + } + catch(...) + { + ROS_WARN("No %s to %s frame received. Assuming identity.", base_frame_id_.c_str(), odom_frame_id_.c_str()); + T_odom2base_.setIdentity(); + T_odom2base_.stamp_ = ros::Time::now(); + } } + // Broadcast transform --------------------------------------------------------------------------- - tf::StampedTransform T_map2odom(T_map2base * T_base2odom, - ros::Time::now(), - map_frame_id_, - odom_frame_id_); + T_map2odom_.setData(T_map2base * T_odom2base_.inverse()); + T_map2odom_.stamp_ = ros::Time::now(); //std::cout << "T_map2odom: " << T_map2odom.getOrigin().getX() << " " << T_map2odom.getOrigin().getY() << " " << T_map2odom.getRotation().getAngle() << std::endl; - tfb_.sendTransform(T_map2odom); + tfb_.sendTransform(T_map2odom_); } }