00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
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
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
00086 return;
00087 }
00088 double range = hypot(x, y);
00089 if (range < laser_scan->range_min) {
00090
00091 return;
00092 }
00093 double angle = atan2(y, x);
00094 if (angle < laser_scan->angle_min || angle > laser_scan->angle_max) {
00095
00096 return;
00097 }
00098
00099 if (range > laser_scan->range_max) {
00100 laser_scan->range_max = range;
00101 }
00102
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
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
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
00280
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
00287
00288
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 }