WorldModelROS.cpp
Go to the documentation of this file.
1 #include "wire/WorldModelROS.h"
2 
3 #include "wire/core/ClassModel.h"
4 #include "wire/core/Property.h"
5 #include "wire/core/Evidence.h"
9 
10 #include "wire/logic/Hypothesis.h"
12 
13 #include "boost/thread.hpp"
14 
15 #include <list>
16 
17 using namespace std;
18 using namespace mhf;
19 
20 WorldModelROS::WorldModelROS(tf::TransformListener* tf_listener)
21  : loop_rate_(20), world_model_(0), tf_listener_(tf_listener), is_tf_owner_(false), last_update_duration(0),
22  max_update_duration(0), world_model_frame_id_("/map"), output_frame_id_("/map"), max_num_hyps_(100), min_prob_ratio_(1e-10),
23  last_update_(0) {
24  initialize();
25 }
26 
28 
29  // delete tf listener
30  if (is_tf_owner_) {
31  delete tf_listener_;
32  }
33 
34  // delete multiple hypothesis filter_
35  delete world_model_;
36 
37  // shutdown subscribers
38  for (list<ros::Subscriber>::iterator it = subs_evidence_.begin(); it != subs_evidence_.end(); ++it) {
39  it->shutdown();
40  }
41 }
42 
44  // get node handle
45  ros::NodeHandle n("~");
46 
47  // set parameters
48  n.getParam("world_model_frame", world_model_frame_id_);
49  n.getParam("output_frame", output_frame_id_);
50  n.getParam("max_num_hypotheses", max_num_hyps_);
51  n.getParam("min_probability_ratio", min_prob_ratio_);
52 
53  string object_models_filename = "";
54  n.getParam("knowledge_filename", object_models_filename);
55 
56  if (object_models_filename == "") {
57  ROS_ERROR("Parameter 'knowledge_filename' not set.");
58  return false;
59  }
60 
61  // Parse object models
62  // ObjectModelParser parser(object_models_filename);
63  ObjectModelParser parser(object_models_filename);
64  if (!parser.parse(KnowledgeDatabase::getInstance())) {
65  // parsing failed
66  ROS_ERROR_STREAM("While parsing '" << object_models_filename << "': " << endl << endl << parser.getErrorMessage());
67  return false;
68  }
69 
70  // create tf listener
71  if (!tf_listener_) {
73  is_tf_owner_ = true;
74  }
75 
76  // Service for resetting the world model
78 
79  // Publishers
80  pub_wm_ = n.advertise<wire_msgs::WorldState>("/world_state", 10);
81 
82  // initialize the filter
84 
85  return true;
86 }
87 
88 void WorldModelROS::registerEvidenceTopic(const std::string& topic_name) {
90  subs_evidence_.push_back(n.subscribe(topic_name, 100, &WorldModelROS::evidenceCallback, this));
91 }
92 
94  processing_thread_ = boost::thread(boost::bind(&WorldModelROS::start, this));
95 }
96 
99 
100  int count = 0;
101  while(ros::ok()) {
102  ros::spinOnce();
104  publish();
105  ++count;
106  if (count == 15) {
107  //showStatistics();
108  count = 0;
109  }
110  r.sleep();
111  }
112 
113  ros::spinOnce();
114 }
115 
116 bool WorldModelROS::objectToMsg(const SemanticObject& obj, wire_msgs::ObjectState& msg) const {
117  msg.ID = obj.getID();
118 
119  const map<Attribute, Property*>& properties = obj.getPropertyMap();
120 
121  for(map<Attribute, Property*>::const_iterator it_prop = properties.begin(); it_prop != properties.end(); ++it_prop) {
122  Property* prop = it_prop->second;
123 
124  wire_msgs::Property prop_msg;
125  prop_msg.attribute = AttributeConv::attribute_str(it_prop->first);
126  pbl::PDFtoMsg(prop->getValue(), prop_msg.pdf);
127  msg.properties.push_back(prop_msg);
128  }
129 
130  return true;
131 }
132 
133 bool WorldModelROS::hypothesisToMsg(const Hypothesis& hyp, wire_msgs::WorldState& msg) const {
134  ros::Time time = ros::Time::now();
135 
136  msg.header.frame_id = world_model_frame_id_;
137  msg.header.stamp = time;
138 
139  for(list<SemanticObject*>::const_iterator it = hyp.getObjects().begin(); it != hyp.getObjects().end(); ++it) {
140 
141  SemanticObject* obj_clone = (*it)->clone();
142  obj_clone->propagate(time.toSec());
143 
144  wire_msgs::ObjectState obj_msg;
145  if (objectToMsg(*obj_clone, obj_msg)) {
146  msg.objects.push_back(obj_msg);
147  }
148 
149  delete obj_clone;
150 
151  }
152 
153  return true;
154 }
155 
156 bool WorldModelROS::transformPosition(const pbl::PDF& pdf_in, const string& frame_in, pbl::Gaussian& pdf_out) const {
157  const pbl::Gaussian* gauss = pbl::PDFtoGaussian(pdf_in);
158 
159  if (!gauss) {
160  ROS_ERROR("Position evidence is not a gaussian!");
161  return false;
162  }
163 
164  const arma::vec& pos = gauss->getMean();
165  tf::Stamped<tf::Point> pos_stamped(tf::Point(pos(0), pos(1), pos(2)), ros::Time(), frame_in);
166 
167  try{
168  tf::Stamped<tf::Point> pos_stamped_world;
169  tf_listener_->transformPoint(world_model_frame_id_, pos_stamped, pos_stamped_world);
170 
171  pbl::Vector3 pos_world(pos_stamped_world.getX(), pos_stamped_world.getY(), pos_stamped_world.getZ());
172  pdf_out.setMean(pos_world);
173 
174  // todo: also transform covariance
175  pdf_out.setCovariance(gauss->getCovariance());
176 
177  } catch (tf::TransformException& ex){
178  ROS_ERROR("[WORLD_MODEL] %s",ex.what());
179  return false;
180  }
181  return true;
182 }
183 
184 bool WorldModelROS::transformOrientation(const pbl::PDF& pdf_in, const string& frame_in, pbl::Gaussian& pdf_out) const {
185  const pbl::Gaussian* gauss = pbl::PDFtoGaussian(pdf_in);
186 
187  if (!gauss) {
188  ROS_ERROR("Orientation evidence is not a gaussian!");
189  return false;
190  }
191 
192  const arma::vec& ori = gauss->getMean();
193  tf::Stamped<tf::Quaternion> ori_stamped(tf::Quaternion(ori(0), ori(1), ori(2), ori(3)), ros::Time(), frame_in);
194 
195  try{
196  tf::Stamped<tf::Quaternion> ori_stamped_world;
197  tf_listener_->transformQuaternion(world_model_frame_id_, ori_stamped, ori_stamped_world);
198 
199  pbl::Vector4 ori_world(ori_stamped_world.getX(), ori_stamped_world.getY(), ori_stamped_world.getZ(), ori_stamped_world.getW());
200  pdf_out.setMean(ori_world);
201 
202  // todo: also transform covariance
203  pdf_out.setCovariance(gauss->getCovariance());
204 
205  } catch (tf::TransformException& ex){
206  ROS_ERROR("[WORLD MODEL] %s",ex.what());
207  return false;
208  }
209  return true;
210 }
211 
212 void WorldModelROS::evidenceCallback(const wire_msgs::WorldEvidence::ConstPtr& world_evidence_msg) {
213  evidence_buffer_.push_back(*world_evidence_msg);
214 }
215 
217 
218  ros::Time start_time = ros::Time::now();
219 
220  while(!evidence_buffer_.empty() && ros::Time::now() - start_time < max_duration) {
221 
222  ros::Time time_before_update = ros::Time::now();
223 
225 
226  last_update_duration = (ros::Time::now().toSec() - time_before_update.toSec());
227  max_update_duration = max(max_update_duration, last_update_duration);
228 
229  evidence_buffer_.pop_back();
230  }
231 }
232 
233 void WorldModelROS::processEvidence(const wire_msgs::WorldEvidence& world_evidence_msg) {
234  ros::Time current_time = ros::Time::now();
235 
236  if (current_time < last_update_) {
237  ROS_WARN("Saw a negative time change of %f seconds; resetting the world model.", (current_time - last_update_).toSec());
238  delete world_model_;
240  }
241  last_update_ = current_time;
242 
243  // reset the warnings stringstream
244  warnings_.str("");
245 
246  EvidenceSet evidence_set;
247  std::list<Evidence*> measurements_mem;
248 
249  const vector<wire_msgs::ObjectEvidence>& object_evidence = world_evidence_msg.object_evidence;
250  for(vector<wire_msgs::ObjectEvidence>::const_iterator it_ev = object_evidence.begin(); it_ev != object_evidence.end(); ++it_ev) {
251  const wire_msgs::ObjectEvidence& evidence = (*it_ev);
252 
253  //Evidence* meas = new Evidence(world_evidence_msg->header.stamp.toSec(), evidence.certainty, evidence.negative);
254  Evidence* meas = new Evidence(current_time.toSec());
255 
256  measurements_mem.push_back(meas);
257 
258  bool position_ok = true;
259 
260  for(vector<wire_msgs::Property>::const_iterator it_prop = evidence.properties.begin(); it_prop != evidence.properties.end(); ++it_prop ) {
261  const wire_msgs::Property& prop = *it_prop;
262 
263  pbl::PDF* pdf = pbl::msgToPDF(prop.pdf);
264 
265  if (pdf) {
266  if (prop.attribute == "position") {
267  pbl::Gaussian pos_pdf(3);
268  if (!transformPosition(*pdf, world_evidence_msg.header.frame_id, pos_pdf)) {
269  // position is a necessary property. If the transform was not successful, abort and don't use the evidence
270  position_ok = false;
271  break;
272  } else {
273  meas->addProperty(AttributeConv::attribute(prop.attribute), pos_pdf);
274  }
275  } else if (prop.attribute == "orientation") {
276  pbl::Gaussian ori_pdf(4);
277  if (transformOrientation(*pdf, world_evidence_msg.header.frame_id, ori_pdf)) {
278  meas->addProperty(AttributeConv::attribute(prop.attribute), ori_pdf);
279  }
280  } else {
281  meas->addProperty(AttributeConv::attribute(prop.attribute), *pdf);
282  }
283  delete pdf;
284  } else {
285  ROS_ERROR_STREAM("For attribute '" << prop.attribute << "': malformed pdf: " << prop.pdf);
286  }
287  }
288 
289  if (position_ok) {
290  evidence_set.add(meas);
291  } else {
292  ROS_ERROR("Unable to transform position.");
293  }
294 
295  } // end iteration over object evidence list
296 
297  world_model_->addEvidence(evidence_set);
298 
299  for(list<Evidence*>::iterator it = measurements_mem.begin(); it != measurements_mem.end(); ++it) {
300  delete (*it);
301  }
302 }
303 
304 bool WorldModelROS::resetWorldModel(std_srvs::Empty::Request& req, std_srvs::Empty::Response& res) {
305  delete world_model_;
307  return true;
308 }
309 
311  wire_msgs::WorldState map_world_msg;
312  hypothesisToMsg(world_model_->getMAPHypothesis(), map_world_msg);
313 
314  // Publish results
315  pub_wm_.publish(map_world_msg);
316 
317 }
318 
319 const list<SemanticObject*>& WorldModelROS::getMAPObjects() const {
320  return world_model_->getMAPObjects();
321 }
322 
324  printf("***** %f *****\n", ros::Time::now().toSec());
326  cout << "Num MAP objects: " << world_model_->getMAPObjects().size() << endl;
327  cout << "Last update: " << last_update_duration << " seconds" << endl;
328  cout << "Max update: " << max_update_duration << " seconds" << endl;
329  cout << "Evidence buffer size: " << evidence_buffer_.size() << endl;
330 
331  /*
332  const list<Hypothesis*>& hyp_list = world_model_->getHypotheses();
333  for(list<Hypothesis* >::const_iterator it_hyp = hyp_list.begin(); it_hyp != hyp_list.end(); ++it_hyp) {
334 
335  const list<SemanticObject*>& objs = (*it_hyp)->getObjects();
336 
337  double hyp_prob = (*it_hyp)->getProbability();
338 
339  cout << "Hyp P = " << hyp_prob << ": " << objs.size() << " object(s)" << endl;
340 
341  }
342  */
343 
344  if (!warnings_.str().empty()) {
345  ROS_WARN_STREAM(warnings_.str());
346  }
347 }
SemanticObject * clone() const
std::string getErrorMessage() const
PDF * msgToPDF(const problib::PDF &msg)
void add(Evidence *ev)
Adds evidence to the evidence set.
Definition: EvidenceSet.cpp:20
static Attribute attribute(const std::string &attribute_str)
attribute
Definition: datatypes.cpp:16
ros::Time last_update_
Definition: WorldModelROS.h:98
void publish(const boost::shared_ptr< M > &message) const
Subscriber subscribe(const std::string &topic, uint32_t queue_size, void(T::*fp)(M), T *obj, const TransportHints &transport_hints=TransportHints())
const std::map< Attribute, Property * > & getPropertyMap() const
void registerEvidenceTopic(const std::string &topic_name)
void publish() const
void addProperty(const Attribute &attribute, const pbl::PDF &value)
Definition: PropertySet.cpp:41
void transformPoint(const std::string &target_frame, const geometry_msgs::PointStamped &stamped_in, geometry_msgs::PointStamped &stamped_out) const
ServiceServer advertiseService(const std::string &service, bool(T::*srv_func)(MReq &, MRes &), T *obj)
bool objectToMsg(const SemanticObject &obj, wire_msgs::ObjectState &msg) const
double max_update_duration
Definition: WorldModelROS.h:84
static KnowledgeDatabase & getInstance()
#define ROS_WARN(...)
mhf::HypothesisTree * world_model_
Definition: WorldModelROS.h:68
static std::string attribute_str(const Attribute &attribute)
attribute_str
Definition: datatypes.cpp:27
iterator(field< oT > &in_M, const bool at_end=false)
void processEvidence(const ros::Duration max_duration)
std::list< ros::Subscriber > subs_evidence_
Definition: WorldModelROS.h:78
bool resetWorldModel(std_srvs::Empty::Request &req, std_srvs::Empty::Response &res)
const arma::mat & getCovariance() const
double loop_rate_
Definition: world_model.cpp:5
void showStatistics() const
The class Evidence represents a set of properties (PropertySet) that all originate from one physical ...
Definition: Evidence.h:61
void addEvidence(const EvidenceSet &ev_set)
const Hypothesis & getMAPHypothesis() const
void transformQuaternion(const std::string &target_frame, const geometry_msgs::QuaternionStamped &stamped_in, geometry_msgs::QuaternionStamped &stamped_out) const
A set of Evidence items which all originate from the same point int time.
Definition: EvidenceSet.h:55
void setMean(const arma::vec &mu)
Duration expectedCycleTime() const
const_iterator(const field< oT > &in_M, const bool at_end=false)
const arma::vec & getMean() const
std::string output_frame_id_
Definition: WorldModelROS.h:90
ROSCPP_DECL bool ok()
bool transformOrientation(const pbl::PDF &pdf_in, const std::string &frame_in, pbl::Gaussian &pdf_out) const
const std::list< SemanticObject * > & getMAPObjects() const
std::list< wire_msgs::WorldEvidence > evidence_buffer_
Definition: WorldModelROS.h:65
T count() const
Publisher advertise(const std::string &topic, uint32_t queue_size, bool latch=false)
arma_warn_unused eT max() const
bool hypothesisToMsg(const mhf::Hypothesis &hyp, wire_msgs::WorldState &msg) const
#define ROS_WARN_STREAM(args)
bool sleep()
bool parse(KnowledgeDatabase &obj_models)
ros::ServiceServer srv_reset_
Definition: WorldModelROS.h:80
const pbl::PDF & getValue() const
Definition: Property.cpp:48
bool getParam(const std::string &key, std::string &s) const
boost::thread processing_thread_
Definition: WorldModelROS.h:60
void propagate(const Time &time)
Propagates the internal state to Time time.
Definition: PropertySet.cpp:95
parser
ros::Publisher pub_wm_
Definition: WorldModelROS.h:75
void evidenceCallback(const wire_msgs::WorldEvidence::ConstPtr &world_evidence_msg)
const std::list< SemanticObject * > & getMAPObjects() const
static Time now()
Col< double > vec
ObjectID getID() const
#define ROS_ERROR_STREAM(args)
const std::list< SemanticObject * > & getObjects() const
Definition: Hypothesis.cpp:60
tf::TransformListener * tf_listener_
Definition: WorldModelROS.h:71
double last_update_duration
Definition: WorldModelROS.h:83
ROSCPP_DECL void spinOnce()
std::string world_model_frame_id_
Definition: WorldModelROS.h:87
void setCovariance(const arma::mat &cov)
#define ROS_ERROR(...)
const Gaussian * PDFtoGaussian(const PDF &pdf)
virtual ~WorldModelROS()
Definition: ClassModel.h:44
void PDFtoMsg(const PDF &pdf, problib::PDF &msg)
std::stringstream warnings_
Definition: WorldModelROS.h:92
bool transformPosition(const pbl::PDF &pdf_in, const std::string &frame_in, pbl::Gaussian &pdf_out) const


wire_core
Author(s): Sjoerd van den Dries, Jos Elfring
autogenerated on Fri Apr 16 2021 02:32:27