YARP
Yet Another Robot Platform
 
Loading...
Searching...
No Matches
FrameTransformClient.cpp
Go to the documentation of this file.
1/*
2 * SPDX-FileCopyrightText: 2006-2021 Istituto Italiano di Tecnologia (IIT)
3 * SPDX-License-Identifier: LGPL-2.1-or-later
4 */
5
6#define _USE_MATH_DEFINES
7#include <cmath>
8
10
11#include <yarp/os/Log.h>
13#include <yarp/os/LogStream.h>
15#include <yarp/math/Math.h>
16
17#include <cmrc/cmrc.hpp>
18#include <mutex>
19#include <fstream>
20
22
23using namespace yarp::dev;
24using namespace yarp::os;
25using namespace yarp::sig;
26using namespace yarp::math;
27
28namespace {
29YARP_LOG_COMPONENT(FRAMETRANSFORMCLIENT, "yarp.device.FrameTransformClient")
30}
31#define LOG_THROTTLE_PERIOD 1.0
32
33//------------------------------------------------------------------------------------------------------------------------------
35{
36 std::lock_guard<std::mutex> lock (m_rpc_mutex);
39 bool ok = in.read(connection);
40 if (!ok) {
41 return false;
42 }
43
44 std::string request = in.get(0).asString();
45 if (request == "help")
46 {
47 out.addVocab32("many");
48 out.addString("get_transform <src> <dst>: print the transform from <src> to <dst>");
49 out.addString("list_transforms: print all the stored frame transforms");
50 out.addString("list_frames: print all the available reference frames");
51 out.addString("list_ports: print all the opened ports for transform broadcasting");
52 out.addString("publish_transform <src> <dst> <portname> [format]: opens a port to publish transform from src to dst");
53 out.addString("unpublish_transform <portname>: closes a previously opened port to publish a transform");
54 out.addString("unpublish_all: closes a all previously opened ports to publish a transform");
55 out.addString("set_static_transform_rad <src> <dst> <x> <y> <z> <roll> <pitch> <yaw>': create a static transform (angles in radians)");
56 out.addString("set_static_transform_deg <src> <dst> <x> <y> <z> <roll> <pitch> <yaw>': create a static transform (angles in degrees)");
57 out.addString("delete_static_transform <src> <dst>': delete a static transform");
58 out.addString("generate_view <option>': generate a frames.pdf file showing the transform tree diagram.");
59 out.addString(" The following values are valid for option (default=none)");
60 out.addString(" 'show_rpy': show rotation as rpy angles");
61 out.addString(" 'show_quaterion:'show rotation as a quaternion");
62 out.addString(" 'show_matrix:'show rotation as a 3x3 rotation matrix");
63 }
64 else if (request == "list_frames")
65 {
66 std::vector<std::string> v;
67 this->getAllFrameIds(v);
68 out.addVocab32("many");
69 out.addString("List of available reference frames:");
70 int count = 0;
71 for (auto& vec : v)
72 {
73 count++;
74 std::string str = std::to_string(count) + "- " + vec;
75 out.addString(str.c_str());
76 }
77 }
78 else if (request == "get_transform")
79 {
80 std::string src = in.get(1).asString();
81 std::string dst = in.get(2).asString();
82 out.addVocab32("many");
84 this->getTransform(src, dst, m);
85 out.addString("Transform from " + src + " to " + dst + " is: ");
86 out.addString(m.toString());
87 }
88 else if (request == "list_ports")
89 {
90 out.addVocab32("many");
91 if (m_array_of_ports.size()==0)
92 {
93 out.addString("No ports are currently active");
94 }
96 {
98 {
99 std::string s = m_array_of_port->port.getName() + " "+ m_array_of_port->transform_src + " -> " + m_array_of_port->transform_dst;
100 out.addString(s);
101 }
102 }
103 }
104 else if (request == "publish_transform")
105 {
106 out.addVocab32("many");
107 std::string src = in.get(1).asString();
108 std::string dst = in.get(2).asString();
109 std::string port_name = in.get(3).asString();
110 std::string format_s = "matrix";
112 if (in.size() == 5) {format_s = in.get(4).asString();}
113
115 else {yCError(FRAMETRANSFORMCLIENT) << "Invalid format" << format_s << "using format `matrix`. Only `matrix` is currently supported."; }
116
117 if (port_name[0] == '/') {
118 port_name.erase(port_name.begin());
119 }
120 std::string full_port_name = m_local_name + "/" + port_name;
121
122 //print a warning if the frames do not exists yet
123 bool exists = false;
124 auto r1 = this->frameExists(src, exists);
125 if (!r1) { return r1; }
126 if (exists == false)
127 {
128 out.addString("Requested src frame " + src + " does not exists.");
129 yCWarning(FRAMETRANSFORMCLIENT, "Requested src frame %s does not exists.", src.c_str());
130 }
131 auto r2 = this->frameExists(dst, exists);
132 if (!r2) { return r2; }
133 if (exists == false)
134 {
135 out.addString("Requested dst frame " + dst + " does not exists.");
136 yCWarning(FRAMETRANSFORMCLIENT, "Requested dst frame %s does not exists.", dst.c_str());
137 }
138
139 //check if the port is already active in yarp
141 if (port_already_exists) { yCError(FRAMETRANSFORMCLIENT, "Requested port already exists!"); }
142
143 //check if the port is already registered by the system
144 bool bcast_already_exists = false;
146 {
148 {
149 bcast_already_exists |= true;
150 break;
151 }
152 }
153
154 //create the broadcaster
155 if (bcast_already_exists == false && port_already_exists == false)
156 {
157 auto* b = new broadcast_port_t;
158 b->transform_src = src;
159 b->transform_dst = dst;
160 b->format = eformat;
161 bool pret = b->port.open(full_port_name);
162 if (pret)
163 {
164 out.addString("Operation complete. Port " + full_port_name + " opened.");
165 m_array_of_ports.push_back(b);
166 if (m_array_of_ports.size() == 1) {
167 this->start();
168 }
169 }
170 else
171 {
172 delete b;
173 out.addString("Operation failed. Unable to open port " + full_port_name + ".");
174 }
175 }
176 else
177 {
178 out.addString("unable to perform operation");
179 }
180 }
181 else if (request == "unpublish_all")
182 {
184 {
185 m_array_of_port->port.close();
186 delete m_array_of_port;
187 m_array_of_port=nullptr;
188 }
189 m_array_of_ports.clear();
190 if (m_array_of_ports.size() == 0) {
191 this->askToStop();
192 }
193 out.addString("Operation complete");
194 }
195 else if (request == "unpublish_transform")
196 {
197 bool ret = false;
198 std::string port_name = in.get(1).asString();
199 if (port_name[0] == '/') {
200 port_name.erase(port_name.begin());
201 }
202 std::string full_port_name = m_local_name + "/" + port_name;
203 for (auto it = m_array_of_ports.begin(); it != m_array_of_ports.end(); it++)
204 {
205 if ((*it)->port.getName() == port_name)
206 {
207 (*it)->port.close();
208 delete (*it);
209 (*it)=nullptr;
210 m_array_of_ports.erase(it);
211 ret = true;
212 break;
213 }
214 }
215 if (ret)
216 {
217 out.addString("Port " + full_port_name + " has been closed.");
218 }
219 else
220 {
221 out.addString("Port " + full_port_name + " was not found.");
222 }
223 if (m_array_of_ports.size() == 0) {
224 this->askToStop();
225 }
226 }
227 else if (request == "set_static_transform_rad" ||
228 request == "set_static_transform_deg")
229 {
231 t.src_frame_id = in.get(1).asString();
232 t.dst_frame_id = in.get(2).asString();
233 t.translation.tX = in.get(3).asFloat64();
234 t.translation.tY = in.get(4).asFloat64();
235 t.translation.tZ = in.get(5).asFloat64();
236 if (request == "set_static_transform_rad")
237 {
238 t.rotFromRPY(in.get(6).asFloat64(),
239 in.get(7).asFloat64(),
240 in.get(8).asFloat64());
241 }
242 else if (request == "set_static_transform_deg")
243 {
244 t.rotFromRPY(in.get(6).asFloat64() * 180 / M_PI,
245 in.get(7).asFloat64() * 180 / M_PI,
246 in.get(8).asFloat64() * 180 / M_PI);
247 }
250 if (ret == true)
251 {
252 yCInfo(FRAMETRANSFORMCLIENT) << "set_static_transform done";
253 out.addString("set_static_transform done");
254 }
255 else
256 {
257 yCError(FRAMETRANSFORMCLIENT) << "read(): something strange happened";
258 out.addString("error");
259 }
260 }
261 else if (request == "generate_view")
262 {
264 if (in.get(1).asString() == "show_quaternion") {
266 } else if (in.get(1).asString() == "show_matrix") {
268 } else if (in.get(1).asString() == "show_rpy") {
270 }
272 out.addString("ok");
273 }
274 else if (request == "delete_static_transform")
275 {
276 std::string src = in.get(1).asString();
277 std::string dst = in.get(2).asString();
278 //@@@check if the transform is static?
279 this->deleteTransform(src,dst);
280 out.addString("delete_static_transform done");
281 }
282 else
283 {
284 yCError(FRAMETRANSFORMCLIENT, "Invalid vocab received in FrameTransformClient");
285 out.clear();
287 out.addString("Invalid command name");
288 }
289
291 if (returnToSender != nullptr)
292 {
293 out.write(*returnToSender);
294 }
295 else
296 {
297 yCError(FRAMETRANSFORMCLIENT) << "Invalid return to sender";
298 }
299 return true;
300}
301
303{
304 yCWarning(FRAMETRANSFORMCLIENT) << "The 'FrameTransformClient' device is experimental and could be modified without any warning";
305
306 if (!this->parseParams(config)) { return false; }
307
308 std::string cfg_string = config.toString();
310 cfg.fromString(cfg_string);
311
312 std::string configuration_to_open;
313 std::string innerFilePath="config_xml/ftc_local_only.xml";
314 if(!m_testxml_from.empty())
315 {
317 if(!m_testxml_context.empty())
318 {
319 findXml.setDefaultContext(m_testxml_context);
320 }
321 innerFilePath = findXml.findFileByName(m_testxml_from);
322 std::ifstream xmlFile(innerFilePath);
323 std::stringstream stream_file;
324 stream_file << xmlFile.rdbuf();
326 }
327 else
328 {
329 auto fs = cmrc::frameTransformRC::get_filesystem();
330 if(!m_filexml_option.empty()) { innerFilePath="config_xml/"+ m_filexml_option;}
331 cfg.unput("filexml_option");
332 auto xmlFile = fs.open(innerFilePath);
333 for(const auto& lemma : xmlFile)
334 {
336 }
337 }
338
339 cfg.unput("local_rpc");
340
342 {
343 yarp::os::Value vval (true);
344 cfg.put("FrameTransform_verbose_debug", vval);
345 }
346
349 if (result.parsingIsSuccessful==false)
350 {
351 yCError(FRAMETRANSFORMCLIENT) << "Unable to parse configuration";
352 return false;
353 }
354
355 m_robot = std::move(result.robot);
356
358 return false;
359 }
360
362 return false;
363 }
364
365 std::string setdeviceName;
366 if (m_robot.hasParam("setDeviceName"))
367 {
368 setdeviceName = m_robot.findParam("setDeviceName");
370 {
371 yCError(FRAMETRANSFORMCLIENT) << "Set device specified (" << setdeviceName << ") was not found in the configuration. The configuration is wrongly written, please check again";
372 return false;
373 }
374 else
375 {
377 if (!polyset || !polyset->view(m_ift_set))
378 {
379 yCError(FRAMETRANSFORMCLIENT) << "Failed to open device driver / interface for " << setdeviceName;
380 return false;
381 }
382 }
383 }
384 else
385 {
386 yCWarning(FRAMETRANSFORMCLIENT) << "Set device name was not provided in the specified configuration. Set operations will not be available";
387 }
388
389 std::string getdeviceName;
390 if (m_robot.hasParam("getDeviceName"))
391 {
392 getdeviceName = m_robot.findParam("getDeviceName");
394 {
395 yCError(FRAMETRANSFORMCLIENT) << "Get device specified (" << getdeviceName << ") was not found in the configuration. The configuration is wrongly written, please check again";
396 return false;
397 }
398 else
399 {
401 if (!polyget || !polyget->view(m_ift_get) || !polyget->view(m_ift_util))
402 {
403 yCError(FRAMETRANSFORMCLIENT) << "Failed to open device driver / interface for " << getdeviceName;
404 return false;
405 }
406 }
407 }
408 else
409 {
410 yCWarning(FRAMETRANSFORMCLIENT) << "Get device name was not provided in the specified configuration. Get operations will not be available";
411 }
412
414 {
415 yCError(FRAMETRANSFORMCLIENT,"Failed to open rpc port");
416 }
417
419
420 return true;
421}
422
434
436{
437 if(!m_ift_util)
438 {
439 yCError(FRAMETRANSFORMCLIENT, "%s: No IFrameTransformStorageUtils interface found. Your device is wrongly configured", __func__);
440 return ReturnValue::return_code::return_value_error_generic;
441 }
444 if (!br || p_cont == nullptr) { yCError(FRAMETRANSFORMCLIENT) << "Failure"; return ReturnValue::return_code::return_value_error_generic; }
445
446 //protect the internal container from concurrent access
447 std::lock_guard<std::recursive_mutex> l(p_cont->m_trf_mutex);
448
449 //process data
450 for (auto it = p_cont->begin(); it != p_cont->end(); it++)
451 {
452 all_frames += it->toString() + " ";
453 }
454 return ReturnValue_ok;
455}
456
457FrameTransformClient::ConnectionType FrameTransformClient::priv_getConnectionType(const std::string &target_frame, const std::string &source_frame, std::string* commonAncestor = nullptr)
458{
459 if (target_frame == source_frame) {return ConnectionType::IDENTITY;}
460
463 if (!br || p_cont == nullptr) { yCError(FRAMETRANSFORMCLIENT) << "Failure"; return ConnectionType::DISCONNECTED; }
464
465 size_t i, j;
466 std::vector<std::string> tar2root_vec;
467 std::vector<std::string> src2root_vec;
468 std::string ancestor, child;
470
471 //protect the internal container from concurrent access
472 std::lock_guard<std::recursive_mutex> l(p_cont->m_trf_mutex);
473
474 //process data
475 while(getParent(child, ancestor))
476 {
478 {
479 return ConnectionType::DIRECT;
480 }
481
482 tar2root_vec.push_back(ancestor);
483 child = ancestor;
484 }
486 while(getParent(child, ancestor))
487 {
489 {
490 return ConnectionType::INVERSE;
491 }
492
493 src2root_vec.push_back(ancestor);
494 child = ancestor;
495 }
496
497 for(i = 0; i < tar2root_vec.size(); i++)
498 {
499 std::string a;
500 a = tar2root_vec[i];
501 for(j = 0; j < src2root_vec.size(); j++)
502 {
503 if(a == src2root_vec[j])
504 {
506 {
507 *commonAncestor = a;
508 }
509 return ConnectionType::UNDIRECT;
510 }
511 }
512 }
513
514 return ConnectionType::DISCONNECTED;
515}
516
517yarp::dev::ReturnValue FrameTransformClient::canTransform(const std::string &target_frame, const std::string &source_frame, bool& canTransform)
518{
519 if(!m_ift_util)
520 {
521 yCError(FRAMETRANSFORMCLIENT, "%s: No IFrameTransformStorageUtils interface found. Your device is wrongly configured", __func__);
522 return ReturnValue::return_code::return_value_error_generic;
523 }
524 auto conntype = priv_getConnectionType(target_frame, source_frame);
525 if (conntype != ConnectionType::DISCONNECTED)
526 {
527 canTransform = true;
528 }
529 else
530 {
531 canTransform = false;
532 }
533 return ReturnValue_ok;
534}
535
537{
538 if(!m_ift_set)
539 {
540 yCError(FRAMETRANSFORMCLIENT, "%s: No IFrameTransformStorageSet interface found. Your device is wrongly configured",__func__);
541 return ReturnValue::return_code::return_value_error_not_ready;
542 }
543 if (m_ift_set)
544 {
545 return m_ift_set->clearAll();
546 }
547 yCError(FRAMETRANSFORMCLIENT, "clear(): interface not available");
548 return ReturnValue::return_code::return_value_error_not_ready;
549}
550
551yarp::dev::ReturnValue FrameTransformClient::frameExists(const std::string &frame_id, bool& exists)
552{
553 if(!m_ift_util)
554 {
555 yCError(FRAMETRANSFORMCLIENT, "%s: No IFrameTransformStorageUtils interface found. Your device is wrongly configured", __func__);
556 return ReturnValue::return_code::return_value_error_not_ready;
557 }
560 if (!br || p_cont == nullptr) { yCError(FRAMETRANSFORMCLIENT) << "Failure"; return ReturnValue::return_code::return_value_error_generic; }
561
562 //protect the internal container from concurrent access
563 std::lock_guard<std::recursive_mutex> l(p_cont->m_trf_mutex);
564
565 //process data
566 for (auto it = p_cont->begin(); it != p_cont->end(); it++)
567 {
568 if (it->src_frame_id == frame_id) { exists = true; return ReturnValue_ok; }
569 if (it->dst_frame_id == frame_id) { exists = true; return ReturnValue_ok; }
570 }
571
572 // condition reached if not found or container is empty
573 exists = false;
574 return ReturnValue_ok;
575}
576
578{
579 if(!m_ift_util)
580 {
581 yCError(FRAMETRANSFORMCLIENT, "%s: No IFrameTransformStorageUtils interface found. Your device is wrongly configured",__func__);
582 return ReturnValue::return_code::return_value_error_not_ready;
583 }
586 if (!br || p_cont == nullptr) { yCError(FRAMETRANSFORMCLIENT) << "Failure"; return ReturnValue::return_code::return_value_error_generic; }
587
588 //protect the internal container from concurrent access
589 std::lock_guard<std::recursive_mutex> l(p_cont->m_trf_mutex);
590
591 //process data
592 for (auto it = p_cont->begin(); it != p_cont->end(); it++)
593 {
594 bool found = false;
595 for (const auto& id : ids)
596 {
597 if (it->src_frame_id == id) { found = true; break; }
598 }
599 if (found == false) {
600 ids.push_back(it->src_frame_id);
601 }
602 }
603
604 for (auto it = p_cont->begin(); it != p_cont->end(); it++)
605 {
606 bool found = false;
607 for (const auto& id : ids)
608 {
609 if (it->dst_frame_id == id) { found = true; break; }
610 }
611 if (found == false) {
612 ids.push_back(it->dst_frame_id);
613 }
614 }
615
616 return ReturnValue_ok;
617}
618
620{
621 if(!m_ift_util)
622 {
623 yCError(FRAMETRANSFORMCLIENT, "%s: No IFrameTransformStorageUtils interface found. Your device is wrongly configured",__func__);
624 return ReturnValue::return_code::return_value_error_not_ready;
625 }
628 if (!br || p_cont == nullptr) { yCError(FRAMETRANSFORMCLIENT) << "Failure"; return ReturnValue::return_code::return_value_error_generic; }
629
630 //protect the internal container from concurrent access
631 std::lock_guard<std::recursive_mutex> l(p_cont->m_trf_mutex);
632
633 //process data
634 for (auto it = p_cont->begin(); it != p_cont->end(); it++)
635 {
636 std::string par(it->dst_frame_id);
637 if (it->dst_frame_id == frame_id)
638 {
639 parent_frame_id = it->src_frame_id;
640 return ReturnValue_ok;
641 }
642 }
643 return ReturnValue::return_code::return_value_error_method_failed;
644}
645
646bool FrameTransformClient::priv_canExplicitTransform(const std::string& target_frame_id, const std::string& source_frame_id) const
647{
650 if (!br || p_cont == nullptr) {yCError(FRAMETRANSFORMCLIENT) << "Failure"; return false; }
651
652 //protect the internal container from concurrent access
653 std::lock_guard<std::recursive_mutex> l(p_cont->m_trf_mutex);
654
655 //process data
656 for (auto it = p_cont->begin(); it != p_cont->end(); it++)
657 {
658 if (it->dst_frame_id == target_frame_id && it->src_frame_id == source_frame_id)
659 {
660 return true;
661 }
662 }
663 return false;
664}
665
666bool FrameTransformClient::priv_getChainedTransform(const std::string& target_frame_id, const std::string& source_frame_id, yarp::sig::Matrix& transform) const
667{
670 if (!br || p_cont == nullptr) { yCError(FRAMETRANSFORMCLIENT) << "Failure"; return false; }
671
672 //protect the internal container from concurrent access
673 std::lock_guard<std::recursive_mutex> l(p_cont->m_trf_mutex);
674
675 //process data
676 for (auto it = p_cont->begin(); it != p_cont->end(); it++)
677 {
678 if (it->dst_frame_id == target_frame_id)
679 {
680 if (it->src_frame_id == source_frame_id)
681 {
682 transform = it->toMatrix();
683 return true;
684 }
685 else
686 {
688 if (priv_getChainedTransform(it->src_frame_id, source_frame_id, m))
689 {
690 transform = m * it->toMatrix();
691 return true;
692 }
693 }
694 }
695 }
696 return false;
697}
698
700{
701 if(!m_ift_util)
702 {
703 yCError(FRAMETRANSFORMCLIENT, "%s: No IFrameTransformStorageUtils interface found. Your device is wrongly configured",__func__);
704 return ReturnValue::return_code::return_value_error_not_ready;
705 }
706 ConnectionType ct;
707 std::string ancestor;
708 ct = priv_getConnectionType(target_frame_id, source_frame_id, &ancestor);
709 if (ct == ConnectionType::DIRECT)
710 {
711 bool ok = priv_getChainedTransform(target_frame_id, source_frame_id, transform);
712 if (ok)
713 {
714 return ReturnValue_ok;
715 }
716 else
717 {
718 return ReturnValue::return_code::return_value_error_method_failed;
719 }
720 }
721 else if (ct == ConnectionType::INVERSE)
722 {
723 yarp::sig::Matrix m(4, 4);
724 priv_getChainedTransform(source_frame_id, target_frame_id, m);
725 transform = yarp::math::SE3inv(m);
726 return ReturnValue_ok;
727 }
728 else if(ct == ConnectionType::UNDIRECT)
729 {
731 priv_getChainedTransform(source_frame_id, ancestor, root2src);
732 priv_getChainedTransform(target_frame_id, ancestor, root2tar);
733 transform = yarp::math::SE3inv(root2src) * root2tar;
734 return ReturnValue_ok;
735 }
736 else if (ct == ConnectionType::IDENTITY)
737 {
738 yarp::sig::Matrix tmp(4, 4); tmp.eye();
739 transform = tmp;
740 return ReturnValue_ok;
741 }
742
743 yCErrorThrottle(FRAMETRANSFORMCLIENT, LOG_THROTTLE_PERIOD) << "getTransform(): Frames " << source_frame_id << " and " << target_frame_id << " are not connected";
744 return ReturnValue::return_code::return_value_error_method_failed;
745}
746
748{
749 if(!m_ift_util)
750 {
751 yCError(FRAMETRANSFORMCLIENT, "%s: No IFrameTransformStorageUtils interface found. Your device is wrongly configured",__func__);
752 return ReturnValue::return_code::return_value_error_not_ready;
753 }
755 {
756 yCErrorThrottle(FRAMETRANSFORMCLIENT, LOG_THROTTLE_PERIOD) << "setTransform(): Invalid transform detected.\n" \
757 "\t Source frame and target frame are both equal to " << source_frame_id;
758 return ReturnValue::return_code::return_value_error_method_failed;
759 }
760
761 bool b1 = priv_canExplicitTransform(target_frame_id, source_frame_id);
762 bool bcanTransform = false;
764 if (!retc) { return retc; }
765 if (!b1 && bcanTransform)
766 {
767 yCErrorThrottle(FRAMETRANSFORMCLIENT, LOG_THROTTLE_PERIOD) << "setTransform(): Such transform already exist by chaining transforms";
768 return ReturnValue::return_code::return_value_error_method_failed;
769 }
770
774
775 if (!tf.fromMatrix(transform))
776 {
777 yCErrorThrottle(FRAMETRANSFORMCLIENT, LOG_THROTTLE_PERIOD) << "setTransform(): Wrong matrix format, it has to be 4 by 4";
778 return ReturnValue::return_code::return_value_error_method_failed;
779 }
780
781 tf.src_frame_id = source_frame_id;
782 tf.dst_frame_id = target_frame_id;
783 tf.isStatic = false;
784 tf.timestamp = yarp::os::Time::now();
785
786 if (m_ift_set)
787 {
788 return m_ift_set->setTransform(tf);
789 }
790 yCError(FRAMETRANSFORMCLIENT, "setTransform(): interface not available");
791 return ReturnValue::return_code::return_value_error_not_ready;
792}
793
795{
796 if(!m_ift_util)
797 {
798 yCError(FRAMETRANSFORMCLIENT, "%s: No IFrameTransformStorageUtils interface found. Your device is wrongly configured",__func__);
799 return ReturnValue::return_code::return_value_error_not_ready;
800 }
802 {
803 yCErrorThrottle(FRAMETRANSFORMCLIENT, LOG_THROTTLE_PERIOD) << "setTransformStatic(): Invalid transform detected.\n" \
804 "\t Source frame and target frame are both equal to " << source_frame_id;
805 return ReturnValue::return_code::return_value_error_method_failed;
806 }
807
808 bool bcanTransform = false;
810 if (bcanTransform)
811 {
812 yCErrorThrottle(FRAMETRANSFORMCLIENT, LOG_THROTTLE_PERIOD) << "setTransform(): Such static transform already exist, directly or by chaining transforms";
813 return ReturnValue::return_code::return_value_error_method_failed;
814 }
815
817 if (!tf.fromMatrix(transform))
818 {
819 yCErrorThrottle(FRAMETRANSFORMCLIENT, LOG_THROTTLE_PERIOD) << "setTransform(): Wrong matrix format, it has to be 4 by 4";
820 return ReturnValue::return_code::return_value_error_method_failed;
821 }
822 tf.src_frame_id = source_frame_id;
823 tf.dst_frame_id = target_frame_id;
824 tf.isStatic = true;
825 tf.timestamp= yarp::os::Time::now();
826
827 if (m_ift_set)
828 {
829 return m_ift_set->setTransform(tf);
830 }
831 yCError(FRAMETRANSFORMCLIENT, "setTransformStatic(): interface not available");
832 return ReturnValue::return_code::return_value_error_not_ready;
833}
834
836{
837 if (m_ift_set)
838 {
840 }
841 yCError(FRAMETRANSFORMCLIENT, "deleteTransform(): interface not available");
842 return ReturnValue::return_code::return_value_error_not_ready;
843}
844
846{
847 if(!m_ift_util)
848 {
849 yCError(FRAMETRANSFORMCLIENT, "%s: No IFrameTransformStorageUtils interface found. Your device is wrongly configured",__func__);
850 return ReturnValue::return_code::return_value_error_not_ready;
851 }
852 if (input_point.size() != 3)
853 {
854 yCErrorThrottle(FRAMETRANSFORMCLIENT, LOG_THROTTLE_PERIOD) << "Only 3 dimensional vector allowed.";
855 return ReturnValue::return_code::return_value_error_method_failed;
856 }
857 yarp::sig::Matrix m(4, 4);
859 {
860 yCErrorThrottle(FRAMETRANSFORMCLIENT, LOG_THROTTLE_PERIOD) << "No transform found between source '" << target_frame_id << "' and target '" << source_frame_id << "'";
861 return ReturnValue::return_code::return_value_error_method_failed;
862 }
864 in.push_back(1);
865 transformed_point = m * in;
866 transformed_point.pop_back();
867 return ReturnValue_ok;
868}
869
871{
872 if(!m_ift_util)
873 {
874 yCError(FRAMETRANSFORMCLIENT, "%s: No IFrameTransformStorageUtils interface found. Your device is wrongly configured",__func__);
875 return ReturnValue::return_code::return_value_error_not_ready;
876 }
877 if (input_pose.size() != 6)
878 {
879 yCErrorThrottle(FRAMETRANSFORMCLIENT, LOG_THROTTLE_PERIOD) << "Only 6 dimensional vector (3 axes + roll pith and yaw) allowed.";
880 return ReturnValue::return_code::return_value_error_method_failed;
881 }
882 if (transformed_pose.size() != 6)
883 {
884 yCWarning(FRAMETRANSFORMCLIENT, "transformPose(): Performance warning: size transformed_pose should be 6, resizing.");
885 transformed_pose.resize(6, 0.0);
886 }
887 yarp::sig::Matrix m(4, 4);
889 {
890 yCErrorThrottle(FRAMETRANSFORMCLIENT, LOG_THROTTLE_PERIOD) << "No transform found between source '" << target_frame_id << "' and target '" << source_frame_id << "'";
891 return ReturnValue::return_code::return_value_error_method_failed;
892 }
896 t.fromMatrix(m * t.toMatrix());
900
902 rot = t.getRPYRot();
903 transformed_pose[3] = rot[0];
904 transformed_pose[4] = rot[1];
905 transformed_pose[5] = rot[2];
906 return ReturnValue_ok;
907}
908
910{
911 if(!m_ift_util)
912 {
913 yCError(FRAMETRANSFORMCLIENT, "%s: No IFrameTransformStorageUtils interface found. Your device is wrongly configured",__func__);
914 return ReturnValue::return_code::return_value_error_not_ready;
915 }
916 yarp::sig::Matrix m(4, 4);
918 {
919 yCErrorThrottle(FRAMETRANSFORMCLIENT, LOG_THROTTLE_PERIOD) << "No transform found between source '" << target_frame_id << "' and target '" << source_frame_id <<"'";
920 return ReturnValue::return_code::return_value_error_method_failed;
921 }
924 transformed_quaternion.fromRotationMatrix(m * t.toMatrix());
925 return ReturnValue_ok;
926}
927
928yarp::dev::ReturnValue FrameTransformClient::waitForTransform(const std::string &target_frame_id, const std::string &source_frame_id, const double &timeout)
929{
930 if(!m_ift_util)
931 {
932 yCError(FRAMETRANSFORMCLIENT, "%s: No IFrameTransformStorageUtils interface found. Your device is wrongly configured",__func__);
933 return ReturnValue::return_code::return_value_error_not_ready;
934 }
935 //loop until canTransform == true or timeout expires
937 bool bcan = false;
938 while (!bcan) {
939 if (yarp::os::SystemClock::nowSystem() - start > timeout) {
940 yCError(FRAMETRANSFORMCLIENT) << "waitForTransform(): timeout expired";
941 return ReturnValue::return_code::return_value_error_method_failed;
942 }
945 if (!ret) { return ret;}
946 }
947 return ReturnValue_ok;
948}
949
953
955
957{
958 yCTrace(FRAMETRANSFORMCLIENT, "Thread started");
959 return true;
960}
961
963{
964 yCTrace(FRAMETRANSFORMCLIENT, "Thread stopped");
965}
966
968{
969 std::lock_guard<std::mutex> lock (m_rpc_mutex);
970 if (m_array_of_ports.size()==0)
971 {
972 return;
973 }
974
976 {
977 if (m_array_of_port)
978 {
979 std::string src = m_array_of_port->transform_src;
980 std::string dst = m_array_of_port->transform_dst;
982 this->getTransform(src, dst, m);
984 {
985 m_array_of_port->port.write(m);
986 }
987 else
988 {
989 yCErrorThrottle(FRAMETRANSFORMCLIENT, LOG_THROTTLE_PERIOD) << "Unknown format requested: " << (int)(m_array_of_port->format);
990 }
991 }
992 }
993}
994
996{
997 if (t == nullptr) {
998 return "";
999 }
1000
1002 {
1003 return "";
1004 }
1006 {
1007 return std::string(",label=\" ") + t->toString(FrameTransform::display_transform_mode_t::rotation_as_quaternion) + "\"";
1008 }
1010 {
1011 return std::string(",label=\" ") + t->toString(FrameTransform::display_transform_mode_t::rotation_as_matrix) + "\"";
1012 }
1014 {
1015 return std::string(",label=\" ") + t->toString(FrameTransform::display_transform_mode_t::rotation_as_rpy) + "\"";
1016 }
1017
1018 yCError(FRAMETRANSFORMCLIENT) << "get_matrix_as_text() invalid option";
1019 return "";
1020 /*
1021 //this is a test to use Latek display
1022 std::string s = "\\begin{ bmatrix } \
1023 1 & 2 & 3\\ \
1024 a & b & c \
1025 \\end{ bmatrix }";
1026 */
1027}
1028
1029
1031{
1034 if (!br || p_cont == nullptr) { yCError(FRAMETRANSFORMCLIENT) << "Failure"; return false; }
1035
1036 //protect the internal container from concurrent access
1037 std::lock_guard<std::recursive_mutex> l(p_cont->m_trf_mutex);
1038
1039 //process data
1040 std::string dot_string = "digraph G { ";
1041 for (auto it = p_cont->begin(); it != p_cont->end(); it++)
1042 {
1043 FrameTransform t = *it;
1044 std::string edge_text = priv_get_matrix_as_text(&t);
1045 std::string trf_text = it->src_frame_id + "->" +
1046 it->dst_frame_id + " " +
1047 "[color = black]";
1048 dot_string += trf_text + '\n';
1049 }
1050
1051 std::string legend = "\n\
1052 rankdir=LR\n\
1053 node[shape=plaintext]\n\
1054 subgraph cluster_01 {\n\
1055 label = \"Legend\";\n\
1056 key[label=<<table border=\"0\" cellpadding=\"2\" cellspacing=\"0\" cellborder=\"0\">\n\
1057 <tr><td align=\"right\" port=\"i1\">YARP timed transform</td></tr>\n\
1058 <tr><td align=\"right\" port=\"i2\">YARP static transform</td></tr>\n\
1059 </table>>]\n\
1060 key2[label=<<table border=\"0\" cellpadding=\"2\" cellspacing=\"0\" cellborder=\"0\">\n\
1061 <tr><td port = \"i1\">&nbsp;</td></tr>\n\
1062 <tr><td port = \"i2\">&nbsp;</td></tr>\n\
1063 </table>>]\n\
1064 key:i1:e -> key2:i1:w [color = blue]\n\
1065 key:i2:e -> key2:i2:w [color = blue, style=dashed]\n\
1066 } }";
1067
1068 std::string command_string = "printf '" + dot_string + legend + "' | dot -Tpdf > frames.pdf";
1069#if defined (__linux__)
1070 int ret = std::system("dot -V");
1071 if (ret != 0)
1072 {
1073 yCError(FRAMETRANSFORMCLIENT) << "dot executable not found. Please install graphviz.";
1074 return false;
1075 }
1076
1077 yCDebug(FRAMETRANSFORMCLIENT) << "Command string is:" << command_string;
1078 ret = std::system(command_string.c_str());
1079 if (ret != 0)
1080 {
1081 yCError(FRAMETRANSFORMCLIENT) << "The following command failed to execute:" << command_string;
1082 return false;
1083 }
1084#else
1085 yCError(FRAMETRANSFORMCLIENT) << "Not yet implemented. Available only Linux";
1086 return false;
1087#endif
1088 return true;
1089}
#define M_PI
#define LOG_THROTTLE_PERIOD
CMRC_DECLARE(frameTransformRC)
constexpr yarp::conf::vocab32_t VOCAB_ERR
bool ret
#define ReturnValue_ok
Definition ReturnValue.h:77
bool parseParams(const yarp::os::Searchable &config) override
Parse the DeviceDriver parameters.
yarp::dev::ReturnValue getParent(const std::string &frame_id, std::string &parent_frame_id) override
Get the parent of a frame.
yarp::dev::IFrameTransformStorageUtils * m_ift_util
yarp::dev::ReturnValue 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.
std::string priv_get_matrix_as_text(yarp::math::FrameTransform *t)
void threadRelease() override
Release method.
yarp::dev::ReturnValue 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.
yarp::dev::ReturnValue deleteTransform(const std::string &target_frame_id, const std::string &source_frame_id) override
Deletes a transform between two frames.
show_transforms_in_diagram_t m_show_transforms_in_diagram
yarp::dev::ReturnValue getTransform(const std::string &target_frame_id, const std::string &source_frame_id, yarp::sig::Matrix &transform) override
Get the transform between two frames.
yarp::dev::ReturnValue getAllFrameIds(std::vector< std::string > &ids) override
Gets a vector containing all the registered frames.
void run() override
Loop function.
yarp::dev::IFrameTransformStorageSet * m_ift_set
bool open(yarp::os::Searchable &config) override
Open the DeviceDriver.
yarp::dev::ReturnValue canTransform(const std::string &target_frame, const std::string &source_frame, bool &exists) override
Test if a transform exists.
bool close() override
Close the DeviceDriver.
yarp::dev::ReturnValue 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.
std::vector< broadcast_port_t * > m_array_of_ports
yarp::dev::ReturnValue 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.
yarp::dev::ReturnValue clear() override
Removes all the registered transforms.
bool read(yarp::os::ConnectionReader &connection) override
Read this object from a network connection.
yarp::robotinterface::Robot m_robot
bool threadInit() override
Initialization method.
yarp::dev::ReturnValue frameExists(const std::string &frame_id, bool &exists) override
Check if a frame exists.
yarp::os::Port m_rpc_InterfaceToUser
yarp::dev::ReturnValue allFramesAsString(std::string &all_frames) override
Creates a debug string containing the list of all registered frames.
yarp::dev::IFrameTransformStorageGet * m_ift_get
yarp::dev::ReturnValue 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.
yarp::dev::ReturnValue 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.
FrameTransformContainer: A class that contains a vector of frame transformations and exposes yarp::de...
virtual yarp::dev::ReturnValue clearAll()=0
Delete all transforms in a storage.
virtual yarp::dev::ReturnValue setTransform(const yarp::math::FrameTransform &transform)=0
Save a frame transform in a storage.
virtual yarp::dev::ReturnValue deleteTransform(std::string src, std::string dst)=0
Delete a single transform in the storage.
virtual yarp::dev::ReturnValue getInternalContainer(yarp::dev::FrameTransformContainer *&container)=0
void transFromVec(double X, double Y, double Z)
yarp::sig::Matrix toMatrix() const
yarp::sig::Vector getRPYRot() const
void rotFromRPY(double R, double P, double Y)
bool fromMatrix(const yarp::sig::Matrix &mat)
std::string toString(display_transform_mode_t format=rotation_as_quaternion) const
struct yarp::math::FrameTransform::Translation_t translation
A simple collection of objects that can be described and transmitted in a portable way.
Definition Bottle.h:64
void addVocab32(yarp::conf::vocab32_t x)
Places a vocabulary item in the bottle, at the end of the list.
Definition Bottle.cpp:164
size_type size() const
Gets the number of elements in the bottle.
Definition Bottle.cpp:251
bool read(ConnectionReader &reader) override
Set the bottle's value based on input from a network connection.
Definition Bottle.cpp:240
Value & get(size_type index) const
Reads a Value v from a certain part of the list.
Definition Bottle.cpp:246
void clear()
Empties the bottle of any objects it contains.
Definition Bottle.cpp:121
bool write(ConnectionWriter &writer) const override
Output a representation of the bottle to a network connection.
Definition Bottle.cpp:230
void addString(const char *str)
Places a string in the bottle, at the end of the list.
Definition Bottle.cpp:170
A mini-server for performing network communication in the background.
An interface for reading from a network connection.
An interface for writing to a network connection.
virtual std::string getName() const
Get name of port.
static bool exists(const std::string &port, bool quiet=true, bool checkVer=true)
Check for a port to be ready and responsive.
Definition Network.cpp:746
An abstraction for a periodic thread.
void askToStop()
Stop the thread.
bool start()
Call this to start the thread.
bool write(const PortWriter &writer, const PortWriter *callback=nullptr) const override
Write an object to the port.
Definition Port.cpp:436
void setReader(PortReader &reader) override
Set an external reader for port data.
Definition Port.cpp:511
void close() override
Stop port activity.
Definition Port.cpp:363
bool open(const std::string &name) override
Start port operation, with a specific name, with automatically-chosen network parameters.
Definition Port.cpp:79
A class for storing options and configuration information.
Definition Property.h:33
Helper class for finding config files and other external resources.
A base class for nested structures that can be searched.
Definition Searchable.h:31
virtual std::string toString() const =0
Return a standard text representation of the content of the object.
static double nowSystem()
static void delaySystem(double seconds)
A single value (typically within a Bottle).
Definition Value.h:43
virtual yarp::conf::float64_t asFloat64() const
Get 64-bit floating point value.
Definition Value.cpp:222
virtual std::string asString() const
Get string value.
Definition Value.cpp:234
yarp::dev::PolyDriver * driver() const
Definition Device.cpp:336
bool hasParam(const std::string &name) const
Definition Robot.cpp:791
bool hasDevice(const std::string &name) const
Definition Robot.cpp:597
bool enterPhase(yarp::robotinterface::ActionPhase phase)
Definition Robot.cpp:629
std::string findParam(const std::string &name) const
Definition Robot.cpp:796
Device & device(const std::string &name)
Definition Robot.cpp:567
Result of the parsing of yarp::robotinterface::XMLReader.
Definition XMLReader.h:26
bool parsingIsSuccessful
True if the parsing was successful, false otherwise.
Definition XMLReader.h:38
Robot robot
If parsingIsSuccessful is true, contains a valid robot instance.
Definition XMLReader.h:43
Class to read an XML file.
Definition XMLReader.h:52
XMLReaderResult getRobotFromString(const std::string &filename, const yarp::os::Searchable &config=yarp::os::Property())
Parse the XML description of a robotinterface from a string.
A class for a Matrix.
Definition Matrix.h:39
void push_back(const T &elem)
Push a new element in the vector: size is changed.
Definition Vector.h:268
#define yCInfo(component,...)
#define yCError(component,...)
#define yCTrace(component,...)
#define yCWarning(component,...)
#define yCDebug(component,...)
#define YARP_LOG_COMPONENT(name,...)
#define yCErrorThrottle(component, period,...)
For streams capable of holding different kinds of content, check what they actually have.
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:912
double now()
Return the current time in seconds, relative to an arbitrary starting point.
Definition Time.cpp:121
An interface to the operating system, including Port based communication.