moving_objects_confidence_enhancer_node.cpp
Go to the documentation of this file.
1 /*********************************************************************
2 * Software License Agreement (BSD License)
3 *
4 * Copyright (c) 2018, Andreas Gustavsson.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 *
11 * * Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * * Redistributions in binary form must reproduce the above
14 * copyright notice, this list of conditions and the following
15 * disclaimer in the documentation and/or other materials provided
16 * with the distribution.
17 * * Neither the name of the Willow Garage nor the names of its
18 * contributors may be used to endorse or promote products derived
19 * from this software without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32 * POSSIBILITY OF SUCH DAMAGE.
33 *
34 * Author: Andreas Gustavsson
35 *********************************************************************/
36 
47 /* ROS */
48 #include <ros/ros.h>
49 #include <sensor_msgs/LaserScan.h>
50 #include <visualization_msgs/Marker.h>
51 #include <visualization_msgs/MarkerArray.h>
52 
53 /* C/C++ */
54 #include <iostream>
55 #include <sstream>
56 #include <cmath>
57 #include <pthread.h>
58 
59 /* Local includes */
60 #include <find_moving_objects/MovingObject.h>
61 #include <find_moving_objects/MovingObjectArray.h>
62 
63 using namespace find_moving_objects;
64 
65 #define MIN(X,Y) (X<Y?X:Y)
66 #define MAX(X,Y) (X>Y?X:Y)
67 
68 #define WL(W) std::setw(W) << std::left
69 #define WR(W) std::setw(W) << std::right
70 const double TWO_PI = 2 * M_PI;
71 
72 /* HANDLE TO THIS NODE */
74 
75 
76 /* PUBLISHERS */
80 
81 
82 /* MOVINGOBJECTARRAY MSG HANDLING */
83 std::vector<find_moving_objects::MovingObjectArray::ConstPtr> g_msg_buffer_moa;
84 pthread_mutex_t g_mutex_moa = PTHREAD_MUTEX_INITIALIZER;
85 pthread_cond_t g_cond_moa = PTHREAD_COND_INITIALIZER;
86 bool g_available_moa = false;
87 int g_sender_index = -1;
88 int g_nr_senders = 0;
89 
90 
91 /* CALLBACK - USE EXTRA WORKER THREAD TO DO THE ACTUAL WORK */
92 void moaCallback(const find_moving_objects::MovingObjectArray::ConstPtr & msg)
93 {
94  // Save names of sending nodes so that we can keep messages apart, only used in this function, so make it a static var
95  static std::vector<std::string> g_msg_buffer_moa_senders;
96 
97  // Local search so that we can avoid locking the mutex
98  int sender_index = 0;
99  for (; sender_index<g_nr_senders; ++sender_index)
100  {
101  if (strcmp(msg->origin_node_name.c_str(), g_msg_buffer_moa_senders[sender_index].c_str()) == 0)
102  {
103  // Found!
104  break;
105  }
106  }
107  // If sender_index == g_nr_senders here, then the sender is unknown to us
108 
109  // CS start
110  pthread_mutex_lock(&g_mutex_moa);
111 
112  if (sender_index == g_nr_senders)
113  {
114  // If sender is not in list of known senders, then add its name and the msg to the buffers
115  g_msg_buffer_moa_senders.push_back(msg->origin_node_name);
116  g_msg_buffer_moa.push_back(msg); // Is the whole message copied when the new ConstPtr is created?
117  // Make sure we know that we added a sender
118  g_nr_senders++;
119  }
120  else
121  {
122  // Replace the cached message
123  g_msg_buffer_moa[sender_index] = msg;
124  }
125 
126  // Point to sender
127  g_sender_index = sender_index;
128 
129  // Signal that a new message is available
130  g_available_moa = true;
131  pthread_cond_signal(&g_cond_moa);
132 
133  // CS end
134  pthread_mutex_unlock(&g_mutex_moa);
135 
136  /*
137  * Now, the buffer of sender names and msgs are up-to-date,
138  * and g_sender_index is pointing to the newly arrived msg.
139  * When accessing the buffers or g_sender_index in the worker thread, the mutex must be taken.
140  * The newly arrived msg and g_sender_index should be immediately saved locally, as soon as the mutex is taken.
141  * Then some unprotected work can be done before each of the other senders' cached msgs are locally saved,
142  * under mutex protection, and then evaluated locally.
143  * This allows the cache of msgs to be updated even if the worker thread is currently doing some evaluation.
144  * Note, however, that only the latest msg is ever considered, which means that msgs can be dropped and that
145  * senders might thus suffer from never having their msgs evaluated and forwarded; this node might be a bottleneck.
146  */
147 }
148 
149 
150 /* WORKER THREAD */
151 void * moaHandlerBody(void * arg)
152 {
153  // Private nodehandle
155 
156  // Read parameters
157  bool verbose;
158  bool print_received_objects;
159  bool publish_objects;
160  bool publish_objects_closest_points_markers;
161  bool publish_objects_velocity_arrows;
162  bool velocity_arrows_use_full_gray_scale;
163  bool velocity_arrows_use_sensor_frame_param;
164  bool velocity_arrows_use_base_frame_param;
165  bool velocity_arrows_use_fixed_frame_param;
166  std::string topic_moving_objects_enhanced;
167  std::string topic_objects_closest_point_markers;
168  std::string topic_objects_velocity_arrows;
169  double threshold_min_confidence;
170  double threshold_max_delta_time_for_different_sources;
171  double threshold_max_delta_position;
172  double threshold_max_delta_velocity;
173  bool ignore_z_map_coordinate_for_position;
174  nh_priv.param("verbose", verbose, false);
175  nh_priv.param("print_received_objects", print_received_objects, false);
176  nh_priv.param("publish_objects", publish_objects, true);
177  nh_priv.param("publish_objects_closest_points_markers", publish_objects_closest_points_markers, true);
178  nh_priv.param("publish_objects_velocity_arrows", publish_objects_velocity_arrows, true);
179  nh_priv.param("velocity_arrows_use_full_gray_scale", velocity_arrows_use_full_gray_scale, false);
180  nh_priv.param("velocity_arrows_use_sensor_frame", velocity_arrows_use_sensor_frame_param, false);
181  nh_priv.param("velocity_arrows_use_base_frame", velocity_arrows_use_base_frame_param, false);
182  nh_priv.param("velocity_arrows_use_fixed_frame", velocity_arrows_use_fixed_frame_param, false);
183  nh_priv.param("threshold_min_confidence", threshold_min_confidence, 0.0);
184  nh_priv.param("threshold_max_delta_time_for_different_sources", threshold_max_delta_time_for_different_sources, 0.2);
185  nh_priv.param("threshold_max_delta_position", threshold_max_delta_position, 0.1);
186  nh_priv.param("threshold_max_delta_velocity", threshold_max_delta_velocity, 0.1);
187  nh_priv.param("ignore_z_map_coordinate_for_position", ignore_z_map_coordinate_for_position, true);
188 
189 
190 
191  bool velocity_arrows_use_sensor_frame = false;
192  bool velocity_arrows_use_base_frame = false;
193  bool velocity_arrows_use_fixed_frame = false;
194  if (velocity_arrows_use_sensor_frame_param)
195  velocity_arrows_use_sensor_frame = true;
196  else if (velocity_arrows_use_base_frame_param)
197  velocity_arrows_use_base_frame = true;
198  else if (velocity_arrows_use_fixed_frame_param)
199  velocity_arrows_use_fixed_frame = true;
200  const double threshold_max_delta_position_line_squared = threshold_max_delta_position *
201  threshold_max_delta_position;
202  const double threshold_max_delta_velocity_squared = threshold_max_delta_velocity * threshold_max_delta_velocity;
203 
204 
205  // Local message pointer
206  find_moving_objects::MovingObjectArray::ConstPtr msg_sender;
207  find_moving_objects::MovingObjectArray::ConstPtr msg_other;
208  int sender_index = -1;
209 
210  // Init msgs
211  sensor_msgs::LaserScan msg_objects_closest_point_markers;
212  const unsigned int points = 720;
213  const double range_min = 0.0;
214  const double range_max = 100.0;
215  const double resolution = TWO_PI / points;
216  const double inverted_resolution = points / TWO_PI;
217  const double out_of_range = range_max + 10.0;
218  if (publish_objects_closest_points_markers)
219  {
220  msg_objects_closest_point_markers.header.seq = 0;
221  msg_objects_closest_point_markers.angle_min = -M_PI;
222  msg_objects_closest_point_markers.angle_max = M_PI;
223  msg_objects_closest_point_markers.angle_increment = resolution;
224  msg_objects_closest_point_markers.time_increment = 0.0;
225  msg_objects_closest_point_markers.scan_time = 0.0;
226  msg_objects_closest_point_markers.range_min = range_min;
227  msg_objects_closest_point_markers.range_max = range_max;
228  msg_objects_closest_point_markers.intensities.resize(points);
229  msg_objects_closest_point_markers.ranges.resize(points);
230  for (unsigned int i=0; i<points; ++i)
231  {
232  msg_objects_closest_point_markers.ranges[i] = out_of_range;
233  msg_objects_closest_point_markers.intensities[i] = 0.0;
234  }
235  }
236  visualization_msgs::Marker msg_objects_velocity_arrow;
237  if (publish_objects_velocity_arrows)
238  {
239  msg_objects_velocity_arrow.ns = "fused_velocity_arrow";
240  msg_objects_velocity_arrow.type = visualization_msgs::Marker::ARROW;
241  msg_objects_velocity_arrow.action = visualization_msgs::Marker::ADD;
242  // msg_objects_velocity_arrow.pose.position.x = 0.0;
243  // msg_objects_velocity_arrow.pose.position.y = 0.0;
244  // msg_objects_velocity_arrow.pose.position.z = 0.0;
245  // msg_objects_velocity_arrow.pose.orientation.x = 0.0;
246  // msg_objects_velocity_arrow.pose.orientation.y = 0.0;
247  // msg_objects_velocity_arrow.pose.orientation.z = 0.0;
248  msg_objects_velocity_arrow.pose.orientation.w = 1.0;
249  msg_objects_velocity_arrow.scale.x = 0.05; // shaft diameter
250  msg_objects_velocity_arrow.scale.y = 0.1; // arrow head diameter
251  // msg_objects_velocity_arrow.scale.z = 0.0;
252  // msg_objects_velocity_arrow.color.r = 0.0;
253  // msg_objects_velocity_arrow.color.g = 0.0;
254  // msg_objects_velocity_arrow.color.b = 0.0;
255  msg_objects_velocity_arrow.color.a = 1.0;
256  msg_objects_velocity_arrow.lifetime = ros::Duration(0.4);
257  msg_objects_velocity_arrow.frame_locked = true;
258  msg_objects_velocity_arrow.points.resize(2);
259  msg_objects_velocity_arrow.points[0].z = 0.0;
260  msg_objects_velocity_arrow.points[1].z = 0.0;
261  }
262  visualization_msgs::MarkerArray msg_objects_velocity_arrows;
263  unsigned int arrow_seq = 0;
264 
265  // Spin
266  while (g_node->ok())
267  {
268  // Count of senders
269  unsigned int nr_senders = 0;
270 
271  // CS start - wait for a message to arrive
272  pthread_mutex_lock(&g_mutex_moa);
273  // Wait for message to be available
274  while (!g_available_moa)
275  {
276  // Exit?
277  if (!g_node->ok())
278  {
279  ROS_BREAK();
280  }
281  pthread_cond_wait(&g_cond_moa, &g_mutex_moa);
282  }
283  // Read that message and put it in the appropriate buffer/space
284  g_available_moa = false;
285  msg_sender = g_msg_buffer_moa[g_sender_index];
286  sender_index = g_sender_index;
287  nr_senders = g_nr_senders;
288 
289  // CS end - we now have a message to work on and the reference to it will not be modified
290  pthread_mutex_unlock(&g_mutex_moa);
291 
292  /* msg_sender points to the newly arrived msg, which comes from the sender with index sender_index */
293 
294  if (print_received_objects)
295  {
296  std::ostringstream stream;
297  stream << "Received moving objects from " << msg_sender->origin_node_name \
298  << " (sender " << sender_index+1 << "/" << nr_senders << "):" << std::endl \
299  << *msg_sender << std::endl;
300  std::string string = stream.str();
301  ROS_DEBUG("%s", string.c_str());
302  }
303 
304  // Look at each object and see if we can find an appropriate object in the latest message from each other sender
305  // Make sure there are objects in the received msg
306  const unsigned int nr_sender_objects = msg_sender->objects.size();
307  if (0 < nr_sender_objects)
308  {
309  // Init output msg
310  find_moving_objects::MovingObjectArray moa;
311  moa.origin_node_name = ros::this_node::getName();
312 
313  /*
314  * Only send objects included in the current msg!
315  * Any other object should already have been reported!
316  */
317 
318  // Sender stamp
319  const double sender_stamp = msg_sender->objects[0].header.stamp.toSec();
320 
321  // Loop over each object in the incoming msg
322  unsigned int nr_objects = 0; // Count of objects to send
323  for (unsigned int j=0; j<nr_sender_objects; ++j)
324  {
325  // Local pointer to the jth sender object
326  const find_moving_objects::MovingObject * sender_mo = & (msg_sender->objects[j]);
327 
328  // Keep track of how many other senders have a matching object and the sum of the confidences
329  unsigned int nr_matching_senders = 0;
330  double confidence_sum = 0.0;
331 
332  // Loop over each sender
333  for (unsigned int i=0; i<nr_senders; ++i)
334  {
335  // Make sure we are not looking at our own sender/message
336  if (i != sender_index)
337  {
338  // Point to the other message and update nr_senders in case new senders have reported seen objects
339  pthread_mutex_lock(&g_mutex_moa);
340  msg_other = g_msg_buffer_moa[i];
341  nr_senders = g_nr_senders;
342  pthread_mutex_unlock(&g_mutex_moa);
343 
344  // Get number of objects reported by the other sender
345  const unsigned int nr_other_objects = msg_other->objects.size();
346 
347  // Make sure there are objects in the other msg
348  if (0 < nr_other_objects)
349  {
350  // Other stamp
351  const double other_stamp = msg_other->objects[0].header.stamp.toSec();
352 
353  // Compare stamps to see if objects occur with low enough difference in time
354  if (fabs(sender_stamp - other_stamp) < threshold_max_delta_time_for_different_sources)
355  {
356  // Loop over other objects to find a corresponding one
357  for (unsigned int k=0; k<nr_other_objects; ++k)
358  {
359  // Local pointer to the kth sender object
360  const find_moving_objects::MovingObject * other_mo = & (msg_other->objects[k]);
361 
362  // Compare position and velocity in global frame (assume this frame is the same for all sources)
363  const double dx = sender_mo->position_in_map_frame.x - other_mo->position_in_map_frame.x;
364  const double dy = sender_mo->position_in_map_frame.y - other_mo->position_in_map_frame.y;
365  const double dz = ignore_z_map_coordinate_for_position ?
366  0.0 :
367  sender_mo->position_in_map_frame.z - other_mo->position_in_map_frame.z;
368  const double dp2 = dx*dx + dy*dy + dz*dz;
369 
370  const double dvx = sender_mo->velocity_in_map_frame.x - other_mo->velocity_in_map_frame.x;
371  const double dvy = sender_mo->velocity_in_map_frame.y - other_mo->velocity_in_map_frame.y;
372  const double dvz = sender_mo->velocity_in_map_frame.z - other_mo->velocity_in_map_frame.z;
373  const double dv2 = dvx*dvx + dvy*dvy + dvz*dvz;
374 
375 // ROS_WARN_STREAM("dp2 = " << dp2 << " (" << threshold_max_delta_position_line_squared << ") dv2 = "
376 // << dv2 << " (" << threshold_max_delta_velocity_squared << ")");
377 
378  // Are the objects quite the same?
379  // Adapt confidence accordingly
380  if (dp2 < threshold_max_delta_position_line_squared &&
381  dv2 < threshold_max_delta_velocity_squared)
382  {
383  // We found another sender that has a message sent within the given time threshold and with an
384  // object matching the current one
385  nr_matching_senders++;
386  confidence_sum += other_mo->confidence;
387  break; // Go to next sender
388  }
389  }
390  }
391  }
392  }
393  }
394 
395  ROS_DEBUG_STREAM("Increasing confidence of object based on " << nr_matching_senders << " matching senders");
396 
397  // Update confidence of object for the object in the output msg
398  double confidence = sender_mo->confidence;
399  if (0 < nr_matching_senders)
400  {
401  confidence += confidence_sum / nr_matching_senders;
402 
403  // Put confidence inside [0,1]
404  confidence = MIN(1.0, confidence);
405  confidence = MAX(0.0, confidence);
406  }
407 
408  // Add object to output moa if confidence is high enough
409  if (threshold_min_confidence <= confidence)
410  {
411  moa.objects.push_back(*sender_mo);
412  nr_objects++;
413  moa.objects.back().confidence = confidence;
414  }
415  }
416 
417  // Do we have any objects?
418  if (0 < nr_objects)
419  {
420  // Send moa msg
421  if (publish_objects)
422  {
423  g_pub_moaf.publish(moa);
424  }
425 
426  // Publish closest point markers
427  if (publish_objects_closest_points_markers)
428  {
429  // Update sequence number and stamp
430  msg_objects_closest_point_markers.header.seq++;
431  msg_objects_closest_point_markers.header.stamp = moa.objects[0].header.stamp;
432 
433  // Use sensor frame
434  msg_objects_closest_point_markers.header.frame_id = moa.objects[0].header.frame_id;
435 
436  // Vector for remembering which range indices have been marked
437  std::vector<int> indices;
438  unsigned int nr_indices = 0;
439  for (unsigned int a=0; a<nr_objects; ++a)
440  {
441  // Calculate angle in sensor frame where object is to be found
442  double angle = moa.objects[a].angle_for_closest_distance; // Angle in [-PI,PI], hopefully
443  angle += M_PI; // Shift by PI with intention to start with 0 angle in the direction of the negative x axis
444  // Put angle in [0, 2PI) so that index can be calculated
445  if (angle < 0 || TWO_PI <= angle)
446  {
447  angle -= floor(angle / TWO_PI) * TWO_PI;
448  }
449 
450  // Calculate index
451  int index = angle * inverted_resolution;
452 
453  // Save range index
454  indices.push_back(index);
455  nr_indices++;
456 
457  // Mark closest point
458  msg_objects_closest_point_markers.ranges[index] = moa.objects[a].closest_distance;
459  }
460 
461  // Publish
462  g_pub_objects_closest_point_markers.publish(msg_objects_closest_point_markers);
463 
464  // Reset ranges
465  for (unsigned k=0; k<nr_indices; ++k)
466  {
467  msg_objects_closest_point_markers.ranges[indices[k]] = out_of_range;
468  }
469  }
470 
471  // Publish velocity arrows
472  if (publish_objects_velocity_arrows)
473  {
474  msg_objects_velocity_arrow.header.seq = ++arrow_seq;
475 
476  for (unsigned int a=0; a<nr_objects; ++a)
477  {
478  msg_objects_velocity_arrow.header.stamp = moa.objects[a].header.stamp;
479  if (velocity_arrows_use_sensor_frame)
480  {
481  msg_objects_velocity_arrow.header.frame_id = moa.objects[a].header.frame_id;
482  msg_objects_velocity_arrow.points[0].x = moa.objects[a].position.x;
483  msg_objects_velocity_arrow.points[0].y = moa.objects[a].position.y;
484  msg_objects_velocity_arrow.points[1].x = moa.objects[a].position.x + moa.objects[a].velocity.x;
485  msg_objects_velocity_arrow.points[1].y = moa.objects[a].position.y + moa.objects[a].velocity.y;
486  }
487  else if (velocity_arrows_use_base_frame)
488  {
489  msg_objects_velocity_arrow.header.frame_id = moa.objects[a].base_frame;
490  msg_objects_velocity_arrow.points[0].x = moa.objects[a].position_in_base_frame.x;
491  msg_objects_velocity_arrow.points[0].y = moa.objects[a].position_in_base_frame.y;
492  msg_objects_velocity_arrow.points[1].x = moa.objects[a].position_in_base_frame.x +
493  moa.objects[a].velocity_in_base_frame.x;
494  msg_objects_velocity_arrow.points[1].y = moa.objects[a].position_in_base_frame.y +
495  moa.objects[a].velocity_in_base_frame.y;
496  }
497  else if (velocity_arrows_use_fixed_frame)
498  {
499  msg_objects_velocity_arrow.header.frame_id = moa.objects[a].fixed_frame;
500  msg_objects_velocity_arrow.points[0].x = moa.objects[a].position_in_fixed_frame.x;
501  msg_objects_velocity_arrow.points[0].y = moa.objects[a].position_in_fixed_frame.y;
502  msg_objects_velocity_arrow.points[1].x = moa.objects[a].position_in_fixed_frame.x +
503  moa.objects[a].velocity_in_fixed_frame.x;
504  msg_objects_velocity_arrow.points[1].y = moa.objects[a].position_in_fixed_frame.y +
505  moa.objects[a].velocity_in_fixed_frame.y;
506  }
507  else // map frame
508  {
509  msg_objects_velocity_arrow.header.frame_id = moa.objects[a].map_frame;
510  msg_objects_velocity_arrow.points[0].x = moa.objects[a].position_in_map_frame.x;
511  msg_objects_velocity_arrow.points[0].y = moa.objects[a].position_in_map_frame.y;
512  msg_objects_velocity_arrow.points[1].x = moa.objects[a].position_in_map_frame.x +
513  moa.objects[a].velocity_in_map_frame.x;
514  msg_objects_velocity_arrow.points[1].y = moa.objects[a].position_in_map_frame.y +
515  moa.objects[a].velocity_in_map_frame.y;
516  }
517  msg_objects_velocity_arrow.id = a;
518 
519  // Color of the arrow represents the confidence black=low, white=high
520  float adapted_confidence = moa.objects[a].confidence;
521  if (velocity_arrows_use_full_gray_scale && threshold_min_confidence < 1)
522  {
523  adapted_confidence = (moa.objects[a].confidence - threshold_min_confidence) /
524  (1 - threshold_min_confidence);
525  }
526  msg_objects_velocity_arrow.color.r = adapted_confidence;
527  msg_objects_velocity_arrow.color.g = adapted_confidence;
528  msg_objects_velocity_arrow.color.b = adapted_confidence;
529 
530  // Add to array of markers
531  msg_objects_velocity_arrows.markers.push_back(msg_objects_velocity_arrow);
532 
533  // Update namespace of velocity arrow
534  msg_objects_velocity_arrows.markers[a].ns.append(msg_sender->origin_node_name);
535  }
536 
537  // Publish the msg
538  g_pub_objects_velocity_arrows.publish(msg_objects_velocity_arrows);
539 
540  // Clear msg from all arrows
541  msg_objects_velocity_arrows.markers.clear();
542  }
543  }
544  } // Here, the moa msg is out of scope and moa.objects[] is thus destroyed
545  }
546 
547  return NULL;
548 }
549 
550 
551 /* ENTRY POINT */
552 int main(int argc, char** argv)
553 {
554  // Init ROS
555  ros::init(argc, argv, "mo_confidence_enhancer", ros::init_options::AnonymousName);
556  g_node = new ros::NodeHandle;
558 
559  // Wait for time to become valid
561 
562  // Init publisher
563  std::string topic_moving_objects_enhanced;
564  std::string topic_objects_velocity_arrows;
565  std::string topic_objects_closest_points_markers;
566  int publish_buffer_size;
567  nh_priv.param("topic_moving_objects_enhanced", topic_moving_objects_enhanced, std::string("moving_objects_enhanced"));
568  nh_priv.param("topic_objects_velocity_arrows", topic_objects_velocity_arrows, std::string("objects_velocity_arrows"));
569  nh_priv.param("topic_objects_closest_points_markers", topic_objects_closest_points_markers, std::string("objects_closest_points_markers"));
570  nh_priv.param("publish_buffer_size", publish_buffer_size, 2);
571  g_pub_moaf = g_node->advertise<find_moving_objects::MovingObjectArray>
572  (topic_moving_objects_enhanced,
573  publish_buffer_size);
574  g_pub_objects_velocity_arrows = g_node->advertise<visualization_msgs::MarkerArray>
575  (topic_objects_velocity_arrows,
576  publish_buffer_size);
577  g_pub_objects_closest_point_markers = g_node->advertise<sensor_msgs::LaserScan>
578  (topic_objects_closest_points_markers,
579  publish_buffer_size);
580 
581  // MovingObjectArray handler thread
582  pthread_t moa_handler;
583  if (pthread_create(&moa_handler, NULL, moaHandlerBody, NULL))
584  {
585  ROS_ERROR("Failed to create thread for handling MovingObjectArray messages");
586  ROS_BREAK();
587  }
588 
589  // Subscribe to interpreter results
590 
591  std::string subscribe_topic;
592  nh_priv.param("subscribe_topic", subscribe_topic, std::string("moving_objects"));
594  nh_priv.param("subscribe_buffer_size", subscribe_buffer_size, 10);
595  ros::Subscriber sub = g_node->subscribe(subscribe_topic,
596  subscribe_buffer_size,
597  moaCallback);
598 
599  // Start main ROS loop
600  ros::spin();
601 
602  return 0;
603 }
void moaCallback(const find_moving_objects::MovingObjectArray::ConstPtr &msg)
void publish(const boost::shared_ptr< M > &message) const
TF2SIMD_FORCE_INLINE tf2Scalar angle(const Quaternion &q1, const Quaternion &q2)
Subscriber subscribe(const std::string &topic, uint32_t queue_size, void(T::*fp)(M), T *obj, const TransportHints &transport_hints=TransportHints())
pthread_mutex_t g_mutex_moa
ROSCPP_DECL void init(int &argc, char **argv, const std::string &name, uint32_t options=0)
ROSCPP_DECL const std::string & getName()
ros::Publisher g_pub_objects_velocity_arrows
ROSCPP_DECL void spin(Spinner &spinner)
void * moaHandlerBody(void *arg)
bool param(const std::string &param_name, T &param_val, const T &default_val) const
Publisher advertise(const std::string &topic, uint32_t queue_size, bool latch=false)
int main(int argc, char **argv)
#define ROS_DEBUG_STREAM(args)
const float TWO_PI
Definition: bank.cpp:109
ros::Publisher g_pub_objects_closest_point_markers
bool ok() const
static bool waitForValid()
#define ROS_BREAK()
#define ROS_ERROR(...)
ros::NodeHandle * g_node
std::vector< find_moving_objects::MovingObjectArray::ConstPtr > g_msg_buffer_moa
#define ROS_DEBUG(...)


find_moving_objects
Author(s): Andreas Gustavsson
autogenerated on Mon Jun 10 2019 13:13:19