$search
00001 #include "object_tracker.h" 00002 00003 #include <hector_nav_msgs/GetDistanceToObstacle.h> 00004 #include <worldmodel_msgs/VerifyObject.h> 00005 #include <worldmodel_msgs/VerifyPercept.h> 00006 00007 #include <Eigen/Geometry> 00008 #include <math.h> 00009 00010 #include "Object.h" 00011 00012 #include <boost/algorithm/string.hpp> 00013 00014 namespace object_tracker { 00015 00016 ObjectTracker::ObjectTracker() 00017 { 00018 ros::NodeHandle priv_nh("~"); 00019 priv_nh.param("project_objects", _project_objects, false); 00020 priv_nh.param("frame_id", _frame_id, std::string("map")); 00021 priv_nh.param("worldmodel_ns", _worldmodel_ns, std::string("worldmodel")); 00022 priv_nh.param("default_distance", _default_distance, 1.0); 00023 priv_nh.param("distance_variance", _distance_variance, pow(1.0, 2)); 00024 priv_nh.param("angle_variance", _angle_variance, pow(10.0 * M_PI / 180.0, 2)); 00025 priv_nh.param("min_height", _min_height, -999.9); 00026 priv_nh.param("max_height", _max_height, 999.9); 00027 priv_nh.param("pending_support", _pending_support, 0.0); 00028 priv_nh.param("pending_time", _pending_time, 0.0); 00029 priv_nh.param("active_support", _active_support, 0.0); 00030 priv_nh.param("active_time", _active_time, 0.0); 00031 priv_nh.param("ageing_threshold", _ageing_threshold, 1.0); 00032 00033 ros::NodeHandle worldmodel(_worldmodel_ns); 00034 imagePerceptSubscriber = worldmodel.subscribe("image_percept", 10, &ObjectTracker::imagePerceptCb, this); 00035 posePerceptSubscriber = worldmodel.subscribe("pose_percept", 10, &ObjectTracker::posePerceptCb, this); 00036 objectAgeingSubscriber = worldmodel.subscribe("object_ageing", 10, &ObjectTracker::objectAgeingCb, this); 00037 modelPublisher = worldmodel.advertise<worldmodel_msgs::ObjectModel>("objects", 10, false); 00038 modelUpdatePublisher = worldmodel.advertise<worldmodel_msgs::Object>("object", 10, false); 00039 00040 Object::setNamespace(_worldmodel_ns); 00041 drawings.setNamespace(_worldmodel_ns); 00042 00043 sysCommandSubscriber = nh.subscribe("syscommand", 10, &ObjectTracker::sysCommandCb, this); 00044 poseDebugPublisher = priv_nh.advertise<geometry_msgs::PoseStamped>("pose", 10, false); 00045 pointDebugPublisher = priv_nh.advertise<geometry_msgs::PointStamped>("point", 10, false); 00046 00047 XmlRpc::XmlRpcValue verification_services; 00048 if (priv_nh.getParam("verification_services", verification_services) && verification_services.getType() == XmlRpc::XmlRpcValue::TypeArray) { 00049 for(int i = 0; i < verification_services.size(); ++i) { 00050 XmlRpc::XmlRpcValue item = verification_services[i]; 00051 if (!item.hasMember("service")) { 00052 ROS_ERROR("Verification service %d could not be intialized: unknown service name", i); 00053 continue; 00054 } 00055 if (!item.hasMember("type")) { 00056 ROS_ERROR("Verification service %d could not be intialized: unknown service type", i); 00057 continue; 00058 } 00059 00060 ros::ServiceClient client; 00061 if (item["type"] == "object") { 00062 client = nh.serviceClient<worldmodel_msgs::VerifyObject>(item["service"]); 00063 } else if (item["type"] == "percept") { 00064 client = nh.serviceClient<worldmodel_msgs::VerifyPercept>(item["service"]); 00065 } 00066 00067 if (!client.isValid()) continue; 00068 if (!client.exists()) { 00069 if (!item.hasMember("required") || !item["required"]) { 00070 ROS_WARN("Verification service %s is not (yet) there...", client.getService().c_str()); 00071 } else { 00072 ROS_WARN("Required verification service %s is not available... waiting...", client.getService().c_str()); 00073 while(ros::ok() && !client.waitForExistence(ros::Duration(1.0))); 00074 } 00075 } 00076 00077 if (item.hasMember("class_id")) { 00078 verificationServices[item["type"]][item["class_id"]].push_back(std::make_pair(client, item)); 00079 ROS_INFO("Using %s verification service %s for objects of class %s", std::string(item["type"]).c_str(), client.getService().c_str(), std::string(item["class_id"]).c_str()); 00080 } else { 00081 verificationServices[item["type"]]["*"].push_back(std::make_pair(client, item)); 00082 ROS_INFO("Using %s verification service %s", std::string(item["type"]).c_str(), client.getService().c_str()); 00083 } 00084 } 00085 } 00086 00087 distanceToObstacle = nh.serviceClient<hector_nav_msgs::GetDistanceToObstacle>("get_distance_to_obstacle"); 00088 if (_project_objects && !distanceToObstacle.waitForExistence(ros::Duration(5.0))) { 00089 ROS_WARN("_project_objects is true, but GetDistanceToObstacle service is not (yet) available"); 00090 } 00091 00092 setObjectState = worldmodel.advertiseService("set_object_state", &ObjectTracker::setObjectStateCb, this); 00093 setObjectName = worldmodel.advertiseService("set_object_name", &ObjectTracker::setObjectNameCb, this); 00094 addObject = worldmodel.advertiseService("add_object", &ObjectTracker::addObjectCb, this); 00095 getObjectModel = worldmodel.advertiseService("get_object_model", &ObjectTracker::getObjectModelCb, this); 00096 } 00097 00098 ObjectTracker::~ObjectTracker() 00099 {} 00100 00101 void ObjectTracker::sysCommandCb(const std_msgs::StringConstPtr &sysCommand) 00102 { 00103 if (sysCommand->data == "reset") { 00104 ROS_INFO("Resetting object model."); 00105 model.reset(); 00106 drawings.reset(); 00107 } 00108 } 00109 00110 void ObjectTracker::imagePerceptCb(const worldmodel_msgs::ImagePerceptConstPtr &percept) 00111 { 00112 worldmodel_msgs::PosePerceptPtr posePercept(new worldmodel_msgs::PosePercept); 00113 tf::Pose pose; 00114 00115 ROS_DEBUG("Incoming image percept with image coordinates [%f,%f] in frame %s", percept->x, percept->y, percept->header.frame_id.c_str()); 00116 00117 posePercept->header = percept->header; 00118 posePercept->info = percept->info; 00119 00120 // retrieve distance information 00121 float distance = percept->distance > 0.0 ? percept->distance : _default_distance; 00122 00123 // retrieve camera model from either the cache or from CameraInfo given in the percept 00124 CameraModelPtr cameraModel; 00125 if (cameraModels.count(percept->header.frame_id) == 0) { 00126 cameraModel.reset(new image_geometry::PinholeCameraModel()); 00127 if (!cameraModel->fromCameraInfo(percept->camera_info)) { 00128 ROS_ERROR("Could not initialize camera model from CameraInfo given in the percept"); 00129 return; 00130 } 00131 cameraModels[percept->header.frame_id] = cameraModel; 00132 } else { 00133 cameraModel = cameraModels[percept->header.frame_id]; 00134 } 00135 00136 // transform Point using the camera mode 00137 cv::Point2d rectified = cameraModel->rectifyPoint(cv::Point2d(percept->x, percept->y)); 00138 cv::Point3d direction_cv = cameraModel->projectPixelTo3dRay(rectified); 00139 // pose.setOrigin(tf::Point(direction_cv.z, -direction_cv.x, -direction_cv.y).normalized() * distance); 00140 // tf::Quaternion direction(atan2(-direction_cv.x, direction_cv.z), atan2(direction_cv.y, sqrt(direction_cv.z*direction_cv.z + direction_cv.x*direction_cv.x)), 0.0); 00141 pose.setOrigin(tf::Point(direction_cv.x, direction_cv.y, direction_cv.z).normalized() * distance); 00142 tf::Quaternion direction; 00143 direction.setEuler(atan2(direction_cv.x, direction_cv.z), atan2(-direction_cv.y, sqrt(direction_cv.z*direction_cv.z + direction_cv.x*direction_cv.x)), 0.0); 00144 direction = direction * tf::Quaternion(0.5, -0.5, 0.5, 0.5); 00145 pose.getBasis().setRotation(direction); 00146 00147 ROS_DEBUG("--> Rectified image coordinates: [%f,%f]", rectified.x, rectified.y); 00148 ROS_DEBUG("--> Projected 3D ray (OpenCV): [%f,%f,%f]", direction_cv.x, direction_cv.y, direction_cv.z); 00149 ROS_DEBUG("--> Projected 3D ray (tf): [%f,%f,%f]", pose.getOrigin().x(), pose.getOrigin().y(),pose.getOrigin().z()); 00150 00151 if (percept->distance == 0.0 && _project_objects) { 00152 hector_nav_msgs::GetDistanceToObstacle::Request request; 00153 hector_nav_msgs::GetDistanceToObstacle::Response response; 00154 00155 // project image percept to the next obstacle 00156 request.point.header = percept->header; 00157 tf::pointTFToMsg(pose.getOrigin(), request.point.point); 00158 if (distanceToObstacle.call(request, response)) { 00159 if (response.distance > 0.0) { 00160 // distance = std::max(response.distance - 0.1f, 0.0f); 00161 distance = std::max(response.distance, 0.0f); 00162 pose.setOrigin(pose.getOrigin().normalized() * distance); 00163 ROS_DEBUG("Projected percept to a distance of %.1f m", distance); 00164 } else { 00165 ROS_WARN("Ignoring percept due to unknown or infinite distance: service %s returned %f", distanceToObstacle.getService().c_str(), response.distance); 00166 return; 00167 } 00168 } else { 00169 ROS_WARN("Ignoring percept due to unknown or infinite distance: service %s is not available", distanceToObstacle.getService().c_str()); 00170 return; 00171 } 00172 } 00173 00174 // set variance 00175 Eigen::Matrix3f covariance(Eigen::Matrix3f::Zero()); 00176 covariance(0,0) = std::max(distance*distance, 1.0f) * tan(_angle_variance); 00177 covariance(1,1) = covariance(0,0); 00178 covariance(2,2) = _distance_variance; 00179 00180 // rotate covariance matrix depending on the position in the image 00181 Eigen::Quaterniond eigen_rotation(direction.w(), direction.x(), direction.y(), direction.z()); 00182 Eigen::Matrix3f rotation_camera_object(eigen_rotation.toRotationMatrix().cast<float>()); 00183 covariance = rotation_camera_object * covariance * rotation_camera_object.transpose(); 00184 00185 // fill posePercept 00186 tf::poseTFToMsg(pose, posePercept->pose.pose); 00187 // tf::quaternionTFToMsg(direction, posePercept->pose.pose.orientation); 00188 posePercept->pose.covariance[0] = covariance(0,0); 00189 posePercept->pose.covariance[1] = covariance(0,1); 00190 posePercept->pose.covariance[2] = covariance(0,2); 00191 posePercept->pose.covariance[6] = covariance(1,0); 00192 posePercept->pose.covariance[7] = covariance(1,1); 00193 posePercept->pose.covariance[8] = covariance(1,2); 00194 posePercept->pose.covariance[12] = covariance(2,0); 00195 posePercept->pose.covariance[13] = covariance(2,1); 00196 posePercept->pose.covariance[14] = covariance(2,2); 00197 00198 // forward to posePercept callback 00199 posePerceptCb(posePercept); 00200 } 00201 00202 void ObjectTracker::posePerceptCb(const worldmodel_msgs::PosePerceptConstPtr &percept) 00203 { 00204 // publish pose in source frame for debugging purposes 00205 if (poseDebugPublisher.getNumSubscribers() > 0) { 00206 geometry_msgs::PoseStamped pose; 00207 pose.pose = percept->pose.pose; 00208 pose.header = percept->header; 00209 poseDebugPublisher.publish(pose); 00210 } 00211 00212 // call percept verification 00213 float support_added_by_percept_verification = 0.0; 00214 if (verificationServices.count("percept") > 0) { 00215 worldmodel_msgs::VerifyPercept::Request request; 00216 worldmodel_msgs::VerifyPercept::Response response; 00217 00218 request.percept = *percept; 00219 00220 std::vector<VerificationService> services(verificationServices["percept"]["*"]); 00221 if (!percept->info.class_id.empty()) { 00222 services.insert(services.end(), verificationServices["percept"][percept->info.class_id].begin(), verificationServices["percept"][percept->info.class_id].end()); 00223 } 00224 00225 for(std::vector<VerificationService>::iterator it = services.begin(); it != services.end(); ++it) { 00226 if (it->second.hasMember("ignore") && it->second["ignore"]) { 00227 ROS_DEBUG("Calling service %s for percept of class '%s'', but ignoring its answer...", it->first.getService().c_str(), percept->info.class_id.c_str()); 00228 it->first.call(request, response); 00229 00230 } else if (it->first.call(request, response)) { 00231 if (response.response == response.DISCARD) { 00232 ROS_DEBUG("Discarded percept of class '%s' due to DISCARD message from service %s", percept->info.class_id.c_str(), it->first.getService().c_str()); 00233 return; 00234 } 00235 if (response.response == response.CONFIRM) { 00236 ROS_DEBUG("We got a CONFIRMation for percept of class '%s' from service %s!", percept->info.class_id.c_str(), it->first.getService().c_str()); 00237 support_added_by_percept_verification = 100.0; 00238 } 00239 if (response.response == response.UNKNOWN) { 00240 ROS_DEBUG("Verification service %s cannot help us with percept of class %s at the moment :-(", it->first.getService().c_str(), percept->info.class_id.c_str()); 00241 } 00242 } else if (it->second.hasMember("required") && it->second["required"]) { 00243 ROS_DEBUG("Discarded percept of class '%s' as required service %s is not available", percept->info.class_id.c_str(), it->first.getService().c_str()); 00244 return; 00245 } 00246 } 00247 } 00248 00249 // convert pose in tf 00250 tf::Pose pose; 00251 tf::poseMsgToTF(percept->pose.pose, pose); 00252 00253 // retrieve distance information 00254 // float distance = pose.getOrigin().length(); 00255 // if (_project_objects) { 00256 // hector_nav_msgs::GetDistanceToObstacle::Request request; 00257 // hector_nav_msgs::GetDistanceToObstacle::Response response; 00258 00259 // // project image percept to the next obstacle 00260 // request.point.header = percept->header; 00261 // tf::pointTFToMsg(pose.getOrigin(), request.point.point); 00262 // if (distanceToObstacle.call(request, response) && response.distance > 0.0) { 00263 // // distance = std::max(response.distance - 0.1f, 0.0f); 00264 // distance = std::max(response.distance, 0.0f); 00265 // pose.setOrigin(pose.getOrigin().normalized() * distance); 00266 // ROS_DEBUG("Projected percept to a distance of %.1f m", distance); 00267 // } else { 00268 // ROS_DEBUG("Ignoring percept due to unknown or infinite distance"); 00269 // return; 00270 // } 00271 // } 00272 00273 // extract variance matrix 00274 Eigen::Matrix<float,6,6> temp; 00275 for(unsigned int i = 0; i < 36; ++i) temp(i) = percept->pose.covariance[i]; 00276 Eigen::Matrix3f covariance = temp.block<3,3>(0,0); 00277 00278 // if no variance is given, set variance to default 00279 if (covariance.isZero()) { 00280 covariance(0,0) = _distance_variance; 00281 covariance(1,1) = _distance_variance; 00282 covariance(2,2) = _distance_variance; 00283 } 00284 00285 // project percept coordinates to map frame 00286 tf::StampedTransform cameraTransform; 00287 if (!_frame_id.empty() && tf.resolve(percept->header.frame_id) != tf.resolve(_frame_id)) { 00288 ROS_DEBUG("Transforming percept from %s frame to %s frame", percept->header.frame_id.c_str(), _frame_id.c_str()); 00289 00290 // retrieve camera transformation from tf 00291 try { 00292 tf.waitForTransform(_frame_id, percept->header.frame_id, percept->header.stamp, ros::Duration(1.0)); 00293 tf.lookupTransform(_frame_id, percept->header.frame_id, percept->header.stamp, cameraTransform); 00294 } catch (tf::TransformException ex) { 00295 ROS_ERROR("%s", ex.what()); 00296 return; 00297 } 00298 00299 pose = cameraTransform * pose; 00300 00301 // rotate covariance matrix to map coordinates 00302 Eigen::Quaterniond eigen_rotation(cameraTransform.getRotation().w(), cameraTransform.getRotation().x(), cameraTransform.getRotation().y(), cameraTransform.getRotation().z()); 00303 Eigen::Matrix3f rotation_map_camera(eigen_rotation.toRotationMatrix().cast<float>()); 00304 covariance = rotation_map_camera * covariance * rotation_map_camera.transpose(); 00305 } 00306 Eigen::Vector3f position(pose.getOrigin().x(), pose.getOrigin().y(), pose.getOrigin().z()); 00307 00308 // check height 00309 float relative_height = pose.getOrigin().z() - cameraTransform.getOrigin().z(); 00310 if (relative_height < _min_height || relative_height > _max_height) { 00311 ROS_INFO("Discarding %s percept with height %f", percept->info.class_id.c_str(), relative_height); 00312 return; 00313 } 00314 00315 // fix height (assume camera is always at 0.475m) 00316 // pose.setOrigin(tf::Point(pose.getOrigin().x(), pose.getOrigin().y(), pose.getOrigin().z() - cameraTransform.getOrigin().z() + 0.475f)); 00317 00318 // calculate observation support 00319 float support = 0.0; 00320 if (!percept->info.object_id.empty()) { 00321 support = percept->info.object_support; 00322 } else if (!percept->info.class_id.empty()) { 00323 support = percept->info.class_support + support_added_by_percept_verification; 00324 } 00325 00326 if (support == 0.0) { 00327 ROS_WARN("Ignoring percept with support == 0.0"); 00328 return; 00329 } 00330 00331 // lock model 00332 model.lock(); 00333 00334 // find correspondence 00335 ObjectPtr object; 00336 float min_distance = 1.0f; 00337 if (percept->info.object_id.empty()) { 00338 for(ObjectModel::iterator it = model.begin(); it != model.end(); ++it) { 00339 ObjectPtr x = *it; 00340 if (!percept->info.class_id.empty() && percept->info.class_id != x->getClassId()) continue; 00341 Eigen::Vector3f diff = x->getPosition() - position; 00342 float distance = (diff.transpose() * (x->getCovariance() + covariance).inverse() * diff)[0]; 00343 if (distance < min_distance) { 00344 object = x; 00345 min_distance = distance; 00346 } 00347 } 00348 } else { 00349 object = model.getObject(percept->info.object_id); 00350 } 00351 00352 if (object && object->getState() < 0) { 00353 ROS_DEBUG("Percept was associated to object %s, which has a fixed state", object->getObjectId().c_str()); 00354 model.unlock(); 00355 return; 00356 } 00357 00358 // create new object 00359 if (!object) { 00360 object = model.add(percept->info.class_id, percept->info.object_id); 00361 00362 object->setPosition(position); 00363 object->setCovariance(covariance); 00364 object->setSupport(support); 00365 00366 ROS_INFO("Found new object %s of class %s at (%f,%f)!", object->getObjectId().c_str(), object->getClassId().c_str(), position.x(), position.y()); 00367 00368 // or update existing object 00369 } else if (support > 0.0) { 00370 //object->update(position, covariance, support); 00371 object->intersect(position, covariance, support); 00372 00373 // or simply decrease support 00374 } else { 00375 object->addSupport(support); 00376 } 00377 00378 // update object state 00379 if (object->getState() == worldmodel_msgs::ObjectState::UNKNOWN && _pending_support > 0) { 00380 if (object->getSupport() >= _pending_support && (percept->header.stamp - object->getHeader().stamp).toSec() >= _pending_time) { 00381 ROS_INFO("Setting object state for %s to PENDING", object->getObjectId().c_str()); 00382 object->setState(worldmodel_msgs::ObjectState::PENDING); 00383 } 00384 } 00385 if (object->getState() == worldmodel_msgs::ObjectState::PENDING && _active_support > 0) { 00386 if (object->getSupport() >= _active_support && (percept->header.stamp - object->getHeader().stamp).toSec() >= _active_time) { 00387 ROS_INFO("Setting object state for %s to ACTIVE", object->getObjectId().c_str()); 00388 object->setState(worldmodel_msgs::ObjectState::ACTIVE); 00389 } 00390 } 00391 00392 // set object orientation 00393 geometry_msgs::Quaternion object_orientation; 00394 tf::quaternionTFToMsg(pose.getRotation(), object_orientation); 00395 object->setOrientation(object_orientation); 00396 00397 // update object header 00398 std_msgs::Header header = percept->header; 00399 header.frame_id = _frame_id; 00400 object->setHeader(header); 00401 00402 // update object name 00403 if (!percept->info.name.empty()) object->setName(percept->info.name); 00404 00405 // unlock model 00406 model.unlock(); 00407 00408 // call object verification 00409 if (verificationServices.count("object") > 0) { 00410 worldmodel_msgs::VerifyObject::Request request; 00411 worldmodel_msgs::VerifyObject::Response response; 00412 00413 request.object = object->getObjectMessage(); 00414 00415 std::vector<VerificationService> services(verificationServices["object"]["*"]); 00416 if (!object->getClassId().empty()) { 00417 services.insert(services.end(), verificationServices["object"][object->getClassId()].begin(), verificationServices["object"][object->getClassId()].end()); 00418 } 00419 00420 for(std::vector<VerificationService>::iterator it = services.begin(); it != services.end(); ++it) { 00421 if (it->second.hasMember("ignore") && it->second["ignore"]) { 00422 ROS_DEBUG("Calling service %s for object %s, but ignoring its answer...", it->first.getService().c_str(), object->getObjectId().c_str()); 00423 it->first.call(request, response); 00424 00425 } else if (it->first.call(request, response)) { 00426 if (response.response == response.DISCARD) { 00427 ROS_DEBUG("Discarded object %s due to DISCARD message from service %s", object->getObjectId().c_str(), it->first.getService().c_str()); 00428 object->setState(worldmodel_msgs::ObjectState::DISCARDED); 00429 } 00430 if (response.response == response.CONFIRM) { 00431 ROS_DEBUG("We got a CONFIRMation for object %s from service %s!", object->getObjectId().c_str(), it->first.getService().c_str()); 00432 object->addSupport(100.0); 00433 } 00434 if (response.response == response.UNKNOWN) { 00435 ROS_DEBUG("Verification service %s cannot help us with object %s at the moment :-(", it->first.getService().c_str(), object->getObjectId().c_str()); 00436 } 00437 } else if (it->second.hasMember("required") && it->second["required"]) { 00438 ROS_DEBUG("Discarded object %s as required service %s is not available", object->getObjectId().c_str(), it->first.getService().c_str()); 00439 object->setState(worldmodel_msgs::ObjectState::DISCARDED); 00440 } 00441 } 00442 } 00443 00444 // publish point in target frame for debugging purposes 00445 if (pointDebugPublisher.getNumSubscribers() > 0) { 00446 geometry_msgs::PointStamped point; 00447 point.point = object->getPose().position; 00448 point.header = object->getHeader(); 00449 pointDebugPublisher.publish(point); 00450 } 00451 00452 modelUpdatePublisher.publish(object->getObjectMessage()); 00453 publishModel(); 00454 } 00455 00456 void ObjectTracker::objectAgeingCb(const std_msgs::Float32ConstPtr &ageing) { 00457 ROS_DEBUG("ageing of all objects by %f", ageing->data); 00458 00459 // lock model 00460 model.lock(); 00461 00462 ObjectModel::ObjectList objects = model.getObjects(); 00463 00464 for(ObjectModel::iterator it = objects.begin(); it != objects.end();) { 00465 ObjectModel::ObjectPtr object = *it; 00466 00467 // update support 00468 object->setSupport(object->getSupport() - ageing->data); 00469 00470 // remove the object if the support is to low 00471 if (object->getSupport() < _ageing_threshold) { 00472 ROS_INFO("remove object %s with support %f", object->getObjectId().c_str(), object->getSupport()); 00473 it = objects.erase(it); 00474 model.remove(object); 00475 } else { 00476 it++; 00477 } 00478 } 00479 00480 // unlock model 00481 model.unlock(); 00482 publishModel(); 00483 } 00484 00485 bool ObjectTracker::setObjectStateCb(worldmodel_msgs::SetObjectState::Request& request, worldmodel_msgs::SetObjectState::Response& response) { 00486 model.lock(); 00487 00488 ObjectPtr object = model.getObject(request.object_id); 00489 if (!object) { 00490 model.unlock(); 00491 return false; 00492 } 00493 00494 object->setState(request.new_state.state); 00495 modelUpdatePublisher.publish(object->getObjectMessage()); 00496 00497 model.unlock(); 00498 publishModel(); 00499 return true; 00500 } 00501 00502 bool ObjectTracker::setObjectNameCb(worldmodel_msgs::SetObjectName::Request& request, worldmodel_msgs::SetObjectName::Response& response) { 00503 model.lock(); 00504 00505 ObjectPtr object = model.getObject(request.object_id); 00506 if (!object) { 00507 model.unlock(); 00508 return false; 00509 } 00510 00511 object->setName(request.name); 00512 modelUpdatePublisher.publish(object->getObjectMessage()); 00513 00514 model.unlock(); 00515 publishModel(); 00516 return true; 00517 } 00518 00519 bool ObjectTracker::addObjectCb(worldmodel_msgs::AddObject::Request& request, worldmodel_msgs::AddObject::Response& response) { 00520 ObjectPtr object; 00521 bool newObject = false; 00522 00523 // check if object already exist 00524 if (!request.object.info.object_id.empty()) { 00525 ROS_INFO("add_object service called for known %s object %s in frame %s", request.object.info.class_id.c_str(), request.object.info.object_id.c_str(), request.object.header.frame_id.c_str()); 00526 object = model.getObject(request.object.info.object_id); 00527 } else { 00528 ROS_INFO("add_object service called for new %s object in frame %s", request.object.info.class_id.c_str(), request.object.header.frame_id.c_str()); 00529 } 00530 00531 // create a new object if object does not exist 00532 if (!object) { 00533 object.reset(new Object(request.object.info.class_id, request.object.info.object_id)); 00534 newObject = true; 00535 } 00536 00537 std_msgs::Header header = request.object.header; 00538 if (header.stamp.isZero()) header.stamp = ros::Time::now(); 00539 00540 geometry_msgs::PoseWithCovariance pose; 00541 if (request.map_to_next_obstacle) { 00542 pose.covariance = request.object.pose.covariance; 00543 if (!mapToNextObstacle(request.object.pose.pose, header, pose.pose)) { 00544 return false; 00545 } 00546 } else { 00547 pose = request.object.pose; 00548 } 00549 00550 // extract variance matrix 00551 Eigen::Matrix<float,6,6> temp; 00552 for(unsigned int i = 0; i < 36; ++i) temp(i) = pose.covariance[i]; 00553 Eigen::Matrix3f covariance = temp.block<3,3>(0,0); 00554 00555 // if no variance is given, set variance to default 00556 if (covariance.isZero()) { 00557 pose.covariance[0] = 1.0; 00558 pose.covariance[7] = 1.0; 00559 pose.covariance[14] = 1.0; 00560 } 00561 00562 if (!transformPose(pose, pose, header)) return false; 00563 00564 model.lock(); 00565 00566 object->setHeader(header); 00567 object->setPose(pose); 00568 object->setState(request.object.state.state); 00569 object->setSupport(request.object.info.support); 00570 00571 if (newObject) model.add(object); 00572 response.object = object->getObjectMessage(); 00573 modelUpdatePublisher.publish(response.object); 00574 00575 model.unlock(); 00576 00577 publishModel(); 00578 return true; 00579 } 00580 00581 bool ObjectTracker::getObjectModelCb(worldmodel_msgs::GetObjectModel::Request& request, worldmodel_msgs::GetObjectModel::Response& response) { 00582 response.model = *(model.getObjectModelMessage()); 00583 return true; 00584 } 00585 00586 bool ObjectTracker::mapToNextObstacle(const geometry_msgs::Pose& source, const std_msgs::Header &header, geometry_msgs::Pose &mapped) { 00587 if (!distanceToObstacle.exists()) return false; 00588 00589 // retrieve distance information 00590 float distance = _default_distance; 00591 hector_nav_msgs::GetDistanceToObstacle::Request request; 00592 hector_nav_msgs::GetDistanceToObstacle::Response response; 00593 00594 // project image percept to the next obstacle 00595 request.point.header = header; 00596 request.point.point = source.position; 00597 // tf::pointTFToMsg(cameraTransform.getOrigin(), request.pose.pose.position); 00598 // tf::Quaternion direction_quaternion = tf::Quaternion(atan(direction.y/direction.x), atan(direction.z/direction.x), 0.0); 00599 // direction_quaternion *= cameraTransform.getRotation(); 00600 // tf::quaternionTFToMsg(direction_quaternion, request.pose.pose.orientation); 00601 if (distanceToObstacle.call(request, response) && response.distance > 0.0) { 00602 // distance = std::max(response.distance - 0.1f, 0.0f); 00603 distance = std::max(response.distance, 0.0f); 00604 } else { 00605 ROS_DEBUG("Could not map object to next obstacle due to unknown or infinite distance"); 00606 return false; 00607 } 00608 00609 tf::Pose sourceTF; 00610 tf::poseMsgToTF(source, sourceTF); 00611 sourceTF.setOrigin(sourceTF.getOrigin().normalized() * distance); 00612 tf::poseTFToMsg(sourceTF, mapped); 00613 00614 return true; 00615 } 00616 00617 bool ObjectTracker::transformPose(const geometry_msgs::Pose& from, geometry_msgs::Pose &to, std_msgs::Header &header, tf::StampedTransform *transform_ptr) { 00618 // retrieve transformation from tf 00619 tf::StampedTransform transform; 00620 try { 00621 tf.waitForTransform(_frame_id, header.frame_id, header.stamp, ros::Duration(1.0)); 00622 tf.lookupTransform(_frame_id, header.frame_id, header.stamp, transform); 00623 } catch (tf::TransformException ex) { 00624 ROS_ERROR("%s", ex.what()); 00625 return false; 00626 } 00627 00628 tf::Pose tfPose; 00629 tf::poseMsgToTF(from, tfPose); 00630 tfPose = transform * tfPose; 00631 tf::poseTFToMsg(tfPose, to); 00632 00633 header.frame_id = _frame_id; 00634 if (transform_ptr) *transform_ptr = transform; 00635 00636 return true; 00637 } 00638 00639 bool ObjectTracker::transformPose(const geometry_msgs::PoseWithCovariance& from, geometry_msgs::PoseWithCovariance &to, std_msgs::Header &header) { 00640 tf::StampedTransform transform; 00641 00642 if (!transformPose(from.pose, to.pose, header, &transform)) return false; 00643 00644 // TODO 00645 // rotate covariance matrix 00646 00647 return true; 00648 } 00649 00650 void ObjectTracker::publishModel() { 00651 // Publish all model data on topic /objects 00652 modelPublisher.publish(model.getObjectModelMessage()); 00653 00654 // Visualize victims and covariance in rviz 00655 visualization_msgs::MarkerArray markers; 00656 model.getVisualization(markers); 00657 // drawings.setTime(ros::Time::now()); 00658 // model.lock(); 00659 // for(ObjectModel::iterator it = model.begin(); it != model.end(); ++it) { 00660 // ObjectPtr object = *it; 00661 // drawings.addMarkers(object->getVisualization()); 00662 // drawings.setColor(1.0, 0.0, 0.0, drawings.markerArray.markers.back().color.a); 00663 // drawings.drawCovariance(Eigen::Vector2f(object->getPosition().x(), object->getPosition().y()), object->getCovariance().block<2,2>(0,0)); 00664 // } 00665 // model.unlock(); 00666 drawings.addMarkers(markers); 00667 drawings.sendAndResetData(); 00668 } 00669 00670 } // namespace object_tracker 00671 00672 00673 int main(int argc, char **argv) 00674 { 00675 ros::init(argc, argv, ROS_PACKAGE_NAME); 00676 00677 object_tracker::ObjectTracker tracker; 00678 ros::spin(); 00679 00680 exit(0); 00681 }