00001 #include <nj_costmap/jockey.h>
00002
00003 namespace nj_costmap
00004 {
00005
00006 Jockey::Jockey(const std::string& name, const double frontier_width) :
00007 lama_jockeys::NavigatingJockey(name),
00008 odom_frame_("odom"),
00009 range_cutoff_(0),
00010 has_crossing_(false),
00011 last_map_orientation_(0),
00012 crossing_detector_(frontier_width),
00013 obstacle_avoider_(frontier_width / 2, "base_laser_link")
00014 {
00015 private_nh_.getParam("odom_frame", odom_frame_);
00016 range_cutoff_set_ = private_nh_.getParam("range_cutoff", range_cutoff_);
00017
00018 pub_twist_ = private_nh_.advertise<geometry_msgs::Twist>("cmd_vel", 1);
00019 pub_crossing_marker_ = private_nh_.advertise<visualization_msgs::Marker>("crossing_marker", 50, true);
00020 pub_exits_marker_ = private_nh_.advertise<visualization_msgs::Marker>("exits_marker", 50, true);
00021 pub_place_profile_ = private_nh_.advertise<sensor_msgs::PointCloud>("place_profile_cloud", 50, true);
00022 pub_crossing_ = private_nh_.advertise<lama_msgs::Crossing>("abs_crossing", 50, true);
00023
00024 initTwistHandlerParam();
00025 }
00026
00027 void Jockey::initTwistHandlerParam()
00028 {
00029
00030 private_nh_.getParam("robot_radius", obstacle_avoider_.robot_radius);
00031 private_nh_.getParam("min_distance", obstacle_avoider_.min_distance);
00032 private_nh_.getParam("long_distance", obstacle_avoider_.long_distance);
00033 private_nh_.getParam("turnrate_collide", obstacle_avoider_.turnrate_collide);
00034 private_nh_.getParam("vel_close_obstacle", obstacle_avoider_.vel_close_obstacle);
00035 private_nh_.getParam("turnrate_factor", obstacle_avoider_.turnrate_factor);
00036 private_nh_.getParam("max_linear_velocity", obstacle_avoider_.max_linear_velocity);
00037 private_nh_.getParam("max_angular_velocity", obstacle_avoider_.max_angular_velocity);
00038
00039
00040 private_nh_.getParam("laser_frame", obstacle_avoider_.laser_frame);
00041
00042 int fake_laser_beam_count;
00043 if (private_nh_.getParam("fake_laser_beam_count", fake_laser_beam_count))
00044 {
00045 if (fake_laser_beam_count > 1)
00046 {
00047 obstacle_avoider_.fake_laser_beam_count = fake_laser_beam_count;
00048 }
00049 else
00050 {
00051 ROS_ERROR_STREAM("Parameter " << private_nh_.getNamespace() << "/fake_laser_beam_count must be at least 2, setting to default");
00052 }
00053 }
00054
00055 private_nh_.getParam("range_max", obstacle_avoider_.range_max);
00056 }
00057
00058 void Jockey::onTraverse()
00059 {
00060 ROS_INFO("Received action TRAVERSE or CONTINUE");
00061 crossing_goer_.resetIntegrals();
00062 costmap_handler_ = private_nh_.subscribe("local_costmap", 1, &Jockey::handleCostmap, this);
00063 ROS_DEBUG("Costmap handler started");
00064
00065 ros::Rate r(100);
00066 while (ros::ok())
00067 {
00068 if (server_.isPreemptRequested() && !ros::ok())
00069 {
00070 ROS_INFO("%s: Preempted", jockey_name_.c_str());
00071
00072 server_.setPreempted();
00073 break;
00074 }
00075
00076 if (has_crossing_)
00077 {
00078 geometry_msgs::Twist twist;
00079
00080 bool goto_crossing = true;
00081 if (rel_crossing_.frontiers.empty())
00082 {
00083 goto_crossing = false;
00084 }
00085 if (rel_crossing_.frontiers.size() == 1)
00086 {
00087 if ((std::abs(rel_crossing_.frontiers[0].angle) > M_PI_2))
00088 {
00089 goto_crossing = false;
00090 }
00091 }
00092 if (rel_crossing_.frontiers.size() == 2)
00093 {
00094 if ((std::abs(rel_crossing_.frontiers[0].angle) > M_PI_2) &&
00095 (std::abs(rel_crossing_.frontiers[1].angle) > M_PI_2))
00096 {
00097 goto_crossing = false;
00098 }
00099 }
00100 if (goto_crossing)
00101 {
00102
00103
00104 bool goal_reached = crossing_goer_.goto_crossing(rel_crossing_, twist);
00105 pub_twist_.publish(twist);
00106 ROS_DEBUG("Go to crossing");
00107
00108 if (goal_reached)
00109 {
00110 result_.final_state = result_.DONE;
00111 result_.completion_time = getCompletionDuration();
00112 server_.setSucceeded(result_);
00113 break;
00114 }
00115 }
00116 else
00117 {
00118
00119 twist = obstacle_avoider_.getTwist(map_);
00120 pub_twist_.publish(twist);
00121 ROS_DEBUG("Avoid obstacles");
00122 }
00123 ROS_DEBUG("twist (%.3f, %.3f)", twist.linear.x, twist.angular.z);
00124 has_crossing_ = false;
00125 }
00126 ros::spinOnce();
00127 r.sleep();
00128 }
00129 ROS_DEBUG("Exiting onTraverse");
00130 }
00131
00132 void Jockey::onStop()
00133 {
00134 ROS_DEBUG("Received action STOP or INTERRUPT");
00135 costmap_handler_.shutdown();
00136 result_.final_state = result_.DONE;
00137 result_.completion_time = ros::Duration(0.0);
00138 server_.setSucceeded(result_);
00139 }
00140
00141 void Jockey::onInterrupt()
00142 {
00143 ROS_DEBUG("Received action INTERRUPT");
00144 onStop();
00145 }
00146
00147 void Jockey::onContinue()
00148 {
00149 ROS_DEBUG("Received action CONTINUE");
00150 onTraverse();
00151 }
00152
00155 void Jockey::handleCostmap(const nav_msgs::OccupancyGridConstPtr& msg)
00156 {
00157 map_ = *msg;
00158 if (range_cutoff_set_)
00159 {
00160 if (std::abs(range_cutoff_ - (-1)) < 1e-10)
00161 {
00162
00163 abs_crossing_ = crossing_detector_.crossingDescriptor(map_);
00164 ROS_DEBUG("Raw Crossing (%.3f, %.3f, %.3f), number of exits: %zu",
00165 abs_crossing_.center.x, abs_crossing_.center.y, abs_crossing_.radius,
00166 abs_crossing_.frontiers.size());
00167
00168 abs_crossing_ = crossing_detector_.crossingDescriptor(map_, 1.8 * abs_crossing_.radius);
00169 ROS_DEBUG("Adapative range cut-off: %.3f", 1.8 * abs_crossing_.radius);
00170 ROS_DEBUG("Crossing with adapted range (%.3f, %.3f, %.3f), number of exits: %zu",
00171 abs_crossing_.center.x, abs_crossing_.center.y, abs_crossing_.radius,
00172 abs_crossing_.frontiers.size());
00173 }
00174 else
00175 {
00176 abs_crossing_ = crossing_detector_.crossingDescriptor(map_, range_cutoff_);
00177 ROS_DEBUG("Crossing: (%.3f, %.3f, %.3f), range cut-off: %.3f, number of exits: %zu",
00178 abs_crossing_.center.x, abs_crossing_.center.y, abs_crossing_.radius,
00179 range_cutoff_, abs_crossing_.frontiers.size());
00180 }
00181 }
00182 else
00183 {
00184 abs_crossing_ = crossing_detector_.crossingDescriptor(map_);
00185 ROS_DEBUG("Crossing (%.3f, %.3f, %.3f), number of exits: %zu",
00186 abs_crossing_.center.x, abs_crossing_.center.y, abs_crossing_.radius, abs_crossing_.frontiers.size());
00187 }
00188
00189 ROS_DEBUG("Crossing (%.3f, %.3f, %.3f), number of exits: %zu",
00190 abs_crossing_.center.x, abs_crossing_.center.y, abs_crossing_.radius, abs_crossing_.frontiers.size());
00191
00192
00193 tf::StampedTransform tr;
00194 bool lookup_successfull = false;
00195 try
00196 {
00197 tf_listener_.waitForTransform(odom_frame_, map_.header.frame_id,
00198 map_.header.stamp, ros::Duration(0.2));
00199 tf_listener_.lookupTransform(odom_frame_, map_.header.frame_id,
00200 map_.header.stamp, tr);
00201 lookup_successfull = true;
00202 }
00203 catch (tf::TransformException ex)
00204 {
00205 ROS_ERROR("%s", ex.what());
00206 }
00207
00208
00209 double map_relative_orientation = last_map_orientation_;
00210 if (lookup_successfull)
00211 {
00212 map_relative_orientation = tf::getYaw(tr.getRotation());
00213 last_map_orientation_ = map_relative_orientation;
00214 }
00215
00216
00217 rel_crossing_ = abs_crossing_;
00218 lama_common::rotateCrossing(rel_crossing_, map_relative_orientation);
00219 has_crossing_ = true;
00220
00221 for (size_t i = 0; i < rel_crossing_.frontiers.size(); ++i)
00222 {
00223 ROS_DEBUG("Relative frontier angle = %.3f", rel_crossing_.frontiers[i].angle);
00224 }
00225
00226
00227 if (pub_crossing_marker_.getNumSubscribers())
00228 {
00229 visualization_msgs::Marker m = lama_common::getCrossingCenterMarker(map_.header.frame_id, abs_crossing_);
00230 pub_crossing_marker_.publish(m);
00231 }
00232
00233
00234 if (pub_exits_marker_.getNumSubscribers())
00235 {
00236 visualization_msgs::Marker m = lama_common::getFrontiersMarker(map_.header.frame_id, abs_crossing_);
00237 pub_exits_marker_.publish(m);
00238 }
00239
00240
00241 if (pub_place_profile_.getNumSubscribers())
00242 {
00243 sensor_msgs::PointCloud cloud = lama_common::placeProfileToPointCloud(crossing_detector_.getPlaceProfile());
00244 pub_place_profile_.publish(cloud);
00245 }
00246
00247 pub_crossing_.publish(rel_crossing_);
00248 }
00249
00250 }
00251