00001
00002
00003
00004
00005
00006
00007
00008 #include <ros/ros.h>
00009 #include <world_canvas_msgs/GetAnnotations.h>
00010 #include <world_canvas_msgs/GetAnnotationsData.h>
00011 #include <world_canvas_msgs/PubAnnotationsData.h>
00012 #include <world_canvas_msgs/DeleteAnnotations.h>
00013 #include <world_canvas_msgs/SaveAnnotationsData.h>
00014 #include <visualization_msgs/MarkerArray.h>
00015
00016 #include "world_canvas_client_cpp/annotation_collection.hpp"
00017
00018
00019 namespace wcf
00020 {
00021
00022 AnnotationCollection::AnnotationCollection(const std::string& world,
00023 const std::string& srv_namespace)
00024 : AnnotationCollection(FilterCriteria(world), srv_namespace)
00025 {
00026 }
00027
00028 AnnotationCollection::AnnotationCollection(const FilterCriteria& criteria,
00029 const std::string& srv_namespace)
00030 : WorldCanvasClient(srv_namespace), filter(criteria)
00031 {
00032
00033 this->filterBy(criteria);
00034 }
00035
00036 AnnotationCollection::~AnnotationCollection()
00037 {
00038 }
00039
00040
00041 bool AnnotationCollection::filterBy(const FilterCriteria& criteria)
00042 {
00043 this->filter = criteria;
00044
00045 try
00046 {
00047 ros::ServiceClient client =
00048 this->getServiceHandle<world_canvas_msgs::GetAnnotations>("get_annotations");
00049
00050 ROS_INFO("Getting annotations for world %s and additional filter criteria",
00051 this->filter.getWorld().c_str());
00052 world_canvas_msgs::GetAnnotations srv;
00053 srv.request.world = this->filter.getWorld();
00054 srv.request.ids = this->filter.getUuids();
00055 srv.request.names = this->filter.getNames();
00056 srv.request.types = this->filter.getTypes();
00057 srv.request.keywords = this->filter.getKeywords();
00058 srv.request.relationships = this->filter.getRelationships();
00059 if (client.call(srv))
00060 {
00061 if (srv.response.result == true)
00062 {
00063 if (srv.response.annotations.size() > 0)
00064 {
00065 ROS_INFO("%lu annotations found", srv.response.annotations.size());
00066 }
00067 else
00068 {
00069 ROS_INFO("No annotations found for world %s with the given search criteria",
00070 this->filter.getWorld().c_str());
00071 }
00072 this->annotations = srv.response.annotations;
00073 return true;
00074 }
00075 else
00076 {
00077 ROS_ERROR("Server reported an error: %s", srv.response.message.c_str());
00078 return false;
00079 }
00080 }
00081 else
00082 {
00083 ROS_ERROR("Failed to call get_annotations service");
00084 return false;
00085 }
00086 }
00087 catch (const ros::Exception& e)
00088 {
00089 ROS_ERROR("ROS exception caught: %s", e.what());
00090 return false;
00091 }
00092 }
00093
00094 bool AnnotationCollection::load()
00095 {
00096
00097 return this->filterBy(this->filter);
00098 }
00099
00100 bool AnnotationCollection::loadData()
00101 {
00102 if (this->annotations.size() == 0)
00103 {
00104 ROS_ERROR("No annotations retrieved. Nothing to load!");
00105 return false;
00106 }
00107
00108 try
00109 {
00110 ros::ServiceClient client =
00111 this->getServiceHandle<world_canvas_msgs::GetAnnotationsData>("get_annotations_data");
00112
00113
00114
00115 ROS_INFO("Loading data for the %lu retrieved annotations", this->annotations.size());
00116 world_canvas_msgs::GetAnnotationsData srv;
00117 srv.request.annotation_ids = this->getAnnotsDataIDs();
00118 if (client.call(srv))
00119 {
00120 if (srv.response.result == true)
00121 {
00122 if (srv.response.data.size() > 0)
00123 {
00124 ROS_INFO("%lu annotations data found", srv.response.data.size());
00125 }
00126 else
00127 {
00128 ROS_INFO("No data found for the %lu retrieved annotations", this->annotations.size());
00129 }
00130 this->annots_data = srv.response.data;
00131 return true;
00132 }
00133 else
00134 {
00135 ROS_ERROR("Server reported an error: %s", srv.response.message.c_str());
00136 return false;
00137 }
00138 }
00139 else
00140 {
00141 ROS_ERROR("Failed to call get_annotations_data service");
00142 return false;
00143 }
00144 }
00145 catch (const ros::Exception& e)
00146 {
00147 ROS_ERROR("ROS exception caught: %s", e.what());
00148 return false;
00149 }
00150 }
00151
00152 bool AnnotationCollection::save()
00153 {
00154 try
00155 {
00156 ros::ServiceClient client =
00157 this->getServiceHandle<world_canvas_msgs::SaveAnnotationsData>("save_annotations_data");
00158
00159
00160 ROS_INFO("Requesting server to save annotations");
00161 world_canvas_msgs::SaveAnnotationsData srv;
00162
00163
00164
00165
00166
00167 for (unsigned int i = 0; i < this->annotations.size(); i++)
00168 {
00169 for (unsigned int j = 0; j < this->annots_data.size(); j++)
00170 {
00171 if (this->annots_data[j].id.uuid == this->annotations[i].data_id.uuid)
00172 {
00173 ROS_DEBUG("Add annotation for saving with uuid '%s'", unique_id::toHexString(this->annotations[i].id).c_str());
00174 ROS_DEBUG("Add annot. data for saving with uuid '%s'", unique_id::toHexString(this->annots_data[j].id).c_str());
00175 srv.request.annotations.push_back(this->annotations[i]);
00176 srv.request.data.push_back(this->annots_data[j]);
00177 break;
00178 }
00179 }
00180 }
00181
00182
00183 if (! (this->annotations.size() == this->annots_data.size() == srv.request.annotations.size() == srv.request.data.size()))
00184 {
00185 ROS_ERROR("Incoherent annotation and data sizes: %lu != %lu != %lu != %lu",
00186 this->annotations.size(), this->annots_data.size(), srv.request.annotations.size(), srv.request.data.size());
00187 }
00188
00189 bool result = false;
00190 if (client.call(srv))
00191 {
00192 if (srv.response.result == true)
00193 {
00194 result = true;
00195 }
00196 else
00197 {
00198 ROS_ERROR("Server reported an error: %s", srv.response.message.c_str());
00199 }
00200 }
00201 else
00202 {
00203 ROS_ERROR("Failed to call save_annotations_data service");
00204 }
00205
00206 if (result == true)
00207 saved = true;
00208
00209 return result && saveDeletes();
00210 }
00211 catch (const ros::Exception& e)
00212 {
00213 ROS_ERROR("ROS exception caught: %s", e.what());
00214 return false;
00215 }
00216 }
00217
00218 bool AnnotationCollection::saveDeletes()
00219 {
00220
00221 if (annots_to_delete.size() == 0)
00222 return true;
00223
00224 try
00225 {
00226 ros::ServiceClient client =
00227 this->getServiceHandle<world_canvas_msgs::DeleteAnnotations>("delete_annotations");
00228
00229
00230 ROS_INFO("Requesting server to delete annotations");
00231 world_canvas_msgs::DeleteAnnotations srv;
00232 srv.request.annotations = annots_to_delete;
00233 if (client.call(srv))
00234 {
00235 if (srv.response.result == true)
00236 {
00237 return true;
00238 }
00239 else
00240 {
00241 ROS_ERROR("Server reported an error: %s", srv.response.message.c_str());
00242 return false;
00243 }
00244 }
00245 else
00246 {
00247 ROS_ERROR("Failed to call delete_annotations service");
00248 return false;
00249 }
00250 }
00251 catch (const ros::Exception& e)
00252 {
00253 ROS_ERROR("ROS exception caught: %s", e.what());
00254 return false;
00255 }
00256 }
00257
00258 bool AnnotationCollection::add(const world_canvas_msgs::Annotation& annotation,
00259 const world_canvas_msgs::AnnotationData& annot_data)
00260 {
00261 if (annotation.data_id.uuid != annot_data.id.uuid)
00262 {
00263 ROS_ERROR("Incoherent annotation and data uuids '%s' != '%s'",
00264 unique_id::toHexString(annotation.id).c_str(), unique_id::toHexString(annot_data.id).c_str());
00265 return false;
00266 }
00267
00268 for (unsigned int i = 0; i < this->annotations.size(); i++)
00269 {
00270 if (this->annotations[i].id.uuid == annotation.id.uuid)
00271 {
00272 ROS_ERROR("Duplicated annotation with uuid '%s'", unique_id::toHexString(annotation.id).c_str());
00273 return false;
00274 }
00275 }
00276
00277 for (unsigned int i = 0; i < this->annots_data.size(); i++)
00278 {
00279 if (this->annots_data[i].id.uuid == annot_data.id.uuid)
00280 {
00281 ROS_ERROR("Duplicated annotation data with uuid '%s'", unique_id::toHexString(annot_data.id).c_str());
00282 return false;
00283 }
00284 }
00285
00286 this->annotations.push_back(annotation);
00287 this->annots_data.push_back(annot_data);
00288
00289
00290 this->publishMarkers("annotation_markers");
00291
00292 saved = false;
00293
00294 return true;
00295 }
00296
00297 bool AnnotationCollection::update(const world_canvas_msgs::Annotation& annotation,
00298 const world_canvas_msgs::AnnotationData& annot_data)
00299 {
00300 if (annotation.data_id.uuid != annot_data.id.uuid)
00301 {
00302 ROS_ERROR("Incoherent annotation and data uuids '%s' != '%s'",
00303 unique_id::toHexString(annotation.id).c_str(), unique_id::toHexString(annot_data.id).c_str());
00304 return false;
00305 }
00306
00307 bool found = false;
00308 for (unsigned int i = 0; i < this->annotations.size(); i++)
00309 {
00310 if (this->annotations[i].id.uuid == annotation.id.uuid)
00311 {
00312 this->annotations[i] = annotation;
00313 found = true;
00314 break;
00315 }
00316 }
00317
00318 if (found == false)
00319 {
00320 ROS_ERROR("Annotation uuid '%s' not found", unique_id::toHexString(annotation.id).c_str());
00321 return false;
00322 }
00323
00324 found = false;
00325 for (unsigned int i = 0; i < this->annots_data.size(); i++)
00326 {
00327 if (this->annots_data[i].id.uuid == annot_data.id.uuid)
00328 {
00329 this->annots_data[i] = annot_data;
00330 found = true;
00331 break;
00332 }
00333 }
00334
00335 if (found == false)
00336 {
00337 ROS_ERROR("Annotation data uuid '%s' not found", unique_id::toHexString(annot_data.id).c_str());
00338 return false;
00339 }
00340
00341
00342 this->publishMarkers("annotation_markers");
00343
00344 saved = false;
00345
00346 return true;
00347 }
00348
00349 bool AnnotationCollection::remove(const uuid_msgs::UniqueID& id)
00350 {
00351 for (unsigned int i = 0; i < this->annotations.size(); i++)
00352 {
00353 if (this->annotations[i].id.uuid == id.uuid)
00354 {
00355 ROS_DEBUG("Annotation '%s' found", unique_id::toHexString(id).c_str());
00356
00357 for (unsigned int j = 0; j < this->annots_data.size(); j++)
00358 {
00359 if (this->annots_data[j].id.uuid == this->annotations[i].data_id.uuid)
00360 {
00361 annots_to_delete.push_back(this->annotations[i]);
00362 saved = false;
00363
00364 ROS_DEBUG("Removed annotation with uuid '%s'", unique_id::toHexString(this->annotations[i].id).c_str());
00365 ROS_DEBUG("Removed annot. data with uuid '%s'", unique_id::toHexString(this->annots_data[j].id).c_str());
00366 this->annotations.erase(this->annotations.begin() + i);
00367 this->annots_data.erase(this->annots_data.begin() + j);
00368
00369
00370 this->publishMarkers("annotation_markers");
00371
00372 return true;
00373 }
00374 }
00375
00376 ROS_ERROR("No data found for annotation '%s' (data uuid is '%s')", unique_id::toHexString(id).c_str(),
00377 unique_id::toHexString(this->annotations[i].data_id).c_str());
00378 return false;
00379 }
00380 }
00381
00382 ROS_WARN("Annotation '%s' not found", unique_id::toHexString(id).c_str());
00383 return false;
00384 }
00385
00386 bool AnnotationCollection::clearMarkers(const std::string& topic)
00387 {
00388 visualization_msgs::MarkerArray markers_array;
00389 visualization_msgs::Marker delete_all;
00390 delete_all.header.frame_id = "/map";
00391 delete_all.action = 3;
00392 markers_array.markers.push_back(delete_all);
00393
00394
00395 if (endsWith(marker_pub.getTopic(), topic) == true)
00396 {
00397 marker_pub.publish(markers_array);
00398 return true;
00399 }
00400
00401 if (endsWith(markers_pub.getTopic(), topic) == true)
00402 {
00403 markers_pub.publish(markers_array);
00404 return true;
00405 }
00406
00407
00408 markers_pub = nh.advertise <visualization_msgs::MarkerArray> (topic, 1, true);
00409 markers_pub.publish(markers_array);
00410 return true;
00411 }
00412
00413 bool AnnotationCollection::publishMarkers(const std::string& topic, bool clear_existing)
00414 {
00415 if (clear_existing == true)
00416 clearMarkers(topic);
00417
00418 if (this->annotations.size() == 0)
00419 {
00420 ROS_ERROR("No annotations retrieved. Nothing to publish!");
00421 return false;
00422 }
00423
00424 if (endsWith(markers_pub.getTopic(), topic) == false)
00425 {
00426
00427 markers_pub = nh.advertise <visualization_msgs::MarkerArray> (topic, 1, true);
00428 }
00429
00430
00431 visualization_msgs::MarkerArray markers_array;
00432 for (unsigned int i = 0; i < this->annotations.size(); i++)
00433 {
00434 markers_array.markers.push_back(makeMarker(i, this->annotations[i]));
00435 markers_array.markers.push_back(makeLabel(markers_array.markers.back()));
00436 }
00437
00438 markers_pub.publish(markers_array);
00439 return true;
00440 }
00441
00442 bool AnnotationCollection::publishMarker(const std::string& topic, int marker_id,
00443 const world_canvas_msgs::Annotation& ann,
00444 bool clear_existing)
00445 {
00446 if (endsWith(marker_pub.getTopic(), topic) == false)
00447 {
00448
00449
00450 marker_pub = nh.advertise <visualization_msgs::MarkerArray> (topic, 1, true);
00451 }
00452
00453 visualization_msgs::MarkerArray markers_array;
00454
00455 if (clear_existing == true)
00456 clearMarkers(topic);
00457
00458 markers_array.markers.push_back(makeMarker(marker_id, ann));
00459 markers_array.markers.push_back(makeLabel(markers_array.markers.back()));
00460 marker_pub.publish(markers_array);
00461
00462 return true;
00463 }
00464
00465 visualization_msgs::Marker AnnotationCollection::makeMarker(int id, const world_canvas_msgs::Annotation& ann)
00466 {
00467 std::stringstream name; name << ann.name << " [" << ann.type << "]";
00468
00469 visualization_msgs::Marker marker;
00470 marker.header.frame_id = ann.pose.header.frame_id;
00471 marker.header.stamp = ros::Time::now();
00472 marker.scale = ann.size;
00473 marker.color = ann.color;
00474 marker.ns = name.str();
00475 marker.id = id;
00476 marker.pose = ann.pose.pose.pose;
00477 marker.type = ann.shape;
00478 marker.action = visualization_msgs::Marker::ADD;
00479
00480 return marker;
00481 }
00482
00483 visualization_msgs::Marker AnnotationCollection::makeLabel(const visualization_msgs::Marker& marker)
00484 {
00485 visualization_msgs::Marker label = marker;
00486 label.id = marker.id + 1000000;
00487 label.type = visualization_msgs::Marker::TEXT_VIEW_FACING;
00488 label.pose.position.z = marker.pose.position.z + marker.scale.z/2.0 + 0.1;
00489 label.text = marker.ns != " []" ? marker.ns : "";
00490 label.scale.x = label.scale.y = label.scale.z = 0.12;
00491 label.color = marker.color;
00492
00493 return label;
00494 }
00495
00496
00497 bool AnnotationCollection::publish(const std::string& topic_name, const std::string& topic_type,
00498 bool by_server, bool as_list)
00499 {
00500 if (this->annotations.size() == 0)
00501 {
00502 ROS_ERROR("No annotations retrieved. Nothing to publish!");
00503 return false;
00504 }
00505
00506 std::string common_tt = topic_type;
00507
00508 if (common_tt.empty() == true)
00509 {
00510 if (as_list == true)
00511 {
00512 ROS_ERROR("Topic type argument is mandatory if as_list is true");
00513 return false;
00514 }
00515 else
00516 {
00517
00518
00519 for (unsigned int i = 0; i < this->annotations.size(); i++)
00520 {
00521 if ((common_tt.empty() == false) && (common_tt != annotations[i].type))
00522 {
00523 ROS_ERROR("Cannot publish annotations of different types (%s, %s)",
00524 common_tt.c_str(), annotations[i].type.c_str());
00525 return false;
00526 }
00527 common_tt = annotations[i].type;
00528 }
00529 }
00530 }
00531
00532 try
00533 {
00534 if (by_server == true)
00535 {
00536 ros::ServiceClient client =
00537 this->getServiceHandle<world_canvas_msgs::PubAnnotationsData>("pub_annotations_data");
00538
00539
00540
00541 ROS_INFO("Requesting server to publish annotations of type '%s'", common_tt.c_str());
00542 world_canvas_msgs::PubAnnotationsData srv;
00543 if (as_list == true)
00544 {
00545
00546 srv.request.annotation_ids = this->getAnnotsDataIDs();
00547 }
00548 else
00549 {
00550
00551
00552
00553 for (unsigned int i = 0; i < this->annotations.size(); i++)
00554 {
00555 if (annotations[i].type == common_tt)
00556 srv.request.annotation_ids.push_back(annotations[i].data_id);
00557 }
00558 }
00559 srv.request.topic_name = topic_name;
00560 srv.request.topic_type = common_tt;
00561 srv.request.pub_as_list = as_list;
00562 if (client.call(srv))
00563 {
00564 if (srv.response.result == true)
00565 {
00566 return true;
00567 }
00568 else
00569 {
00570 ROS_ERROR("Server reported an error: %s", srv.response.message.c_str());
00571 return false;
00572 }
00573 }
00574 else
00575 {
00576 ROS_ERROR("Failed to call pub_annotations_data service");
00577 return false;
00578 }
00579 }
00580 else
00581 {
00582
00583
00584
00585
00586 ROS_ERROR("Publish by client not implemented!");
00587 return false;
00588 }
00589 }
00590 catch (const ros::Exception& e)
00591 {
00592 ROS_ERROR("ROS exception caught: %s", e.what());
00593 return false;
00594 }
00595 }
00596
00597 bool AnnotationCollection::hasAnnotation(const UniqueIDmsg& id)
00598 {
00599 for (unsigned int i = 0; i < annotations.size(); i++)
00600 {
00601 if (annotations[i].id.uuid == id.uuid)
00602 return true;
00603 }
00604 return false;
00605 }
00606
00607 const world_canvas_msgs::Annotation& AnnotationCollection::getAnnotation(const UniqueIDmsg& id)
00608 {
00609 for (unsigned int i = 0; i < annotations.size(); i++)
00610 {
00611 if (annotations[i].id.uuid == id.uuid)
00612 return annotations[i];
00613 }
00614 throw ros::Exception("Uuid not found: " + unique_id::toHexString(id));
00615 }
00616
00617 std::vector<world_canvas_msgs::Annotation>
00618 AnnotationCollection::getAnnotations(const std::string& name)
00619 {
00620 std::vector<world_canvas_msgs::Annotation> result;
00621 for (unsigned int i = 0; i < annotations.size(); i++)
00622 {
00623 if (annotations[i].name == name)
00624 result.push_back(annotations[i]);
00625 }
00626 return result;
00627 }
00628
00629 std::vector<UniqueIDmsg> AnnotationCollection::getAnnotationIDs()
00630 {
00631 std::vector<UniqueIDmsg> uuids(annotations.size());
00632 for (unsigned int i = 0; i < annotations.size(); i++)
00633 {
00634 uuids[i] = annotations[i].id;
00635 }
00636 return uuids;
00637 }
00638
00639 std::vector<UniqueIDmsg> AnnotationCollection::getAnnotsDataIDs()
00640 {
00641 std::vector<UniqueIDmsg> uuids(annotations.size());
00642 for (unsigned int i = 0; i < annotations.size(); i++)
00643 {
00644 uuids[i] = annotations[i].data_id;
00645 }
00646 return uuids;
00647 }
00648
00649 const world_canvas_msgs::AnnotationData&
00650 AnnotationCollection::getData(const world_canvas_msgs::Annotation& ann)
00651 {
00652 for (unsigned int i = 0; i < this->annots_data.size(); i++)
00653 {
00654 if (this->annots_data[i].id.uuid == ann.data_id.uuid)
00655 {
00656 return this->annots_data[i];
00657 }
00658 }
00659
00660 throw ros::Exception("Data uuid not found: " + unique_id::toHexString(ann.data_id));
00661 }
00662
00663 }