tango_ros_conversions_helper.cpp
Go to the documentation of this file.
1 // Copyright 2017 Intermodalics All Rights Reserved.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
15 
16 #include <glog/logging.h>
17 
18 #include <ros/ros.h>
20 #include <sensor_msgs/PointField.h>
22 
25  double time_offset,
26  const std::string& base_frame_id,
27  const std::string& target_frame_id,
28  geometry_msgs::TransformStamped* transform) {
29  transform->header.stamp.fromSec(pose.timestamp + time_offset);
30  transform->header.frame_id = base_frame_id;
31  transform->child_frame_id = target_frame_id;
32 
33  transform->transform.translation.x = pose.translation[0];
34  transform->transform.translation.y = pose.translation[1];
35  transform->transform.translation.z = pose.translation[2];
36  transform->transform.rotation.x = pose.orientation[0];
37  transform->transform.rotation.y = pose.orientation[1];
38  transform->transform.rotation.z = pose.orientation[2];
39  transform->transform.rotation.w = pose.orientation[3];
40 }
41 
42 void toPointCloud2(const TangoPointCloud& tango_point_cloud,
43  double time_offset,
44  sensor_msgs::PointCloud2* point_cloud) {
45  point_cloud->width = tango_point_cloud.num_points;
46  point_cloud->height = 1;
47  point_cloud->point_step = (sizeof(float) * NUMBER_OF_FIELDS_IN_POINT_CLOUD);
48  point_cloud->is_dense = true;
49  point_cloud->row_step = point_cloud->width;
50  point_cloud->is_bigendian = false;
51  point_cloud->data.resize(tango_point_cloud.num_points);
52  sensor_msgs::PointCloud2Modifier modifier(*point_cloud);
54  "x", 1, sensor_msgs::PointField::FLOAT32,
55  "y", 1, sensor_msgs::PointField::FLOAT32,
56  "z", 1, sensor_msgs::PointField::FLOAT32,
57  "c", 1, sensor_msgs::PointField::FLOAT32);
58  modifier.resize(tango_point_cloud.num_points);
59  sensor_msgs::PointCloud2Iterator<float> iter_x(*point_cloud, "x");
60  sensor_msgs::PointCloud2Iterator<float> iter_y(*point_cloud, "y");
61  sensor_msgs::PointCloud2Iterator<float> iter_z(*point_cloud, "z");
62  sensor_msgs::PointCloud2Iterator<float> iter_c(*point_cloud, "c");
63  for (size_t i = 0; i < tango_point_cloud.num_points;
64  ++i, ++iter_x, ++iter_y, ++iter_z, ++iter_c) {
65  *iter_x = tango_point_cloud.points[i][0];
66  *iter_y = tango_point_cloud.points[i][1];
67  *iter_z = tango_point_cloud.points[i][2];
68  *iter_c = tango_point_cloud.points[i][3];
69  }
70  point_cloud->header.stamp.fromSec(tango_point_cloud.timestamp + time_offset);
71 }
72 
73 void toLaserScanRange(double x, double y, double z, double min_height,
74  double max_height, double min_range, double max_range,
75  sensor_msgs::LaserScan* laser_scan) {
76  if (std::isnan(x) || std::isnan(y) || std::isnan(z)) {
77  // NAN point.
78  return;
79  }
80  double distance = sqrt(x * x + y * y + z * z);
81  if (distance < min_range || distance > max_range) {
82  return;
83  }
84  if (z > max_height || z < min_height) {
85  // Z not in height range.
86  return;
87  }
88  double range = hypot(x, y);
89  if (range < laser_scan->range_min) {
90  // Point not in distance range.
91  return;
92  }
93  double angle = atan2(y, x);
94  if (angle < laser_scan->angle_min || angle > laser_scan->angle_max) {
95  // Point not in angle range.
96  return;
97  }
98 
99  if (range > laser_scan->range_max) {
100  laser_scan->range_max = range;
101  }
102  // Overwrite range at laser scan ray if new range is smaller.
103  int index = (angle - laser_scan->angle_min) / laser_scan->angle_increment;
104  if (range < laser_scan->ranges[index]) {
105  laser_scan->ranges[index] = range;
106  }
107 }
108 
109 void toLaserScan(const TangoPointCloud& tango_point_cloud,
110  double time_offset,
111  double min_height,
112  double max_height,
113  double min_range,
114  double max_range,
115  const tf::Transform& point_cloud_T_laser,
116  sensor_msgs::LaserScan* laser_scan) {
117  for (size_t i = 0; i < tango_point_cloud.num_points; ++i) {
118  const tf::Vector3 point_cloud_p(tango_point_cloud.points[i][0],
119  tango_point_cloud.points[i][1],
120  tango_point_cloud.points[i][2]);
121  tf::Vector3 laser_scan_p = point_cloud_T_laser.inverse() * point_cloud_p;
122  toLaserScanRange(laser_scan_p.getX(), laser_scan_p.getY(), laser_scan_p.getZ(),
123  min_height, max_height, min_range, max_range, laser_scan);
124  }
125  laser_scan->header.stamp.fromSec(tango_point_cloud.timestamp + time_offset);
126 }
127 
128 std::string toFrameId(const TangoCoordinateFrameType& tango_frame_type) {
129  std::string string_frame_type;
130  switch(tango_frame_type) {
132  string_frame_type = "area_description";
133  break;
135  string_frame_type = "camera_color";
136  break;
138  string_frame_type = "camera_depth";
139  break;
141  string_frame_type = "camera_fisheye";
142  break;
144  string_frame_type = "device";
145  break;
147  string_frame_type = "display";
148  break;
150  string_frame_type = "global_wgs84";
151  break;
153  string_frame_type = "imu";
154  break;
156  string_frame_type = "previous_device_pose";
157  break;
159  string_frame_type = "start_of_service";
160  break;
162  string_frame_type = "uuid";
163  break;
164  default:
165  ROS_WARN("Unknown TangoCoordinateFrameType: %d", tango_frame_type);
166  string_frame_type = "unknown";
167  break;
168  }
169  return string_frame_type;
170 }
171 
172 void toCameraInfo(const TangoCameraIntrinsics& camera_intrinsics,
173  sensor_msgs::CameraInfo* camera_info) {
174  camera_info->height = camera_intrinsics.height;
175  camera_info->width = camera_intrinsics.width;
176  camera_info->K = {camera_intrinsics.fx, 0., camera_intrinsics.cx,
177  0., camera_intrinsics.fy, camera_intrinsics.cy,
178  0., 0., 1.};
179  camera_info->R = {1., 0., 0., 0., 1., 0., 0., 0., 1.};
180  camera_info->P = {camera_intrinsics.fx, 0., camera_intrinsics.cx, 0.,
181  0., camera_intrinsics.fy, camera_intrinsics.cy, 0.,
182  0., 0., 1., 0.};
183  if (camera_intrinsics.camera_id == TangoCameraId::TANGO_CAMERA_FISHEYE) {
184  camera_info->distortion_model = sensor_msgs::distortion_models::PLUMB_BOB;
185  camera_info->D = {camera_intrinsics.distortion[0],
186  camera_intrinsics.distortion[1], camera_intrinsics.distortion[2],
187  camera_intrinsics.distortion[3], camera_intrinsics.distortion[4]};
188  } else if (camera_intrinsics.camera_id == TangoCameraId::TANGO_CAMERA_COLOR) {
189  camera_info->distortion_model = sensor_msgs::distortion_models::RATIONAL_POLYNOMIAL;
190  camera_info->D = {camera_intrinsics.distortion[0],
191  camera_intrinsics.distortion[1], 0., 0., camera_intrinsics.distortion[2]};
192  } else {
193  ROS_WARN("Unknown camera ID: %d", camera_intrinsics.camera_id);
194  }
195 }
196 
198  const TangoCameraIntrinsics& camera_intrinsics,
199  Tango3DR_CameraCalibration* t3dr_camera_intrinsics) {
200  t3dr_camera_intrinsics->calibration_type =
201  static_cast<Tango3DR_TangoCalibrationType>(camera_intrinsics.calibration_type);
202  t3dr_camera_intrinsics->width = camera_intrinsics.width;
203  t3dr_camera_intrinsics->height = camera_intrinsics.height;
204  t3dr_camera_intrinsics->fx = camera_intrinsics.fx;
205  t3dr_camera_intrinsics->fy = camera_intrinsics.fy;
206  t3dr_camera_intrinsics->cx = camera_intrinsics.cx;
207  t3dr_camera_intrinsics->cy = camera_intrinsics.cy;
208  std::copy(std::begin(camera_intrinsics.distortion),
209  std::end(camera_intrinsics.distortion),
210  std::begin(t3dr_camera_intrinsics->distortion));
211 }
212 
213 void toTango3DR_Pose(const TangoPoseData& tango_pose_data, Tango3DR_Pose* t3dr_pose) {
214  std::copy(std::begin(tango_pose_data.translation),
215  std::end(tango_pose_data.translation),
216  std::begin(t3dr_pose->translation));
217  std::copy(std::begin(tango_pose_data.orientation),
218  std::end(tango_pose_data.orientation),
219  std::begin(t3dr_pose->orientation));
220 }
221 
222 void toMeshMarker(const Tango3DR_GridIndex& grid_index,
223  const Tango3DR_Mesh& tango_mesh,
224  double time_offset, const std::string& base_frame_id,
225  visualization_msgs::Marker* mesh_marker) {
226  mesh_marker->header.frame_id = base_frame_id;
227  mesh_marker->header.stamp.fromSec(tango_mesh.timestamp + time_offset);
228  mesh_marker->ns = "tango";
229  mesh_marker->type = visualization_msgs::Marker::TRIANGLE_LIST;
230  mesh_marker->action = visualization_msgs::Marker::ADD;
231  mesh_marker->pose.orientation.w = 1.0;
232  mesh_marker->scale.x = 1.0;
233  mesh_marker->scale.y = 1.0;
234  mesh_marker->scale.z = 1.0;
235  mesh_marker->color.r = 1.0;
236  mesh_marker->color.g = 1.0;
237  mesh_marker->color.b = 1.0;
238  mesh_marker->color.a = 1.0;
239  mesh_marker->lifetime = ros::Duration(0);
240  // Make unique id from tango mesh indices.
241  mesh_marker->id = grid_index[0];
242  mesh_marker->id *= 37;
243  mesh_marker->id += grid_index[1];
244  mesh_marker->id *= 37;
245  mesh_marker->id += grid_index[2];
246  mesh_marker->points.resize(tango_mesh.num_faces * 3);
247  mesh_marker->colors.resize(tango_mesh.num_faces * 3);
248  for (size_t i = 0; i < tango_mesh.num_faces; ++i) {
249  // Add the 3 points of the triangle face and the corresponding colors.
250  geometry_msgs::Point point;
251  toPoint(tango_mesh.vertices[tango_mesh.faces[i][0]], &point);
252  mesh_marker->points[i * 3] = point;
253  toPoint(tango_mesh.vertices[tango_mesh.faces[i][1]], &point);
254  mesh_marker->points[i * 3 + 1] = point;
255  toPoint(tango_mesh.vertices[tango_mesh.faces[i][2]], &point);
256  mesh_marker->points[i * 3 + 2] = point;
257 
258  std_msgs::ColorRGBA color;
259  toColor(tango_mesh.colors[tango_mesh.faces[i][0]], &color);
260  mesh_marker->colors[i * 3] = color;
261  toColor(tango_mesh.colors[tango_mesh.faces[i][1]], &color);
262  mesh_marker->colors[i * 3 + 1] = color;
263  toColor(tango_mesh.colors[tango_mesh.faces[i][2]], &color);
264  mesh_marker->colors[i * 3 + 2] = color;
265  }
266 }
267 
268 void toOccupancyGrid(const Tango3DR_ImageBuffer& image_grid,
269  const Tango3DR_Vector2& origin, double time_offset,
270  const std::string& base_frame_id, double resolution,
271  uint8_t threshold, nav_msgs::OccupancyGrid* occupancy_grid) {
272  occupancy_grid->header.frame_id = base_frame_id;
273  occupancy_grid->header.stamp.fromSec(image_grid.timestamp + time_offset);
274  occupancy_grid->info.map_load_time = occupancy_grid->header.stamp;
275  occupancy_grid->info.width = image_grid.width;
276  occupancy_grid->info.height = image_grid.height;
277  occupancy_grid->info.resolution = resolution;
278  occupancy_grid->info.origin.position.x = origin[0];
279  // We have the position of the top left pixel, instead we want the position
280  // of the bottom left pixel.
281  occupancy_grid->info.origin.position.y = origin[1] - image_grid.height * resolution;
282 
283  occupancy_grid->data.reserve(image_grid.height * image_grid.width);
284  for (size_t i = 0; i < image_grid.height; ++i) {
285  for (size_t j = 0; j < image_grid.width; ++j) {
286  // The image uses a coordinate system with (x: right, y: down), while
287  // the occupancy grid is using (x: right, y: up). The image is therefore
288  // flipped around the x axis.
289  uint8_t value = image_grid.data[j + (image_grid.height - i - 1) * image_grid.width];
290  if (value == 128) {
291  occupancy_grid->data.push_back(UNKNOWN_CELL);
292  } else if (value <= threshold) {
293  occupancy_grid->data.push_back(FREE_CELL);
294  } else if (value > threshold) {
295  occupancy_grid->data.push_back(OCCUPIED_CELL);
296  } else {
297  LOG(WARNING) << "Unknown value: " << static_cast<int>(value);
298  }
299  }
300  }
301 }
302 
303 void toPoint(const Tango3DR_Vector3& tango_vector, geometry_msgs::Point* point) {
304  point->x = tango_vector[0];
305  point->y = tango_vector[1];
306  point->z = tango_vector[2];
307 }
308 
309 void toColor(const Tango3DR_Color& tango_color, std_msgs::ColorRGBA* color) {
310  color->r = tango_color[0] / 255.;
311  color->g = tango_color[1] / 255.;
312  color->b = tango_color[2] / 255.;
313  color->a = tango_color[3] / 255.;
314 }
315 } // namespace tango_ros_conversions_helper
TangoCoordinateFrameType
double timestamp
const std::string RATIONAL_POLYNOMIAL
TANGO_COORDINATE_FRAME_DISPLAY
void toPointCloud2(const TangoPointCloud &tango_point_cloud, double time_offset, sensor_msgs::PointCloud2 *point_cloud)
void toTango3DR_Pose(const TangoPoseData &tango_pose_data, Tango3DR_Pose *t3dr_pose)
TangoCameraId camera_id
TANGO_CAMERA_COLOR
double translation[3]
void toLaserScan(const TangoPointCloud &tango_point_cloud, double time_offset, double min_height, double max_height, double min_range, double max_range, const tf::Transform &point_cloud_T_laser, sensor_msgs::LaserScan *laser_scan)
TANGO_COORDINATE_FRAME_PREVIOUS_DEVICE_POSE
INLINE Rall1d< T, V, S > hypot(const Rall1d< T, V, S > &y, const Rall1d< T, V, S > &x)
TFSIMD_FORCE_INLINE const tfScalar & getY() const
void setPointCloud2Fields(int n_fields,...)
uint32_t num_faces
TFSIMD_FORCE_INLINE tfScalar distance(const Vector3 &v) const
TANGO_COORDINATE_FRAME_CAMERA_COLOR
TANGO_COORDINATE_FRAME_START_OF_SERVICE
TFSIMD_FORCE_INLINE const tfScalar & getZ() const
#define ROS_WARN(...)
TANGO_COORDINATE_FRAME_UUID
TFSIMD_FORCE_INLINE tfScalar angle(const Quaternion &q1, const Quaternion &q2)
float Tango3DR_Vector2[2]
Tango3DR_Color * colors
double orientation[4]
double timestamp
Tango3DR_Vector3 * vertices
TANGO_COORDINATE_FRAME_AREA_DESCRIPTION
TANGO_COORDINATE_FRAME_CAMERA_FISHEYE
TANGO_COORDINATE_FRAME_IMU
TANGO_COORDINATE_FRAME_CAMERA_DEPTH
void toColor(const Tango3DR_Color &tango_color, std_msgs::ColorRGBA *color)
Tango3DR_Face * faces
void toTransformStamped(const TangoPoseData &pose, double time_offset, const std::string &base_frame_id, const std::string &target_frame_id, geometry_msgs::TransformStamped *transform)
Transform inverse() const
std::string toFrameId(const TangoCoordinateFrameType &tango_frame_type)
INLINE Rall1d< T, V, S > sqrt(const Rall1d< T, V, S > &arg)
TANGO_COORDINATE_FRAME_DEVICE
uint32_t num_points
void toCameraInfo(const TangoCameraIntrinsics &camera_intrinsics, sensor_msgs::CameraInfo *camera_info)
TANGO_CAMERA_FISHEYE
void toTango3DR_CameraCalibration(const TangoCameraIntrinsics &camera_intrinsics, Tango3DR_CameraCalibration *t3dr_camera_intrinsics)
void toLaserScanRange(double x, double y, double z, double min_height, double max_height, double min_range, double max_range, sensor_msgs::LaserScan *laser_scan)
float Tango3DR_Vector3[3]
Tango3DR_TangoCalibrationType
INLINE Rall1d< T, V, S > atan2(const Rall1d< T, V, S > &y, const Rall1d< T, V, S > &x)
void toPoint(const Tango3DR_Vector3 &tango_vector, geometry_msgs::Point *point)
TFSIMD_FORCE_INLINE const tfScalar & getX() const
void toOccupancyGrid(const Tango3DR_ImageBuffer &image_grid, const Tango3DR_Vector2 &origin, double time_offset, const std::string &base_frame_id, double resolution, uint8_t threshold, nav_msgs::OccupancyGrid *occupancy_grid)
world coordinates (x: right, y: up).
void toMeshMarker(const Tango3DR_GridIndex &grid_index, const Tango3DR_Mesh &tango_mesh, double time_offset, const std::string &base_frame_id, visualization_msgs::Marker *mesh_marker)
TANGO_COORDINATE_FRAME_GLOBAL_WGS84
double orientation[4]
TangoCalibrationType calibration_type
Tango3DR_TangoCalibrationType calibration_type
double translation[3]
int Tango3DR_GridIndex[3]
uint8_t Tango3DR_Color[4]
float(* points)[4]


tango_ros_native
Author(s):
autogenerated on Mon Jun 10 2019 15:37:51