pose_utilities.cpp
Go to the documentation of this file.
2 
4 
5 #include <string>
6 
7 namespace
8 {
9 bool isValid(tf2::Vector3 const& vector)
10 {
11  return (!std::isnan(vector.x()) && !std::isnan(vector.y()) && !std::isnan(vector.z()));
12 }
13 
14 tf2Scalar fixZeroValue(double value, double epsilon = 0.00001)
15 {
16  if (std::abs(value) <= epsilon)
17  {
18  return tf2Scalar(0.0);
19  }
20  return tf2Scalar(value);
21 }
22 
23 tf2::Vector3 vector3FromNxLib(NxLibItem const& node)
24 {
25  double x = node[0].asDouble();
26  double y = node[1].asDouble();
27  double z = node[2].asDouble();
28  return tf2::Vector3(tf2Scalar(x), tf2Scalar(y), tf2Scalar(z));
29 }
30 } // namespace
31 
32 bool isValid(tf2::Transform const& transform)
33 {
34  auto origin = transform.getOrigin();
35  if (!isValid(origin))
36  {
37  return false;
38  }
39 
40  auto rotation = transform.getRotation();
41  if (std::isnan(rotation.getAngle()))
42  {
43  return false;
44  }
45 
46  auto rotationAxis = rotation.getAxis();
47  return isValid(rotationAxis);
48 }
49 
50 bool isValid(TransformMsg const& transform)
51 {
52  return isValid(fromMsg(transform));
53 }
54 
55 bool isIdentity(tf2::Transform const& transform)
56 {
57  tf2::Matrix3x3 basis(
58  fixZeroValue(transform.getBasis().getRow(0).getX()), fixZeroValue(transform.getBasis().getRow(0).getY()),
59  fixZeroValue(transform.getBasis().getRow(0).getZ()), fixZeroValue(transform.getBasis().getRow(1).getX()),
60  fixZeroValue(transform.getBasis().getRow(1).getY()), fixZeroValue(transform.getBasis().getRow(1).getZ()),
61  fixZeroValue(transform.getBasis().getRow(2).getX()), fixZeroValue(transform.getBasis().getRow(2).getY()),
62  fixZeroValue(transform.getBasis().getRow(2).getZ()));
63 
64  tf2::Vector3 origin(fixZeroValue(transform.getOrigin().getX()), fixZeroValue(transform.getOrigin().getY()),
65  fixZeroValue(transform.getOrigin().getZ()));
66 
67  return (basis == tf2::Matrix3x3::getIdentity() && origin.isZero());
68 }
69 
70 void writeTransformToNxLib(tf2::Transform const& transform, NxLibItem const& node)
71 {
72  // Initialize the node to be empty. This is necessary, because there is a bug in some versions of the NxLib that
73  // overwrites the whole transformation node with an identity transformation as soon as a new node in /Links gets
74  // created.
75  if (node.path.find("ViewPose") == std::string::npos)
76  {
77  // The ensenso SDK 2.2.x has a structure locked ViewPose item in the global params. So it cannot be set to null.
78  node.setNull();
79  }
80 
81  if (isValid(transform))
82  {
83  // ROS transformation is in meters, NxLib expects it to be in millimeters.
84  auto origin = transform.getOrigin();
85  origin *= 1000;
86  node[itmTranslation][0] = origin.x();
87  node[itmTranslation][1] = origin.y();
88  node[itmTranslation][2] = origin.z();
89 
90  auto rotation = transform.getRotation();
91  node[itmRotation][itmAngle] = rotation.getAngle();
92 
93  auto rotationAxis = rotation.getAxis();
94  node[itmRotation][itmAxis][0] = rotationAxis.x();
95  node[itmRotation][itmAxis][1] = rotationAxis.y();
96  node[itmRotation][itmAxis][2] = rotationAxis.z();
97  }
98  else
99  {
100  ENSENSO_ERROR("Given transform is not valid for writing to the NxLib, using identity transform instead");
101  // Use an identity transformation as a reasonable default value.
102  node[itmTranslation][0] = 0;
103  node[itmTranslation][1] = 0;
104  node[itmTranslation][2] = 0;
105 
106  node[itmRotation][itmAngle] = 0;
107  node[itmRotation][itmAxis][0] = 1;
108  node[itmRotation][itmAxis][1] = 0;
109  node[itmRotation][itmAxis][2] = 0;
110  }
111 }
112 
113 namespace tf2
114 {
115 void convertMsg(TransformMsg const& transform, PoseMsg& pose)
116 {
117  pose.orientation = transform.rotation;
118  pose.position.x = transform.translation.x;
119  pose.position.y = transform.translation.y;
120  pose.position.z = transform.translation.z;
121 }
122 
123 void convertMsg(PoseMsg const& pose, TransformMsg& transform)
124 {
125  transform.rotation = pose.orientation;
126  transform.translation.x = pose.position.x;
127  transform.translation.y = pose.position.y;
128  transform.translation.z = pose.position.z;
129 }
130 
131 void convertMsg(StampedTransformMsg const& transform, StampedPoseMsg& pose)
132 {
133  convertMsg(transform.transform, pose.pose);
134  pose.header = transform.header;
135 }
136 
137 void convertMsg(StampedPoseMsg const& pose, StampedTransformMsg& transform)
138 {
139  convertMsg(pose.pose, transform.transform);
140  transform.header = pose.header;
141 }
142 } // namespace tf2
143 
144 tf2::Transform transformFromNxLib(NxLibItem const& node)
145 {
146  tf2::Transform transform;
147 
148  // NxLib transformation is in millimeters, ROS expects it to be in meters.
149  tf2::Vector3 origin = vector3FromNxLib(node[itmTranslation]);
150  origin /= 1000;
151  transform.setOrigin(origin);
152 
153  tf2::Quaternion rotation(vector3FromNxLib(node[itmRotation][itmAxis]), node[itmRotation][itmAngle].asDouble());
154  transform.setRotation(rotation);
155 
156  return transform;
157 }
158 
159 StampedPoseMsg stampedPoseFromNxLib(NxLibItem const& node, std::string const& parentFrame, ensenso::ros::Time timestamp)
160 {
161  StampedTransformMsg stampedTransform;
162  tf2::Transform transform = transformFromNxLib(node);
163  tf2::convert(transform, stampedTransform.transform);
164 
165  StampedPoseMsg stampedPose;
166  tf2::convertMsg(stampedTransform, stampedPose);
167  stampedPose.header.frame_id = parentFrame;
168  stampedPose.header.stamp = timestamp;
169 
170  return stampedPose;
171 }
172 
173 StampedTransformMsg transformFromPose(StampedPoseMsg const& pose, std::string const& childFrame)
174 {
175  StampedTransformMsg transform;
176  tf2::convertMsg(pose, transform);
177  transform.child_frame_id = childFrame;
178 
179  return transform;
180 }
181 
183 {
184  StampedPoseMsg pose;
185  tf2::convertMsg(transform, pose);
186 
187  return pose;
188 }
189 
191 {
192  tf2::Transform transform;
193  tf2::convert(tStamped.transform, transform);
194 
195  return transform;
196 }
197 
199 {
200  StampedTransformMsg tStamped;
201  tf2::convertMsg(pStamped, tStamped);
202 
203  tf2::Transform transform;
204  tf2::convert(tStamped.transform, transform);
205 
206  return transform;
207 }
208 
210 {
211  tf2::Transform transform;
212  tf2::convert(t, transform);
213 
214  return transform;
215 }
216 
218 {
219  TransformMsg t;
220  tf2::convertMsg(p, t);
221 
222  tf2::Transform transform;
223  tf2::convert(t, transform);
224 
225  return transform;
226 }
227 
229 {
230  TransformMsg t;
231  tf2::convert(transform, t);
232 
233  PoseMsg pose;
234  tf2::convertMsg(t, pose);
235 
236  return pose;
237 }
238 
239 StampedTransformMsg fromTf(tf2::Transform const& transform, std::string parentFrame, std::string childFrame,
240  ensenso::ros::Time timestamp)
241 {
242  StampedTransformMsg tStamped;
243  tf2::convert(transform, tStamped.transform);
244  tStamped.header.stamp = timestamp;
245  tStamped.header.frame_id = std::move(parentFrame);
246  tStamped.child_frame_id = std::move(childFrame);
247 
248  return tStamped;
249 }
250 
251 tf2::Transform getLatestTransform(tf2_ros::Buffer const& tfBuffer, std::string const& cameraFrame,
252  std::string const& targetFrame)
253 {
254  tf2::Transform transform;
255  try
256  {
257  StampedTransformMsg tStamped;
258  tStamped = tfBuffer.lookupTransform(cameraFrame, targetFrame, ensenso::ros::Time(0));
259 
260  transform = fromMsg(tStamped.transform);
261  }
262  catch (tf2::TransformException& ex)
263  {
264  ENSENSO_WARN("%s", ex.what());
265  }
266  return transform;
267 }
bool isValid(tf2::Transform const &transform)
void ENSENSO_ERROR(T... args)
Definition: logging.h:278
static const Matrix3x3 & getIdentity()
TF2SIMD_FORCE_INLINE Matrix3x3 & getBasis()
::ros::Time Time
Definition: time.h:67
TF2SIMD_FORCE_INLINE void setRotation(const Quaternion &q)
tf2::Transform getLatestTransform(tf2_ros::Buffer const &tfBuffer, std::string const &cameraFrame, std::string const &targetFrame)
StampedPoseMsg stampedPoseFromNxLib(NxLibItem const &node, std::string const &parentFrame, ensenso::ros::Time timestamp)
void writeTransformToNxLib(tf2::Transform const &transform, NxLibItem const &node)
geometry_msgs::msg::TransformStamped StampedTransformMsg
double tf2Scalar
tf2::Transform transformFromNxLib(NxLibItem const &node)
bool isIdentity(tf2::Transform const &transform)
StampedPoseMsg poseFromTransform(StampedTransformMsg const &transform)
geometry_msgs::msg::Pose PoseMsg
geometry_msgs::TransformStamped t
tf2Scalar getAngle() const
geometry_msgs::msg::PoseStamped StampedPoseMsg
void convertMsg(TransformMsg const &transform, PoseMsg &pose)
virtual geometry_msgs::TransformStamped lookupTransform(const std::string &target_frame, const std::string &source_frame, const ros::Time &time, const ros::Duration timeout) const
StampedTransformMsg fromTf(tf2::Transform const &transform, std::string parentFrame, std::string childFrame, ensenso::ros::Time timestamp)
TF2SIMD_FORCE_INLINE Vector3 & getOrigin()
void fromMsg(const A &, B &b)
Vector3 getAxis() const
TF2SIMD_FORCE_INLINE void setOrigin(const Vector3 &origin)
TF2SIMD_FORCE_INLINE const Vector3 & getRow(int i) const
void ENSENSO_WARN(T... args)
Definition: logging.h:210
Quaternion getRotation() const
void convert(const A &a, B &b)
tf2::Transform fromMsg(StampedTransformMsg const &tStamped)
geometry_msgs::msg::Transform TransformMsg
StampedTransformMsg transformFromPose(StampedPoseMsg const &pose, std::string const &childFrame)


ensenso_camera
Author(s): Ensenso
autogenerated on Sat Jun 3 2023 02:17:04