tango_ros_conversions_helper.cpp
Go to the documentation of this file.
00001 // Copyright 2017 Intermodalics All Rights Reserved.
00002 //
00003 // Licensed under the Apache License, Version 2.0 (the "License");
00004 // you may not use this file except in compliance with the License.
00005 // You may obtain a copy of the License at
00006 //
00007 //      http://www.apache.org/licenses/LICENSE-2.0
00008 //
00009 // Unless required by applicable law or agreed to in writing, software
00010 // distributed under the License is distributed on an "AS IS" BASIS,
00011 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00012 // See the License for the specific language governing permissions and
00013 // limitations under the License.
00014 #include "tango_ros_native/tango_ros_conversions_helper.h"
00015 
00016 #include <glog/logging.h>
00017 
00018 #include <ros/ros.h>
00019 #include <sensor_msgs/distortion_models.h>
00020 #include <sensor_msgs/PointField.h>
00021 #include <sensor_msgs/point_cloud2_iterator.h>
00022 
00023 namespace tango_ros_conversions_helper {
00024 void toTransformStamped(const TangoPoseData& pose,
00025                         double time_offset,
00026                         const std::string& base_frame_id,
00027                         const std::string& target_frame_id,
00028                         geometry_msgs::TransformStamped* transform) {
00029   transform->header.stamp.fromSec(pose.timestamp + time_offset);
00030   transform->header.frame_id = base_frame_id;
00031   transform->child_frame_id = target_frame_id;
00032 
00033   transform->transform.translation.x = pose.translation[0];
00034   transform->transform.translation.y = pose.translation[1];
00035   transform->transform.translation.z = pose.translation[2];
00036   transform->transform.rotation.x = pose.orientation[0];
00037   transform->transform.rotation.y = pose.orientation[1];
00038   transform->transform.rotation.z = pose.orientation[2];
00039   transform->transform.rotation.w = pose.orientation[3];
00040 }
00041 
00042 void toPointCloud2(const TangoPointCloud& tango_point_cloud,
00043                    double time_offset,
00044                    sensor_msgs::PointCloud2* point_cloud) {
00045   point_cloud->width = tango_point_cloud.num_points;
00046   point_cloud->height = 1;
00047   point_cloud->point_step = (sizeof(float) * NUMBER_OF_FIELDS_IN_POINT_CLOUD);
00048   point_cloud->is_dense = true;
00049   point_cloud->row_step = point_cloud->width;
00050   point_cloud->is_bigendian = false;
00051   point_cloud->data.resize(tango_point_cloud.num_points);
00052   sensor_msgs::PointCloud2Modifier modifier(*point_cloud);
00053   modifier.setPointCloud2Fields(NUMBER_OF_FIELDS_IN_POINT_CLOUD,
00054                                 "x", 1, sensor_msgs::PointField::FLOAT32,
00055                                 "y", 1, sensor_msgs::PointField::FLOAT32,
00056                                 "z", 1, sensor_msgs::PointField::FLOAT32,
00057                                 "c", 1, sensor_msgs::PointField::FLOAT32);
00058   modifier.resize(tango_point_cloud.num_points);
00059   sensor_msgs::PointCloud2Iterator<float> iter_x(*point_cloud, "x");
00060   sensor_msgs::PointCloud2Iterator<float> iter_y(*point_cloud, "y");
00061   sensor_msgs::PointCloud2Iterator<float> iter_z(*point_cloud, "z");
00062   sensor_msgs::PointCloud2Iterator<float> iter_c(*point_cloud, "c");
00063   for (size_t i = 0; i < tango_point_cloud.num_points;
00064       ++i, ++iter_x, ++iter_y, ++iter_z, ++iter_c) {
00065     *iter_x = tango_point_cloud.points[i][0];
00066     *iter_y = tango_point_cloud.points[i][1];
00067     *iter_z = tango_point_cloud.points[i][2];
00068     *iter_c = tango_point_cloud.points[i][3];
00069   }
00070   point_cloud->header.stamp.fromSec(tango_point_cloud.timestamp + time_offset);
00071 }
00072 
00073 void toLaserScanRange(double x, double y, double z, double min_height,
00074                       double max_height, double min_range, double max_range,
00075                       sensor_msgs::LaserScan* laser_scan) {
00076   if (std::isnan(x) || std::isnan(y) || std::isnan(z)) {
00077     // NAN point.
00078     return;
00079   }
00080   double distance = sqrt(x * x  + y * y + z * z);
00081   if (distance < min_range || distance > max_range) {
00082     return;
00083   }
00084   if (z > max_height || z < min_height) {
00085     // Z not in height range.
00086     return;
00087   }
00088   double range = hypot(x, y);
00089   if (range < laser_scan->range_min) {
00090     // Point not in distance range.
00091     return;
00092   }
00093   double angle = atan2(y, x);
00094   if (angle < laser_scan->angle_min || angle > laser_scan->angle_max) {
00095     // Point not in angle range.
00096     return;
00097   }
00098 
00099   if (range > laser_scan->range_max) {
00100     laser_scan->range_max = range;
00101   }
00102   // Overwrite range at laser scan ray if new range is smaller.
00103   int index = (angle - laser_scan->angle_min) / laser_scan->angle_increment;
00104   if (range < laser_scan->ranges[index]) {
00105     laser_scan->ranges[index] = range;
00106   }
00107 }
00108 
00109 void toLaserScan(const TangoPointCloud& tango_point_cloud,
00110                  double time_offset,
00111                  double min_height,
00112                  double max_height,
00113                  double min_range,
00114                  double max_range,
00115                  const tf::Transform& point_cloud_T_laser,
00116                  sensor_msgs::LaserScan* laser_scan) {
00117   for (size_t i = 0; i < tango_point_cloud.num_points; ++i) {
00118     const tf::Vector3 point_cloud_p(tango_point_cloud.points[i][0],
00119                                     tango_point_cloud.points[i][1],
00120                                     tango_point_cloud.points[i][2]);
00121     tf::Vector3 laser_scan_p  = point_cloud_T_laser.inverse() * point_cloud_p;
00122     toLaserScanRange(laser_scan_p.getX(), laser_scan_p.getY(), laser_scan_p.getZ(),
00123         min_height, max_height, min_range, max_range, laser_scan);
00124   }
00125   laser_scan->header.stamp.fromSec(tango_point_cloud.timestamp + time_offset);
00126 }
00127 
00128 std::string toFrameId(const TangoCoordinateFrameType& tango_frame_type) {
00129   std::string string_frame_type;
00130   switch(tango_frame_type) {
00131     case TANGO_COORDINATE_FRAME_AREA_DESCRIPTION:
00132       string_frame_type = "area_description";
00133       break;
00134     case TANGO_COORDINATE_FRAME_CAMERA_COLOR:
00135       string_frame_type = "camera_color";
00136       break;
00137     case TANGO_COORDINATE_FRAME_CAMERA_DEPTH:
00138       string_frame_type = "camera_depth";
00139       break;
00140     case TANGO_COORDINATE_FRAME_CAMERA_FISHEYE:
00141       string_frame_type = "camera_fisheye";
00142       break;
00143     case TANGO_COORDINATE_FRAME_DEVICE:
00144       string_frame_type = "device";
00145       break;
00146     case TANGO_COORDINATE_FRAME_DISPLAY:
00147       string_frame_type = "display";
00148       break;
00149     case TANGO_COORDINATE_FRAME_GLOBAL_WGS84:
00150       string_frame_type = "global_wgs84";
00151       break;
00152     case TANGO_COORDINATE_FRAME_IMU:
00153       string_frame_type = "imu";
00154       break;
00155     case TANGO_COORDINATE_FRAME_PREVIOUS_DEVICE_POSE:
00156       string_frame_type = "previous_device_pose";
00157       break;
00158     case TANGO_COORDINATE_FRAME_START_OF_SERVICE:
00159       string_frame_type = "start_of_service";
00160       break;
00161     case TANGO_COORDINATE_FRAME_UUID:
00162       string_frame_type = "uuid";
00163       break;
00164     default:
00165       ROS_WARN("Unknown TangoCoordinateFrameType: %d", tango_frame_type);
00166       string_frame_type = "unknown";
00167       break;
00168   }
00169   return string_frame_type;
00170 }
00171 
00172 void toCameraInfo(const TangoCameraIntrinsics& camera_intrinsics,
00173                   sensor_msgs::CameraInfo* camera_info) {
00174   camera_info->height = camera_intrinsics.height;
00175   camera_info->width = camera_intrinsics.width;
00176   camera_info->K = {camera_intrinsics.fx, 0., camera_intrinsics.cx,
00177                     0., camera_intrinsics.fy, camera_intrinsics.cy,
00178                     0., 0., 1.};
00179   camera_info->R = {1., 0., 0., 0., 1., 0., 0., 0., 1.};
00180   camera_info->P = {camera_intrinsics.fx, 0., camera_intrinsics.cx, 0.,
00181                     0., camera_intrinsics.fy, camera_intrinsics.cy, 0.,
00182                     0., 0., 1., 0.};
00183   if (camera_intrinsics.camera_id == TangoCameraId::TANGO_CAMERA_FISHEYE) {
00184     camera_info->distortion_model = sensor_msgs::distortion_models::PLUMB_BOB;
00185     camera_info->D = {camera_intrinsics.distortion[0],
00186         camera_intrinsics.distortion[1], camera_intrinsics.distortion[2],
00187         camera_intrinsics.distortion[3], camera_intrinsics.distortion[4]};
00188   } else if (camera_intrinsics.camera_id == TangoCameraId::TANGO_CAMERA_COLOR) {
00189     camera_info->distortion_model = sensor_msgs::distortion_models::RATIONAL_POLYNOMIAL;
00190     camera_info->D = {camera_intrinsics.distortion[0],
00191         camera_intrinsics.distortion[1], 0., 0., camera_intrinsics.distortion[2]};
00192   } else {
00193     ROS_WARN("Unknown camera ID: %d", camera_intrinsics.camera_id);
00194   }
00195 }
00196 
00197 void toTango3DR_CameraCalibration(
00198     const TangoCameraIntrinsics& camera_intrinsics,
00199     Tango3DR_CameraCalibration* t3dr_camera_intrinsics) {
00200   t3dr_camera_intrinsics->calibration_type =
00201           static_cast<Tango3DR_TangoCalibrationType>(camera_intrinsics.calibration_type);
00202   t3dr_camera_intrinsics->width = camera_intrinsics.width;
00203   t3dr_camera_intrinsics->height = camera_intrinsics.height;
00204   t3dr_camera_intrinsics->fx = camera_intrinsics.fx;
00205   t3dr_camera_intrinsics->fy = camera_intrinsics.fy;
00206   t3dr_camera_intrinsics->cx = camera_intrinsics.cx;
00207   t3dr_camera_intrinsics->cy = camera_intrinsics.cy;
00208   std::copy(std::begin(camera_intrinsics.distortion),
00209             std::end(camera_intrinsics.distortion),
00210             std::begin(t3dr_camera_intrinsics->distortion));
00211 }
00212 
00213 void toTango3DR_Pose(const TangoPoseData& tango_pose_data, Tango3DR_Pose* t3dr_pose) {
00214   std::copy(std::begin(tango_pose_data.translation),
00215             std::end(tango_pose_data.translation),
00216             std::begin(t3dr_pose->translation));
00217   std::copy(std::begin(tango_pose_data.orientation),
00218             std::end(tango_pose_data.orientation),
00219             std::begin(t3dr_pose->orientation));
00220 }
00221 
00222 void toMeshMarker(const Tango3DR_GridIndex& grid_index,
00223                   const Tango3DR_Mesh& tango_mesh,
00224                   double time_offset, const std::string& base_frame_id,
00225                   visualization_msgs::Marker* mesh_marker) {
00226   mesh_marker->header.frame_id = base_frame_id;
00227   mesh_marker->header.stamp.fromSec(tango_mesh.timestamp + time_offset);
00228   mesh_marker->ns = "tango";
00229   mesh_marker->type = visualization_msgs::Marker::TRIANGLE_LIST;
00230   mesh_marker->action = visualization_msgs::Marker::ADD;
00231   mesh_marker->pose.orientation.w = 1.0;
00232   mesh_marker->scale.x = 1.0;
00233   mesh_marker->scale.y = 1.0;
00234   mesh_marker->scale.z = 1.0;
00235   mesh_marker->color.r = 1.0;
00236   mesh_marker->color.g = 1.0;
00237   mesh_marker->color.b = 1.0;
00238   mesh_marker->color.a = 1.0;
00239   mesh_marker->lifetime = ros::Duration(0);
00240   // Make unique id from tango mesh indices.
00241   mesh_marker->id = grid_index[0];
00242   mesh_marker->id *= 37;
00243   mesh_marker->id += grid_index[1];
00244   mesh_marker->id *= 37;
00245   mesh_marker->id += grid_index[2];
00246   mesh_marker->points.resize(tango_mesh.num_faces * 3);
00247   mesh_marker->colors.resize(tango_mesh.num_faces * 3);
00248   for (size_t i = 0; i < tango_mesh.num_faces; ++i) {
00249     // Add the 3 points of the triangle face and the corresponding colors.
00250     geometry_msgs::Point point;
00251     toPoint(tango_mesh.vertices[tango_mesh.faces[i][0]], &point);
00252     mesh_marker->points[i * 3] = point;
00253     toPoint(tango_mesh.vertices[tango_mesh.faces[i][1]], &point);
00254     mesh_marker->points[i * 3 + 1] = point;
00255     toPoint(tango_mesh.vertices[tango_mesh.faces[i][2]], &point);
00256     mesh_marker->points[i * 3 + 2] = point;
00257 
00258     std_msgs::ColorRGBA color;
00259     toColor(tango_mesh.colors[tango_mesh.faces[i][0]], &color);
00260     mesh_marker->colors[i * 3] = color;
00261     toColor(tango_mesh.colors[tango_mesh.faces[i][1]], &color);
00262     mesh_marker->colors[i * 3 + 1] = color;
00263     toColor(tango_mesh.colors[tango_mesh.faces[i][2]], &color);
00264     mesh_marker->colors[i * 3 + 2] = color;
00265   }
00266 }
00267 
00268 void toOccupancyGrid(const Tango3DR_ImageBuffer& image_grid,
00269                      const Tango3DR_Vector2& origin, double time_offset,
00270                      const std::string& base_frame_id, double resolution,
00271                      uint8_t threshold, nav_msgs::OccupancyGrid* occupancy_grid) {
00272   occupancy_grid->header.frame_id = base_frame_id;
00273   occupancy_grid->header.stamp.fromSec(image_grid.timestamp + time_offset);
00274   occupancy_grid->info.map_load_time = occupancy_grid->header.stamp;
00275   occupancy_grid->info.width = image_grid.width;
00276   occupancy_grid->info.height = image_grid.height;
00277   occupancy_grid->info.resolution = resolution;
00278   occupancy_grid->info.origin.position.x = origin[0];
00279   // We have the position of the top left pixel, instead we want the position
00280   // of the bottom left pixel.
00281   occupancy_grid->info.origin.position.y = origin[1] - image_grid.height * resolution;
00282 
00283   occupancy_grid->data.reserve(image_grid.height * image_grid.width);
00284   for (size_t i = 0; i < image_grid.height; ++i) {
00285     for (size_t j = 0; j < image_grid.width; ++j) {
00286       // The image uses a coordinate system with (x: right, y: down), while
00287       // the occupancy grid is using (x: right, y: up). The image is therefore
00288       // flipped around the x axis.
00289       uint8_t value = image_grid.data[j + (image_grid.height - i - 1) * image_grid.width];
00290       if (value == 128) {
00291         occupancy_grid->data.push_back(UNKNOWN_CELL);
00292       } else if (value <= threshold) {
00293         occupancy_grid->data.push_back(FREE_CELL);
00294       } else if (value > threshold) {
00295         occupancy_grid->data.push_back(OCCUPIED_CELL);
00296       } else {
00297         LOG(WARNING) << "Unknown value: " << static_cast<int>(value);
00298       }
00299     }
00300   }
00301 }
00302 
00303 void toPoint(const Tango3DR_Vector3& tango_vector, geometry_msgs::Point* point) {
00304   point->x = tango_vector[0];
00305   point->y = tango_vector[1];
00306   point->z = tango_vector[2];
00307 }
00308 
00309 void toColor(const Tango3DR_Color& tango_color, std_msgs::ColorRGBA* color) {
00310   color->r = tango_color[0] / 255.;
00311   color->g = tango_color[1] / 255.;
00312   color->b = tango_color[2] / 255.;
00313   color->a = tango_color[3] / 255.;
00314 }
00315 } // namespace tango_ros_conversions_helper


tango_ros_native
Author(s):
autogenerated on Thu Jun 6 2019 19:49:54