YARP
Yet Another Robot Platform
FrameTransformServer.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2006-2020 Istituto Italiano di Tecnologia (IIT)
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17  */
18 
19 // example: yarpdev --device transformServer --ROS::enable_ros_publisher 0 --ROS::enable_ros_subscriber 0
20 
21 #include "FrameTransformServer.h"
22 #include <sstream>
23 #include <limits>
25 #include <yarp/os/Log.h>
26 #include <yarp/os/LogComponent.h>
27 #include <yarp/os/LogStream.h>
28 #include <mutex>
29 #include <cstdlib>
30 
31 using namespace yarp::sig;
32 using namespace yarp::math;
33 using namespace yarp::dev;
34 using namespace yarp::os;
35 using namespace std;
36 
37 
38 namespace {
39 YARP_LOG_COMPONENT(FRAMETRANSFORMSERVER, "yarp.device.transformServer")
40 }
41 
42 
48 {
49  std::lock_guard<std::mutex> lock(m_mutex);
50  if (id >= 0 && (size_t)id < m_transforms.size())
51  {
52  m_transforms.erase(m_transforms.begin() + id);
53  return true;
54  }
55  return false;
56 }
57 
59 {
60  std::lock_guard<std::mutex> lock(m_mutex);
61  for (auto& m_transform : m_transforms)
62  {
63  //@@@ this linear search requires optimization!
64  if (m_transform.dst_frame_id == t.dst_frame_id && m_transform.src_frame_id == t.src_frame_id)
65  {
66  //transform already exists, update it
67  m_transform=t;
68  return true;
69  }
70  }
71 
72  //add a new transform
73  m_transforms.push_back(t);
74  return true;
75 }
76 
78 {
79  std::lock_guard<std::mutex> lock(m_mutex);
80  if (t1=="*" && t2=="*")
81  {
82  m_transforms.clear();
83  return true;
84  }
85  else
86  if (t1=="*")
87  {
88  for (size_t i = 0; i < m_transforms.size(); )
89  {
90  //source frame is jolly, thus delete all frames with destination == t2
91  if (m_transforms[i].dst_frame_id == t2)
92  {
93  m_transforms.erase(m_transforms.begin() + i);
94  i=0; //the erase operation invalidates the iteration, loop restart is required
95  }
96  else
97  {
98  i++;
99  }
100  }
101  return true;
102  }
103  else
104  if (t2=="*")
105  {
106  for (size_t i = 0; i < m_transforms.size(); )
107  {
108  //destination frame is jolly, thus delete all frames with source == t1
109  if (m_transforms[i].src_frame_id == t1)
110  {
111  m_transforms.erase(m_transforms.begin() + i);
112  i=0; //the erase operation invalidates the iteration, loop restart is required
113  }
114  else
115  {
116  i++;
117  }
118  }
119  return true;
120  }
121  else
122  {
123  for (size_t i = 0; i < m_transforms.size(); i++)
124  {
125  if ((m_transforms[i].dst_frame_id == t1 && m_transforms[i].src_frame_id == t2) ||
126  (m_transforms[i].dst_frame_id == t2 && m_transforms[i].src_frame_id == t1) )
127  {
128  m_transforms.erase(m_transforms.begin() + i);
129  return true;
130  }
131  }
132  }
133  return false;
134 }
135 
137 {
138  std::lock_guard<std::mutex> lock(m_mutex);
139  m_transforms.clear();
140 }
141 
147 {
148  m_period = DEFAULT_THREAD_PERIOD;
149  m_enable_publish_ros_tf = false;
150  m_enable_subscribe_ros_tf = false;
151  m_yarp_static_transform_storage = nullptr;
152  m_yarp_timed_transform_storage = nullptr;
153  m_ros_static_transform_storage = nullptr;
154  m_ros_timed_transform_storage = nullptr;
155  m_rosNode = nullptr;
156  m_FrameTransformTimeout = 0.200; //ms
157 }
158 
160 {
161  threadRelease();
162  if (m_yarp_static_transform_storage)
163  {
164  delete m_yarp_static_transform_storage;
165  m_yarp_static_transform_storage = nullptr;
166  }
167  if (m_yarp_timed_transform_storage)
168  {
169  delete m_yarp_timed_transform_storage;
170  m_yarp_timed_transform_storage = nullptr;
171  }
172  if (m_ros_timed_transform_storage)
173  {
174  delete m_ros_timed_transform_storage;
175  m_ros_timed_transform_storage = nullptr;
176  }
177  if (m_ros_static_transform_storage)
178  {
179  delete m_ros_static_transform_storage;
180  m_ros_static_transform_storage = nullptr;
181  }
182 }
183 
184 void FrameTransformServer::list_response(yarp::os::Bottle& out)
185 {
186  std::vector<Transforms_server_storage*> storages;
187  std::vector<string> storageDescription;
188  storages.push_back(m_ros_timed_transform_storage);
189  storageDescription.emplace_back("ros timed transforms");
190 
191  storages.push_back(m_ros_static_transform_storage);
192  storageDescription.emplace_back("ros static transforms");
193 
194  storages.push_back(m_yarp_timed_transform_storage);
195  storageDescription.emplace_back("yarp timed transforms");
196 
197  storages.push_back(m_yarp_static_transform_storage);
198  storageDescription.emplace_back("yarp static transforms");
199 
200  if (storages[0]->size() == 0 &&
201  storages[1]->size() == 0 &&
202  storages[2]->size() == 0 &&
203  storages[3]->size() == 0)
204  {
205  out.addString("no transforms found");
206  return;
207  }
208 
209  for(size_t s = 0; s < storages.size(); s++ )
210  {
211  if(!storages[s])
212  {
213  continue;
214  }
215 
216  std::string text_to_print = storageDescription[s] + std::string("(") +std::to_string(storages[s]->size())+ std::string("): ");
217  out.addString(text_to_print);
218 
219  for(size_t i = 0; i < storages[s]->size(); i++)
220  {
221  out.addString((*storages[s])[i].toString());
222  }
223 
224  }
225 }
226 
227 bool FrameTransformServer::read(yarp::os::ConnectionReader& connection)
228 {
229  std::lock_guard<std::mutex> lock(m_mutex);
230  yarp::os::Bottle in;
231  yarp::os::Bottle out;
232  bool ok = in.read(connection);
233  if (!ok) return false;
234 
235  string request = in.get(0).asString();
236 
237  // parse in, prepare out
238  int code = in.get(0).asVocab();
239  bool ret = false;
240  if (code == VOCAB_ITRANSFORM)
241  {
242  int cmd = in.get(1).asVocab();
243  if (cmd == VOCAB_TRANSFORM_SET)
244  {
245  if (in.size() != 12)
246  {
247  yCError(FRAMETRANSFORMSERVER) << "read(): Protocol error";
248  out.clear();
249  out.addVocab(VOCAB_FAILED);
250  }
251  else
252  {
254  t.src_frame_id = in.get(2).asString();
255  t.dst_frame_id = in.get(3).asString();
256  double duration = in.get(4).asFloat64();
257  t.translation.tX = in.get(5).asFloat64();
258  t.translation.tY = in.get(6).asFloat64();
259  t.translation.tZ = in.get(7).asFloat64();
260  t.rotation.w() = in.get(8).asFloat64();
261  t.rotation.x() = in.get(9).asFloat64();
262  t.rotation.y() = in.get(10).asFloat64();
263  t.rotation.z() = in.get(11).asFloat64();
264  t.timestamp = yarp::os::Time::now();
265 
266  if (duration > 0)
267  {
268  ret = m_yarp_timed_transform_storage->set_transform(t);
269  }
270  else
271  {
272  ret = m_yarp_static_transform_storage->set_transform(t);
273  }
274 
275  if (ret == true)
276  {
277  out.clear();
278  out.addVocab(VOCAB_OK);
279  }
280  else
281  {
282  out.clear();
283  out.addVocab(VOCAB_FAILED);
284  yCError(FRAMETRANSFORMSERVER) << "read(): Something strange happened";
285  }
286  }
287  }
288  else if (cmd == VOCAB_TRANSFORM_DELETE_ALL)
289  {
290  m_yarp_timed_transform_storage->clear();
291  m_yarp_static_transform_storage->clear();
292  m_ros_timed_transform_storage->clear();
293  m_ros_static_transform_storage->clear();
294  out.clear();
295  out.addVocab(VOCAB_OK);
296  }
297  else if (cmd == VOCAB_TRANSFORM_DELETE)
298  {
299  string frame1 = in.get(2).asString();
300  string frame2 = in.get(3).asString();
301  bool ret1 = m_yarp_timed_transform_storage->delete_transform(frame1, frame2);
302  if (ret1 == true)
303  {
304  out.clear();
305  out.addVocab(VOCAB_OK);
306  }
307  else
308  {
309  bool ret2 = m_yarp_static_transform_storage->delete_transform(frame1, frame2);
310  if (ret2 == true)
311  {
312  out.clear();
313  out.addVocab(VOCAB_OK);
314  }
315  }
316 
317  }
318  else
319  {
320  yCError(FRAMETRANSFORMSERVER, "Invalid vocab received");
321  out.clear();
322  out.addVocab(VOCAB_ERR);
323  }
324  }
325  else if(request == "help")
326  {
327  out.addVocab(Vocab::encode("many"));
328  out.addString("'list': get all transforms stored");
329  out.addString("'delete_all': delete all transforms");
330  out.addString("'set_static_transform <src> <dst> <x> <y> <z> <roll> <pitch> <yaw>': create a static transform");
331  out.addString("'delete_static_transform <src> <dst>': delete a static transform");
332  }
333  else if (request == "set_static_transform")
334  {
336  t.src_frame_id = in.get(1).asString();
337  t.dst_frame_id = in.get(2).asString();
338  t.translation.tX = in.get(3).asFloat64();
339  t.translation.tY = in.get(4).asFloat64();
340  t.translation.tZ = in.get(5).asFloat64();
341  t.rotFromRPY(in.get(6).asFloat64(), in.get(7).asFloat64(), in.get(8).asFloat64());
342  t.timestamp = yarp::os::Time::now();
343  ret = m_yarp_static_transform_storage->set_transform(t);
344  if (ret == true)
345  {
346  yCInfo(FRAMETRANSFORMSERVER) << "set_static_transform done";
347  out.addString("set_static_transform done");
348  }
349  else
350  {
351  yCError(FRAMETRANSFORMSERVER) << "read(): something strange happened";
352  }
353  }
354  else if(request == "delete_all")
355  {
356  m_yarp_timed_transform_storage->clear();
357  m_yarp_static_transform_storage->clear();
358  m_ros_timed_transform_storage->clear();
359  m_ros_static_transform_storage->clear();
360  yCInfo(FRAMETRANSFORMSERVER) << "delete_all done";
361  out.addString("delete_all done");
362  }
363  else if (request == "list")
364  {
365  out.addVocab(Vocab::encode("many"));
366  list_response(out);
367  }
368  else if (request == "delete_static_transform")
369  {
370  std::string src = in.get(1).asString();
371  std::string dst = in.get(2).asString();
372  m_yarp_static_transform_storage->delete_transform(src,dst);
373  m_ros_static_transform_storage->delete_transform(src,dst);
374  out.addString("delete_static_transform done");
375  }
376  else
377  {
378  yCError(FRAMETRANSFORMSERVER, "Invalid vocab received");
379  out.clear();
380  out.addVocab(VOCAB_ERR);
381  }
382 
383  yarp::os::ConnectionWriter *returnToSender = connection.getWriter();
384  if (returnToSender != nullptr)
385  {
386  out.write(*returnToSender);
387  }
388  else
389  {
390  yCError(FRAMETRANSFORMSERVER) << "Invalid return to sender";
391  }
392  return true;
393 }
394 
396 {
397  //open rpc port
398  if (!m_rpcPort.open(m_rpcPortName))
399  {
400  yCError(FRAMETRANSFORMSERVER, "Failed to open port %s", m_rpcPortName.c_str());
401  return false;
402  }
403  m_rpcPort.setReader(*this);
404 
405  // open data port
406  if (!m_streamingPort.open(m_streamingPortName))
407  {
408  yCError(FRAMETRANSFORMSERVER, "Failed to open port %s", m_streamingPortName.c_str());
409  return false;
410  }
411 
412  //open ros publisher (if requested)
413  if (m_enable_publish_ros_tf)
414  {
415  if (m_rosNode == nullptr)
416  {
417  m_rosNode = new yarp::os::Node(ROSNODENAME);
418  }
419  if (!m_rosPublisherPort_tf_timed.topic(ROSTOPICNAME_TF))
420  {
421  yCError(FRAMETRANSFORMSERVER) << "Unable to publish data on " << ROSTOPICNAME_TF << " topic, check your yarp-ROS network configuration";
422  return false;
423  }
424  if (!m_rosPublisherPort_tf_static.topic(ROSTOPICNAME_TF_STATIC))
425  {
426  yCError(FRAMETRANSFORMSERVER) << "Unable to publish data on " << ROSTOPICNAME_TF_STATIC << " topic, check your yarp-ROS network configuration";
427  return false;
428  }
429  }
430 
431  //open ros subscriber(if requested)
432  if (m_enable_subscribe_ros_tf)
433  {
434  if (m_rosNode == nullptr)
435  {
436  m_rosNode = new yarp::os::Node(ROSNODENAME);
437  }
438  if (!m_rosSubscriberPort_tf_timed.topic(ROSTOPICNAME_TF))
439  {
440  yCError(FRAMETRANSFORMSERVER) << "Unable to subscribe to " << ROSTOPICNAME_TF << " topic, check your yarp-ROS network configuration";
441  return false;
442  }
443  m_rosSubscriberPort_tf_timed.setStrict();
444  if (!m_rosSubscriberPort_tf_static.topic(ROSTOPICNAME_TF_STATIC))
445  {
446  yCError(FRAMETRANSFORMSERVER) << "Unable to subscribe to " << ROSTOPICNAME_TF_STATIC << " topic, check your yarp-ROS network configuration";
447  return false;
448  }
449  m_rosSubscriberPort_tf_static.setStrict();
450  }
451 
452  m_yarp_static_transform_storage = new Transforms_server_storage();
453  m_yarp_timed_transform_storage = new Transforms_server_storage();
454 
455  m_ros_static_transform_storage = new Transforms_server_storage();
456  m_ros_timed_transform_storage = new Transforms_server_storage();
457 
458  yCInfo(FRAMETRANSFORMSERVER) << "Transform server started";
459  return true;
460 }
461 
462 bool FrameTransformServer::parseStartingTf(yarp::os::Searchable &config)
463 {
464 
465  if (config.check("USER_TF"))
466  {
467  Bottle all_transforms_group = config.findGroup("USER_TF").tail();
468  yCDebug(FRAMETRANSFORMSERVER) << all_transforms_group.toString();
469 
470  for (size_t i = 0; i < all_transforms_group.size(); i++)
471  {
473 
474  Bottle* b = all_transforms_group.get(i).asList();
475  if(!b)
476  {
477  yCError(FRAMETRANSFORMSERVER) << "No entries in USER_TF group";
478  return false;
479  }
480 
481  if(b->size() == 18)
482  {
483  bool r(true);
484  Matrix m(4, 4);
485 
486  for(int i = 0; i < 16; i++)
487  {
488  if(!b->get(i).isFloat64())
489  {
490  yCError(FRAMETRANSFORMSERVER) << "transformServer: element " << i << " is not a double.";
491  r = false;
492  }
493  else
494  {
495  m.data()[i] = b->get(i).asFloat64();
496  }
497  }
498 
499  if(!b->get(16).isString() || !b->get(17).isString())
500  {
501  r = false;
502  }
503 
504  if(!r)
505  {
506  yCError(FRAMETRANSFORMSERVER) << "transformServer: param not correct.. for the 4x4 matrix mode" <<
507  "you must provide 18 parameter. the matrix, the source frame(string) and the destination frame(string)";
508  return false;
509  }
510 
511  t.fromMatrix(m);
512  t.src_frame_id = b->get(16).asString();
513  t.dst_frame_id = b->get(17).asString();
514  }
515  else if( b->size() == 8 &&
516  b->get(0).isFloat64() &&
517  b->get(1).isFloat64() &&
518  b->get(2).isFloat64() &&
519  b->get(3).isFloat64() &&
520  b->get(4).isFloat64() &&
521  b->get(5).isFloat64() &&
522  b->get(6).isString() &&
523  b->get(7).isString())
524  {
525  t.translation.set(b->get(0).asFloat64(), b->get(1).asFloat64(), b->get(2).asFloat64());
526  t.rotFromRPY(b->get(3).asFloat64(), b->get(4).asFloat64(), b->get(5).asFloat64());
527  t.src_frame_id = b->get(6).asString();
528  t.dst_frame_id = b->get(7).asString();
529  }
530  else
531  {
532  yCError(FRAMETRANSFORMSERVER) << "transformServer: param not correct.. a tf requires 8 param in the format:" <<
533  "x(dbl) y(dbl) z(dbl) r(dbl) p(dbl) y(dbl) src(str) dst(str)";
534  return false;
535  }
536 
537  if(m_yarp_static_transform_storage->set_transform(t))
538  {
539  yCInfo(FRAMETRANSFORMSERVER) << "Transform from" << t.src_frame_id << "to" << t.dst_frame_id << "successfully set";
540  }
541  else
542  {
543  yCInfo(FRAMETRANSFORMSERVER) << "Unbale to set transform from " << t.src_frame_id << "to" << t.dst_frame_id;
544  }
545  }
546  return true;
547  }
548  else
549  {
550  yCInfo(FRAMETRANSFORMSERVER) << "No starting tf found";
551  }
552  return true;
553 }
554 
556 {
557  Property params;
558  params.fromString(config.toString());
559 
560  if (!config.check("period"))
561  {
562  m_period = 0.01;
563  }
564  else
565  {
566  m_period = config.find("period").asInt32() / 1000.0;
567  yCInfo(FRAMETRANSFORMSERVER) << "Thread period set to:" << m_period;
568  }
569 
570  if (config.check("transforms_lifetime"))
571  {
572  m_FrameTransformTimeout = config.find("transforms_lifetime").asFloat64();
573  yCInfo(FRAMETRANSFORMSERVER) << "transforms_lifetime set to:" << m_FrameTransformTimeout;
574  }
575 
576  std::string name;
577  if (!config.check("name"))
578  {
579  name = "transformServer";
580  }
581  else
582  {
583  name = config.find("name").asString();
584  }
585  m_streamingPortName = "/"+ name + "/transforms:o";
586  m_rpcPortName = "/" + name + "/rpc";
587 
588  //ROS configuration
589  if (!config.check("ROS"))
590  {
591  yCError(FRAMETRANSFORMSERVER) << "Missing ROS group";
592  return false;
593  }
594  Bottle ROS_config = config.findGroup("ROS");
595  if (ROS_config.check("enable_ros_publisher") == false)
596  {
597  yCError(FRAMETRANSFORMSERVER) << "Missing 'enable_ros_publisher' in ROS group";
598  return false;
599  }
600  if (ROS_config.find("enable_ros_publisher").asInt32() == 1 || ROS_config.find("enable_ros_publisher").asString() == "true")
601  {
602  m_enable_publish_ros_tf = true;
603  yCInfo(FRAMETRANSFORMSERVER) << "Enabled ROS publisher";
604  }
605  if (ROS_config.check("enable_ros_subscriber") == false)
606  {
607  yCError(FRAMETRANSFORMSERVER) << "Missing 'enable_ros_subscriber' in ROS group";
608  return false;
609  }
610  if (ROS_config.find("enable_ros_subscriber").asInt32() == 1 || ROS_config.find("enable_ros_subscriber").asString() == "true")
611  {
612  m_enable_subscribe_ros_tf = true;
613  yCInfo(FRAMETRANSFORMSERVER) << "Enabled ROS subscriber";
614  }
615 
616  this->start();
617 
619  parseStartingTf(config);
620 
621  return true;
622 }
623 
625 {
626  m_streamingPort.interrupt();
627  m_streamingPort.close();
628  m_rpcPort.interrupt();
629  m_rpcPort.close();
630  if (m_enable_publish_ros_tf)
631  {
632  m_rosPublisherPort_tf_timed.interrupt();
633  m_rosPublisherPort_tf_timed.close();
634  }
635  if (m_enable_subscribe_ros_tf)
636  {
637  m_rosSubscriberPort_tf_timed.interrupt();
638  m_rosSubscriberPort_tf_timed.close();
639  }
640  if (m_enable_publish_ros_tf)
641  {
642  m_rosPublisherPort_tf_static.interrupt();
643  m_rosPublisherPort_tf_static.close();
644  }
645  if (m_enable_subscribe_ros_tf)
646  {
647  m_rosSubscriberPort_tf_static.interrupt();
648  m_rosSubscriberPort_tf_static.close();
649  }
650  if (m_rosNode)
651  {
652  m_rosNode->interrupt();
653  delete m_rosNode;
654  m_rosNode = nullptr;
655  }
656 }
657 
659 {
660  std::lock_guard<std::mutex> lock(m_mutex);
661  if (true)
662  {
663  double current_time = yarp::os::Time::now();
664 
665  //timeout check for yarp timed transforms.
666  bool repeat_check;
667  do
668  {
669  repeat_check = false;
670  size_t tfVecSize_timed_yarp = m_yarp_timed_transform_storage->size();
671  for (size_t i = 0; i < tfVecSize_timed_yarp; i++)
672  {
673  if (current_time - (*m_yarp_timed_transform_storage)[i].timestamp > m_FrameTransformTimeout)
674  {
675  m_yarp_timed_transform_storage->delete_transform(i);
676  repeat_check = true;
677  break;
678  }
679  }
680  }
681  while (repeat_check);
682 
683  //timeout check for ROS timed transforms.
684  do
685  {
686  repeat_check = false;
687  size_t tfVecSize_timed_ros = m_ros_timed_transform_storage->size();
688  for (size_t i = 0; i < tfVecSize_timed_ros; i++)
689  {
690  if (current_time - (*m_ros_timed_transform_storage)[i].timestamp > m_FrameTransformTimeout)
691  {
692  m_ros_timed_transform_storage->delete_transform(i);
693  repeat_check = true;
694  break;
695  }
696  }
697  } while (repeat_check);
698 
699  //ros subscriber
700  if (m_enable_subscribe_ros_tf)
701  {
702  yarp::rosmsg::tf2_msgs::TFMessage* rosInData_timed = nullptr;
703  do
704  {
705  rosInData_timed = m_rosSubscriberPort_tf_timed.read(false);
706  if (rosInData_timed != nullptr)
707  {
708  std::vector <yarp::rosmsg::geometry_msgs::TransformStamped> tfs = rosInData_timed->transforms;
709  size_t tfs_size = tfs.size();
710  for (size_t i = 0; i < tfs_size; i++)
711  {
713  t.translation.tX = tfs[i].transform.translation.x;
714  t.translation.tY = tfs[i].transform.translation.y;
715  t.translation.tZ = tfs[i].transform.translation.z;
716  t.rotation.x() = tfs[i].transform.rotation.x;
717  t.rotation.y() = tfs[i].transform.rotation.y;
718  t.rotation.z() = tfs[i].transform.rotation.z;
719  t.rotation.w() = tfs[i].transform.rotation.w;
720  t.src_frame_id = tfs[i].header.frame_id;
721  t.dst_frame_id = tfs[i].child_frame_id;
722  //@@@ should we use yarp or ROS timestamps?
723  t.timestamp = yarp::os::Time::now();
724  //t.timestamp = tfs[i].header.stamp.sec; //@@@this needs some revising
725  (*m_ros_timed_transform_storage).set_transform(t);
726  }
727  }
728  } while (rosInData_timed != nullptr);
729 
730  yarp::rosmsg::tf2_msgs::TFMessage* rosInData_static = nullptr;
731  do
732  {
733  rosInData_static = m_rosSubscriberPort_tf_static.read(false);
734  if (rosInData_static != nullptr)
735  {
736  std::vector <yarp::rosmsg::geometry_msgs::TransformStamped> tfs = rosInData_static->transforms;
737  size_t tfs_size = tfs.size();
738  for (size_t i = 0; i < tfs_size; i++)
739  {
741  t.translation.tX = tfs[i].transform.translation.x;
742  t.translation.tY = tfs[i].transform.translation.y;
743  t.translation.tZ = tfs[i].transform.translation.z;
744  t.rotation.x() = tfs[i].transform.rotation.x;
745  t.rotation.y() = tfs[i].transform.rotation.y;
746  t.rotation.z() = tfs[i].transform.rotation.z;
747  t.rotation.w() = tfs[i].transform.rotation.w;
748  t.src_frame_id = tfs[i].header.frame_id;
749  t.dst_frame_id = tfs[i].child_frame_id;
750  //@@@ should we use yarp or ROS timestamps?
751  t.timestamp = yarp::os::Time::now();
752  //t.timestamp = tfs[i].header.stamp; //@@@ is this ok?
753  (*m_ros_static_transform_storage).set_transform(t);
754  }
755  }
756  } while (rosInData_static != nullptr);
757  }
758 
759  //yarp streaming port
760  m_lastStateStamp.update();
761  size_t tfVecSize_static_yarp = m_yarp_static_transform_storage->size();
762  size_t tfVecSize_timed_yarp = m_yarp_timed_transform_storage->size();
763  size_t tfVecSize_static_ros = m_ros_static_transform_storage->size();
764  size_t tfVecSize_timed_ros = m_ros_timed_transform_storage->size();
765 #if 0
766  yCDebug(FRAMETRANSFORMSERVER) << "yarp size" << tfVecSize_yarp << "ros_size" << tfVecSize_ros;
767 #endif
768  yarp::os::Bottle& b = m_streamingPort.prepare();
769  b.clear();
770 
771  for (size_t i = 0; i < tfVecSize_static_yarp; i++)
772  {
773  yarp::os::Bottle& transform = b.addList();
774  transform.addString((*m_yarp_static_transform_storage)[i].src_frame_id);
775  transform.addString((*m_yarp_static_transform_storage)[i].dst_frame_id);
776  transform.addFloat64((*m_yarp_static_transform_storage)[i].timestamp);
777 
778  transform.addFloat64((*m_yarp_static_transform_storage)[i].translation.tX);
779  transform.addFloat64((*m_yarp_static_transform_storage)[i].translation.tY);
780  transform.addFloat64((*m_yarp_static_transform_storage)[i].translation.tZ);
781 
782  transform.addFloat64((*m_yarp_static_transform_storage)[i].rotation.w());
783  transform.addFloat64((*m_yarp_static_transform_storage)[i].rotation.x());
784  transform.addFloat64((*m_yarp_static_transform_storage)[i].rotation.y());
785  transform.addFloat64((*m_yarp_static_transform_storage)[i].rotation.z());
786  }
787  for (size_t i = 0; i < tfVecSize_timed_yarp; i++)
788  {
789  yarp::os::Bottle& transform = b.addList();
790  transform.addString((*m_yarp_timed_transform_storage)[i].src_frame_id);
791  transform.addString((*m_yarp_timed_transform_storage)[i].dst_frame_id);
792  transform.addFloat64((*m_yarp_timed_transform_storage)[i].timestamp);
793 
794  transform.addFloat64((*m_yarp_timed_transform_storage)[i].translation.tX);
795  transform.addFloat64((*m_yarp_timed_transform_storage)[i].translation.tY);
796  transform.addFloat64((*m_yarp_timed_transform_storage)[i].translation.tZ);
797 
798  transform.addFloat64((*m_yarp_timed_transform_storage)[i].rotation.w());
799  transform.addFloat64((*m_yarp_timed_transform_storage)[i].rotation.x());
800  transform.addFloat64((*m_yarp_timed_transform_storage)[i].rotation.y());
801  transform.addFloat64((*m_yarp_timed_transform_storage)[i].rotation.z());
802  }
803  for (size_t i = 0; i < tfVecSize_timed_ros; i++)
804  {
805  yarp::os::Bottle& transform = b.addList();
806  transform.addString((*m_ros_timed_transform_storage)[i].src_frame_id);
807  transform.addString((*m_ros_timed_transform_storage)[i].dst_frame_id);
808  transform.addFloat64((*m_ros_timed_transform_storage)[i].timestamp);
809 
810  transform.addFloat64((*m_ros_timed_transform_storage)[i].translation.tX);
811  transform.addFloat64((*m_ros_timed_transform_storage)[i].translation.tY);
812  transform.addFloat64((*m_ros_timed_transform_storage)[i].translation.tZ);
813 
814  transform.addFloat64((*m_ros_timed_transform_storage)[i].rotation.w());
815  transform.addFloat64((*m_ros_timed_transform_storage)[i].rotation.x());
816  transform.addFloat64((*m_ros_timed_transform_storage)[i].rotation.y());
817  transform.addFloat64((*m_ros_timed_transform_storage)[i].rotation.z());
818  }
819  for (size_t i = 0; i < tfVecSize_static_ros; i++)
820  {
821  yarp::os::Bottle& transform = b.addList();
822  transform.addString((*m_ros_static_transform_storage)[i].src_frame_id);
823  transform.addString((*m_ros_static_transform_storage)[i].dst_frame_id);
824  transform.addFloat64((*m_ros_static_transform_storage)[i].timestamp);
825 
826  transform.addFloat64((*m_ros_static_transform_storage)[i].translation.tX);
827  transform.addFloat64((*m_ros_static_transform_storage)[i].translation.tY);
828  transform.addFloat64((*m_ros_static_transform_storage)[i].translation.tZ);
829 
830  transform.addFloat64((*m_ros_static_transform_storage)[i].rotation.w());
831  transform.addFloat64((*m_ros_static_transform_storage)[i].rotation.x());
832  transform.addFloat64((*m_ros_static_transform_storage)[i].rotation.y());
833  transform.addFloat64((*m_ros_static_transform_storage)[i].rotation.z());
834  }
835 
836  m_streamingPort.setEnvelope(m_lastStateStamp);
837  m_streamingPort.write();
838 
839  //ros publisher
840  if (m_enable_publish_ros_tf)
841  {
842  static int rosMsgCounter = 0;
843  yarp::rosmsg::tf2_msgs::TFMessage& rosOutData_timed = m_rosPublisherPort_tf_timed.prepare();
845  rosOutData_timed.transforms.clear();
846  for (size_t i = 0; i < tfVecSize_timed_yarp; i++)
847  {
848  transform_timed.child_frame_id = (*m_yarp_timed_transform_storage)[i].dst_frame_id;
849  transform_timed.header.frame_id = (*m_yarp_timed_transform_storage)[i].src_frame_id;
850  transform_timed.header.seq = rosMsgCounter;
851  transform_timed.header.stamp = (*m_yarp_timed_transform_storage)[i].timestamp;
852  transform_timed.transform.rotation.x = (*m_yarp_timed_transform_storage)[i].rotation.x();
853  transform_timed.transform.rotation.y = (*m_yarp_timed_transform_storage)[i].rotation.y();
854  transform_timed.transform.rotation.z = (*m_yarp_timed_transform_storage)[i].rotation.z();
855  transform_timed.transform.rotation.w = (*m_yarp_timed_transform_storage)[i].rotation.w();
856  transform_timed.transform.translation.x = (*m_yarp_timed_transform_storage)[i].translation.tX;
857  transform_timed.transform.translation.y = (*m_yarp_timed_transform_storage)[i].translation.tY;
858  transform_timed.transform.translation.z = (*m_yarp_timed_transform_storage)[i].translation.tZ;
859 
860  rosOutData_timed.transforms.push_back(transform_timed);
861  }
862  m_rosPublisherPort_tf_timed.write();
863 
864  yarp::rosmsg::tf2_msgs::TFMessage& rosOutData_static = m_rosPublisherPort_tf_static.prepare();
866  rosOutData_static.transforms.clear();
867  for (size_t i = 0; i < tfVecSize_static_yarp; i++)
868  {
869  transform_static.child_frame_id = (*m_yarp_static_transform_storage)[i].dst_frame_id;
870  transform_static.header.frame_id = (*m_yarp_static_transform_storage)[i].src_frame_id;
871  transform_static.header.seq = rosMsgCounter;
872  transform_static.header.stamp = yarp::os::Time::now(); //@@@check timestamp of static transform?
873  transform_static.transform.rotation.x = (*m_yarp_static_transform_storage)[i].rotation.x();
874  transform_static.transform.rotation.y = (*m_yarp_static_transform_storage)[i].rotation.y();
875  transform_static.transform.rotation.z = (*m_yarp_static_transform_storage)[i].rotation.z();
876  transform_static.transform.rotation.w = (*m_yarp_static_transform_storage)[i].rotation.w();
877  transform_static.transform.translation.x = (*m_yarp_static_transform_storage)[i].translation.tX;
878  transform_static.transform.translation.y = (*m_yarp_static_transform_storage)[i].translation.tY;
879  transform_static.transform.translation.z = (*m_yarp_static_transform_storage)[i].translation.tZ;
880 
881  rosOutData_static.transforms.push_back(transform_static);
882  }
883  m_rosPublisherPort_tf_static.write();
884 
885  rosMsgCounter++;
886  }
887 
888  }
889  else
890  {
891  yCError(FRAMETRANSFORMSERVER, "Returned error");
892  }
893 }
894 
896 {
897  yCTrace(FRAMETRANSFORMSERVER, "Close");
898  if (PeriodicThread::isRunning())
899  {
900  PeriodicThread::stop();
901  }
902 
903  return true;
904 }
#define DEFAULT_THREAD_PERIOD
Definition: AnalogWrapper.h:46
define control board standard interfaces
float t
#define ROSTOPICNAME_TF
#define ROSTOPICNAME_TF_STATIC
constexpr yarp::conf::vocab32_t VOCAB_OK
Definition: GenericVocabs.h:18
constexpr yarp::conf::vocab32_t VOCAB_FAILED
Definition: GenericVocabs.h:19
constexpr yarp::conf::vocab32_t VOCAB_ERR
Definition: GenericVocabs.h:20
constexpr yarp::conf::vocab32_t VOCAB_TRANSFORM_DELETE
constexpr yarp::conf::vocab32_t VOCAB_TRANSFORM_SET
constexpr yarp::conf::vocab32_t VOCAB_TRANSFORM_DELETE_ALL
constexpr yarp::conf::vocab32_t VOCAB_ITRANSFORM
bool ret
#define ROSNODENAME
Definition: Map2DServer.h:107
bool close() override
Close the DeviceDriver.
void threadRelease() override
Release method.
FrameTransformServer()
FrameTransformServer.
bool open(yarp::os::Searchable &params) override
Open the DeviceDriver.
bool threadInit() override
Initialization method.
void run() override
Loop function.
bool delete_transform(int id)
Transforms storage.
bool set_transform(const yarp::math::FrameTransform &t)
bool open(const std::string &name) override
Start port operation, with a specific name, with automatically-chosen network parameters.
void setReader(PortReader &reader) override
Set an external reader for port data.
void close() override
Stop port activity.
void interrupt() override
Interrupt any current reads or writes attached to the port.
A simple collection of objects that can be described and transmitted in a portable way.
Definition: Bottle.h:73
Bottle & addList()
Places an empty nested list in the bottle, at the end of the list.
Definition: Bottle.cpp:185
size_type size() const
Gets the number of elements in the bottle.
Definition: Bottle.cpp:254
bool read(ConnectionReader &reader) override
Set the bottle's value based on input from a network connection.
Definition: Bottle.cpp:243
void addFloat64(yarp::conf::float64_t x)
Places a 64-bit floating point number in the bottle, at the end of the list.
Definition: Bottle.cpp:161
void addVocab(int x)
Places a vocabulary item in the bottle, at the end of the list.
Definition: Bottle.cpp:167
Value & get(size_type index) const
Reads a Value v from a certain part of the list.
Definition: Bottle.cpp:249
bool check(const std::string &key) const override
Check if there exists a property of the given name.
Definition: Bottle.cpp:280
Bottle tail() const
Get all but the first element of a bottle.
Definition: Bottle.cpp:391
void clear()
Empties the bottle of any objects it contains.
Definition: Bottle.cpp:124
bool write(ConnectionWriter &writer) const override
Output a representation of the bottle to a network connection.
Definition: Bottle.cpp:233
void addString(const char *str)
Places a string in the bottle, at the end of the list.
Definition: Bottle.cpp:173
std::string toString() const override
Gives a human-readable textual representation of the bottle.
Definition: Bottle.cpp:214
Value & find(const std::string &key) const override
Gets a value corresponding to a given keyword.
Definition: Bottle.cpp:290
void close() override
Stop port activity.
bool setEnvelope(PortWriter &envelope) override
Set an envelope (e.g., a timestamp) to the next message which will be sent.
bool open(const std::string &name) override
Start port operation, with a specific name, with automatically-chosen network parameters.
void interrupt() override
Interrupt any current reads or writes attached to the port.
void write(bool forceStrict=false)
Write the current object being returned by BufferedPort::prepare.
T & prepare()
Access the object which will be transmitted by the next call to yarp::os::BufferedPort::write.
An interface for reading from a network connection.
virtual ConnectionWriter * getWriter()=0
Gets a way to reply to the message, if possible.
An interface for writing to a network connection.
The Node class.
Definition: Node.h:27
void interrupt()
interrupt delegates the call to the Node port interrupt.
Definition: Node.cpp:600
An abstraction for a periodic thread.
bool start()
Call this to start the thread.
A class for storing options and configuration information.
Definition: Property.h:37
void fromString(const std::string &txt, bool wipe=true)
Interprets a string as a list of properties.
Definition: Property.cpp:1046
void close() override
Stop port activity.
Definition: Publisher.h:88
bool topic(const std::string &name)
Set topic to publish to.
Definition: Publisher.h:67
T & prepare()
Access the object which will be transmitted by the next call to yarp::os::Publisher::write.
Definition: Publisher.h:127
void interrupt() override
Interrupt any current reads or writes attached to the port.
Definition: Publisher.h:94
void write(bool forceStrict=false)
Write the current object being returned by Publisher::prepare.
Definition: Publisher.h:152
A base class for nested structures that can be searched.
Definition: Searchable.h:69
virtual Value & find(const std::string &key) const =0
Gets a value corresponding to a given keyword.
virtual bool check(const std::string &key) const =0
Check if there exists a property of the given name.
virtual std::string toString() const =0
Return a standard text representation of the content of the object.
virtual Bottle & findGroup(const std::string &key) const =0
Gets a list corresponding to a given keyword.
void update()
Set the timestamp to the current time, and increment the sequence number (wrapping to 0 if the sequen...
Definition: Stamp.cpp:113
void close() override
Stop port activity.
Definition: Subscriber.h:87
T * read(bool shouldWait=true)
Read a message from the port.
Definition: Subscriber.h:117
void setStrict(bool strict=true)
Definition: Subscriber.h:154
bool topic(const std::string &name)
Set topic to subscribe to.
Definition: Subscriber.h:66
void interrupt() override
Interrupt any current reads or writes attached to the port.
Definition: Subscriber.h:93
virtual yarp::conf::float64_t asFloat64() const
Get 64-bit floating point value.
Definition: Value.cpp:225
virtual bool isString() const
Checks if value is a string.
Definition: Value.cpp:159
virtual std::int32_t asInt32() const
Get 32-bit integer value.
Definition: Value.cpp:207
virtual Bottle * asList() const
Get list value.
Definition: Value.cpp:243
virtual bool isFloat64() const
Checks if value is a 64-bit floating point number.
Definition: Value.cpp:153
virtual std::int32_t asVocab() const
Get vocabulary identifier as an integer.
Definition: Value.cpp:231
virtual std::string asString() const
Get string value.
Definition: Value.cpp:237
yarp::rosmsg::geometry_msgs::Transform transform
yarp::rosmsg::geometry_msgs::Quaternion rotation
Definition: Transform.h:38
yarp::rosmsg::geometry_msgs::Vector3 translation
Definition: Transform.h:37
yarp::conf::float64_t y
Definition: Vector3.h:41
yarp::conf::float64_t z
Definition: Vector3.h:42
yarp::conf::float64_t x
Definition: Vector3.h:40
yarp::rosmsg::TickTime stamp
Definition: Header.h:48
std::vector< yarp::rosmsg::geometry_msgs::TransformStamped > transforms
Definition: TFMessage.h:33
A class for a Matrix.
Definition: Matrix.h:46
std::string toString(const T &value)
convert an arbitrary type to string.
#define yCInfo(component,...)
Definition: LogComponent.h:135
#define yCError(component,...)
Definition: LogComponent.h:157
#define yCTrace(component,...)
Definition: LogComponent.h:88
#define yCDebug(component,...)
Definition: LogComponent.h:112
#define YARP_LOG_COMPONENT(name,...)
Definition: LogComponent.h:80
An interface for the device drivers.
double now()
Return the current time in seconds, relative to an arbitrary starting point.
Definition: Time.cpp:124
void delay(double seconds)
Wait for a certain number of seconds.
Definition: Time.cpp:114
NetInt32 encode(const std::string &str)
Convert a string into a vocabulary identifier.
Definition: Vocab.cpp:14
An interface to the operating system, including Port based communication.
Signal processing.
Definition: Image.h:25