15 import tf2_geometry_msgs
16 from sensor_msgs.msg
import Image
17 from geometry_msgs.msg
import PointStamped
18 from cv_bridge
import CvBridge, CvBridgeError
19 from ifm3d.msg
import Extrinsics
26 TP: 14 May 2018 - heavily adapted from my old o3d3xx-ros test of the same 29 This class tests the following: 30 - Getting data from the camera 31 - Computing the Cartesian data and comparing it to ground truth 32 - To do the comparison to ground truth, the computed cartesian data 33 must be transformed, to do that we use the tf2 API. It follows that 34 this indirectly is testing our tf2 static publisher which is publishing 35 the transform between the optical and camera frames 37 NOTE: The camera h/w is needed to run this test. 41 super(TestCamera, self).
__init__(*args)
52 rospy.init_node(
'test_camera')
56 rospy.Subscriber(
"/ifm3d/camera/distance", Image, self.
image_cb,
57 queue_size=
None, callback_args=
"rdis")
59 rospy.Subscriber(
"/ifm3d/camera/xyz_image", Image, self.
image_cb,
60 queue_size=
None, callback_args=
"cloud")
62 rospy.Subscriber(
"/ifm3d/camera/unit_vectors", Image, self.
image_cb,
63 queue_size=
None, callback_args=
"uvec")
65 rospy.Subscriber(
"/ifm3d/camera/extrinsics", Extrinsics,
68 rospy.Subscriber(
"/ifm3d/camera/confidence", Image, self.
image_cb,
69 queue_size=
None, callback_args=
"conf")
72 timeout_t = time.time() + 10.0
73 rate = rospy.Rate(10.0)
74 while ((
not rospy.is_shutdown())
and 76 (time.time() < timeout_t)):
78 if ((self.
rdis_ is not None)
and 79 (self.
cloud_ is not None)
and 80 (self.
uvec_ is not None)
and 82 (self.
conf_ is not None)):
86 d = self.
rdis_.header.stamp - self.
cloud_.header.stamp
88 d2 = self.
rdis_.header.stamp - self.
conf_.header.stamp
113 if im_type ==
"rdis":
114 if self.
rdis_ is None:
116 elif im_type ==
"cloud":
119 elif im_type ==
"uvec":
120 if self.
uvec_ is None:
122 elif im_type ==
"conf":
123 if self.
conf_ is None:
128 Computes the Cartesian data from the radial distance image, unit 129 vectors, and extrinsics. Then transforms it to the camera frame using 130 the tf2 api. Once transformed, it will do a pixel-by-pixel comparision 133 Returns a bool indicating the the success of the computation. 144 if ((cloud.dtype == np.float32)
or 145 (cloud.dtype == np.float64)):
152 x_cam = x_cam.astype(np.int16)
153 y_cam = y_cam.astype(np.int16)
154 z_cam = z_cam.astype(np.int16)
170 rdis_f = rdis.astype(np.float32)
171 if (rdis.dtype == np.float32):
176 x_ = ex * rdis_f + tx
177 y_ = ey * rdis_f + ty
178 z_ = ez * rdis_f + tz
181 bad_mask = (np.bitwise_and(conf, 0x1) == 0x1)
199 x_f = np.zeros((n_rows, n_cols), dtype=np.float32)
200 y_f = np.zeros((n_rows, n_cols), dtype=np.float32)
201 z_f = np.zeros((n_rows, n_cols), dtype=np.float32)
202 for i
in range(n_rows):
203 for j
in range(n_cols):
205 p.header = self.
rdis_.header
209 pt = tf_buffer.transform(p, self.
cloud_.header.frame_id,
211 x_f[i,j] = pt.point.x
212 y_f[i,j] = pt.point.y
213 z_f[i,j] = pt.point.z
216 x_i = x_f.astype(np.int16)
217 y_i = y_f.astype(np.int16)
218 z_i = z_f.astype(np.int16)
221 x_mask = np.fabs(x_i - x_cam) > tol
222 y_mask = np.fabs(y_i - y_cam) > tol
223 z_mask = np.fabs(z_i - z_cam) > tol
227 self.assertTrue(x_mask.sum() == 0)
228 self.assertTrue(y_mask.sum() == 0)
229 self.assertTrue(z_mask.sum() == 0)
236 rostest.rosrun(
'ifm3d',
'test_camera', TestCamera, sys.argv)
239 if __name__ ==
'__main__':
def extrinsics_cb(self, data, args)
def image_cb(self, data, args)
def compute_cartesian(self)