ed_sensor_integration
laser/updater.cpp
Go to the documentation of this file.
1 #include "ed/laser/updater.h"
2 
4 
5 #include <ed/convex_hull_calc.h>
6 #include <ed/entity.h>
7 #include <ed/update_request.h>
8 #include <ed/io/json_writer.h>
9 #include <ed/world_model.h>
10 
11 #include <geolib/Shape.h>
12 
13 #include <ros/console.h>
14 
15 #include <tue/profiling/timer.h>
16 
17 #include <iostream>
18 #include <opencv2/imgproc/imgproc.hpp>
19 
20 #define MIN_N_POINTS_FITTING 3
21 
33 double getFittingError(const ed::Entity& e, const geo::LaserRangeFinder& lrf, const geo::Pose3D& rel_pose,
34  const std::vector<double>& sensor_ranges, const std::vector<double>& model_ranges,
35  int& num_model_points)
36 {
37  std::vector<double> test_model_ranges = model_ranges;
38 
39  // Render the entity with the given relative pose
41  opt.setMesh(e.visual()->getMesh(), rel_pose);
42 
43  geo::LaserRangeFinder::RenderResult res(test_model_ranges);
44  lrf.render(opt, res);
45 
46  uint num_sensor_points = 0;
47  num_model_points = 0;
48  double total_error = 0;
49  for (unsigned int i = 0; i < test_model_ranges.size(); ++i)
50  {
51  double ds = sensor_ranges[i];
52  double dm = test_model_ranges[i];
53 
54  if (ds <= 0) // No sensor data
55  continue;
56 
57  ++num_sensor_points;
58 
59  if (dm <= 0) // No raytrace collision in model
60  {
61  total_error += 0.1;
62  continue;
63  }
64 
65  double diff = std::abs(ds - dm);
66  if (diff < 0.1)
67  total_error += diff;
68  else
69  {
70  if (ds > dm)
71  total_error += 1;
72  else
73  total_error += 0.1;
74  }
75 
76  ++num_model_points;
77  }
78 
79  return total_error / (num_sensor_points+1); // To be sure to never divide by zero.
80 }
81 
82 // Retrieve pose from cache, otherwise add pose to cache
84 {
85  const ed::UUID ID = e.id();
86  geo::Pose3D old_pose = e.pose();
87  if (pose_cache.find(ID) == pose_cache.end())
88  {
89  pose_cache[ID] = old_pose;
90  }
91  else
92  {
93  old_pose = pose_cache[ID];
94  }
95  return old_pose;
96 }
97 
115 geo::Pose3D fitEntity(const ed::Entity& e, const geo::Pose3D& sensor_pose, const geo::LaserRangeFinder& lrf,
116  const std::vector<double>& sensor_ranges, const std::vector<double>& model_ranges,
117  double x_window, double x_step, double y_window, double y_step, double yaw_min, double yaw_plus, double yaw_step, std::map<ed::UUID, geo::Pose3D>& pose_cache)
118 {
119  const geo::Pose3D& old_pose = getPoseFromCache(e, pose_cache);
120 
121  geo::Pose3D sensor_pose_inv = sensor_pose.inverse();
122 
123  double min_error = 1e6;
124  geo::Pose3D best_pose = e.pose();
125 
126  for(double dyaw = yaw_min; dyaw <= yaw_plus; dyaw += yaw_step)
127  {
128  geo::Mat3 rot;
129  rot.setRPY(0, 0, dyaw);
130  geo::Pose3D test_pose = old_pose;
131  test_pose.R = old_pose.R * rot;
132 
133  for(double dx = -x_window; dx <= x_window; dx += x_step)
134  {
135  test_pose.t.x = old_pose.t.x + dx;
136  for(double dy = -y_window; dy <= y_window; dy += y_step)
137  {
138  test_pose.t.y = old_pose.t.y + dy;
139 
140  int num_model_points;
141  double error = getFittingError(e, lrf, sensor_pose_inv * test_pose, sensor_ranges, model_ranges, num_model_points);
142 
143  if (error < min_error && num_model_points >= MIN_N_POINTS_FITTING)
144  {
145  best_pose = test_pose;
146  min_error = error;
147  }
148  }
149  }
150  }
151  return best_pose;
152 }
153 
162 {
163  float max_dist = 0.3; //TODO magic number
164 
165  // Find nearby entities to associate the measurements with
167 
168  if (!clusters.empty())
169  {
170  geo::Vec2 area_min(clusters[0].pose.t.x, clusters[0].pose.t.y);
171  geo::Vec2 area_max(clusters[0].pose.t.x, clusters[0].pose.t.y);
172  for (std::vector<EntityUpdate>::const_iterator it = clusters.cbegin(); it != clusters.cend(); ++it)
173  {
174  const EntityUpdate& cluster = *it;
175 
176  area_min.x = std::min(area_min.x, cluster.pose.t.x);
177  area_min.y = std::min(area_min.y, cluster.pose.t.y);
178 
179  area_max.x = std::max(area_max.x, cluster.pose.t.x);
180  area_max.y = std::max(area_max.y, cluster.pose.t.y);
181  }
182 
183  area_min -= geo::Vec2(max_dist, max_dist);
184  area_max += geo::Vec2(max_dist, max_dist);
185 
186  for(ed::WorldModel::const_iterator it = world.begin(); it != world.end(); ++it)
187  {
188  const ed::EntityConstPtr& e = *it;
189  if (e->visual() || !e->has_pose())
190  continue;
191 
192  const geo::Pose3D& entity_pose = e->pose();
193  const ed::ConvexHull& entity_chull = e->convexHull();
194 
195  if (entity_chull.points.empty())
196  continue;
197 
198  if (entity_pose.t.x < area_min.x || entity_pose.t.x > area_max.x
199  || entity_pose.t.y < area_min.y || entity_pose.t.y > area_max.y)
200  continue;
201 
202  entities.push_back(e);
203  }
204  }
205  return entities;
206 }
207 
218 {
219  // Create association matrix
220  ed_sensor_integration::AssociationMatrix assoc_matrix(clusters.size());
221  for (unsigned int i_cluster = 0; i_cluster < clusters.size(); ++i_cluster)
222  {
223  const EntityUpdate& cluster = clusters[i_cluster];
224 
225  for (unsigned int i_entity = 0; i_entity < entities.size(); ++i_entity)
226  {
227  const ed::EntityConstPtr& e = entities[i_entity];
228 
229  const geo::Pose3D& entity_pose = e->pose();
230  const ed::ConvexHull& entity_chull = e->convexHull();
231 
232  float dx = entity_pose.t.x - cluster.pose.t.x;
233  float dy = entity_pose.t.y - cluster.pose.t.y;
234  float dz = 0;
235 
236  if (entity_chull.z_max + entity_pose.t.z < cluster.chull.z_min + cluster.pose.t.z
237  || cluster.chull.z_max + cluster.pose.t.z < entity_chull.z_min + entity_pose.t.z)
238  // The convex hulls are non-overlapping in z
239  dz = entity_pose.t.z - cluster.pose.t.z;
240 
241  float dist_sq = (dx * dx + dy * dy + dz * dz);
242 
243  // TODO: better prob calculation + magic numbers
244  double prob = 1.0 / (1.0 + 100 * dist_sq);
245  double dt = current_time - e->lastUpdateTimestamp();
246  double e_max_dist = std::max(0.2, std::min(0.5, dt * 10));
247 
248  if (dist_sq > e_max_dist * e_max_dist)
249  prob = 0;
250 
251  if (prob > 0)
252  assoc_matrix.setEntry(i_cluster, i_entity, prob);
253  }
254  }
255  return assoc_matrix.calculateBestAssignment(assig);
256 }
257 
259 {
260  config.value("world_association_distance", world_association_distance_);
261  int temp_min_segment_size_pixels = 0;
262  config.value("min_segment_size_pixels", temp_min_segment_size_pixels);
263  min_segment_size_pixels_ = temp_min_segment_size_pixels;
264  config.value("segment_depth_threshold", segment_depth_threshold_);
265  config.value("min_cluster_size", min_cluster_size_);
266  config.value("max_cluster_size", max_cluster_size_);
267  int temp_max_gap_size = 0;
268  config.value("max_gap_size", temp_max_gap_size);
269  max_gap_size_ = temp_max_gap_size;
270 
271  fit_entities_ = false;
273 
274  if (config.hasError())
275  return;
276 }
277 
278 void LaserUpdater::update(const ed::WorldModel& world, std::vector<double>& sensor_ranges,
279  const geo::Pose3D& sensor_pose, const double timestamp, ed::UpdateRequest& req)
280 {
281  uint num_beams = sensor_ranges.size();
282 
283  // Filter measurment
284  for(unsigned int i = 1; i < num_beams - 1; ++i)
285  {
286  double rs = sensor_ranges[i];
287  // Get rid of points that are isolated from their neighbours
288  if (std::abs(rs - sensor_ranges[i - 1]) > 0.1 && std::abs(rs - sensor_ranges[i + 1]) > 0.1) // TODO: magic number
289  {
290  sensor_ranges[i] = sensor_ranges[i - 1];
291  }
292  }
293 
294  // Render world model as seen by laser
295  std::vector<double> model_ranges(num_beams, 0);
296  renderWorld(sensor_pose, world, model_ranges);
297 
298  // Fit the doors
299  if (fit_entities_)
300  {
301  geo::Pose3D sensor_pose_inv = sensor_pose.inverse();
302 
303  for(ed::WorldModel::const_iterator it = world.begin(); it != world.end(); ++it)
304  {
305  const ed::EntityConstPtr& e = *it;
306 
307  if (!e->visual() || !e->has_pose())
308  continue;
309 
310  geo::Pose3D e_pose_SENSOR = sensor_pose_inv * e->pose();
311 
312  // If not in sensor view, continue
313  if (e_pose_SENSOR.t.length2() > 5.0 * 5.0 || e_pose_SENSOR.t.x < 0) // TODO magic number: 5.0 = maximum distance from sensor
314  continue;
315 
316  if (e->hasType("left_door") || e->hasType("door_left") || e->hasType("right_door") || e->hasType("door_right"))
317  {
318  // Try to update the pose
319  geo::Pose3D new_pose = fitEntity(*e, sensor_pose, lrf_model_, sensor_ranges, model_ranges, 0, 0.1, 0, 0.1, -1.57, 1.57, 0.1, pose_cache);
320  req.setPose(e->id(), new_pose);
321 
322  // Render the door with the updated pose
324  opt.setMesh(e->visual()->getMesh(), sensor_pose_inv * new_pose);
325 
326  geo::LaserRangeFinder::RenderResult res(model_ranges);
327  lrf_model_.render(opt, res);
328  }
329  }
330  }
331 
332  // Try to associate sensor laser points to rendered model points, and filter out the associated ones
333  associate(sensor_ranges, model_ranges);
334 
335  // Segment the remaining points into clusters
336  std::vector<ScanSegment> segments = segment(sensor_ranges);
337 
338  // Convert the segments to convex hulls, and check for collisions with other convex hulls
339  std::vector<EntityUpdate> clusters(segments.size());
340 
341  for(uint i_seg=0; i_seg < segments.size(); ++i_seg)
342  {
343  clusters[i_seg] = segmentToConvexHull(segments[i_seg], sensor_pose, sensor_ranges);
344  }
345 
346  // Create selection of world model entities that could associate
347  std::vector<ed::EntityConstPtr> entities = findNearbyEntities(clusters, world);
349  if (!associateSegmentsWithEntities(clusters, entities, timestamp, assig))
350  {
351  ROS_WARN("Association failed!");
352  return;
353  }
354 
355  // Fill update request
356  for (unsigned int i_cluster = 0; i_cluster < clusters.size(); ++i_cluster)
357  {
358  const EntityUpdate& cluster = clusters[i_cluster];
359 
360  // Get the assignment for this cluster
361  int i_entity = assig[i_cluster];
362 
363  ed::UUID id;
364  ed::ConvexHull new_chull;
365  geo::Pose3D new_pose;
366 
367  if (i_entity == -1)
368  {
369  // No assignment, so add as new cluster
370  new_chull = cluster.chull;
371  new_pose = cluster.pose;
372 
373  // Generate unique ID
374  id = ed::Entity::generateID().str() + "-laser";
375 
376  // Update existence probability
377  req.setExistenceProbability(id, 1.0); // TODO magic number
378  }
379  else
380  {
381  // Update the entity
382  const ed::EntityConstPtr& e = entities[i_entity];
383 
384  if (!e->hasFlag("locked"))
385  {
386  new_chull = cluster.chull;
387  new_pose = cluster.pose;
388  }
389 
390  // Update existence probability
391  double p_exist = e->existenceProbability();
392  req.setExistenceProbability(e->id(), std::min(1.0, p_exist + 0.1)); // TODO: very ugly prob update
393 
394  id = e->id();
395  }
396 
397  // Set convex hull and pose
398  if (!new_chull.points.empty())
399  {
400  req.setConvexHullNew(id, new_chull, new_pose, timestamp, lrf_frame_);
401 
402  // --------------------------
403  // Temp for RoboCup 2015; todo: remove after
404 
405  if (!cluster.flag.empty())
406  req.setFlag(id, cluster.flag);
407 
408  // --------------------------
409  }
410 
411  // Set timestamp
412  req.setLastUpdateTimestamp(id, timestamp);
413  }
414 
415  /* Jan2022 this code has not been used for a long time but it does contain
416  an interesting concept: entities that you should see but don't should be removed
417  This code is left here to serve as inspiration should anyone wish to
418  impement this functionality again.
419  Note that some supporting functionality has been removed. Including filling entities_associated
420  and the PointisPresent method
421  */
422 
423  /* Clear unassociated entities in view
424 
425  for(unsigned int i = 0; i < entities_associated.size(); ++i)
426  {
427  const ed::EntityConstPtr& e = entities[i];
428 
429  // If the entity is associated, skip it
430  if (entities_associated[i] >= 0)
431  continue;
432 
433  const geo::Pose3D& pose = e->pose();
434 
435  // Transform to sensor frame
436  geo::Vector3 p = sensor_pose.inverse() * pose.t;
437 
438  if (!pointIsPresent(p, lrf_model_, sensor_ranges))
439  {
440  double p_exist = e->existenceProbability();
441  if (p_exist < 0.3) // TODO: magic number
442  req.removeEntity(e->id());
443  else
444  {
445  req.setExistenceProbability(e->id(), std::max(0.0, p_exist - 0.1)); // TODO: very ugly prob update
446  }
447  }
448  }*/
449 }
450 
451 void LaserUpdater::renderWorld(const geo::Pose3D& sensor_pose, const ed::WorldModel& world, std::vector<double>& model_ranges)
452 {
453  geo::Pose3D sensor_pose_inv = sensor_pose.inverse();
454 
455  for(ed::WorldModel::const_iterator it = world.begin(); it != world.end(); ++it)
456  {
457  const ed::EntityConstPtr& e = *it;
458 
459  if (e->visual() && e->has_pose() && !(e->hasType("left_door") || e->hasType("door_left") || e->hasType("right_door") || e->hasType("door_right")))
460  {
461  // Set render options
463  opt.setMesh(e->visual()->getMesh(), sensor_pose_inv * e->pose());
464 
465  geo::LaserRangeFinder::RenderResult res(model_ranges);
466  lrf_model_.render(opt, res);
467  }
468  }
469 }
470 
471 void LaserUpdater::associate(std::vector<double>& sensor_ranges, const std::vector<double>& model_ranges){
472  for (unsigned int i = 0; i < sensor_ranges.size(); ++i)
473  {
474  double rs = sensor_ranges[i];
475  double rm = model_ranges[i];
476 
477  if (rs <= 0
478  || (rm > 0 && rs > rm) // If the sensor point is behind the world model, skip it
479  || (std::abs(rm - rs) < world_association_distance_))
480  sensor_ranges[i] = 0;
481  }
482 }
483 
485 {
486  std::vector<ScanSegment> segments;
487  uint num_beams = sensor_ranges.size();
488 
489  // Find first valid value
490  ScanSegment current_segment;
491  for(unsigned int i = 0; i < num_beams; ++i)
492  {
493  if (sensor_ranges[i] > 0)
494  {
495  current_segment.push_back(i);
496  break;
497  }
498  }
499 
500  if (current_segment.empty()) // no residual point cloud
501  {
502  return segments;
503  }
504 
505  uint gap_size = 0;
506 
507  for(unsigned int i = current_segment.front(); i < num_beams; ++i)
508  {
509  double rs = sensor_ranges[i];
510 
511  if (rs == 0 || std::abs(rs - sensor_ranges[current_segment.back()]) > segment_depth_threshold_ || i == num_beams - 1)
512  {
513  // Found a gap or at final reading
514  ++gap_size;
515 
516  if (gap_size >= max_gap_size_ || i == num_beams - 1)
517  {
518  i = current_segment.back() + 1;
519 
520  if (current_segment.size() >= min_segment_size_pixels_)
521  {
522  // Calculate bounding box
523  geo::Vec2 seg_min, seg_max;
524  for(unsigned int k = 0; k < current_segment.size(); ++k)
525  {
526  geo::Vector3 p = lrf_model_.rayDirections()[current_segment[k]] * sensor_ranges[current_segment[k]];
527 
528  if (k == 0)
529  {
530  seg_min = geo::Vec2(p.x, p.y);
531  seg_max = geo::Vec2(p.x, p.y);
532  }
533  else
534  {
535  seg_min.x = std::min(p.x, seg_min.x);
536  seg_min.y = std::min(p.y, seg_min.y);
537  seg_max.x = std::max(p.x, seg_max.x);
538  seg_max.y = std::max(p.y, seg_max.y);
539  }
540  }
541 
542  geo::Vec2 bb = seg_max - seg_min;
543  if ((bb.x > min_cluster_size_ || bb.y > min_cluster_size_) && bb.x < max_cluster_size_ && bb.y < max_cluster_size_)
544  segments.push_back(current_segment);
545  }
546 
547  current_segment.clear();
548 
549  // Find next good value
550  while(sensor_ranges[i] == 0 && i < num_beams)
551  ++i;
552 
553  current_segment.push_back(i);
554  }
555  }
556  else
557  {
558  gap_size = 0;
559  current_segment.push_back(i);
560  }
561  }
562  return segments;
563 }
564 
565 EntityUpdate LaserUpdater::segmentToConvexHull(const ScanSegment& segment, const geo::Pose3D& sensor_pose, const std::vector<double>& sensor_ranges)
566 {
567  unsigned int segment_size = segment.size();
568 
569  std::vector<geo::Vec2f> points(segment_size);
570 
571  float z_min = 0., z_max = 0.;
572  for(unsigned int i = 0; i < segment_size; ++i)
573  {
574  unsigned int j = segment[i];
575 
576  // Calculate the cartesian coordinate of the point in the segment (in sensor frame)
577  geo::Vector3 p_sensor = lrf_model_.rayDirections()[j] * sensor_ranges[j];
578 
579  // Transform to world frame
580  geo::Vector3 p = sensor_pose * p_sensor;
581 
582  // Add to cv array
583  points[i] = geo::Vec2f(p.x, p.y);
584 
585  if (i == 0)
586  {
587  z_min = p.z;
588  z_max = p.z;
589  }
590  else
591  {
592  z_min = std::min<float>(z_min, p.z);
593  z_max = std::max<float>(z_max, p.z);
594  }
595  }
596 
597  EntityUpdate cluster;
598 
599  cluster.pose = geo::Pose3D::identity();
600  ed::convex_hull::create(points, z_min, z_max, cluster.chull, cluster.pose);
601 
602  // --------------------------
603  // Temp for RoboCup 2016; todo: remove after
604 
605  // Determine the cluster size
606  geo::Vec2f diff = points.back() - points.front();
607  float size_sq = diff.length2();
608  if (size_sq > 0.35 * 0.35 && size_sq < 0.8 * 0.8)
609  cluster.flag = "possible_human";
610 
611  // --------------------------
612  return cluster;
613 }
geo::Vector3::y
const real & y() const
ed::ConvexHull::z_min
float z_min
ed::UpdateRequest
LaserUpdater::configure
void configure(tue::Configuration &config)
Configure updater.
Definition: laser/updater.cpp:258
ed_sensor_integration::AssociationMatrix::setEntry
void setEntry(int i_measurement, int i_entity, double prob)
Definition: association_matrix.cpp:30
EntityUpdate
collection structure for laser entities
Definition: kinect/entity_update.h:9
updater.h
ed::ConvexHull
ed::convex_hull::create
void create(const std::vector< geo::Vec2f > &points, float z_min, float z_max, ConvexHull &chull, geo::Pose3D &pose)
json_writer.h
update_request.h
geo::Vec2T::y
T y
LaserUpdater::min_cluster_size_
double min_cluster_size_
Definition: laser/updater.h:88
geo::Transform3T::identity
static Transform3T identity()
EntityUpdate::flag
std::string flag
Definition: laser/entity_update.h:13
std::vector< double >
std::map::find
T find(T... args)
std::vector::size
T size(T... args)
getPoseFromCache
geo::Pose3D getPoseFromCache(const ed::Entity &e, std::map< ed::UUID, geo::Pose3D > &pose_cache)
Definition: laser/updater.cpp:83
LaserUpdater::segment_depth_threshold_
double segment_depth_threshold_
Definition: laser/updater.h:87
LaserUpdater::segment
std::vector< ScanSegment > segment(const std::vector< double > &sensor_ranges)
divide the sensor ranges into segments
Definition: laser/updater.cpp:484
LaserUpdater::world_association_distance_
double world_association_distance_
Definition: laser/updater.h:86
LaserUpdater::min_segment_size_pixels_
uint min_segment_size_pixels_
Definition: laser/updater.h:85
Shape.h
geo::Vec2T::x
T x
MIN_N_POINTS_FITTING
#define MIN_N_POINTS_FITTING
Definition: laser/updater.cpp:20
getFittingError
double getFittingError(const ed::Entity &e, const geo::LaserRangeFinder &lrf, const geo::Pose3D &rel_pose, const std::vector< double > &sensor_ranges, const std::vector< double > &model_ranges, int &num_model_points)
Calculate an error based on the quality of a fit.
Definition: laser/updater.cpp:33
std::vector::back
T back(T... args)
geo::Transform3T
geo::Vec2f
Vec2T< float > Vec2f
iostream
geo::LaserRangeFinder::render
void render(const geo::LaserRangeFinder::RenderOptions &options, geo::LaserRangeFinder::RenderResult &res) const
std::vector::front
T front(T... args)
ed::WorldModel::begin
const_iterator begin() const
LaserUpdater::max_cluster_size_
double max_cluster_size_
Definition: laser/updater.h:89
ed::WorldModel::const_iterator
EntityIterator const_iterator
std::vector::clear
T clear(T... args)
ed::EntityConstPtr
shared_ptr< const Entity > EntityConstPtr
ed::WorldModel::end
const_iterator end() const
std::vector::push_back
T push_back(T... args)
geo::Vec3T::y
T y
tue::config::ReaderWriter
LaserUpdater::update
void update(const ed::WorldModel &world, std::vector< double > &sensor_ranges, const geo::Pose3D &sensor_pose, const double timestamp, ed::UpdateRequest &req)
update update the worldmodel based on a novel laserscan message.
Definition: laser/updater.cpp:278
geo::Transform3T::inverse
Transform3T inverse() const
LaserUpdater::segmentToConvexHull
EntityUpdate segmentToConvexHull(const ScanSegment &segment, const geo::Pose3D &sensor_pose, const std::vector< double > &sensor_ranges)
convert a segment of ranges to a convex hull
Definition: laser/updater.cpp:565
error
std::ostream & error()
LaserUpdater::fit_entities_
bool fit_entities_
Definition: laser/updater.h:90
geo::LaserRangeFinder::rayDirections
const std::vector< geo::Vector3 > & rayDirections() const
ed::Entity
geo::Transform3T::t
Vec3T< T > t
geo::Vec3T::length2
T length2() const
tue::config::OPTIONAL
OPTIONAL
ed::UUID
ed::Entity::pose
const geo::Pose3D & pose() const
LaserUpdater::renderWorld
void renderWorld(const geo::Pose3D &sensor_pose, const ed::WorldModel &world, std::vector< double > &model_ranges)
render the worldmodel as would be seen by the lrf.
Definition: laser/updater.cpp:451
req
string req
LaserUpdater::max_gap_size_
uint max_gap_size_
Definition: laser/updater.h:91
geo::LaserRangeFinder::RenderOptions::setMesh
void setMesh(const geo::Mesh &mesh, const geo::Pose3D &pose)
geo::Vector3
std::map
geo::Vec2
Vec2T< real > Vec2
ed::WorldModel
geo::Vector3::z
const real & z() const
timer.h
std::min
T min(T... args)
geo::Mat3T
ed::Entity::generateID
static UUID generateID()
LaserUpdater::lrf_frame_
std::string lrf_frame_
Definition: laser/updater.h:114
geo::LaserRangeFinder
tue::config::ReaderWriter::value
bool value(const std::string &name, T &value, RequiredOrOptional opt=REQUIRED)
fitEntity
geo::Pose3D fitEntity(const ed::Entity &e, const geo::Pose3D &sensor_pose, const geo::LaserRangeFinder &lrf, const std::vector< double > &sensor_ranges, const std::vector< double > &model_ranges, double x_window, double x_step, double y_window, double y_step, double yaw_min, double yaw_plus, double yaw_step, std::map< ed::UUID, geo::Pose3D > &pose_cache)
estimate the pose of an entity that best describes the sensor data.
Definition: laser/updater.cpp:115
world_model.h
diff
IMETHOD Twist diff(const Frame &F_a_b1, const Frame &F_a_b2, double dt=1)
std::vector::cbegin
T cbegin(T... args)
geo::LaserRangeFinder::RenderOptions
LaserUpdater::lrf_model_
geo::LaserRangeFinder lrf_model_
Definition: laser/updater.h:113
geo::Transform3T::R
Mat3T< T > R
EntityUpdate::pose
geo::Pose3D pose
Definition: laser/entity_update.h:12
geo::Vector3::x
const real & x() const
LaserUpdater::associate
void associate(std::vector< double > &sensor_ranges, const std::vector< double > &model_ranges)
associate: filter sensor information and remove ranges that can be associated with the worldmodel....
Definition: laser/updater.cpp:471
EntityUpdate::chull
ed::ConvexHull chull
Definition: kinect/entity_update.h:20
geo::Vec3T::z
T z
std::vector::empty
T empty(T... args)
findNearbyEntities
std::vector< ed::EntityConstPtr > findNearbyEntities(std::vector< EntityUpdate > &clusters, const ed::WorldModel &world)
findNearbyEntities create a list of entities that are close to detected clusters
Definition: laser/updater.cpp:161
std::map::end
T end(T... args)
LaserUpdater::pose_cache
std::map< ed::UUID, geo::Pose3D > pose_cache
Definition: laser/updater.h:116
std::max
T max(T... args)
ed::Entity::id
const UUID & id() const
entity.h
ed::ConvexHull::z_max
float z_max
convex_hull_calc.h
association_matrix.h
ed_sensor_integration::AssociationMatrix
Definition: association_matrix.h:12
geo::Mat3T::setRPY
void setRPY(T roll, T pitch, T yaw)
ed::Entity::visual
geo::ShapeConstPtr visual() const
geo::Vec3T::x
T x
geo::LaserRangeFinder::RenderResult
ed_sensor_integration::AssociationMatrix::calculateBestAssignment
bool calculateBestAssignment(Assignment &assig)
Definition: association_matrix.cpp:44
geo::Vec2T
associateSegmentsWithEntities
bool associateSegmentsWithEntities(std::vector< EntityUpdate > &clusters, const std::vector< ed::EntityConstPtr > &entities, double current_time, ed_sensor_integration::Assignment &assig)
Associate segments with etities in the world model.
Definition: laser/updater.cpp:217
ed::UUID::str
const std::string & str() const
config
tue::config::ReaderWriter config
tue::config::ReaderWriter::hasError
bool hasError() const
ed::ConvexHull::points
std::vector< geo::Vec2f > points