YARP
Yet Another Robot Platform
FrameTransformClient.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 #include "FrameTransformClient.h"
20 #include <yarp/os/Log.h>
21 #include <yarp/os/LogComponent.h>
22 #include <yarp/os/LogStream.h>
23 #include <yarp/math/Math.h>
24 #include <mutex>
25 
28 //example: yarpdev --device transformClient --local /transformClient --remote /transformServer
29 
30 using namespace yarp::dev;
31 using namespace yarp::os;
32 using namespace yarp::sig;
33 using namespace yarp::math;
34 
35 
36 namespace {
37 YARP_LOG_COMPONENT(FRAMETRANSFORMCLIENT, "yarp.device.transformClient")
38 }
39 
41 {
42  std::lock_guard<std::recursive_mutex> l(m_mutex);
43 }
44 
46 {
47  m_now = Time::now();
48  std::lock_guard<std::recursive_mutex> guard(m_mutex);
49 
50  if (m_count>0)
51  {
52  double tmpDT = m_now - m_prev;
53  m_deltaT += tmpDT;
54  if (tmpDT>m_deltaTMax)
55  m_deltaTMax = tmpDT;
56  if (tmpDT<m_deltaTMin)
57  m_deltaTMin = tmpDT;
58 
59  //compare network time
60  /*if (tmpDT*1000<TRANSFORM_TIMEOUT)
61  {
62  state = b.get(5).asInt32();
63  }
64  else
65  {
66  state = TRANSFORM_TIMEOUT;
67  }*/
68  }
69 
70  m_prev = m_now;
71  m_count++;
72 
73  m_lastBottle = b;
74  Stamp newStamp;
75  getEnvelope(newStamp);
76 
77  //initialization (first received data)
78  if (m_lastStamp.isValid() == false)
79  {
80  m_lastStamp = newStamp;
81  }
82 
83  //now compare timestamps
84  // if ((1000 * (newStamp.getTime() - m_lastStamp.getTime()))<TRANSFORM_TIMEOUT)
85  if (true)
86  {
88 
89  m_transforms.clear();
90  int bsize= b.size();
91  for (int i = 0; i < bsize; i++)
92  {
93  //this includes: timed yarp transforms, static yarp transforms, ros transforms
94  Bottle* bt = b.get(i).asList();
95  if (bt != nullptr)
96  {
98  t.src_frame_id = bt->get(0).asString();
99  t.dst_frame_id = bt->get(1).asString();
100  t.timestamp = bt->get(2).asFloat64();
101  t.translation.tX = bt->get(3).asFloat64();
102  t.translation.tY = bt->get(4).asFloat64();
103  t.translation.tZ = bt->get(5).asFloat64();
104  t.rotation.w() = bt->get(6).asFloat64();
105  t.rotation.x() = bt->get(7).asFloat64();
106  t.rotation.y() = bt->get(8).asFloat64();
107  t.rotation.z() = bt->get(9).asFloat64();
108  m_transforms.push_back(t);
109  }
110  }
111  }
112  else
113  {
115  }
116  m_lastStamp = newStamp;
117 }
118 
120 {
121  std::lock_guard<std::recursive_mutex> guard(m_mutex);
122 
123  int ret = m_state;
125  {
126  data = m_lastBottle;
127  stmp = m_lastStamp;
128  }
129 
130  return ret;
131 }
132 
134 {
135  std::lock_guard<std::recursive_mutex> guard(m_mutex);
136  int ret = m_count;
137  return ret;
138 }
139 
140 // time is in ms
141 void Transforms_client_storage::getEstFrequency(int &ite, double &av, double &min, double &max)
142 {
143  std::lock_guard<std::recursive_mutex> guard(m_mutex);
144  ite=m_count;
145  min=m_deltaTMin*1000;
146  max=m_deltaTMax*1000;
147  if (m_count<1)
148  {
149  av=0;
150  }
151  else
152  {
153  av=m_deltaT/m_count;
154  }
155  av=av*1000;
156 }
157 
159 {
160  std::lock_guard<std::recursive_mutex> l(m_mutex);
161  m_transforms.clear();
162 }
163 
165 {
166  m_count = 0;
167  m_deltaT = 0;
168  m_deltaTMax = 0;
169  m_deltaTMin = 1e22;
170  m_now = Time::now();
171  m_prev = m_now;
172 
173  if (!this->open(local_streaming_name))
174  {
175  yCError(FRAMETRANSFORMCLIENT, "open(): Could not open port %s, check network", local_streaming_name.c_str());
176  }
177  this->useCallback();
178 }
179 
181 {
182  this->interrupt();
183  this->close();
184 }
185 
187 {
188  std::lock_guard<std::recursive_mutex> l(m_mutex);
189  return m_transforms.size();
190 }
191 
193 {
194  std::lock_guard<std::recursive_mutex> l(m_mutex);
195  return m_transforms[idx];
196 };
197 
198 //------------------------------------------------------------------------------------------------------------------------------
200 {
201  std::lock_guard<std::mutex> lock (m_rpc_mutex);
202  yarp::os::Bottle in;
203  yarp::os::Bottle out;
204  bool ok = in.read(connection);
205  if (!ok) return false;
206 
207  std::string request = in.get(0).asString();
208  if (request == "help")
209  {
210  out.addVocab(Vocab::encode("many"));
211  out.addString("'get_transform <src> <dst>: print the transform from <src> to <dst>");
212  out.addString("'list_frames: print all the available reference frames");
213  out.addString("'list_ports: print all the opened ports for transform broadcasting");
214  out.addString("'publish_transform <src> <dst> <portname> <format>: opens a port to publish transform from src to dst");
215  out.addString("'unpublish_transform <portname>: closes a previously opened port to publish a transform");
216  out.addString("'unpublish_all <portname>: closes a all previously opened ports to publish a transform");
217  out.addString("'is_connected'");
218  out.addString("'reconnect'");
219  }
220  else if (request == "is_connected")
221  {
222  if (isConnectedWithServer())
223  {
224  out.addString("yes");
225  }
226  else
227  {
228  out.addString("no");
229  }
230  }
231  else if (request == "reconnect")
232  {
233  if (reconnectWithServer())
234  {
235  out.addString("successful");
236  }
237  else
238  {
239  out.addString("unsuccessful");
240  }
241  }
242  else if (request == "list_frames")
243  {
244  std::vector<std::string> v;
245  this->getAllFrameIds(v);
246  out.addVocab(Vocab::encode("many"));
247  out.addString("List of available reference frames:");
248  int count = 0;
249  for (auto& vec : v)
250  {
251  count++;
252  std::string str = std::to_string(count) + "- " + vec;
253  out.addString(str.c_str());
254  }
255  }
256  else if (request == "get_transform")
257  {
258  std::string src = in.get(1).asString();
259  std::string dst = in.get(2).asString();
260  out.addVocab(Vocab::encode("many"));
262  this->getTransform(src, dst, m);
263  out.addString("Transform from " + src + " to " + dst + " is: ");
264  out.addString(m.toString());
265  }
266  else if (request == "list_ports")
267  {
268  out.addVocab(Vocab::encode("many"));
269  if (m_array_of_ports.size()==0)
270  {
271  out.addString("No ports are currently active");
272  }
273  for (auto& m_array_of_port : m_array_of_ports)
274  {
275  if (m_array_of_port)
276  {
277  std::string s = m_array_of_port->port.getName() + " "+ m_array_of_port->transform_src + " -> " + m_array_of_port->transform_dst;
278  out.addString(s);
279  }
280  }
281  }
282  else if (request == "publish_transform")
283  {
284  out.addVocab(Vocab::encode("many"));
285  std::string src = in.get(1).asString();
286  std::string dst = in.get(2).asString();
287  std::string port_name = in.get(3).asString();
288  std::string format = "matrix";
289  if (in.size() > 4)
290  {format= in.get(4).asString();}
291  if (port_name[0]=='/') port_name.erase(port_name.begin());
292  std::string full_port_name = m_local_name + "/" + port_name;
293  bool ret = true;
294  for (auto& m_array_of_port : m_array_of_ports)
295  {
296  if (m_array_of_port && m_array_of_port->port.getName() == full_port_name)
297  {
298  ret = false;
299  break;
300  }
301  }
302  if (this->frameExists(src)==false)
303  {
304  out.addString("Requested src frame " + src + " does not exists.");
305  yCWarning(FRAMETRANSFORMCLIENT, "Requested src frame %s does not exists.", src.c_str());
306  }
307  if (this->frameExists(dst)==false)
308  {
309  out.addString("Requested dst frame " + dst + " does not exists.");
310  yCWarning(FRAMETRANSFORMCLIENT, "Requested fst frame %s does not exists.", dst.c_str());
311  }
312  if (ret == true)
313  {
314  auto* b = new broadcast_port_t;
315  b->transform_src = src;
316  b->transform_dst = dst;
317  b->format = format;
318  bool pret = b->port.open(full_port_name);
319  if (pret)
320  {
321  out.addString("Operation complete. Port " + full_port_name + " opened.");
322  m_array_of_ports.push_back(b);
323  if (m_array_of_ports.size()==1) this->start();
324  }
325  else
326  {
327  delete b;
328  out.addString("Operation failed. Unable to open port " + full_port_name + ".");
329  }
330  }
331  else
332  {
333  out.addString("unable to perform operation");
334  }
335  }
336  else if (request == "unpublish_all")
337  {
338  for (auto& m_array_of_port : m_array_of_ports)
339  {
340  m_array_of_port->port.close();
341  delete m_array_of_port;
342  m_array_of_port=nullptr;
343  }
344  m_array_of_ports.clear();
345  if (m_array_of_ports.size()==0) this->askToStop();
346  out.addString("Operation complete");
347  }
348  else if (request == "unpublish_transform")
349  {
350  bool ret = false;
351  std::string port_name = in.get(1).asString();
352  if (port_name[0]=='/') port_name.erase(port_name.begin());
353  std::string full_port_name = m_local_name + "/" + port_name;
354  for (auto it = m_array_of_ports.begin(); it != m_array_of_ports.end(); it++)
355  {
356  if ((*it)->port.getName() == port_name)
357  {
358  (*it)->port.close();
359  delete (*it);
360  (*it)=nullptr;
361  m_array_of_ports.erase(it);
362  ret = true;
363  break;
364  }
365  }
366  if (ret)
367  {
368  out.addString("Port " + full_port_name + " has been closed.");
369  }
370  else
371  {
372  out.addString("Port " + full_port_name + " was not found.");
373  }
374  if (m_array_of_ports.size()==0) this->askToStop();
375  }
376  else
377  {
378  yCError(FRAMETRANSFORMCLIENT, "Invalid vocab received in FrameTransformClient");
379  out.clear();
380  out.addVocab(VOCAB_ERR);
381  out.addString("Invalid command name");
382  }
383 
384  yarp::os::ConnectionWriter *returnToSender = connection.getWriter();
385  if (returnToSender != nullptr)
386  {
387  out.write(*returnToSender);
388  }
389  else
390  {
391  yCError(FRAMETRANSFORMCLIENT) << "Invalid return to sender";
392  }
393  return true;
394 }
395 
397 {
398  m_local_name.clear();
399  m_remote_name.clear();
400 
401  m_local_name = config.find("local").asString();
402  m_remote_name = config.find("remote").asString();
403  m_streaming_connection_type = "udp";
404 
405  if (m_local_name == "")
406  {
407  yCError(FRAMETRANSFORMCLIENT, "open(): Invalid local name");
408  return false;
409  }
410  if (m_remote_name == "")
411  {
412  yCError(FRAMETRANSFORMCLIENT, "open(): Invalid remote name");
413  return false;
414  }
415 
416  if (config.check("period"))
417  {
418  m_period = config.find("period").asInt32() / 1000.0;
419  }
420  else
421  {
422  m_period = 0.010;
423  yCWarning(FRAMETRANSFORMCLIENT, "Using default period of %f s" , m_period);
424  }
425 
426  m_local_rpcServer = m_local_name + "/rpc:o";
427  m_local_rpcUser = m_local_name + "/rpc:i";
428  m_remote_rpc = m_remote_name + "/rpc";
429  m_remote_streaming_name = m_remote_name + "/transforms:o";
430  m_local_streaming_name = m_local_name + "/transforms:i";
431 
432  if (!m_rpc_InterfaceToUser.open(m_local_rpcUser))
433  {
434  yCError(FRAMETRANSFORMCLIENT, "open(): Could not open rpc port %s, check network", m_local_rpcUser.c_str());
435  return false;
436  }
437 
438  if (!m_rpc_InterfaceToServer.open(m_local_rpcServer))
439  {
440  yCError(FRAMETRANSFORMCLIENT, "open(): Could not open rpc port %s, check network", m_local_rpcServer.c_str());
441  return false;
442  }
443 
444  m_transform_storage = new Transforms_client_storage(m_local_streaming_name);
445  bool ok = Network::connect(m_remote_streaming_name.c_str(), m_local_streaming_name.c_str(), m_streaming_connection_type.c_str());
446  if (!ok)
447  {
448  yCError(FRAMETRANSFORMCLIENT, "open(): Could not connect to %s", m_remote_streaming_name.c_str());
449  return false;
450  }
451 
452  ok = Network::connect(m_local_rpcServer, m_remote_rpc);
453  if (!ok)
454  {
455  yCError(FRAMETRANSFORMCLIENT, "open(): Could not connect to %s", m_remote_rpc.c_str());
456  return false;
457  }
458 
459 
460  m_rpc_InterfaceToUser.setReader(*this);
461  return true;
462 }
463 
465 {
466  m_rpc_InterfaceToServer.close();
467  m_rpc_InterfaceToUser.close();
468  if (m_transform_storage != nullptr)
469  {
470  delete m_transform_storage;
471  m_transform_storage = nullptr;
472  }
473  return true;
474 }
475 
476 bool FrameTransformClient::allFramesAsString(std::string &all_frames)
477 {
478  for (size_t i = 0; i < m_transform_storage->size(); i++)
479  {
480  all_frames += (*m_transform_storage)[i].toString() + " ";
481  }
482  return true;
483 }
484 
485 FrameTransformClient::ConnectionType FrameTransformClient::getConnectionType(const std::string &target_frame, const std::string &source_frame, std::string* commonAncestor = nullptr)
486 {
487  if (target_frame == source_frame) {return IDENTITY;}
488 
489  Transforms_client_storage& tfVec = *m_transform_storage;
490  size_t i, j;
491  std::vector<std::string> tar2root_vec;
492  std::vector<std::string> src2root_vec;
493  std::string ancestor, child;
494  child = target_frame;
495  std::lock_guard<std::recursive_mutex> l(tfVec.m_mutex);
496  while(getParent(child, ancestor))
497  {
498  if(ancestor == source_frame)
499  {
500  return DIRECT;
501  }
502 
503  tar2root_vec.push_back(ancestor);
504  child = ancestor;
505  }
506  child = source_frame;
507  while(getParent(child, ancestor))
508  {
509  if(ancestor == target_frame)
510  {
511  return INVERSE;
512  }
513 
514  src2root_vec.push_back(ancestor);
515  child = ancestor;
516  }
517 
518  for(i = 0; i < tar2root_vec.size(); i++)
519  {
520  std::string a;
521  a = tar2root_vec[i];
522  for(j = 0; j < src2root_vec.size(); j++)
523  {
524  if(a == src2root_vec[j])
525  {
526  if(commonAncestor)
527  {
528  *commonAncestor = a;
529  }
530  return UNDIRECT;
531  }
532  }
533  }
534 
535  return DISCONNECTED;
536 }
537 
538 bool FrameTransformClient::canTransform(const std::string &target_frame, const std::string &source_frame)
539 {
540  return getConnectionType(target_frame, source_frame) != DISCONNECTED;
541 }
542 
544 {
546  yarp::os::Bottle resp;
549  bool ret = m_rpc_InterfaceToServer.write(b, resp);
550  if (ret)
551  {
552  if (resp.get(0).asVocab() != VOCAB_OK)
553  {
554  yCError(FRAMETRANSFORMCLIENT) << "clear(): Received error from server";
555  return false;
556  }
557  }
558  else
559  {
560  yCError(FRAMETRANSFORMCLIENT) << "clear(): Error on writing on rpc port";
561  return false;
562  }
563 
564  m_transform_storage->clear();
565  return true;
566 }
567 
568 bool FrameTransformClient::frameExists(const std::string &frame_id)
569 {
570  for (size_t i = 0; i < m_transform_storage->size(); i++)
571  {
572  if (((*m_transform_storage)[i].src_frame_id) == frame_id) { return true; }
573  if (((*m_transform_storage)[i].dst_frame_id) == frame_id) { return true; }
574  }
575  return false;
576 }
577 
578 bool FrameTransformClient::getAllFrameIds(std::vector< std::string > &ids)
579 {
580  for (size_t i = 0; i < m_transform_storage->size(); i++)
581  {
582  bool found = false;
583  for (const auto& id : ids)
584  {
585  if (((*m_transform_storage)[i].src_frame_id) == id) { found = true; break; }
586  }
587  if (found == false) ids.push_back((*m_transform_storage)[i].src_frame_id);
588  }
589 
590  for (size_t i = 0; i < m_transform_storage->size(); i++)
591  {
592  bool found = false;
593  for (const auto& id : ids)
594  {
595  if (((*m_transform_storage)[i].dst_frame_id) == id) { found = true; break; }
596  }
597  if (found == false) ids.push_back((*m_transform_storage)[i].dst_frame_id);
598  }
599 
600  return true;
601 }
602 
603 bool FrameTransformClient::getParent(const std::string &frame_id, std::string &parent_frame_id)
604 {
605  for (size_t i = 0; i < m_transform_storage->size(); i++)
606  {
607  std::string par((*m_transform_storage)[i].dst_frame_id);
608  if (((*m_transform_storage)[i].dst_frame_id == frame_id))
609  {
610 
611  parent_frame_id = (*m_transform_storage)[i].src_frame_id;
612  return true;
613  }
614  }
615  return false;
616 }
617 
618 bool FrameTransformClient::canExplicitTransform(const std::string& target_frame_id, const std::string& source_frame_id) const
619 {
620  Transforms_client_storage& tfVec = *m_transform_storage;
621  size_t i, tfVec_size;
622  std::lock_guard<std::recursive_mutex> l(tfVec.m_mutex);
623 
624  tfVec_size = tfVec.size();
625  for (i = 0; i < tfVec_size; i++)
626  {
627  if (tfVec[i].dst_frame_id == target_frame_id && tfVec[i].src_frame_id == source_frame_id)
628  {
629  return true;
630  }
631  }
632  return false;
633 }
634 
635 bool FrameTransformClient::getChainedTransform(const std::string& target_frame_id, const std::string& source_frame_id, yarp::sig::Matrix& transform) const
636 {
637  Transforms_client_storage& tfVec = *m_transform_storage;
638  size_t i, tfVec_size;
639  std::lock_guard<std::recursive_mutex> l(tfVec.m_mutex);
640 
641  tfVec_size = tfVec.size();
642  for (i = 0; i < tfVec_size; i++)
643  {
644  if (tfVec[i].dst_frame_id == target_frame_id)
645  {
646  if (tfVec[i].src_frame_id == source_frame_id)
647  {
648  transform = tfVec[i].toMatrix();
649  return true;
650  }
651  else
652  {
654  if (getChainedTransform(tfVec[i].src_frame_id, source_frame_id, m))
655  {
656  transform = m * tfVec[i].toMatrix();
657  return true;
658  }
659  }
660  }
661  }
662  return false;
663 }
664 
665 bool FrameTransformClient::getTransform(const std::string& target_frame_id, const std::string& source_frame_id, yarp::sig::Matrix& transform)
666 {
667  ConnectionType ct;
668  std::string ancestor;
669  ct = getConnectionType(target_frame_id, source_frame_id, &ancestor);
670  if (ct == DIRECT)
671  {
672  return getChainedTransform(target_frame_id, source_frame_id, transform);
673  }
674  else if (ct == INVERSE)
675  {
676  yarp::sig::Matrix m(4, 4);
677  getChainedTransform(source_frame_id, target_frame_id, m);
678  transform = yarp::math::SE3inv(m);
679  return true;
680  }
681  else if(ct == UNDIRECT)
682  {
683  yarp::sig::Matrix root2tar(4, 4), root2src(4, 4);
684  getChainedTransform(source_frame_id, ancestor, root2src);
685  getChainedTransform(target_frame_id, ancestor, root2tar);
686  transform = yarp::math::SE3inv(root2src) * root2tar;
687  return true;
688  }
689  else if (ct == IDENTITY)
690  {
691  yarp::sig::Matrix tmp(4, 4); tmp.eye();
692  transform = tmp;
693  return true;
694  }
695 
696  yCError(FRAMETRANSFORMCLIENT) << "getTransform(): Frames " << source_frame_id << " and " << target_frame_id << " are not connected";
697  return false;
698 }
699 
700 bool FrameTransformClient::setTransform(const std::string& target_frame_id, const std::string& source_frame_id, const yarp::sig::Matrix& transform)
701 {
702  if(target_frame_id == source_frame_id)
703  {
704  yCError(FRAMETRANSFORMCLIENT) << "setTransform(): Invalid transform detected.\n" \
705  "\t Source frame and target frame are both equal to " << source_frame_id;
706  return false;
707  }
708 
709  if (!canExplicitTransform(target_frame_id, source_frame_id) && canTransform(target_frame_id, source_frame_id))
710  {
711  yCError(FRAMETRANSFORMCLIENT) << "setTransform(): Such transform already exist by chaining transforms";
712  return false;
713  }
714 
716  yarp::os::Bottle resp;
718 
719  if (!tf.fromMatrix(transform))
720  {
721  yCError(FRAMETRANSFORMCLIENT) << "setTransform(): Wrong matrix format, it has to be 4 by 4";
722  return false;
723  }
724 
727  b.addString(source_frame_id);
728  b.addString(target_frame_id);
729  b.addFloat64(1000.0); //transform lifetime
730  b.addFloat64(tf.translation.tX);
731  b.addFloat64(tf.translation.tY);
732  b.addFloat64(tf.translation.tZ);
733  b.addFloat64(tf.rotation.w());
734  b.addFloat64(tf.rotation.x());
735  b.addFloat64(tf.rotation.y());
736  b.addFloat64(tf.rotation.z());
737  bool ret = m_rpc_InterfaceToServer.write(b, resp);
738  if (ret)
739  {
740  if (resp.get(0).asVocab() != VOCAB_OK)
741  {
742  yCError(FRAMETRANSFORMCLIENT) << "setTransform(): Received error from server on creating frame between " + source_frame_id + " and " + target_frame_id;
743  return false;
744  }
745  }
746  else
747  {
748  yCError(FRAMETRANSFORMCLIENT) << "setTransform(): Error on writing on rpc port";
749  return false;
750  }
751  return true;
752 }
753 
754 bool FrameTransformClient::setTransformStatic(const std::string &target_frame_id, const std::string &source_frame_id, const yarp::sig::Matrix &transform)
755 {
756  if(target_frame_id == source_frame_id)
757  {
758  yCError(FRAMETRANSFORMCLIENT) << "setTransformStatic(): Invalid transform detected.\n" \
759  "\t Source frame and target frame are both equal to " << source_frame_id;
760  return false;
761  }
762 
763  if (canTransform(target_frame_id, source_frame_id))
764  {
765  yCError(FRAMETRANSFORMCLIENT) << "setTransform(): Such static transform already exist, directly or by chaining transforms";
766  return false;
767  }
768 
770  yarp::os::Bottle resp;
772 
773  if (!tf.fromMatrix(transform))
774  {
775  yCError(FRAMETRANSFORMCLIENT) << "setTransform(): Wrong matrix format, it has to be 4 by 4";
776  return false;
777  }
778 
781  b.addString(source_frame_id);
782  b.addString(target_frame_id);
783  b.addFloat64(-1);
784  b.addFloat64(tf.translation.tX);
785  b.addFloat64(tf.translation.tY);
786  b.addFloat64(tf.translation.tZ);
787  b.addFloat64(tf.rotation.w());
788  b.addFloat64(tf.rotation.x());
789  b.addFloat64(tf.rotation.y());
790  b.addFloat64(tf.rotation.z());
791  bool ret = m_rpc_InterfaceToServer.write(b, resp);
792  if (ret)
793  {
794  if (resp.get(0).asVocab() != VOCAB_OK)
795  {
796  yCError(FRAMETRANSFORMCLIENT) << "setTransform(): Received error from server on creating frame between " + source_frame_id + " and " + target_frame_id;
797  return false;
798  }
799  }
800  else
801  {
802  yCError(FRAMETRANSFORMCLIENT) << "setTransform(): Error on writing on rpc port";
803  return false;
804  }
805  return true;
806 }
807 
808 bool FrameTransformClient::deleteTransform(const std::string &target_frame_id, const std::string &source_frame_id)
809 {
811  yarp::os::Bottle resp;
814  b.addString(target_frame_id);
815  b.addString(source_frame_id);
816  bool ret = m_rpc_InterfaceToServer.write(b, resp);
817  if (ret)
818  {
819  if (resp.get(0).asVocab()!=VOCAB_OK)
820  {
821  yCError(FRAMETRANSFORMCLIENT) << "Received error from server on deleting frame between "+source_frame_id+" and "+target_frame_id;
822  return false;
823  }
824  }
825  else
826  {
827  yCError(FRAMETRANSFORMCLIENT) << "deleteFrame(): Error on writing on rpc port";
828  return false;
829  }
830  return true;
831 }
832 
833 bool FrameTransformClient::transformPoint(const std::string &target_frame_id, const std::string &source_frame_id, const yarp::sig::Vector &input_point, yarp::sig::Vector &transformed_point)
834 {
835  if (input_point.size() != 3)
836  {
837  yCError(FRAMETRANSFORMCLIENT) << "Only 3 dimensional vector allowed.";
838  return false;
839  }
840  yarp::sig::Matrix m(4, 4);
841  if (!getTransform(target_frame_id, source_frame_id, m))
842  {
843  yCError(FRAMETRANSFORMCLIENT) << "No transform found between source '" << target_frame_id << "' and target '" << source_frame_id << "'";
844  return false;
845  }
846  yarp::sig::Vector in = input_point;
847  in.push_back(1);
848  transformed_point = m * in;
849  transformed_point.pop_back();
850  return true;
851 }
852 
853 bool FrameTransformClient::transformPose(const std::string &target_frame_id, const std::string &source_frame_id, const yarp::sig::Vector &input_pose, yarp::sig::Vector &transformed_pose)
854 {
855  if (input_pose.size() != 6)
856  {
857  yCError(FRAMETRANSFORMCLIENT) << "Only 6 dimensional vector (3 axes + roll pith and yaw) allowed.";
858  return false;
859  }
860  if (transformed_pose.size() != 6)
861  {
862  yCWarning(FRAMETRANSFORMCLIENT, "transformPose(): Performance warning: size transformed_pose should be 6, resizing.");
863  transformed_pose.resize(6, 0.0);
864  }
865  yarp::sig::Matrix m(4, 4);
866  if (!getTransform(target_frame_id, source_frame_id, m))
867  {
868  yCError(FRAMETRANSFORMCLIENT) << "No transform found between source '" << target_frame_id << "' and target '" << source_frame_id << "'";
869  return false;
870  }
872  t.transFromVec(input_pose[0], input_pose[1], input_pose[2]);
873  t.rotFromRPY(input_pose[3], input_pose[4], input_pose[5]);
874  t.fromMatrix(m * t.toMatrix());
875  transformed_pose[0] = t.translation.tX;
876  transformed_pose[1] = t.translation.tY;
877  transformed_pose[2] = t.translation.tZ;
878 
879  yarp::sig::Vector rot;
880  rot = t.getRPYRot();
881  transformed_pose[3] = rot[0];
882  transformed_pose[4] = rot[1];
883  transformed_pose[5] = rot[2];
884  return true;
885 }
886 
887 bool FrameTransformClient::transformQuaternion(const std::string &target_frame_id, const std::string &source_frame_id, const yarp::math::Quaternion &input_quaternion, yarp::math::Quaternion &transformed_quaternion)
888 {
889  yarp::sig::Matrix m(4, 4);
890  if (!getTransform(target_frame_id, source_frame_id, m))
891  {
892  yCError(FRAMETRANSFORMCLIENT) << "No transform found between source '" << target_frame_id << "' and target '" << source_frame_id <<"'";
893  return false;
894  }
896  t.rotation=input_quaternion;
897  transformed_quaternion.fromRotationMatrix(m * t.toMatrix());
898  return true;
899 }
900 
901 bool FrameTransformClient::waitForTransform(const std::string &target_frame_id, const std::string &source_frame_id, const double &timeout)
902 {
903  //loop until canTransform == true or timeout expires
904  double start = yarp::os::SystemClock::nowSystem();
905  while (!canTransform(target_frame_id, source_frame_id))
906  {
907  if (yarp::os::SystemClock::nowSystem() - start > timeout)
908  {
909  yCError(FRAMETRANSFORMCLIENT) << "waitForTransform(): timeout expired";
910  return false;
911  }
913  }
914  return true;
915 }
916 
918  m_transform_storage(nullptr),
919  m_period(0.01)
920 {
921 }
922 
924 
926 {
927  yCTrace(FRAMETRANSFORMCLIENT, "Thread started");
928  return true;
929 }
930 
932 {
933  yCTrace(FRAMETRANSFORMCLIENT, "Thread stopped");
934 }
935 
937 {
938  std::lock_guard<std::mutex> lock (m_rpc_mutex);
939  if (m_array_of_ports.size()==0)
940  {
941  return;
942  }
943 
944  for (auto& m_array_of_port : m_array_of_ports)
945  {
946  if (m_array_of_port)
947  {
948  std::string src = m_array_of_port->transform_src;
949  std::string dst = m_array_of_port->transform_dst;
951  this->getTransform(src, dst, m);
952  if (m_array_of_port->format == "matrix")
953  {
954  m_array_of_port->port.write(m);
955  }
956  else
957  {
958  yCError(FRAMETRANSFORMCLIENT) << "Unknown format requested: " << m_array_of_port->format;
959  }
960  }
961  }
962 }
963 
965 {
966  bool ok1 = Network::isConnected(m_local_rpcServer.c_str(), m_remote_rpc.c_str());
967  if (!ok1) yCInfo(FRAMETRANSFORMCLIENT) << m_local_rpcServer << "is not connected to: " << m_remote_rpc;
968 
969  bool ok2 = Network::isConnected(m_remote_streaming_name.c_str(), m_local_streaming_name.c_str(),m_streaming_connection_type.c_str());
970  if (!ok2) yCInfo(FRAMETRANSFORMCLIENT) << m_remote_streaming_name << "is not connected to: " << m_local_streaming_name;
971 
972  return ok1 && ok2;
973 }
974 
976 {
977  bool ok = Network::connect(m_remote_streaming_name.c_str(), m_local_streaming_name.c_str(), m_streaming_connection_type.c_str());
978  if (!ok)
979  {
980  yCError(FRAMETRANSFORMCLIENT, "reconnectWithServer(): Could not connect to %s", m_remote_streaming_name.c_str());
981  return false;
982  }
983 
984  ok = Network::connect(m_local_rpcServer, m_remote_rpc);
985  if (!ok)
986  {
987  yCError(FRAMETRANSFORMCLIENT, "reconnectWithServer(): Could not connect to %s", m_remote_rpc.c_str());
988  return false;
989  }
990  return true;
991 }
LogStream.h
Transforms_client_storage::~Transforms_client_storage
~Transforms_client_storage()
Definition: FrameTransformClient.cpp:180
FrameTransformClient::transformQuaternion
bool transformQuaternion(const std::string &target_frame_id, const std::string &source_frame_id, const yarp::math::Quaternion &input_quaternion, yarp::math::Quaternion &transformed_quaternion) override
Transform a quaternion into the target frame.
Definition: FrameTransformClient.cpp:887
FrameTransformClient::m_rpc_mutex
std::mutex m_rpc_mutex
Definition: FrameTransformClient.h:117
Transforms_client_storage::Transforms_client_storage
Transforms_client_storage(std::string port_name)
Definition: FrameTransformClient.cpp:164
yarp::os::Bottle
A simple collection of objects that can be described and transmitted in a portable way.
Definition: Bottle.h:73
yarp::os::Value::asVocab
virtual std::int32_t asVocab() const
Get vocabulary identifier as an integer.
Definition: Value.cpp:231
Transforms_client_storage::operator[]
yarp::math::FrameTransform & operator[](std::size_t idx)
Definition: FrameTransformClient.cpp:192
Transforms_client_storage
Definition: FrameTransformClient.h:46
yarp::sig::Matrix::toString
std::string toString(int precision=-1, int width=-1, const char *endRowStr="\n") const
Print matrix to a string.
Definition: Matrix.cpp:167
yarp::math::FrameTransform
Definition: FrameTransform.h:21
yarp::os::Bottle::clear
void clear()
Empties the bottle of any objects it contains.
Definition: Bottle.cpp:124
yarp::sig::VectorOf::resize
void resize(size_t size) override
Resize the vector.
Definition: Vector.h:254
Transforms_client_storage::clear
void clear()
Definition: FrameTransformClient.cpp:158
yarp::os::Searchable
A base class for nested structures that can be searched.
Definition: Searchable.h:69
Transforms_client_storage::getEstFrequency
void getEstFrequency(int &ite, double &av, double &min, double &max)
Definition: FrameTransformClient.cpp:141
yarp::math::Quaternion::fromRotationMatrix
void fromRotationMatrix(const yarp::sig::Matrix &R)
Converts a rotation matrix to a quaternion.
Definition: Quaternion.cpp:154
VOCAB_TRANSFORM_SET
constexpr yarp::conf::vocab32_t VOCAB_TRANSFORM_SET
Definition: IFrameTransform.h:168
Transforms_client_storage::m_mutex
std::recursive_mutex m_mutex
Definition: FrameTransformClient.h:61
yarp::os::Bottle::size
size_type size() const
Gets the number of elements in the bottle.
Definition: Bottle.cpp:254
FrameTransformClient::m_remote_streaming_name
std::string m_remote_streaming_name
Definition: FrameTransformClient.h:111
yarp::sig
Signal processing.
Definition: Image.h:25
t
float t
Definition: FfmpegWriter.cpp:74
FrameTransformClient.h
yCWarning
#define yCWarning(component,...)
Definition: LogComponent.h:146
FrameTransformClient::open
bool open(yarp::os::Searchable &config) override
Open the DeviceDriver.
Definition: FrameTransformClient.cpp:396
FrameTransformClient::FrameTransformClient
FrameTransformClient()
Definition: FrameTransformClient.cpp:917
FrameTransformClient::run
void run() override
Loop function.
Definition: FrameTransformClient.cpp:936
YARP_LOG_COMPONENT
#define YARP_LOG_COMPONENT(name,...)
Definition: LogComponent.h:80
FrameTransformClient::waitForTransform
bool waitForTransform(const std::string &target_frame_id, const std::string &source_frame_id, const double &timeout) override
Block until a transform from source_frame_id to target_frame_id is possible or it times out.
Definition: FrameTransformClient.cpp:901
FrameTransformClient::m_array_of_ports
std::vector< broadcast_port_t * > m_array_of_ports
Definition: FrameTransformClient.h:125
FrameTransformClient::getTransform
bool getTransform(const std::string &target_frame_id, const std::string &source_frame_id, yarp::sig::Matrix &transform) override
Get the transform between two frames.
Definition: FrameTransformClient.cpp:665
FrameTransformClient::allFramesAsString
bool allFramesAsString(std::string &all_frames) override
Creates a debug string containing the list of all registered frames.
Definition: FrameTransformClient.cpp:476
VOCAB_TRANSFORM_DELETE
constexpr yarp::conf::vocab32_t VOCAB_TRANSFORM_DELETE
Definition: IFrameTransform.h:169
ret
bool ret
Definition: ImplementAxisInfo.cpp:72
Transforms_client_storage::resetStat
void resetStat()
Definition: FrameTransformClient.cpp:40
yarp::os::Bottle::addFloat64
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
yarp::math
Definition: FrameTransform.h:18
yarp::os::Time::now
double now()
Return the current time in seconds, relative to an arbitrary starting point.
Definition: Time.cpp:124
yarp::dev
An interface for the device drivers.
Definition: audioBufferSizeData.cpp:17
yarp::os::SystemClock::nowSystem
static double nowSystem()
Definition: SystemClock.cpp:37
FrameTransformClient::reconnectWithServer
bool reconnectWithServer() override
Attempts to reconnect the client with the server.
Definition: FrameTransformClient.cpp:975
FrameTransformClient::getParent
bool getParent(const std::string &frame_id, std::string &parent_frame_id) override
Get the parent of a frame.
Definition: FrameTransformClient.cpp:603
yarp::sig::VectorOf< double >
FrameTransformClient::transformPose
bool transformPose(const std::string &target_frame_id, const std::string &source_frame_id, const yarp::sig::Vector &input_pose, yarp::sig::Vector &transformed_pose) override
Transform a Stamped Pose into the target frame.
Definition: FrameTransformClient.cpp:853
FrameTransformClient::isConnectedWithServer
bool isConnectedWithServer() override
Returns true if the client is connected with the server, false otherwise.
Definition: FrameTransformClient.cpp:964
Log.h
yarp::os::Bottle::get
Value & get(size_type index) const
Reads a Value v from a certain part of the list.
Definition: Bottle.cpp:249
yarp::os::Bottle::write
bool write(ConnectionWriter &writer) const override
Output a representation of the bottle to a network connection.
Definition: Bottle.cpp:233
Math.h
yarp::os::ConnectionWriter
An interface for writing to a network connection.
Definition: ConnectionWriter.h:40
yarp::os::SystemClock::delaySystem
static void delaySystem(double seconds)
Definition: SystemClock.cpp:32
yarp::sig::Matrix::eye
const Matrix & eye()
Build an identity matrix, don't resize.
Definition: Matrix.cpp:429
FrameTransformClient::close
bool close() override
Close the DeviceDriver.
Definition: FrameTransformClient.cpp:464
yarp::sig::VectorOf::pop_back
void pop_back()
Pop an element out of the vector: size is changed.
Definition: Vector.h:310
yarp::os::Value::asString
virtual std::string asString() const
Get string value.
Definition: Value.cpp:237
Transforms_client_storage::getLast
int getLast(yarp::os::Bottle &data, yarp::os::Stamp &stmp)
Definition: FrameTransformClient.cpp:119
yarp::os::Searchable::check
virtual bool check(const std::string &key) const =0
Check if there exists a property of the given name.
yarp::dev::IFrameTransform::TRANSFORM_OK
@ TRANSFORM_OK
Definition: IFrameTransform.h:37
yarp::os::Searchable::find
virtual Value & find(const std::string &key) const =0
Gets a value corresponding to a given keyword.
yarp::os::Vocab::encode
NetInt32 encode(const std::string &str)
Convert a string into a vocabulary identifier.
Definition: Vocab.cpp:14
yarp::math::Quaternion
Definition: Quaternion.h:27
yarp::os::ConnectionReader::getWriter
virtual ConnectionWriter * getWriter()=0
Gets a way to reply to the message, if possible.
Transforms_client_storage::getIterations
int getIterations()
Definition: FrameTransformClient.cpp:133
FrameTransformClient::canTransform
bool canTransform(const std::string &target_frame, const std::string &source_frame) override
Test if a transform exists.
Definition: FrameTransformClient.cpp:538
Transforms_client_storage::onRead
void onRead(yarp::os::Bottle &v) override
Definition: FrameTransformClient.cpp:45
yarp::os::Bottle::addString
void addString(const char *str)
Places a string in the bottle, at the end of the list.
Definition: Bottle.cpp:173
FrameTransformClient::transformPoint
bool transformPoint(const std::string &target_frame_id, const std::string &source_frame_id, const yarp::sig::Vector &input_point, yarp::sig::Vector &transformed_point) override
Transform a point into the target frame.
Definition: FrameTransformClient.cpp:833
yarp::dev::IFrameTransform::TRANSFORM_GENERAL_ERROR
@ TRANSFORM_GENERAL_ERROR
Definition: IFrameTransform.h:38
yarp::os::PeriodicThread
An abstraction for a periodic thread.
Definition: PeriodicThread.h:25
FrameTransformClient::clear
bool clear() override
Removes all the registered transforms.
Definition: FrameTransformClient.cpp:543
FrameTransformClient::setTransformStatic
bool setTransformStatic(const std::string &target_frame_id, const std::string &source_frame_id, const yarp::sig::Matrix &transform) override
Register a static transform between two frames.
Definition: FrameTransformClient.cpp:754
yarp::os::Bottle::addVocab
void addVocab(int x)
Places a vocabulary item in the bottle, at the end of the list.
Definition: Bottle.cpp:167
LogComponent.h
FrameTransformClient::broadcast_port_t::transform_src
std::string transform_src
Definition: FrameTransformClient.h:122
FrameTransformClient::m_local_rpcServer
std::string m_local_rpcServer
Definition: FrameTransformClient.h:108
VOCAB_ERR
constexpr yarp::conf::vocab32_t VOCAB_ERR
Definition: GenericVocabs.h:20
yarp::os::ConnectionReader
An interface for reading from a network connection.
Definition: ConnectionReader.h:40
yarp::os::Stamp
An abstraction for a time stamp and/or sequence number.
Definition: Stamp.h:25
yCError
#define yCError(component,...)
Definition: LogComponent.h:157
yarp::os::Value::asInt32
virtual std::int32_t asInt32() const
Get 32-bit integer value.
Definition: Value.cpp:207
yCInfo
#define yCInfo(component,...)
Definition: LogComponent.h:135
yarp::os
An interface to the operating system, including Port based communication.
Definition: AbstractCarrier.h:17
FrameTransformClient::setTransform
bool setTransform(const std::string &target_frame_id, const std::string &source_frame_id, const yarp::sig::Matrix &transform) override
Register a transform between two frames.
Definition: FrameTransformClient.cpp:700
Transforms_client_storage::size
size_t size()
Definition: FrameTransformClient.cpp:186
FrameTransformClient::deleteTransform
bool deleteTransform(const std::string &target_frame_id, const std::string &source_frame_id) override
Deletes a transform between two frames.
Definition: FrameTransformClient.cpp:808
FrameTransformClient::m_remote_rpc
std::string m_remote_rpc
Definition: FrameTransformClient.h:110
yarp::os::Bottle::read
bool read(ConnectionReader &reader) override
Set the bottle's value based on input from a network connection.
Definition: Bottle.cpp:243
yarp::os::Value::asList
virtual Bottle * asList() const
Get list value.
Definition: Value.cpp:243
tf
Definition: FrameGraph.h:22
FrameTransformClient::read
bool read(yarp::os::ConnectionReader &connection) override
Read this object from a network connection.
Definition: FrameTransformClient.cpp:199
yarp::sig::VectorOf::size
size_t size() const
Definition: Vector.h:355
yCTrace
#define yCTrace(component,...)
Definition: LogComponent.h:88
FrameTransformClient::m_local_streaming_name
std::string m_local_streaming_name
Definition: FrameTransformClient.h:112
FrameTransformClient::getAllFrameIds
bool getAllFrameIds(std::vector< std::string > &ids) override
Gets a vector containing all the registered frames.
Definition: FrameTransformClient.cpp:578
FrameTransformClient::threadRelease
void threadRelease() override
Release method.
Definition: FrameTransformClient.cpp:931
FrameTransformClient::m_streaming_connection_type
std::string m_streaming_connection_type
Definition: FrameTransformClient.h:114
yarp::os::Value::asFloat64
virtual yarp::conf::float64_t asFloat64() const
Get 64-bit floating point value.
Definition: Value.cpp:225
yarp::sig::VectorOf::push_back
void push_back(const T &elem)
Push a new element in the vector: size is changed.
Definition: Vector.h:282
FrameTransformClient::frameExists
bool frameExists(const std::string &frame_id) override
Check if a frame exists.
Definition: FrameTransformClient.cpp:568
yarp::math::SE3inv
yarp::sig::Matrix SE3inv(const yarp::sig::Matrix &H)
Returns the inverse of a 4 by 4 rototranslational matrix (defined in Math.h).
Definition: math.cpp:883
FrameTransformClient::threadInit
bool threadInit() override
Initialization method.
Definition: FrameTransformClient.cpp:925
VOCAB_OK
constexpr yarp::conf::vocab32_t VOCAB_OK
Definition: GenericVocabs.h:18
FrameTransformClient::broadcast_port_t
Definition: FrameTransformClient.h:119
FrameTransformClient::~FrameTransformClient
~FrameTransformClient()
VOCAB_TRANSFORM_DELETE_ALL
constexpr yarp::conf::vocab32_t VOCAB_TRANSFORM_DELETE_ALL
Definition: IFrameTransform.h:170
yarp::dev::IFrameTransform::TRANSFORM_TIMEOUT
@ TRANSFORM_TIMEOUT
Definition: IFrameTransform.h:39
yarp::sig::Matrix
A class for a Matrix.
Definition: Matrix.h:46
VOCAB_ITRANSFORM
constexpr yarp::conf::vocab32_t VOCAB_ITRANSFORM
Definition: IFrameTransform.h:167