6#define _USE_MATH_DEFINES
16#include <cmrc/cmrc.hpp>
30#define LOG_THROTTLE_PERIOD 1.0
38 bool ok = in.
read(connection);
44 if (request ==
"help")
47 out.
addString(
"get_transform <src> <dst>: print the transform from <src> to <dst>");
48 out.
addString(
"list_transforms: print all the stored frame transforms");
49 out.
addString(
"list_frames: print all the available reference frames");
50 out.
addString(
"list_ports: print all the opened ports for transform broadcasting");
51 out.
addString(
"publish_transform <src> <dst> <portname> [format]: opens a port to publish transform from src to dst");
52 out.
addString(
"unpublish_transform <portname>: closes a previously opened port to publish a transform");
53 out.
addString(
"unpublish_all: closes a all previously opened ports to publish a transform");
54 out.
addString(
"set_static_transform_rad <src> <dst> <x> <y> <z> <roll> <pitch> <yaw>': create a static transform (angles in radians)");
55 out.
addString(
"set_static_transform_deg <src> <dst> <x> <y> <z> <roll> <pitch> <yaw>': create a static transform (angles in degrees)");
56 out.
addString(
"delete_static_transform <src> <dst>': delete a static transform");
57 out.
addString(
"generate_view <option>': generate a frames.pdf file showing the transform tree diagram.");
58 out.
addString(
" The following values are valid for option (default=none)");
59 out.
addString(
" 'show_rpy': show rotation as rpy angles");
60 out.
addString(
" 'show_quaterion:'show rotation as a quaternion");
61 out.
addString(
" 'show_matrix:'show rotation as a 3x3 rotation matrix");
63 else if (request ==
"list_frames")
65 std::vector<std::string> v;
68 out.
addString(
"List of available reference frames:");
77 else if (request ==
"get_transform")
84 out.
addString(
"Transform from " + src +
" to " + dst +
" is: ");
87 else if (request ==
"list_ports")
92 out.
addString(
"No ports are currently active");
98 std::string s = m_array_of_port->port.getName() +
" "+ m_array_of_port->transform_src +
" -> " + m_array_of_port->transform_dst;
103 else if (request ==
"publish_transform")
109 std::string format_s =
"matrix";
114 else {
yCError(FRAMETRANSFORMCLIENT) <<
"Invalid format" << format_s <<
"using format `matrix`. Only `matrix` is currently supported."; }
116 if (port_name[0] ==
'/') {
117 port_name.erase(port_name.begin());
119 std::string full_port_name =
m_local_name +
"/" + port_name;
124 out.
addString(
"Requested src frame " + src +
" does not exists.");
125 yCWarning(FRAMETRANSFORMCLIENT,
"Requested src frame %s does not exists.", src.c_str());
129 out.
addString(
"Requested dst frame " + dst +
" does not exists.");
130 yCWarning(FRAMETRANSFORMCLIENT,
"Requested fst frame %s does not exists.", dst.c_str());
135 if (port_already_exists) {
yCError(FRAMETRANSFORMCLIENT,
"Requested port already exists!"); }
138 bool bcast_already_exists =
false;
141 if (m_array_of_port && m_array_of_port->port.getName() == full_port_name)
143 bcast_already_exists |=
true;
149 if (bcast_already_exists ==
false && port_already_exists ==
false)
153 b->transform_dst = dst;
155 bool pret = b->port.open(full_port_name);
158 out.
addString(
"Operation complete. Port " + full_port_name +
" opened.");
167 out.
addString(
"Operation failed. Unable to open port " + full_port_name +
".");
172 out.
addString(
"unable to perform operation");
175 else if (request ==
"unpublish_all")
179 m_array_of_port->port.close();
180 delete m_array_of_port;
181 m_array_of_port=
nullptr;
189 else if (request ==
"unpublish_transform")
193 if (port_name[0] ==
'/') {
194 port_name.erase(port_name.begin());
196 std::string full_port_name =
m_local_name +
"/" + port_name;
199 if ((*it)->port.getName() == port_name)
211 out.
addString(
"Port " + full_port_name +
" has been closed.");
215 out.
addString(
"Port " + full_port_name +
" was not found.");
221 else if (request ==
"set_static_transform_rad" ||
222 request ==
"set_static_transform_deg")
230 if (request ==
"set_static_transform_rad")
236 else if (request ==
"set_static_transform_deg")
246 yCInfo(FRAMETRANSFORMCLIENT) <<
"set_static_transform done";
247 out.
addString(
"set_static_transform done");
251 yCError(FRAMETRANSFORMCLIENT) <<
"read(): something strange happened";
255 else if (request ==
"generate_view")
260 }
else if (in.
get(1).
asString() ==
"show_matrix") {
268 else if (request ==
"delete_static_transform")
274 out.
addString(
"delete_static_transform done");
278 yCError(FRAMETRANSFORMCLIENT,
"Invalid vocab received in FrameTransformClient");
285 if (returnToSender !=
nullptr)
287 out.
write(*returnToSender);
291 yCError(FRAMETRANSFORMCLIENT) <<
"Invalid return to sender";
298 yCWarning(FRAMETRANSFORMCLIENT) <<
"The 'FrameTransformClient' device is experimental and could be modified without any warning";
300 std::string cfg_string = config.
toString();
304 std::string configuration_to_open;
305 std::string innerFilePath=
"config_xml/ftc_local_only.xml";
306 if(cfg.
check(
"testxml_option"))
309 std::ifstream xmlFile(innerFilePath);
310 std::stringstream stream_file;
311 stream_file << xmlFile.rdbuf();
312 configuration_to_open = stream_file.str();
316 auto fs = cmrc::frameTransformRC::get_filesystem();
317 if(cfg.
check(
"filexml_option")) { innerFilePath=
"config_xml/"+cfg.
find(
"filexml_option").
toString();}
318 cfg.
unput(
"filexml_option");
319 auto xmlFile =
fs.open(innerFilePath);
320 for(
const auto& lemma : xmlFile)
322 configuration_to_open += lemma;
326 std::string m_local_rpcUser =
"/ftClient/rpc";
329 cfg.
unput(
"local_rpc");
331 if (config.
check(
"FrameTransform_verbose_debug"))
334 cfg.
put(
"FrameTransform_verbose_debug", vval);
351 std::string setdeviceName =
"ftc_storage";
355 yCAssert(FRAMETRANSFORMCLIENT, polyset);
359 std::string getdeviceName =
"ftc_storage";
363 yCAssert(FRAMETRANSFORMCLIENT, polyget);
369 if (config.
check(
"period"))
377 yCError(FRAMETRANSFORMCLIENT,
"Failed to open rpc port");
389 yCDebug(FRAMETRANSFORMCLIENT,
"rpc port closed");
401 if (!br || p_cont ==
nullptr) {
yCError(FRAMETRANSFORMCLIENT) <<
"Failure";
return false; }
404 std::lock_guard<std::recursive_mutex> l(p_cont->
m_trf_mutex);
407 for (
auto it = p_cont->
begin(); it != p_cont->
end(); it++)
409 all_frames += it->toString() +
" ";
414FrameTransformClient::ConnectionType FrameTransformClient::priv_getConnectionType(
const std::string &target_frame,
const std::string &source_frame, std::string* commonAncestor =
nullptr)
416 if (target_frame == source_frame) {
return ConnectionType::IDENTITY;}
420 if (!br || p_cont ==
nullptr) {
yCError(FRAMETRANSFORMCLIENT) <<
"Failure";
return ConnectionType::DISCONNECTED; }
423 std::vector<std::string> tar2root_vec;
424 std::vector<std::string> src2root_vec;
425 std::string ancestor, child;
426 child = target_frame;
429 std::lock_guard<std::recursive_mutex> l(p_cont->
m_trf_mutex);
434 if(ancestor == source_frame)
436 return ConnectionType::DIRECT;
439 tar2root_vec.push_back(ancestor);
442 child = source_frame;
445 if(ancestor == target_frame)
447 return ConnectionType::INVERSE;
450 src2root_vec.push_back(ancestor);
454 for(i = 0; i < tar2root_vec.size(); i++)
458 for(j = 0; j < src2root_vec.size(); j++)
460 if(a == src2root_vec[j])
466 return ConnectionType::UNDIRECT;
471 return ConnectionType::DISCONNECTED;
476 return priv_getConnectionType(target_frame, source_frame) != ConnectionType::DISCONNECTED;
485 yCError(FRAMETRANSFORMCLIENT,
"clear(): interface not available");
493 if (!br || p_cont ==
nullptr) {
yCError(FRAMETRANSFORMCLIENT) <<
"Failure";
return false; }
496 std::lock_guard<std::recursive_mutex> l(p_cont->
m_trf_mutex);
499 for (
auto it = p_cont->
begin(); it != p_cont->
end(); it++)
501 if (it->src_frame_id == frame_id) {
return true; }
502 if (it->dst_frame_id == frame_id) {
return true; }
513 if (!br || p_cont ==
nullptr) {
yCError(FRAMETRANSFORMCLIENT) <<
"Failure";
return false; }
516 std::lock_guard<std::recursive_mutex> l(p_cont->
m_trf_mutex);
519 for (
auto it = p_cont->
begin(); it != p_cont->
end(); it++)
522 for (
const auto&
id : ids)
524 if (it->src_frame_id ==
id) { found =
true;
break; }
526 if (found ==
false) {
527 ids.push_back(it->src_frame_id);
531 for (
auto it = p_cont->
begin(); it != p_cont->
end(); it++)
534 for (
const auto&
id : ids)
536 if (it->dst_frame_id ==
id) { found =
true;
break; }
538 if (found ==
false) {
539 ids.push_back(it->dst_frame_id);
550 if (!br || p_cont ==
nullptr) {
yCError(FRAMETRANSFORMCLIENT) <<
"Failure";
return false; }
553 std::lock_guard<std::recursive_mutex> l(p_cont->
m_trf_mutex);
556 for (
auto it = p_cont->
begin(); it != p_cont->
end(); it++)
558 std::string par(it->dst_frame_id);
559 if (it->dst_frame_id == frame_id)
561 parent_frame_id = it->src_frame_id;
568bool FrameTransformClient::priv_canExplicitTransform(
const std::string& target_frame_id,
const std::string& source_frame_id)
const
572 if (!br || p_cont ==
nullptr) {
yCError(FRAMETRANSFORMCLIENT) <<
"Failure";
return false; }
575 std::lock_guard<std::recursive_mutex> l(p_cont->
m_trf_mutex);
578 for (
auto it = p_cont->
begin(); it != p_cont->
end(); it++)
580 if (it->dst_frame_id == target_frame_id && it->src_frame_id == source_frame_id)
588bool FrameTransformClient::priv_getChainedTransform(
const std::string& target_frame_id,
const std::string& source_frame_id,
yarp::sig::Matrix& transform)
const
592 if (!br || p_cont ==
nullptr) {
yCError(FRAMETRANSFORMCLIENT) <<
"Failure";
return false; }
595 std::lock_guard<std::recursive_mutex> l(p_cont->
m_trf_mutex);
598 for (
auto it = p_cont->
begin(); it != p_cont->
end(); it++)
600 if (it->dst_frame_id == target_frame_id)
602 if (it->src_frame_id == source_frame_id)
604 transform = it->toMatrix();
610 if (priv_getChainedTransform(it->src_frame_id, source_frame_id, m))
612 transform = m * it->toMatrix();
624 std::string ancestor;
625 ct = priv_getConnectionType(target_frame_id, source_frame_id, &ancestor);
626 if (ct == ConnectionType::DIRECT)
628 return priv_getChainedTransform(target_frame_id, source_frame_id, transform);
630 else if (ct == ConnectionType::INVERSE)
633 priv_getChainedTransform(source_frame_id, target_frame_id, m);
637 else if(ct == ConnectionType::UNDIRECT)
640 priv_getChainedTransform(source_frame_id, ancestor, root2src);
641 priv_getChainedTransform(target_frame_id, ancestor, root2tar);
645 else if (ct == ConnectionType::IDENTITY)
658 if(target_frame_id == source_frame_id)
661 "\t Source frame and target frame are both equal to " << source_frame_id;
665 if (!priv_canExplicitTransform(target_frame_id, source_frame_id) &&
canTransform(target_frame_id, source_frame_id))
675 if (!
tf.fromMatrix(transform))
681 tf.src_frame_id = source_frame_id;
682 tf.dst_frame_id = target_frame_id;
690 yCError(FRAMETRANSFORMCLIENT,
"setTransform(): interface not available");
696 if(target_frame_id == source_frame_id)
699 "\t Source frame and target frame are both equal to " << source_frame_id;
710 if (!
tf.fromMatrix(transform))
715 tf.src_frame_id = source_frame_id;
716 tf.dst_frame_id = target_frame_id;
724 yCError(FRAMETRANSFORMCLIENT,
"setTransformStatic(): interface not available");
734 yCError(FRAMETRANSFORMCLIENT,
"deleteTransform(): interface not available");
740 if (input_point.
size() != 3)
753 transformed_point = m * in;
760 if (input_pose.
size() != 6)
765 if (transformed_pose.
size() != 6)
767 yCWarning(FRAMETRANSFORMCLIENT,
"transformPose(): Performance warning: size transformed_pose should be 6, resizing.");
768 transformed_pose.
resize(6, 0.0);
777 t.transFromVec(input_pose[0], input_pose[1], input_pose[2]);
778 t.rotFromRPY(input_pose[3], input_pose[4], input_pose[5]);
779 t.fromMatrix(m *
t.toMatrix());
780 transformed_pose[0] =
t.translation.tX;
781 transformed_pose[1] =
t.translation.tY;
782 transformed_pose[2] =
t.translation.tZ;
786 transformed_pose[3] = rot[0];
787 transformed_pose[4] = rot[1];
788 transformed_pose[5] = rot[2];
801 t.rotation=input_quaternion;
814 yCError(FRAMETRANSFORMCLIENT) <<
"waitForTransform(): timeout expired";
831 yCTrace(FRAMETRANSFORMCLIENT,
"Thread started");
837 yCTrace(FRAMETRANSFORMCLIENT,
"Thread stopped");
852 std::string src = m_array_of_port->transform_src;
853 std::string dst = m_array_of_port->transform_dst;
858 m_array_of_port->port.write(m);
880 return std::string(
",label=\" ") +
t->toString(FrameTransform::display_transform_mode_t::rotation_as_quaternion) +
"\"";
884 return std::string(
",label=\" ") +
t->toString(FrameTransform::display_transform_mode_t::rotation_as_matrix) +
"\"";
888 return std::string(
",label=\" ") +
t->toString(FrameTransform::display_transform_mode_t::rotation_as_rpy) +
"\"";
891 yCError(FRAMETRANSFORMCLIENT) <<
"get_matrix_as_text() invalid option";
907 if (!br || p_cont ==
nullptr) {
yCError(FRAMETRANSFORMCLIENT) <<
"Failure";
return false; }
910 std::lock_guard<std::recursive_mutex> l(p_cont->
m_trf_mutex);
913 std::string dot_string =
"digraph G { ";
914 for (
auto it = p_cont->
begin(); it != p_cont->
end(); it++)
918 std::string trf_text = it->src_frame_id +
"->" +
919 it->dst_frame_id +
" " +
921 dot_string += trf_text +
'\n';
924 std::string legend =
"\n\
926 node[shape=plaintext]\n\
927 subgraph cluster_01 {\n\
928 label = \"Legend\";\n\
929 key[label=<<table border=\"0\" cellpadding=\"2\" cellspacing=\"0\" cellborder=\"0\">\n\
930 <tr><td align=\"right\" port=\"i1\">YARP timed transform</td></tr>\n\
931 <tr><td align=\"right\" port=\"i2\">YARP static transform</td></tr>\n\
933 key2[label=<<table border=\"0\" cellpadding=\"2\" cellspacing=\"0\" cellborder=\"0\">\n\
934 <tr><td port = \"i1\"> </td></tr>\n\
935 <tr><td port = \"i2\"> </td></tr>\n\
937 key:i1:e -> key2:i1:w [color = blue]\n\
938 key:i2:e -> key2:i2:w [color = blue, style=dashed]\n\
941 std::string command_string =
"printf '" + dot_string + legend +
"' | dot -Tpdf > frames.pdf";
942#if defined (__linux__)
943 int ret = std::system(
"dot -V");
946 yCError(FRAMETRANSFORMCLIENT) <<
"dot executable not found. Please install graphviz.";
950 yCDebug(FRAMETRANSFORMCLIENT) <<
"Command string is:" << command_string;
951 ret = std::system(command_string.c_str());
954 yCError(FRAMETRANSFORMCLIENT) <<
"The following command failed to execute:" << command_string;
958 yCError(FRAMETRANSFORMCLIENT) <<
"Not yet implemented. Available only Linux";
constexpr yarp::conf::vocab32_t VOCAB_ERR
void fromRotationMatrix(const yarp::sig::Matrix &R)
Converts a rotation matrix to a quaternion.
A simple collection of objects that can be described and transmitted in a portable way.
void addVocab32(yarp::conf::vocab32_t x)
Places a vocabulary item in the bottle, at the end of the list.
size_type size() const
Gets the number of elements in the bottle.
bool read(ConnectionReader &reader) override
Set the bottle's value based on input from a network connection.
Value & get(size_type index) const
Reads a Value v from a certain part of the list.
void clear()
Empties the bottle of any objects it contains.
bool write(ConnectionWriter &writer) const override
Output a representation of the bottle to a network connection.
void addString(const char *str)
Places a string in the bottle, at the end of the list.
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.
static bool exists(const std::string &port, bool quiet=true, bool checkVer=true)
Check for a port to be ready and responsive.
An abstraction for a periodic thread.
bool setPeriod(double period)
Set the (new) period of the thread.
void askToStop()
Stop the thread.
bool start()
Call this to start the thread.
void setReader(PortReader &reader) override
Set an external reader for port data.
void close() override
Stop port activity.
bool open(const std::string &name) override
Start port operation, with a specific name, with automatically-chosen network parameters.
A class for storing options and configuration information.
Value & find(const std::string &key) const override
Gets a value corresponding to a given keyword.
void fromString(const std::string &txt, bool wipe=true)
Interprets a string as a list of properties.
void put(const std::string &key, const std::string &value)
Associate the given key with the given string.
bool check(const std::string &key) const override
Check if there exists a property of the given name.
void unput(const std::string &key)
Remove the association from the given key to a value, if present.
A base class for nested structures that can be searched.
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 Value & find(const std::string &key) const =0
Gets a value corresponding to a given keyword.
static double nowSystem()
static void delaySystem(double seconds)
A single value (typically within a Bottle).
virtual yarp::conf::float64_t asFloat64() const
Get 64-bit floating point value.
std::string toString() const override
Return a standard text representation of the content of the object.
virtual std::string asString() const
Get string value.
yarp::dev::PolyDriver * driver() const
bool hasParam(const std::string &name) const
bool hasDevice(const std::string &name) const
bool enterPhase(yarp::robotinterface::ActionPhase phase)
std::string findParam(const std::string &name) const
Device & device(const std::string &name)
Result of the parsing of yarp::robotinterface::XMLReader.
bool parsingIsSuccessful
True if the parsing was successful, false otherwise.
Robot robot
If parsingIsSuccessful is true, contains a valid robot instance.
Class to read an XML file.
XMLReaderResult getRobotFromString(const std::string &filename, const yarp::os::Searchable &config=yarp::os::Property())
Parse the XML description of a robotinterface from a string.
std::string toString(int precision=-1, int width=-1, const char *endRowStr="\n") const
Print matrix to a string.
const Matrix & eye()
Build an identity matrix, don't resize.
void resize(size_t size) override
Resize the vector.
void push_back(const T &elem)
Push a new element in the vector: size is changed.
void pop_back()
Pop an element out of the vector: size is changed.
#define yCInfo(component,...)
#define yCError(component,...)
#define yCAssert(component, x)
#define yCTrace(component,...)
#define yCWarning(component,...)
#define yCDebug(component,...)
#define YARP_LOG_COMPONENT(name,...)
#define yCErrorThrottle(component, period,...)
std::string to_string(IntegerType x)
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).
double now()
Return the current time in seconds, relative to an arbitrary starting point.
An interface to the operating system, including Port based communication.