eband_local_planner学习2

在move_base中CONTROLLING中调用了
tc_->computeVelocityCommands(cmd_vel)
bool EBandPlannerROS::computeVelocityCommands(geometry_msgs::Twist& cmd_vel)
    {
      // check if plugin initialized
      if(!initialized_)
      {
        ROS_ERROR("This planner has not been initialized, please call initialize() before using this planner");
        return false;
      }

      // instantiate local variables
      //std::vector<geometry_msgs::PoseStamped> local_plan;
      tf::Stamped<tf::Pose> global_pose;
      geometry_msgs::PoseStamped global_pose_msg;
      std::vector<geometry_msgs::PoseStamped> tmp_plan;

      // get curent robot position
      ROS_DEBUG("Reading current robot Position from costmap and appending it to elastic band.");
      if(!costmap_ros_->getRobotPose(global_pose))
      {
        ROS_WARN("Could not retrieve up to date robot pose from costmap for local planning.");
        return false;
      }

      // convert robot pose to frame in plan and set position in band at which to append
      tf::poseStampedTFToMsg(global_pose, global_pose_msg);
      tmp_plan.assign(1, global_pose_msg);
      eband_local_planner::AddAtPosition add_frames_at = add_front;

      // set it to elastic band and let eband connect it
      if(!eband_->addFrames(tmp_plan, add_frames_at))
      {
        ROS_WARN("Could not connect robot pose to existing elastic band.");
        return false;
      }

      // get additional path-frames which are now in moving window
      ROS_DEBUG("Checking for new path frames in moving window");
      std::vector<int> plan_start_end_counter = plan_start_end_counter_;
      std::vector<geometry_msgs::PoseStamped> append_transformed_plan;
      // transform global plan to the map frame we are working in - careful this also cuts the plan off (reduces it to local window)
      if(!eband_local_planner::transformGlobalPlan(*tf_, global_plan_, *costmap_ros_, costmap_ros_->getGlobalFrameID(), transformed_plan_, plan_start_end_counter))
      {
        // if plan could not be tranformed abort control and local planning
        ROS_WARN("Could not transform the global plan to the frame of the controller");
        return false;
      }

      // also check if there really is a plan
      if(transformed_plan_.empty())
      {
        // if global plan passed in is empty... we won't do anything
        ROS_WARN("Transformed plan is empty. Aborting local planner!");
        return false;
      }

      ROS_DEBUG("Retrieved start-end-counts are: (%d, %d)", plan_start_end_counter.at(0), plan_start_end_counter.at(1));
      ROS_DEBUG("Current start-end-counts are: (%d, %d)", plan_start_end_counter_.at(0), plan_start_end_counter_.at(1));

      // identify new frames - if there are any
      append_transformed_plan.clear();
      // did last transformed plan end futher away from end of complete plan than this transformed plan?
      if(plan_start_end_counter_.at(1) > plan_start_end_counter.at(1)) // counting from the back (as start might be pruned)
      {
        // new frames in moving window
        if(plan_start_end_counter_.at(1) > plan_start_end_counter.at(0)) // counting from the back (as start might be pruned)
        {
          // append everything
          append_transformed_plan = transformed_plan_;
        }
        else
        {
          // append only the new portion of the plan
          int discarded_frames = plan_start_end_counter.at(0) - plan_start_end_counter_.at(1);
          ROS_ASSERT(transformed_plan_.begin() + discarded_frames + 1 >= transformed_plan_.begin());
          ROS_ASSERT(transformed_plan_.begin() + discarded_frames + 1 < transformed_plan_.end());
          append_transformed_plan.assign(transformed_plan_.begin() + discarded_frames + 1, transformed_plan_.end());
        }

        // set it to elastic band and let eband connect it
        ROS_DEBUG("Adding %d new frames to current band", (int) append_transformed_plan.size());
        add_frames_at = add_back;
        if(eband_->addFrames(append_transformed_plan, add_back))
        {
          // appended frames succesfully to global plan - set new start-end counts
          ROS_DEBUG("Sucessfully added frames to band");
          plan_start_end_counter_ = plan_start_end_counter;
        }
        else {
          ROS_WARN("Failed to add frames to existing band");
          return false;
        }
      }
      else
        ROS_DEBUG("Nothing to add");

      // update Elastic Band (react on obstacle from costmap, ...)
      ROS_DEBUG("Calling optimization method for elastic band");
      std::vector<eband_local_planner::Bubble> current_band;
      if(!eband_->optimizeBand())
      {
        ROS_WARN("Optimization failed - Band invalid - No controls availlable");
        // display current band
        if(eband_->getBand(current_band))
          eband_visual_->publishBand("bubbles", current_band);
        return false;
      }

      // get current Elastic Band and
      eband_->getBand(current_band);
      
      // set it to the controller
      if(!eband_trj_ctrl_->setBand(current_band))
      {
        ROS_DEBUG("Failed to to set current band to Trajectory Controller");
        return false;
      }

      // set Odometry to controller
      if(!eband_trj_ctrl_->setOdometry(base_odom_))
      {
        ROS_DEBUG("Failed to to set current odometry to Trajectory Controller");
        return false;
      }

      // get resulting commands from the controller
      geometry_msgs::Twist cmd_twist;
      if(!eband_trj_ctrl_->getTwist(cmd_twist, goal_reached_))
      {
        ROS_DEBUG("Failed to calculate Twist from band in Trajectory Controller");
        return false;
      }


      // set retrieved commands to reference variable
      ROS_DEBUG("Retrieving velocity command: (%f, %f, %f)", cmd_twist.linear.x, cmd_twist.linear.y, cmd_twist.angular.z);
      cmd_vel = cmd_twist;


      // publish plan
      std::vector<geometry_msgs::PoseStamped> refined_plan;
      if(eband_->getPlan(refined_plan))
        // TODO publish local and current gloabl plan
        base_local_planner::publishPlan(refined_plan, g_plan_pub_);
      //base_local_planner::publishPlan(local_plan, l_plan_pub_, 0.0, 0.0, 1.0, 0.0);

      // display current band
      if(eband_->getBand(current_band))
        eband_visual_->publishBand("bubbles", current_band);

      return true;
    }
一.得到机器人的位姿并 加入到 elastic_band_


if(!costmap_ros_->getRobotPose(global_pose))
      {
        ROS_WARN("Could not retrieve up to date robot pose from costmap for local planning.");
        return false;
      }

      // convert robot pose to frame in plan and set position in band at which to append
      tf::poseStampedTFToMsg(global_pose, global_pose_msg);
      tmp_plan.assign(1, global_pose_msg);
      eband_local_planner::AddAtPosition add_frames_at = add_front;

      // set it to elastic band and let eband connect it
      if(!eband_->addFrames(tmp_plan, add_frames_at))    //  执行插入
      {
        ROS_WARN("Could not connect robot pose to existing elastic band.");
        return false;
      }
二.优化 elastic_band_
eband_->optimizeBand();
optimizeBand(elastic_band_);   //实际调用
bool EBandPlanner::optimizeBand(std::vector<Bubble>& band)
  {
    // check if plugin initialized
    if(!initialized_)
    {
      ROS_ERROR("This planner has not been initialized, please call initialize() before using this planner");
      return false;
    }

    // check whether band and costmap are in the same frame
    if(band.front().center.header.frame_id != costmap_ros_->getGlobalFrameID())
    {
      ROS_ERROR("Elastic Band expects plan for optimization in the %s frame, the plan was sent in the %s frame.",
          costmap_ros_->getGlobalFrameID().c_str(), band.front().center.header.frame_id.c_str());
      return false;
    }

    double distance;
    for(int i = 0; i < ((int) band.size()); i++)
    {
      // update Size of Bubbles in band by calculating Dist to nearest Obstacle [depends kinematic, environment]
      if(!calcObstacleKinematicDistance(band.at(i).center.pose, distance))
      {
        ROS_DEBUG("Optimization (Elastic Band) - Calculation of Distance failed. Frame %d of %d Probably outside map coordinates.",
            i, ((int) band.size()) );
        return false;
      }

      if(distance == 0.0)
      {
        // frame must not be immediately in collision -> otherwise calculation of gradient will later be invalid
        ROS_DEBUG("Optimization (Elastic Band) - Calculation of Distance failed. Frame %d of %d in collision. Plan invalid. Trying to refine band.",
            i, ((int) band.size()) );
        // TODO if frame in collision try to repair band instead of aborting everything
        return false;
      }

      band.at(i).expansion = distance;
    }
    ROS_DEBUG("before refineBand.size() %d.", (int) band.size());
    // close gaps and remove redundant bubbles
    if(!refineBand(band))
    {
      ROS_DEBUG("Elastic Band is broken. Could not close gaps in band. Global replanning needed.");
      return false;
    }
    ROS_DEBUG("refineBand.size() %d.", (int) band.size());
    // get a copy of current (valid) band
    std::vector<Bubble> tmp_band = band;

    // now optimize iteratively (for instance by miminizing the energy-function of the full system)
    for(int i = 0; i < num_optim_iterations_; i++)
    {
      ROS_DEBUG("Inside optimization: Cycle no %d", i);

      // calculate forces and apply changes
      if(!modifyBandArtificialForce(tmp_band))
      {
        ROS_DEBUG("Optimization failed while trying to modify Band.");
        // something went wrong -> discard changes and stop process
        return false;
      }

      // check whether band still valid - refine if neccesarry
      if(!refineBand(tmp_band))
      {
        ROS_DEBUG("Optimization failed while trying to refine modified band");
        // modified band is not valid anymore -> discard changes and stop process
        return false;
      }
    }

    // copy changes back to band
    band = tmp_band;
    return true;
  }
1. refineBand(band)
2. modifyBandArtificialForce(tmp_band)
while( (i>0) && (i < ((int) band.size() - 1)) )
{
     calcInternalForces(i, band, band.at(i), internal_forces.at(i));
     calcExternalForces(i, band.at(i), external_forces.at(i));
}
InternalForces + ExternalForces
// sum up external and internal forces over all bubbles
      forces.at(i).wrench.force.x = internal_forces.at(i).wrench.force.x + external_forces.at(i).wrench.force.x;
      forces.at(i).wrench.force.y = internal_forces.at(i).wrench.force.y + external_forces.at(i).wrench.force.y;
      forces.at(i).wrench.force.z = internal_forces.at(i).wrench.force.z + external_forces.at(i).wrench.force.z;

      forces.at(i).wrench.torque.x = internal_forces.at(i).wrench.torque.x + external_forces.at(i).wrench.torque.x;
      forces.at(i).wrench.torque.y = internal_forces.at(i).wrench.torque.y + external_forces.at(i).wrench.torque.y;
      forces.at(i).wrench.torque.z = internal_forces.at(i).wrench.torque.z + external_forces.at(i).wrench.torque.z;
抑制切向力
suppressTangentialForces(i, band, forces.at(i))
applyForces(i, band, forces)
------------------------------------------------------------

calcInternalForces (i, band, band. at (i), internal_forces. at (i))

calcBubbleDistance(curr_bubble.center.pose, band[bubble_num-1].center.pose, distance1)
calcBubbleDistance(curr_bubble.center.pose, band[bubble_num+1].center.pose, distance2)
calcBubbleDifference(curr_bubble.center.pose, band[bubble_num-1].center.pose, difference1)
calcBubbleDifference(curr_bubble.center.pose, band[bubble_num+1].center.pose, difference2)

wrench.force.x = internal_force_gain_*(difference1.linear.x/distance1 + difference2.linear.x/distance2);
wrench.force.y = internal_force_gain_*(difference1.linear.y/distance1 + difference2.linear.y/distance2);
wrench.force.z = internal_force_gain_*(difference1.linear.z/distance1 + difference2.linear.z/distance2);
wrench.torque.x = internal_force_gain_*(difference1.angular.x/distance1 + difference2.angular.x/distance2);
wrench.torque.y = internal_force_gain_*(difference1.angular.y/distance1 + difference2.angular.y/distance2);
wrench.torque.z = internal_force_gain_*(difference1.angular.z/distance1 + difference2.angular.z/distance2);

------------------------------------------------------------

calcExternalForces (i, band. at (i), external_forces. at (i))
// calculate delta-poses (on upper edge of bubble) for x-direction
    edge = curr_bubble.center.pose;
    edge.position.x = edge.position.x + curr_bubble.expansion;
    // get expansion on bubble at this point
    if(!calcObstacleKinematicDistance(edge, distance1))
    {
      ROS_DEBUG("Bubble %d probably at edge of map - cannot retrieve distance information to calculate external forces", bubble_num);
      // we cannot calculate external forces for this bubble - but still continue for the other bubbles
      return true;
    }
    // calculate delta-poses (on lower edge of bubble) for x-direction
    edge.position.x = edge.position.x - 2.0*curr_bubble.expansion;
    // get expansion on bubble at this point
    if(!calcObstacleKinematicDistance(edge, distance2))
    {
      ROS_DEBUG("Bubble %d probably at edge of map - cannot retrieve distance information to calculate external forces", bubble_num);
      // we cannot calculate external forces for this bubble - but still continue for the other bubbles
      return true;
    }

    // calculate difference-quotient (approx. of derivative) in x-direction
    if(curr_bubble.expansion <= tiny_bubble_expansion_)
    {
      // avoid division by (almost) zero to avoid numerical problems
      wrench.force.x = -external_force_gain_*(distance2 - distance1)/(2.0*tiny_bubble_expansion_);
      // actually we should never end up here - band should have been considered as broken
      ROS_DEBUG("Calculating external forces on broken band. Bubble should have been removed. Local Planner probably ill configured");
    }
    else
      wrench.force.x = -external_force_gain_*(distance2 - distance1)/(2.0*curr_bubble.expansion);
    // TODO above equations skip term to make forces continuous at end of influence region - test to add corresponding term


    // calculate delta-poses (on upper edge of bubble) for y-direction
    edge = curr_bubble.center.pose;
    edge.position.y = edge.position.y + curr_bubble.expansion;
    // get expansion on bubble at this point
    if(!calcObstacleKinematicDistance(edge, distance1))
    {
      ROS_DEBUG("Bubble %d probably at edge of map - cannot retrieve distance information to calculate external forces", bubble_num);
      // we cannot calculate external forces for this bubble - but still continue for the other bubbles
      return true;
    }
    // calculate delta-poses (on lower edge of bubble) for x-direction
    edge.position.y = edge.position.y - 2.0*curr_bubble.expansion;
    // get expansion on bubble at this point
    if(!calcObstacleKinematicDistance(edge, distance2))
    {
      ROS_DEBUG("Bubble %d probably at edge of map - cannot retrieve distance information to calculate external forces", bubble_num);
      // we cannot calculate external forces for this bubble - but still continue for the other bubbles
      return true;
    }

    // calculate difference-quotient (approx. of derivative) in x-direction
    if(curr_bubble.expansion <= tiny_bubble_expansion_)
    {
      // avoid division by (almost) zero to avoid numerical problems
      wrench.force.y = -external_force_gain_*(distance2 - distance1)/(2.0*tiny_bubble_expansion_);
      // actually we should never end up here - band should have been considered as broken
      ROS_DEBUG("Calculating external forces on broken band. Bubble should have been removed. Local Planner probably ill configured");
    }
    else
      wrench.force.y = -external_force_gain_*(distance2 - distance1)/(2.0*curr_bubble.expansion);
    // TODO above equations skip term to make forces continuous at end of influence region - test to add corresponsing term


    // no force in z-direction
    wrench.force.z = 0.0;


    // no torque around x and y axis
    wrench.torque.x = 0.0;
    wrench.torque.y = 0.0;


    // calculate delta-poses (on upper edge of bubble) for x-direction
    PoseToPose2D(curr_bubble.center.pose, edge_pose2D);
    edge_pose2D.theta = edge_pose2D.theta + (curr_bubble.expansion/getCircumscribedRadius(*costmap_ros_));
    edge_pose2D.theta = angles::normalize_angle(edge_pose2D.theta);
    PoseToPose2D(edge, edge_pose2D);
    // get expansion on bubble at this point
    if(!calcObstacleKinematicDistance(edge, distance1))
    {
      ROS_DEBUG("Bubble %d probably at edge of map - cannot retrieve distance information to calculate external forces", bubble_num);
      // we cannot calculate external forces for this bubble - but still continue for the other bubbles
      return true;
    }
    // calculate delta-poses (on lower edge of bubble) for x-direction
    edge_pose2D.theta = edge_pose2D.theta - 2.0*(curr_bubble.expansion/getCircumscribedRadius(*costmap_ros_));
    edge_pose2D.theta = angles::normalize_angle(edge_pose2D.theta);
    PoseToPose2D(edge, edge_pose2D);
    // get expansion on bubble at this point
    if(!calcObstacleKinematicDistance(edge, distance2))
    {
      ROS_DEBUG("Bubble %d probably at edge of map - cannot retrieve distance information to calculate external forces", bubble_num);
      // we cannot calculate external forces for this bubble - but still continue for the other bubbles
      return true;
    }

    // calculate difference-quotient (approx. of derivative) in x-direction
    if(curr_bubble.expansion <= tiny_bubble_expansion_)
    {
      // avoid division by (almost) zero to avoid numerical problems
      wrench.torque.z = -external_force_gain_*(distance2 - distance1)/(2.0*tiny_bubble_expansion_);
      // actually we should never end up here - band should have been considered as broken
      ROS_DEBUG("Calculating external forces on broken band. Bubble should have been removed. Local Planner probably ill configured");
    }
    else
      wrench.torque.z = -external_force_gain_*(distance2 - distance1)/(2.0*curr_bubble.expansion);
    // TODO above equations skip term to make forces continuous at end of influence region - test to add corresponsing term


------------------------------------------------------------

抑制切向力

suppressTangentialForces(i, band, forces.at(i))

// get pose-difference from following to preceding bubble -> "direction of the band in this bubble"
    if(!calcBubbleDifference(band[bubble_num+1].center.pose, band[bubble_num-1].center.pose, difference))
      return false;

    // "project wrench" in middle bubble onto connecting vector
    // scalar wrench*difference
    scalar_fd = forces.wrench.force.x*difference.linear.x + forces.wrench.force.y*difference.linear.y +
      forces.wrench.force.z*difference.linear.z + forces.wrench.torque.x*difference.angular.x +
      forces.wrench.torque.y*difference.angular.y + forces.wrench.torque.z*difference.angular.z;

    // abs of difference-vector: scalar difference*difference
    scalar_dd = difference.linear.x*difference.linear.x + difference.linear.y*difference.linear.y + difference.linear.z*difference.linear.z +
      difference.angular.x*difference.angular.x + difference.angular.y*difference.angular.y + difference.angular.z*difference.angular.z;

    // avoid division by (almost) zero -> check if bubbles have (almost) same center-pose
    if(scalar_dd <= tiny_bubble_distance_)
    {
      // there are redundant bubbles, this should normally not hapen -> probably error in band refinement
      ROS_DEBUG("Calculating tangential forces for redundant bubbles. Bubble should have been removed. Local Planner probably ill configured");
    }

    // calculate orthogonal components
    forces.wrench.force.x = forces.wrench.force.x - scalar_fd/scalar_dd * difference.linear.x;
    forces.wrench.force.y = forces.wrench.force.y - scalar_fd/scalar_dd * difference.linear.y;
    forces.wrench.force.z = forces.wrench.force.z - scalar_fd/scalar_dd * difference.linear.z;
    forces.wrench.torque.x = forces.wrench.torque.x - scalar_fd/scalar_dd * difference.angular.x;
    forces.wrench.torque.y = forces.wrench.torque.y - scalar_fd/scalar_dd * difference.angular.y;
    forces.wrench.torque.z = forces.wrench.torque.z - scalar_fd/scalar_dd * difference.angular.z;

------------------------------------------------------------

applyForces(i, band, forces)

// move bubble
    bubble_pose = band.at(bubble_num).center.pose;
    PoseToPose2D(bubble_pose, bubble_pose2D);

    // move according to bubble_new = bubble_old + alpha*force -> we choose alpha to be the current expansion of the modified bubble
    bubble_jump.linear.x = band.at(bubble_num).expansion*forces.at(bubble_num).wrench.force.x;
    bubble_jump.linear.y = band.at(bubble_num).expansion*forces.at(bubble_num).wrench.force.y;
    bubble_jump.linear.z = 0.0;
    bubble_jump.angular.x = 0.0;
    bubble_jump.angular.y = 0.0;
    bubble_jump.angular.z = band.at(bubble_num).expansion/getCircumscribedRadius(*costmap_ros_) * forces.at(bubble_num).wrench.torque.z;
    bubble_jump.angular.z = angles::normalize_angle(bubble_jump.angular.z);

    // apply changes to calc tmp bubble position
    new_bubble_pose2D.x = bubble_pose2D.x + bubble_jump.linear.x;
    new_bubble_pose2D.y = bubble_pose2D.y + bubble_jump.linear.y;
    new_bubble_pose2D.theta = bubble_pose2D.theta + bubble_jump.angular.z;
    new_bubble_pose2D.theta = angles::normalize_angle(new_bubble_pose2D.theta);

    // apply changes to local copy
    Pose2DToPose(new_bubble_pose, new_bubble_pose2D);
    new_bubble.center.pose = new_bubble_pose;












  • 0
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值