39 #include <pluginlib/class_list_macros.h>
40 #include <geometry_msgs/Point.h>
41 #include <boost/foreach.hpp>
47 namespace car_maneuver_recovery
50 CarManeuverRecovery::CarManeuverRecovery()
51 : tfListener_(NULL), globalCostmapROS_(NULL), localCostmapROS_(NULL)
52 , worldModel_(NULL), initialized_(
false)
57 CarManeuverRecovery::~CarManeuverRecovery()
63 void CarManeuverRecovery::initialize(std::string name,
64 tf::TransformListener* tfListener,
65 costmap_2d::Costmap2DROS* globalCostmapROS,
66 costmap_2d::Costmap2DROS* localCostmapROS)
70 ROS_ERROR(
"Plugin already initialized. Doing nothing.");
76 tfListener_ = tfListener;
77 globalCostmapROS_ = globalCostmapROS;
78 localCostmapROS_ = localCostmapROS;
81 ros::NodeHandle pnh(
"~/" + name);
83 pnh.param(
"recovery_speed", recoverySpeed_, 0.5);
84 pnh.param(
"recovery_steering_angle", recoverySteeringAngle_, 0.5);
85 pnh.param(
"wheelbase", wheelbase_, 0.5);
86 pnh.param<
bool>(
"four_wheel_steering", fourWheelSteering_,
false);
87 pnh.param<
bool>(
"crab_steering", crabSteering_,
false);
88 pnh.param<
double>(
"timeout", timeout_, 5.0);
90 twistPub_ = pnh.advertise<geometry_msgs::Twist>(
"/cmd_vel", 1);
93 worldModel_ =
new base_local_planner::CostmapModel(
94 *localCostmapROS_->getCostmap());
101 void CarManeuverRecovery::runBehavior()
105 ROS_ERROR(
"Plugin must be initialized before recovery behavior is run!");
109 if(globalCostmapROS_ == NULL || localCostmapROS_ == NULL)
111 ROS_ERROR(
"The costmaps passed to the CarManeuverRecovery object cannot "
112 "be NULL. Doing nothing.");
116 ROS_WARN(
"Car Maneuver recovery behavior started.");
118 ros::Rate loopRate(5);
119 ros::Time time = ros::Time::now();
121 while (ros::ok() && (ros::Time::now() - time).toSec() < timeout_)
124 std::vector<geometry_msgs::Point> footprint;
125 localCostmapROS_->getOrientedFootprint(footprint);
127 double frontLineCost = lineCost(footprint[2], footprint[3]);
128 double rearLineCost = lineCost(footprint[0], footprint[1]);
129 double leftLineCost = lineCost(footprint[1], footprint[2]);
130 double rightLineCost = lineCost(footprint[0], footprint[3]);
132 ROS_DEBUG(
"Front side cost: %f", frontLineCost);
133 ROS_DEBUG(
"Rear side cost: %f", rearLineCost);
134 ROS_DEBUG(
"Left side cost: %f", leftLineCost);
135 ROS_DEBUG(
"Right side cost: %f", rightLineCost);
137 int front = frontLineCost < 128;
138 int rear = rearLineCost < 128;
139 int left = leftLineCost < 128;
140 int right = rightLineCost < 128;
142 if (front && rear && left && right)
144 else if (!front && !rear)
146 ROS_FATAL(
"Unable to recover!");
150 geometry_msgs::Twist cmd;
155 speed = recoverySpeed_ * ((frontLineCost > rearLineCost) ? 1 : -1);
157 speed = (front - rear) * recoverySpeed_;
159 if (fourWheelSteering_)
161 cmd.linear.x = speed;
164 cmd.linear.y = (left - right) * fabs(speed)
165 * tan(recoverySteeringAngle_);
169 (speed > 0.0) ? (left - right) * recoverySteeringAngle_ : 0.0;
171 (speed < 0.0) ? (right - left) * recoverySteeringAngle_ : 0.0;
172 double beta = atan((tan(fsa) + tan(rsa)) / 2);
173 cmd.linear.x = speed;
174 cmd.linear.y = cmd.linear.x * tan(beta);
175 cmd.angular.z = speed * cos(beta) * (tan(fsa) - tan(rsa))/ wheelbase_;
180 double fsa = (left - right) * recoverySteeringAngle_;
181 double beta = atan(tan(fsa) / 2);
182 cmd.linear.x = speed * sqrt(1 / (1 + pow(tan(beta), 2)));
183 cmd.linear.y = cmd.linear.x * tan(beta);
184 cmd.angular.z = speed * cos(beta) * tan(fsa) / wheelbase_;
188 twistPub_.publish(cmd);
193 if ((ros::Time::now() - time).toSec() < timeout_)
194 ROS_WARN(
"Car Maneuver recovery behavior timed out!");
196 ROS_WARN(
"Car maneuver recovery behavior finished.");
200 double CarManeuverRecovery::lineCost(geometry_msgs::Point point1,
201 geometry_msgs::Point point2)
203 unsigned int x[2], y[2];
204 localCostmapROS_->getCostmap()->worldToMap(point1.x, point1.y, x[0], y[0]);
205 localCostmapROS_->getCostmap()->worldToMap(point2.x, point2.y, x[1], y[1]);
209 for (
unsigned int i = 0; i < 2; i++)
210 cost += localCostmapROS_->getCostmap()->getCost(x[i], y[i]) / 2;
PLUGINLIB_DECLARE_CLASS(car_maneuver_recovery, CarManeuverRecovery, car_maneuver_recovery::CarManeuverRecovery, nav_core::RecoveryBehavior) namespace car_maneuver_recovery
A move base plugin that implements car like maneuvers as a recovery behavior.