ROS Resources: Documentation | Support | Discussion Forum | Index | Service Status | ros @ Robotics Stack Exchange
Ask Your Question

robotiqsguy's profile - activity

2022-04-06 14:09:46 -0500 received badge  Famous Question (source)
2016-05-09 21:00:10 -0500 received badge  Notable Question (source)
2013-12-17 13:18:55 -0500 commented answer Hydro move_base/tf2 extrapolation error into the future errror

To debug this problem I was thinking of pushing values on to the error_string. That way it would only get printed when an error happens.

2013-12-17 13:16:42 -0500 commented answer Hydro move_base/tf2 extrapolation error into the future errror

HI Niccer, I'm noobie to ROS, so please keep the suggestions coming. This is an intermittent problem. After the change I made to send a vector of Transforms the problem happens much less. But it still happens. I wish there were some good tools for online debugging of TF2 problems.

2013-12-12 10:21:44 -0500 commented answer Hydro move_base/tf2 extrapolation error into the future errror

We timestamp our local and global transforms with the same time. They are being published in the same sendTransform since we use a vector of transforms. I assume upon receiving a vector that access to tf is locked, so if one transform is in tf the other one would be too. Transforms are sent at 20Hz.

2013-12-12 04:11:23 -0500 commented answer Hydro move_base/tf2 extrapolation error into the future errror

Our chain is world->global->local->base. One node publishes world, global and local transforms. They were being sent individually with SendTransform. I changed it to send a vactor of transforms which helped, but didn't fix the problem. I still think there is a bug in tf2.

2013-12-09 02:08:12 -0500 received badge  Famous Question (source)
2013-12-07 16:17:46 -0500 commented answer setTransform return unhandled

I think that it is reasonable to add debug output in there. If for some reason it does fail I think its better to know about it than not.

2013-12-07 16:15:29 -0500 received badge  Popular Question (source)
2013-12-06 09:15:51 -0500 commented answer Hydro move_base/tf2 extrapolation error into the future errror

I have now verified that it fails in the tf.transformPose() statement right after tf.lookupTransform. The first thing transformPose does is a lookupTransform, though. Different path through the code but still ends up calling BufferCore::WalktoTopParent(). I'll continue debugging.

2013-12-06 04:12:09 -0500 commented answer Hydro move_base/tf2 extrapolation error into the future errror

Pretty sure, I put some ROS_INFO statements around the lookupTransform. If you look at BufferCore::walkToTopParent if time == ros::Time() it calls getLatestCommonTime(...) to get a time. I believe this is where the time value seen in the error message is coming from. I'm trying to verify.

2013-12-05 06:52:29 -0500 answered a question Hydro move_base/tf2 extrapolation error into the future errror
Hi Niccer,

Because, I've run tests where I published transforms at 10Hz and 20Hz tf_monitor reports different delays. But here is an example of 20hz test.

Node: /state_filter 60.0905 Hz, Average Delay: 0.0086032 Max Delay: 0.0267848

I believe that the error happens in Time_Cache::find_closest in tf2/src/cache.cpp

To be verbose(sorry) this is the call chain

// move_base/src/move_base.cpp
        if(tc_->computeVelocityCommands(cmd_vel)){  

//dwa_local_planner/src/dwa_planner_ros.cpp
      bool DWAPlannerROS::computeVelocityCommands(geometry_msgs::Twist& cmd_vel) {
    // dispatches to either dwa sampling control or stop and rotate control, depending on whether we have been close enough to goal
    if ( ! costmap_ros_->getRobotPose(current_pose_)) {
      ROS_ERROR("Could not get robot pose");
      return false;
    }
    std::vector<geometry_msgs::PoseStamped> transformed_plan;
    if ( ! planner_util_.getLocalPlan(current_pose_, transformed_plan)) {
      ROS_ERROR("Could not get local plan");
      return false;
    }   

//base_local_planner/src/local_planner_util.cpp
bool LocalPlannerUtil::getLocalPlan(tf::Stamped<tf::Pose>& global_pose, std::vector<geometry_msgs::PoseStamped>& transformed_plan) {
  //get the global plan in our frame
  if(!base_local_planner::transformGlobalPlan(
      *tf_,
      global_plan_,
      global_pose,
      *costmap_,
      global_frame_,
      transformed_plan)) {
    ROS_WARN("LocalPlannerUtil::getLocalPlan - Could not transform the global plan to the frame of the controller");
    return false;
  }

//base_local_planner/src/goal_functions.cpp
  bool transformGlobalPlan(
      const tf::TransformListener& tf,
      const std::vector<geometry_msgs::PoseStamped>& global_plan,
      const tf::Stamped<tf::Pose>& global_pose,
      const costmap_2d::Costmap2D& costmap,
      const std::string& global_frame,
      std::vector<geometry_msgs::PoseStamped>& transformed_plan){
    const geometry_msgs::PoseStamped& plan_pose = global_plan[0];

    transformed_plan.clear();

    try {
      if (!global_plan.size() > 0) {
        ROS_ERROR("transformGlobalPlan - Received plan with zero length");
        return false;
      }

      // get plan_to_global_transform from plan frame to global_frame
      tf::StampedTransform plan_to_global_transform;
      tf.lookupTransform(global_frame, ros::Time(), 
          plan_pose.header.frame_id, plan_pose.header.stamp, 
          plan_pose.header.frame_id, plan_to_global_transform);

//tf/src/tf.cpp
void Transformer::lookupTransform(const std::string& target_frame,const ros::Time& target_time, const std::string& source_frame,
                     const ros::Time& source_time, const std::string& fixed_frame, StampedTransform& transform) const
{
  geometry_msgs::TransformStamped output = 
    tf2_buffer_.lookupTransform(strip_leading_slash(target_frame), target_time,
                                strip_leading_slash(source_frame), source_time,
                                strip_leading_slash(fixed_frame));
  transformStampedMsgToTF(output, transform);
};

//tf2/src/buffer_core.cpp
geometry_msgs::TransformStamped BufferCore::lookupTransform(const std::string& target_frame, 
                                                        const ros::Time& target_time,
                                                        const std::string& source_frame,
                                                        const ros::Time& source_time,
                                                        const std::string& fixed_frame) const
{
  validateFrameId("lookupTransform argument target_frame", target_frame);
  validateFrameId("lookupTransform argument source_frame", source_frame);
  validateFrameId("lookupTransform argument fixed_frame", fixed_frame);

  geometry_msgs::TransformStamped output;
  geometry_msgs::TransformStamped temp1 =  lookupTransform(fixed_frame, source_frame, source_time);
  geometry_msgs::TransformStamped temp2 =  lookupTransform(target_frame, fixed_frame, target_time);


//tf2/src/buffer_core.cpp
geometry_msgs::TransformStamped BufferCore::lookupTransform(const std::string& target_frame,
                                                            const std::string& source_frame,
                                                            const ros::Time& time) const
{
  boost::mutex::scoped_lock lock(frame_mutex_);

  if (target_frame == source_frame) {
    geometry_msgs::TransformStamped identity;
    identity.header.frame_id = target_frame;
    identity.child_frame_id = source_frame;
    identity.transform.rotation.w = 1;

    if (time == ros::Time())
    {
      CompactFrameID target_id = lookupFrameNumber(target_frame);
      TimeCacheInterfacePtr cache = getFrame(target_id);
      if (cache)
        identity.header.stamp = cache->getLatestTimestamp();
      else
        identity.header.stamp = time;
    }
    else
      identity.header.stamp = time;

    return identity;
  }

  //Identify case does not need to be validated above
  CompactFrameID target_id = validateFrameId("lookupTransform argument target_frame", target_frame);
  CompactFrameID source_id = validateFrameId("lookupTransform argument source_frame", source_frame);

  std::string error_string;
  TransformAccum accum;
  int retval = walkToTopParent(accum, time, target_id, source_id, &error_string);
  if (retval != tf2_msgs::TF2Error::NO_ERROR)
  {
    switch (retval)
    {
    case tf2_msgs::TF2Error::CONNECTIVITY_ERROR:
      throw ConnectivityException(error_string);
    case tf2_msgs::TF2Error::EXTRAPOLATION_ERROR ...
(more)
2013-12-05 04:54:36 -0500 received badge  Notable Question (source)
2013-12-05 03:44:15 -0500 received badge  Student (source)
2013-12-04 07:42:35 -0500 received badge  Organizer (source)
2013-12-04 07:36:49 -0500 asked a question setTransform return unhandled

In tf2_ros/src/transform_listener.cpp line 123 in TransformListener::subscription_callback_impl(...) the call buffer_.setTransform returns a boolean. If I've read things right it appears like that the return value should be checked, and handled in some way (error message if false??)

2013-12-04 07:31:43 -0500 received badge  Popular Question (source)
2013-12-04 05:45:31 -0500 received badge  Editor (source)
2013-12-04 05:23:17 -0500 asked a question Hydro move_base/tf2 extrapolation error into the future errror

Hi All,

We are using Hyrdo's move_base and we continue to get an extrapolation error into the future. I believe this is causing our robot to stop and start during a traverse.

In looking the ROS source code it appears that the lookupTransform in navigation/base_local_planner/src/goal_functions.cpp line 110 in transformGlobalPlan is returning the error. We are using the dwa_local_planner. We are publishing transforms at 20hz from a separate node. The parameters to tf.lookupTransform are global_frame = "local" and the plan_pose.header.frame_id = "global", and the plan_pose.header.stamp comes from the generating the gloabl plan. I think the bug is coming from tf2/src/buffer_core.cpp in WalkToTopParent(). I still need to do more debugging to find the exact problem. I've turned the debug information on for move_base so I'm including a snippet of it, and the console log below. Any help would be appreciated. Thanks.

[DEBUG] [1386166204.375994679]: The action server has received a new goal request
[DEBUG] [1386166204.376260355]: A new goal has been recieved by the single goal action server
[DEBUG] [1386166204.376656845]: Accepting a new goal
[DEBUG] [1386166204.376895493]: Accepting goal, id: /waypoint_management_node-1-1386166204.372833387, stamp: 1386166204.37
[DEBUG] [1386166204.377491239]: Publishing feedback for goal, id: /waypoint_management_node-1-1386166204.372833387, stamp: 1386166204.37
[DEBUG] [1386166204.377705512]: Publishing feedback for goal with id: /waypoint_management_node-1-1386166204.372833387 and stamp: 1386166204.37
[DEBUG] [1386166204.378025665]: Planning...
[DEBUG] [1386166204.378168840]: Waiting for plan, in the planning state.
[DEBUG] [1386166204.378332478]: Full control cycle time: 0.000979315

[DEBUG] [1386166204.455307564]: Got Plan with 49 points!
[DEBUG] [1386166204.457263957]: Generated a plan from the base_global_planner
[DEBUG] [1386166204.458307175]: Planner thread is suspending
[DEBUG] [1386166204.477544259]: Publishing feedback for goal, id: /waypoint_management_node-1-1386166204.372833387, stamp: 1386166204.37
[DEBUG] [1386166204.477708316]: Publishing feedback for goal with id: /waypoint_management_node-1-1386166204.372833387 and stamp: 1386166204.37
[DEBUG] [1386166204.477914069]: Got a new plan...swap pointers
[DEBUG] [1386166204.478065066]: pointers swapped!
[ INFO] [1386166204.478229751]: Got new plan
[DEBUG] [1386166204.478925371]: In controlling state.
[DEBUG] [1386166204.515009849]: Got a valid command from the local planner: 0.500, 0.000, 2.000
[DEBUG] [1386166204.516475469]: Full control cycle time: 0.037907056

[DEBUG] [1386166204.578542367]: Publishing feedback for goal, id: /waypoint_management_node-1-1386166204.372833387, stamp: 1386166204.37
[DEBUG] [1386166204.579298889]: Publishing feedback for goal with id: /waypoint_management_node-1-1386166204.372833387 and stamp: 1386166204.37
[DEBUG] [1386166204.580845315]: In controlling state.
[DEBUG] [1386166204.609181880]: Got a valid command from the local planner: 0.500, 0.000, 2.000
[DEBUG] [1386166204.610400540]: Full control cycle time: 0.031062960

[DEBUG] [1386166204.677557610]: Publishing feedback for goal, id: /waypoint_management_node-1-1386166204.372833387, stamp: 1386166204.37
[DEBUG] [1386166204.677725508]: Publishing feedback for goal with id: /waypoint_management_node-1-1386166204.372833387 and stamp: 1386166204.37
[DEBUG] [1386166204.677947673]: In controlling state.
[DEBUG] [1386166204.704567051]: Got a valid command from the local planner: 0.500, 0.000, 2.000
[DEBUG] [1386166204.705445516]: Full control cycle time: 0.027409982

[DEBUG] [1386166204.777927638]: Publishing feedback for goal, id: /waypoint_management_node-1-1386166204.372833387, stamp: 1386166204.37
[DEBUG] [1386166204.779469173]: Publishing feedback for goal with id: /waypoint_management_node-1-1386166204.372833387 and stamp: 1386166204.37 ...
(more)