scene_configurator.cpp
Go to the documentation of this file.
1 
18 // Local Includes
20 
21 // Global Includes
22 #include <iostream>
23 
24 // ISM Includes
25 #include <ISM/utility/Util.hpp>
26 
27 
28 
29 /****** Keyboard input includes and defines******/
30 #include <unistd.h> //STDIN_FILENO
31 
32 #define KEYCODE_AUTOMATIC_PROCESSING 0x20 //space
33 #define KEYCODE_PROCESS_ONLY_MARKED 0x6D //m
34 
35 #define KEYCODE_PROCESS_CONFIGURATION 0x0A //enter
36 
37 #define KEYCODE_RESET 0x7F //delete or backspace
38 #define KEYCODE_ADD 0x61 //a
39 #define KEYCODE_SHOW 0x73 //s
40 #define KEYCODE_REMOVE 0x64 //d
41 #define KEYCODE_UPDATE_VIEW 0x75 //u
42 
43 #define KEYCODE_HELP 0x68 //h
44 /****************************/
45 
47  : processKeyboardInputFunc_(processKeyboardInputFunc), processObjectInputFunc_(processObjectInputFunc)
48 {
49  nh_ = ros::NodeHandle(ros::this_node::getName(), "scene_configurator");
50 
51  assert(!processConfigFunc.empty());
52  processConfigurationFunc_ = processConfigFunc;
53  ROS_DEBUG_STREAM("processKeyboardInputFunc_ is empty: " << std::boolalpha << processKeyboardInputFunc_.empty());
54 
55  /* Required parameter from ROS environment */
56  std::string object_input_topic;
57  int object_input_queue_size;
58  int object_input_thread_count;
59  bool ignore_ids, ignore_types;
60  std::string base_frame;
61  bool use_confidence_from_msg;
62  int enable_rotation_mode;
63  std::string rotation_frame, rotation_object_type, rotation_object_id;
64  bool enable_neighborhood_evaluation;
65  double neighbour_angle_threshold, neighbour_distance_threshold;
66  double automatic_processing_interval;
67  int keyboard_poll_rate;
68  std::string input_visualization_topic;
69 
70  getNodeParameters(object_input_topic, object_input_queue_size, object_input_thread_count, base_frame, ignore_types, ignore_ids, use_confidence_from_msg,
71  enable_rotation_mode, rotation_frame, rotation_object_type, rotation_object_id,
72  enable_neighborhood_evaluation, neighbour_angle_threshold, neighbour_distance_threshold,
73  keyboard_poll_rate, automatic_processing_interval, input_visualization_topic);
74 
75 
76  /* default-state */
79 
80  automatic_processing_timer_ = nh_.createTimer(ros::Duration(automatic_processing_interval), &SceneConfigurator::automaticProcessingCallback, this, false, false);
81 
82  /* Set-up keyboard input */
83  tcgetattr( STDIN_FILENO, &original_terminal_settings_); // save original terminal settings
85  modified_terminal_settings_.c_lflag &= ~(ICANON | ECHO); // disable buffering
86  modified_terminal_settings_.c_iflag |= IUCLC; // map upper case to lower case
87  modified_terminal_settings_.c_cc[VMIN] = 0; // minimal characters awaited
88  modified_terminal_settings_.c_cc[VTIME] = 0; // time keep reading after last byte
89  tcsetattr( STDIN_FILENO, TCSANOW, &modified_terminal_settings_); // apply modified terminal settings
90 
91  //Set-up thread to poll keyboard input
92  keyboard_thread_ = new boost::thread(&SceneConfigurator::keyboardInputMain, this, keyboard_poll_rate);
93 
94 
95  /* Set-up object input */
96  object_msg_converter_ = IH::ObjectConverterPtr(new IH::ObjectConverter(base_frame, ignore_types, ignore_ids, enable_rotation_mode, rotation_frame, rotation_object_type, rotation_object_id, use_confidence_from_msg));
97  data_ = new SceneConfiguratorData(enable_neighborhood_evaluation, neighbour_angle_threshold, neighbour_distance_threshold);
98  ptu_ = ros::NodeHandlePtr(new ros::NodeHandle("asr_flir_ptu_driver"));
99  ros::NodeHandle object_input_nh_ = ros::NodeHandle(nh_, "object_input");
100  object_input_nh_.setCallbackQueue(&object_queue_);
101  object_input_subscriber_ = object_input_nh_.subscribe(object_input_topic, object_input_queue_size, &SceneConfigurator::objectInputCallback, this);
102  spinner_ = new ros::AsyncSpinner(object_input_thread_count, &object_queue_);
103  spinner_->start();
104 
105 
106  /* Set-up visualization */
107  visualization_publisher_ = nh_.advertise<visualization_msgs::MarkerArray>(input_visualization_topic, 10000);
108  object_model_visualizer_ = new VIZ::ObjectModelVisualizerRVIZ(visualization_publisher_, base_frame, "", 0);
109  visualization_timer_ = nh_.createTimer(ros::Duration(std::max(automatic_processing_interval, 0.5)), &SceneConfigurator::updateVisualizationCallback, this);
110 
111  printHelpText();
112 }
113 
115 {
116  ROS_DEBUG("~SceneConfigurator():");
117  //Stop keyboard-thread and restore terminal settings
118  keyboard_thread_->interrupt();
119  keyboard_thread_->join();
120  tcsetattr( STDIN_FILENO, TCSANOW, &original_terminal_settings_); // restore original terminal settings
121  ROS_DEBUG("Terminal Settings restored");
122 
123 
124  //Stop object input handling
125  spinner_->stop();
126  delete spinner_;
127 
129 }
130 
132 {
133  return this->automatic_processing_active_;
134 }
135 
136 void SceneConfigurator::keyboardInputMain(const unsigned int poll_rate)
137 {
138  ros::Rate rate(poll_rate);
139  try
140  {
141  while (ros::ok())
142  {
143  boost::this_thread::interruption_point();
144 
146 
147  rate.sleep();
148  }
149  }
150  catch (boost::thread_interrupted&) {}
151 
152  return;
153 }
154 
156 {
157  int temp_key_value = getchar();
158  tcflush(STDIN_FILENO, TCIFLUSH); //flush unread input, because we don't want to process old input from buffer.
159 
160  // don't accept repeated key input if a key is still pressed.
161  bool old_key_pressed = key_pressed_;
162  key_pressed_ = (temp_key_value < 0) ? false : true;
163  if(!key_pressed_ || old_key_pressed)
164  {
165  return;
166  }
167 
168 
169  // commands to change state, and print help info.
170  switch(temp_key_value)
171  {
174  printStatus();
175  return;
179  {
181  }
182  else
183  {
185  }
186 
187  printStatus();
188  return;
189  case KEYCODE_HELP:
190  printHelpText();
191  // No return so the key will be passed (processKeyboardInputFunc_) for additional help text.
192  }
193 
194  // commands for configurator with disabled auto capturing
196  {
197  switch(temp_key_value)
198  {
199  case KEYCODE_RESET:
200  ISM::printRed("\tRESET\n");
202  break;
203  case KEYCODE_ADD:
204  ISM::printBlue("\tADD\n");
206  break;
207  case KEYCODE_REMOVE:
208  ISM::printBlue("\tREMOVE\n");
210  break;
212  ISM::printGreen("\tPROCESS_CONFIGURATION!\n");
214  break;
215  case KEYCODE_SHOW:
216  ISM::printBlue("\tSHOW_CONFIGURATION\n");
218  break;
219  case KEYCODE_UPDATE_VIEW:
220  ISM::printBlue("\tUPDATE_VIEW\n");
223  break;
224  default:
226  {
227  processKeyboardInputFunc_(temp_key_value);
228  }
229  break;
230  }
231  }
232 
233  return;
234 }
235 
236 void SceneConfigurator::objectInputCallback(const asr_msgs::AsrObject &object)
237 {
238  ROS_DEBUG_STREAM("Received object message. THREAD-ID: " << boost::this_thread::get_id());
239 
240  //Do not capture and transform objects while CAMERA is moving around.
241  if (isCameraInMotion())
242  {
243  ROS_DEBUG("Rejected object message and clean estimations since camera is currently moving ");
244 
247  return;
248  }
249 
250  try
251  {
252  ISM::ObjectPtr obj = object_msg_converter_->pbdObjectToISMObject(object);
253 
254  data_->addEstimation(obj);
255 
257  {
259  }
260  }
261  catch (tf::TransformException& e)
262  {
263  ROS_ERROR_STREAM(e.what());
264  }
265 }
266 
268 {
269  bool isInMotion;
270 
271  // is PTU moving?
272  bool stopped = false;
273  bool retrieved = ptu_->getParam("reached_desired_position", stopped);
274  isInMotion = !stopped && retrieved;
275 
276  return isInMotion;
277 }
278 
280 {
282  if (set->objects.empty())
283  {
284  ISM::printRed("Configuration is empty!\n");
285  }
286  else
287  {
288  //Normalize rotation invarince objects, e.g. Cup, PlateDeep
289  object_msg_converter_->normalizeRotationInvariantObjects(set);
290 
292  }
293 }
294 
296 {
298  ISM::printGreen("\tAUTO_PROCESS_CONFIGURATION!\n");
300 
301  // reset values to use only use objects that are still there
305 }
306 
308 {
310  ISM::printGreen("Marked and in view:\n");
311  for (const ObjectEstimationPtr est : estimations)
312  {
313  if (est->marked && est->in_view)
314  {
315  std::cout << "\t" << est->object->type << " " << est->object->observedId << std::endl;
316  }
317  }
318  ISM::printBlue("Marked and out of view:\n");
319  for (const ObjectEstimationPtr est : estimations)
320  {
321  if (est->marked && !est->in_view)
322  {
323  std::cout << "\t" << est->object->type << " " << est->object->observedId << std::endl;
324  }
325  }
326  ISM::printYellow("Not marked:\n");
327  for (const ObjectEstimationPtr est : estimations)
328  {
329  if (!est->marked)
330  {
331  std::cout << "\t" << est->object->type << " " << est->object->observedId << std::endl;
332  }
333  }
334  std::cout << std::endl;
335 }
336 
338 {
339  std::stringstream commands;
341  {
342  commands << "Commands for Auto Processing:\n"
343  << "\tpress \"m\"\tchange PROCESSING_MODE\n"
344  << "\tpress \"space\"\tswitch to Manual Processing\n\n"
345  << "\tpress \"h\"\tshow INFO and COMMAND description\n"
346  << "\tpress \"^C\"\tquit node\n";
347  }
348  else
349  {
350  commands << "Commands for Manual Processing:\n"
351  << "\tpress \"m\"\t-change PROCESSING_MODE\n"
352  << "\tpress \"space\"\t-switch to Auto Processing\n\n"
353  << "\tpress \"enter\"\t-process object configuration\n"
354  << "\tpress \"delete\\\t-reset all objects\n\t backspace\"\n\n"
355  << "\tpress \"a\"\t-add objects from current view to marked objects\n"
356  << "\tpress \"d\"\t-remove objects in the current view from marked objects\n"
357  << "\tpress \"u\"\t-update view to get rid of old estimations\n\n"
358  << "\tpress \"s\"\t-show object configuration\n\n"
359  << "\tpress \"h\"\t-show INFO and COMMAND description\n"
360  << "\tpress \"^C\"\t-quit node\n";
361  }
362 
363  printStatus();
364  ISM::printYellow(commands.str() + "\n");
365 
366  return;
367 }
368 
370 {
371  std::stringstream status, info;
372 
373  info << "rviz color legend: ";
374 
376  {
377  status << "STATUS: Auto Processing";
378  }
379  else
380  {
381  status << "STATUS: Manual Processing";
382  }
383 
384  status << "\t\tPROCESSING_MODE: ";
385 
387  {
388  status << "Only Marked Objects\n";
389 
390  info << "\033[32;1m" << "marked and in current view (green), "
391  << "\033[36m" << "marked but not in current view (blue)."
392  << "\033[0m" << "\n";
393  }
394  else
395  {
396  status << "All Objects\n";
397 
398  info << "\033[32;1m" << "marked and in current view (green), "
399  << "\033[36m" << "marked but not in current view (blue), "
400  << "\033[33m" << "not marked but in the current view (yellow)."
401  << "\033[0m" << "\n";
402  }
403 
404  ISM::printGreen(status.str());
405  std::cout << "\n" << info.str() << "\n";
406 
407  return;
408 }
409 
411 {
413  {
414  ROS_DEBUG("Publish marker");
415 
417 
418  std::vector<ISM::ObjectPtr> objects;
419  std::map<ISM::ObjectPtr, double> objects_to_hue_map;
420 
421  for (const ObjectEstimationPtr est : estimations)
422  {
423  double hueTemp;
424  bool visualize = false;
425  if (est->marked)
426  {
427  hueTemp = est->in_view ? 120.0 : 180.0;
428  visualize = true;
429  }
430  else if (!use_only_marked_objects_ && est->in_view)
431  {
432  hueTemp = 60.0;
433  visualize = true;
434  }
435 
436  if (visualize)
437  {
438  objects.push_back(est->object);
439  objects_to_hue_map.insert(std::make_pair(est->object, hueTemp));
440  }
441  }
442  object_model_visualizer_->clearAllMarkerOfTopic();
443  object_model_visualizer_->drawObjectModels(objects, objects_to_hue_map);
444  }
445  else
446  {
447  ROS_DEBUG("No subscriber exist for the visualization.\n");
448  }
449 }
450 
451 void SceneConfigurator::getNodeParameters(std::string& object_topic, int& queue_size, int& object_input_thread_count, std::string& base_frame, bool& ignore_types, bool& ignore_ids, bool& use_confidence_from_msg,
452  int& enable_rotation_mode, std::string& rotation_frame, std::string& rotation_object_type, std::string& rotation_object_id,
453  bool& enable_neighborhood_evaluation, double& neighbour_angle_threshold, double& neighbour_distance_threshold,
454  int& keyboard_poll_rate, double& automatic_processing_interval, std::string& input_visualization_topic)
455 {
456  // NodeHandle with the parent namespace (e.g. parent = recorder or recognizer), because the parameters are prefixed with this namespace.
458 
459  if (!nh.getParam("objectTopic", object_topic))
460  {
461  object_topic = "/objects";
462  }
463  ROS_INFO_STREAM("objectTopic: " << object_topic);
464 
465  if (!nh.getParam("queueSizePbdObjectCallback", queue_size))
466  {
467  queue_size = 100;
468  }
469  ROS_INFO_STREAM("queueSizePbdObjectCallback: " << queue_size);
470 
471  if (!nh.getParam("object_input_thread_count", object_input_thread_count))
472  {
473  object_input_thread_count = 1;
474  }
475  ROS_INFO_STREAM("object_input_thread_count: " << object_input_thread_count);
476 
477  if (!nh.getParam("baseFrame", base_frame))
478  {
479  base_frame = "/map";
480  }
481  ROS_INFO_STREAM("baseFrame: " << base_frame);
482 
483  if (!nh.getParam("use_confidence_from_msg", use_confidence_from_msg))
484  {
485  use_confidence_from_msg = false;
486  }
487  ROS_INFO_STREAM("use_confidence_from_msg: " << use_confidence_from_msg);
488 
489  if (!nh.getParam("enableRotationMode", enable_rotation_mode))
490  {
491  enable_rotation_mode = 0;
492  }
493  ROS_INFO_STREAM("enableRotationMode: " << enable_rotation_mode);
494 
495  if (!nh.getParam("rotationFrame", rotation_frame))
496  {
497  rotation_frame = "/map";
498  }
499  ROS_INFO_STREAM("rotationFrame: " << rotation_frame);
500 
501  if (!nh.getParam("rotationObjectType", rotation_object_type))
502  {
503  rotation_object_type = "";
504  }
505  ROS_INFO_STREAM("rotationObjectType: " << rotation_object_type);
506 
507  if (!nh.getParam("rotationObjectId", rotation_object_id))
508  {
509  rotation_object_id = "";
510  }
511  ROS_INFO_STREAM("rotationObjectId: " << rotation_object_id);
512 
513  if (!nh.getParam("enableNeighborhoodEvaluation", enable_neighborhood_evaluation))
514  {
515  enable_neighborhood_evaluation = false;
516  }
517  ROS_INFO_STREAM("enableNeighborhoodEvaluation: " << enable_neighborhood_evaluation);
518 
519  if (!nh.getParam("angleNeighbourThreshold", neighbour_angle_threshold))
520  {
521  neighbour_angle_threshold = 30;
522  }
523  ROS_INFO_STREAM("angleNeighbourThreshold: " << neighbour_angle_threshold);
524 
525  if (!nh.getParam("distanceNeighbourThreshold", neighbour_distance_threshold))
526  {
527  neighbour_distance_threshold = 0.05;
528  }
529  ROS_INFO_STREAM("distanceNeighbourThreshold: " << neighbour_distance_threshold);
530 
531  if (!nh.getParam("keyboard_poll_rate", keyboard_poll_rate))
532  {
533  keyboard_poll_rate = 10;
534  }
535  ROS_INFO_STREAM("keyboard_poll_rate: " << keyboard_poll_rate);
536 
537  if (!nh.getParam("capture_interval", automatic_processing_interval))
538  {
539  automatic_processing_interval = 1;
540  }
541  ROS_INFO_STREAM("captureInterval: " << automatic_processing_interval);
542 
543  if (!nh.getParam("input_objects_visualization_topic", input_visualization_topic))
544  {
545  input_visualization_topic = "input_objects_scene_configurator_viz";
546  }
547  ROS_INFO_STREAM("input_objects_visualization_topic: " << input_visualization_topic);
548 
549  if (!nh.getParam("ignoreTypes", ignore_types))
550  {
551  ignore_types = false;
552  }
553  ROS_INFO_STREAM("ignoreTypes: " << ignore_types);
554 
555  if (!nh.getParam("ignoreIds", ignore_ids))
556  {
557  ignore_ids = false;
558  }
559  ROS_INFO_STREAM("ignoreIds: " << ignore_ids);
560 }
ISM::ObjectSetPtr getObjectSetFromAllEstimations()
ProcessKeyboardInputFunction processKeyboardInputFunc_
SceneConfigurator(ProcessConfigurationFunction processConfigFunc, ProcessKeyboardInputFunction processKeyboardInputFunc=ProcessKeyboardInputFunction(), ProcessObjectInputFunction processObjectInputFunc=ProcessObjectInputFunction())
void objectInputCallback(const asr_msgs::AsrObject &object)
void keyboardInputMain(const unsigned int poll_rate)
boost::function< void(ISM::ObjectSetPtr)> ProcessConfigurationFunction
void updateVisualizationCallback(const ros::TimerEvent &e)
boost::function< void(int)> ProcessKeyboardInputFunction
#define KEYCODE_REMOVE
void automaticProcessingCallback(const ros::TimerEvent &e)
boost::shared_ptr< ObjectConverter > ObjectConverterPtr
Definition: ism_helper.hpp:133
Subscriber subscribe(const std::string &topic, uint32_t queue_size, void(T::*fp)(M), T *obj, const TransportHints &transport_hints=TransportHints())
#define KEYCODE_AUTOMATIC_PROCESSING
void stop()
ros::CallbackQueue object_queue_
void start()
#define KEYCODE_ADD
ROSCPP_DECL const std::string & getName()
boost::function< void(ISM::ObjectPtr)> ProcessObjectInputFunction
boost::shared_ptr< NodeHandle > NodeHandlePtr
void getNodeParameters(std::string &object_topic, int &queue_size, int &object_input_thread_count, std::string &base_frame, bool &ignore_types, bool &ignore_ids, bool &use_confidence_from_msg, int &enable_rotation_mode, std::string &rotation_frame, std::string &rotation_object_type, std::string &rotation_object_id, bool &enable_neighborhood_evaluation, double &neighbour_angle_threshold, double &neighbour_distance_threshold, int &keyboard_poll_rate, double &automatic_processing_interval, std::string &visualization_topic)
ProcessObjectInputFunction processObjectInputFunc_
void addEstimation(ISM::ObjectPtr object)
ros::AsyncSpinner * spinner_
ros::Timer visualization_timer_
#define KEYCODE_PROCESS_ONLY_MARKED
ROSCPP_DECL void set(const std::string &key, const XmlRpc::XmlRpcValue &v)
boost::thread * keyboard_thread_
void setCallbackQueue(CallbackQueueInterface *queue)
ros::Publisher visualization_publisher_
ROSCPP_DECL bool ok()
Timer createTimer(Rate r, Handler h, Obj o, bool oneshot=false, bool autostart=true) const
Publisher advertise(const std::string &topic, uint32_t queue_size, bool latch=false)
#define ROS_DEBUG_STREAM(args)
#define KEYCODE_SHOW
VIZ::ObjectModelVisualizerRVIZ * object_model_visualizer_
bool sleep()
ISM::ObjectSetPtr getObjectSetFromMarkedEstimations()
std::vector< ObjectEstimationPtr > ObjectEstimationPtrs
uint32_t getNumSubscribers() const
#define ROS_INFO_STREAM(args)
IH::ObjectConverterPtr object_msg_converter_
bool getParam(const std::string &key, std::string &s) const
#define KEYCODE_PROCESS_CONFIGURATION
#define KEYCODE_UPDATE_VIEW
ros::Subscriber object_input_subscriber_
ProcessConfigurationFunction processConfigurationFunc_
ros::Timer automatic_processing_timer_
#define ROS_ERROR_STREAM(args)
#define KEYCODE_RESET
SceneConfiguratorData * data_
#define KEYCODE_HELP
ros::NodeHandlePtr ptu_
void setMarkedForAllEstimationsInView(bool marked)
ObjectEstimationPtrs getAllEstimations()
#define ROS_DEBUG(...)


asr_ism
Author(s): Borella Jocelyn, Hanselmann Fabian, Heller Florian, Heizmann Heinrich, Kübler Marcel, Mehlhaus Jonas, Meißner Pascal, Qattan Mohamad, Reckling Reno, Stroh Daniel
autogenerated on Thu Jan 9 2020 07:20:58