diff --git a/voxblox/include/voxblox/integrator/projective_tsdf_integrator.h b/voxblox/include/voxblox/integrator/projective_tsdf_integrator.h new file mode 100644 index 000000000..b0e6e5ce1 --- /dev/null +++ b/voxblox/include/voxblox/integrator/projective_tsdf_integrator.h @@ -0,0 +1,67 @@ +#ifndef VOXBLOX_INCLUDE_VOXBLOX_INTEGRATOR_PROJECTIVE_TSDF_INTEGRATOR_H_ +#define VOXBLOX_INCLUDE_VOXBLOX_INTEGRATOR_PROJECTIVE_TSDF_INTEGRATOR_H_ + +#include + +#include "voxblox/integrator/tsdf_integrator.h" + +namespace voxblox { +enum class InterpolationScheme { + kNearestNeighbor, + kMinNeighbor, + kBilinear, + kAdaptive +}; +template +class ProjectiveTsdfIntegrator : public voxblox::TsdfIntegratorBase { + public: + ProjectiveTsdfIntegrator(const Config& config, + voxblox::Layer* layer); + + void integratePointCloud(const Transformation& T_G_C, + const Pointcloud& points_C, const Colors& colors, + const bool freespace_points = false) override; + void integratePointCloud(const Transformation& T_G_C, + const Pointcloud& points_C, const Colors& colors, + const bool freespace_points = false, + const bool deintegrate = false); + + private: + // Sensor model + const int horizontal_resolution_; + const int vertical_resolution_; + const double vertical_fov_rad_; + const double ray_intersections_per_distance_squared_; + + Eigen::MatrixXf range_image_; + + // Calculate the number of voxels per block + const size_t num_voxels_per_block_; + + void parsePointcloud(const Transformation& T_G_C, const Pointcloud& points_C, + Eigen::MatrixXf* range_image, + voxblox::IndexSet* touched_block_indices); + + void updateTsdfBlocks(const Transformation& T_G_C, + const Eigen::MatrixXf& range_image, + const voxblox::IndexSet& touched_block_indices, + const bool deintegrate = false); + inline void updateTsdfVoxel(const Transformation& T_G_C, + const Eigen::MatrixXf& range_image, + const Point& t_C_voxel, TsdfVoxel* tsdf_voxel, + const bool deintegrate = false); + + template + Point imageToBearing(const T h, const T w); + + template + bool bearingToImage(const Point& b_C_normalized, T* h, T* w); + + inline float interpolate(const Eigen::MatrixXf& range_image, const float h, + const float w); +}; +} // namespace voxblox + +#include "voxblox/integrator/projective_tsdf_integrator_inl.h" + +#endif // VOXBLOX_INCLUDE_VOXBLOX_INTEGRATOR_PROJECTIVE_TSDF_INTEGRATOR_H_ diff --git a/voxblox/include/voxblox/integrator/projective_tsdf_integrator_inl.h b/voxblox/include/voxblox/integrator/projective_tsdf_integrator_inl.h new file mode 100644 index 000000000..0ca12eda0 --- /dev/null +++ b/voxblox/include/voxblox/integrator/projective_tsdf_integrator_inl.h @@ -0,0 +1,450 @@ +#ifndef VOXBLOX_INTEGRATOR_PROJECTIVE_TSDF_INTEGRATOR_INL_H_ +#define VOXBLOX_INTEGRATOR_PROJECTIVE_TSDF_INTEGRATOR_INL_H_ + +#include +#include +#include +#include + +#include "voxblox/core/block.h" + +namespace voxblox { +template +ProjectiveTsdfIntegrator::ProjectiveTsdfIntegrator( + const voxblox::TsdfIntegratorBase::Config &config, + voxblox::Layer *layer) + : TsdfIntegratorBase(config, layer), + horizontal_resolution_(config.sensor_horizontal_resolution), + vertical_resolution_(config.sensor_vertical_resolution), + vertical_fov_rad_(config.sensor_vertical_field_of_view_degrees * M_PI / + 180.0), + range_image_(config.sensor_vertical_resolution, + config.sensor_horizontal_resolution), + num_voxels_per_block_(layer_->voxels_per_side() * + layer_->voxels_per_side() * + layer_->voxels_per_side()), + ray_intersections_per_distance_squared_( + voxel_size_ * horizontal_resolution_ / + (2 * M_PI) // horizontal point density + * voxel_size_ * vertical_resolution_ / + vertical_fov_rad_) // vertical point density +{ + CHECK_GT(horizontal_resolution_, 0) + << "The horizontal sensor resolution must be a positive integer"; + CHECK_GT(vertical_resolution_, 0) + << "The vertical sensor resolution must be a positive integer"; + CHECK_GT(vertical_fov_rad_, 0) + << "The vertical field of view of the sensor must be a positive float"; + CHECK(config_.use_const_weight) << "Scaling the weight by the inverse square " + "depth is (not yet) supported."; +} + +template +void ProjectiveTsdfIntegrator::integratePointCloud( + const Transformation &T_G_C, const Pointcloud &points_C, + const Colors &colors, const bool freespace_points) { + integratePointCloud(T_G_C, points_C, colors, freespace_points, false); +} + +template +void ProjectiveTsdfIntegrator::integratePointCloud( + const Transformation &T_G_C, const Pointcloud &points_C, + const Colors &colors, const bool freespace_points, const bool deintegrate) { + // Construct the range image and select the blocks it affects + voxblox::IndexSet touched_block_indices; + timing::Timer range_image_and_block_selector_timer( + "range_image_and_block_selector_timer"); + parsePointcloud(T_G_C, points_C, &range_image_, &touched_block_indices); + range_image_and_block_selector_timer.Stop(); + + // Process all blocks + timing::Timer integration_timer("integration_timer"); + if (config_.integrator_threads == 1) { + updateTsdfBlocks(T_G_C, range_image_, touched_block_indices, deintegrate); + } else { + std::vector block_index_subsets( + config_.integrator_threads); + size_t idx = 0; + for (const auto &block_index : touched_block_indices) { + block_index_subsets[idx % config_.integrator_threads].emplace( + block_index); + idx++; + } + std::list integration_threads; + for (size_t i = 0; i < config_.integrator_threads; ++i) { + integration_threads.emplace_back( + &ProjectiveTsdfIntegrator::updateTsdfBlocks, this, T_G_C, + range_image_, block_index_subsets[i], deintegrate); + } + for (std::thread &integration_thread : integration_threads) { + integration_thread.join(); + } + } + integration_timer.Stop(); +} + +template +void ProjectiveTsdfIntegrator::parsePointcloud( + const Transformation &T_G_C, const Pointcloud &points_C, + Eigen::MatrixXf *range_image, voxblox::IndexSet *touched_block_indices) { + CHECK_NOTNULL(range_image); + CHECK_NOTNULL(touched_block_indices); + range_image->setZero(); + voxblox::Point t_G_C_scaled = T_G_C.getPosition() * layer_->block_size_inv(); + for (const voxblox::Point &point_C : points_C) { + // Compute the point's bearing vector + float distance = point_C.norm(); + if (std::abs(distance) < kFloatEpsilon) { + // Avoid divisions by zero + continue; + } + Point point_C_bearing = point_C / distance; + + // Get the bearing vector's coordinates in the range image + // NOTE: In this first implementation we only update the range image at its + // nearest neighbor coordinate + int h, w; + if (!bearingToImage(point_C_bearing, &h, &w)) { + continue; + } + + // Set the range image distance + if (range_image->operator()(h, w) < kFloatEpsilon) { + range_image->operator()(h, w) = distance; + } else { + // If the range pixel has already been updated by another ray, + // we resolve the conflict by taking the minimum distance + range_image->operator()(h, w) = + std::min(range_image->operator()(h, w), distance); + } + + // Mark the blocks hit by this ray + if (config_.min_ray_length_m <= distance && + distance <= config_.max_ray_length_m) { + Point point_G_scaled = + T_G_C * + (point_C_bearing * (distance + config_.default_truncation_distance)) * + layer_->block_size_inv(); + Point t_G_C_truncated_scaled; + if (config_.voxel_carving_enabled) { + t_G_C_truncated_scaled = t_G_C_scaled; + } else { + t_G_C_truncated_scaled = + point_G_scaled - T_G_C * point_C_bearing * + config_.default_truncation_distance * + layer_->block_size_inv(); + } + voxblox::GlobalIndex block_index; + voxblox::RayCaster ray_caster(point_G_scaled, t_G_C_truncated_scaled); + while (ray_caster.nextRayIndex(&block_index)) { + touched_block_indices->insert(block_index.cast()); + } + } + } + + // Allocate all the blocks + // NOTE: The layer's BlockHashMap is not thread safe, so doing it here before + // we start the multi-threading makes life easier + for (const BlockIndex &block_index : *touched_block_indices) { + layer_->allocateBlockPtrByIndex(block_index); + } +} + +template +void ProjectiveTsdfIntegrator::updateTsdfBlocks( + const Transformation &T_G_C, const Eigen::MatrixXf &range_image, + const voxblox::IndexSet &touched_block_indices, const bool deintegrate) { + for (const voxblox::BlockIndex &block_index : touched_block_indices) { + voxblox::Block::Ptr block_ptr = + layer_->getBlockPtrByIndex(block_index); + block_ptr->updated().set(); + + for (size_t linear_index = 0u; linear_index < num_voxels_per_block_; + ++linear_index) { + TsdfVoxel *tsdf_voxel = &block_ptr->getVoxelByLinearIndex(linear_index); + const Point t_C_voxel = + T_G_C.inverse() * + block_ptr->computeCoordinatesFromLinearIndex(linear_index); + updateTsdfVoxel(T_G_C, range_image, t_C_voxel, tsdf_voxel, deintegrate); + } + } +} + +template +void ProjectiveTsdfIntegrator::updateTsdfVoxel( + const Transformation &T_G_C, const Eigen::MatrixXf &range_image, + const Point &t_C_voxel, TsdfVoxel *tsdf_voxel, const bool deintegrate) { + // Skip voxels that are too far or too close + const float distance_to_voxel = t_C_voxel.norm(); + if (distance_to_voxel < config_.min_ray_length_m || + distance_to_voxel > config_.max_ray_length_m) { + return; + } + + // Project the current voxel into the range image + float h, w; + if (!bearingToImage(t_C_voxel / distance_to_voxel, &h, &w)) { + return; + } + + // Compute the signed distance + const float distance_to_surface = interpolate(range_image, h, w); + const float sdf = distance_to_surface - distance_to_voxel; + + // Approximate how many rays would have updated the voxel + // NOTE: We do this to reflect that we are more certain about + // the updates applied to nearer voxels + const float num_rays_intersecting_voxel = + ray_intersections_per_distance_squared_ / + (distance_to_voxel * distance_to_voxel); + + // Skip voxels that fall outside the TSDF truncation distance + if (sdf < -config_.default_truncation_distance) { + return; + } + if (!config_.voxel_carving_enabled && + sdf > config_.default_truncation_distance) { + return; + } + + // Compute the weight of the measurement + float observation_weight; + { + // Set the sign of the measurement weight + if (deintegrate) { + observation_weight = -num_rays_intersecting_voxel; + } else { + observation_weight = num_rays_intersecting_voxel; + } + + // NOTE: Scaling the weight by the inverse square depth is not yet + // supported, since this problem is ill-defined for LiDAR + + // Apply weight drop-off if appropriate + const FloatingPoint dropoff_epsilon = voxel_size_; + if (config_.use_weight_dropoff && sdf < -dropoff_epsilon) { + observation_weight = + observation_weight * (config_.default_truncation_distance + sdf) / + (config_.default_truncation_distance - dropoff_epsilon); + observation_weight = std::max(observation_weight, 0.0f); + } + + // Apply sparsity compensation if appropriate + if (config_.use_sparsity_compensation_factor) { + if (std::abs(sdf) < config_.default_truncation_distance) { + observation_weight *= config_.sparsity_compensation_factor; + } + } + } + + // Truncate the new total voxel weight according to the max weight + const float new_voxel_weight = tsdf_voxel->weight + observation_weight; + + // Make sure voxels go back to zero when deintegrating + if (deintegrate && new_voxel_weight < 1.0) { + tsdf_voxel->distance = 0.0f; + tsdf_voxel->weight = 0.0f; + return; + } + + // Store the updated voxel weight and distance + tsdf_voxel->distance = (tsdf_voxel->distance * tsdf_voxel->weight + + std::min(config_.default_truncation_distance, sdf) * + observation_weight) / + new_voxel_weight; + tsdf_voxel->weight = std::min(new_voxel_weight, config_.max_weight); +} + +template +template +Point ProjectiveTsdfIntegrator::imageToBearing( + const T h, const T w) { + double altitude_angle = + vertical_fov_rad_ * (1.0 / 2.0 - h / (vertical_resolution_ - 1.0)); + double azimuth_angle = + 2.0 * M_PI * static_cast(w) / horizontal_resolution_; + + Point bearing; + bearing.x() = std::cos(altitude_angle) * std::cos(azimuth_angle); + bearing.y() = -std::cos(altitude_angle) * std::sin(azimuth_angle); + bearing.z() = std::sin(altitude_angle); + + return bearing; +} + +template +template +bool ProjectiveTsdfIntegrator::bearingToImage( + const Point &b_C_normalized, T *h, T *w) { + CHECK_NOTNULL(h); + CHECK_NOTNULL(w); + + double altitude_angle = std::asin(b_C_normalized.z()); + *h = static_cast((vertical_resolution_ - 1.0) * + (1.0 / 2.0 - altitude_angle / vertical_fov_rad_)); + if (*h < 0 || vertical_resolution_ - 1 < *h) { + return false; + } + + double azimuth_angle; + if (b_C_normalized.x() > 0) { + if (b_C_normalized.y() > 0) { + azimuth_angle = + 2.0 * M_PI + std::atan(-b_C_normalized.y() / b_C_normalized.x()); + } else { + azimuth_angle = std::atan(-b_C_normalized.y() / b_C_normalized.x()); + } + } else { + azimuth_angle = M_PI + std::atan(-b_C_normalized.y() / b_C_normalized.x()); + } + *w = static_cast(horizontal_resolution_ * azimuth_angle / (2.0 * M_PI)); + if (*w < 0) { + *w += horizontal_resolution_; + } + + return (0 < *w && *w < horizontal_resolution_ - 1); +} + +template <> +inline float +ProjectiveTsdfIntegrator::interpolate( + const Eigen::MatrixXf &range_image, const float h, const float w) { + return range_image(std::round(h), std::round(w)); +} + +template <> +inline float +ProjectiveTsdfIntegrator::interpolate( + const Eigen::MatrixXf &range_image, const float h, const float w) { + // TODO(victorr): Implement better edge handling + if (h >= vertical_resolution_ || w >= horizontal_resolution_) { + return range_image(std::floor(h), std::floor(w)); + } + + const float min_neighbor = + range_image.block<2, 2>(std::floor(h), std::floor(w)).minCoeff(); + + if (min_neighbor < config_.min_ray_length_m) { + return range_image(std::round(h), std::round(w)); + } else { + return min_neighbor; + } +} + +template <> +inline float +ProjectiveTsdfIntegrator::interpolate( + const Eigen::MatrixXf &range_image, const float h, const float w) { + // TODO(victorr): Implement better edge handling + // Check if we're on the edge, to avoid out-of-bounds matrix access + if (h >= vertical_resolution_ || w >= horizontal_resolution_) { + return range_image(std::floor(h), std::floor(w)); + } + + // Check if all of the neighbors are valid values + // NOTE: This for example removes LiDAR points that had no return, + // which are encoded as zeros + if ((range_image.block<2, 2>(std::floor(h), std::floor(w)).array() < + config_.min_ray_length_m) + .any()) { + return range_image(std::round(h), std::round(w)); + } + + // TODO(victorr): Write this as a matrix + float h_int, w_int; + const float h_decimals = std::modf(h, &h_int); + const float w_decimals = std::modf(w, &w_int); + const float left = (1 - h_decimals) * range_image(h_int, w_int) + + h_decimals * range_image(h_int + 1, w_int); + const float right = (1 - h_decimals) * range_image(h_int, w_int + 1) + + h_decimals * range_image(h_int + 1, w_int + 1); + return (1 - w_decimals) * left + w_decimals * right; +} + +template <> +inline float +ProjectiveTsdfIntegrator::interpolate( + const Eigen::MatrixXf &range_image, const float h, const float w) { + // Check if we're on the edge, to avoid out-of-bounds matrix access + if (h >= vertical_resolution_ || w >= horizontal_resolution_) { + return range_image(std::floor(h), std::floor(w)); + } + + // Get the bilinear interpolation coefficients + float h_int, w_int; + const float h_decimals = std::modf(h, &h_int); + const float w_decimals = std::modf(w, &w_int); + + // Define easy to read names for all four range image pixels + const float top_left = range_image(h_int, w_int); + const float top_right = range_image(h_int, w_int + 1); + const float bottom_left = range_image(h_int + 1, w_int); + const float bottom_right = range_image(h_int + 1, w_int + 1); + + // Left column + float bilinear_left, min_left; + if (top_left < config_.min_ray_length_m) { + min_left = bottom_left; + bilinear_left = bottom_left; + } else if (bottom_left < config_.min_ray_length_m) { + min_left = top_left; + bilinear_left = top_left; + } else { + min_left = std::min(top_left, bottom_left); + bilinear_left = (1 - h_decimals) * top_left + h_decimals * bottom_left; + } + + // Right column + float bilinear_right, min_right; + if (top_right < config_.min_ray_length_m) { + min_right = bottom_right; + bilinear_right = bottom_right; + } else if (bottom_right < config_.min_ray_length_m) { + min_right = top_right; + bilinear_right = top_right; + } else { + min_right = std::min(bottom_right, top_right); + bilinear_right = (1 - h_decimals) * top_right + h_decimals * bottom_right; + } + + // Combine left and right bilinear values + float bilinear_distance; + if (bilinear_left < config_.min_ray_length_m) { + if (bilinear_right < config_.min_ray_length_m) { + bilinear_distance = 0.0f; + } else { + bilinear_distance = bilinear_right; + } + } else if (bilinear_right < config_.min_ray_length_m) { + bilinear_distance = bilinear_left; + } else { + bilinear_distance = + (1 - w_decimals) * bilinear_left + w_decimals * bilinear_right; + } + + // Combine left and right min values + float min_distance; + if (min_left < config_.min_ray_length_m) { + if (min_right < config_.min_ray_length_m) { + min_distance = 0.0f; + } else { + min_distance = min_right; + } + } else if (min_right < config_.min_ray_length_m) { + min_distance = min_left; + } else { + min_distance = std::min(min_left, min_right); + } + + // Use the bilinear distance unless the min distance is much smaller, + // in which case we go for the safe option + if (min_distance + 0.5f * config_.default_truncation_distance < + bilinear_distance) { + return min_distance; + } else { + return bilinear_distance; + } +} +} // namespace voxblox + +#endif // VOXBLOX_INTEGRATOR_PROJECTIVE_TSDF_INTEGRATOR_INL_H_ diff --git a/voxblox/include/voxblox/integrator/tsdf_integrator.h b/voxblox/include/voxblox/integrator/tsdf_integrator.h index 9dcf81760..f684002e5 100644 --- a/voxblox/include/voxblox/integrator/tsdf_integrator.h +++ b/voxblox/include/voxblox/integrator/tsdf_integrator.h @@ -31,14 +31,16 @@ enum class TsdfIntegratorType : int { kSimple = 1, kMerged = 2, kFast = 3, + kProjective = 4, }; -static constexpr size_t kNumTsdfIntegratorTypes = 3u; +static constexpr size_t kNumTsdfIntegratorTypes = 4u; const std::array kTsdfIntegratorTypeNames = {{/*kSimple*/ "simple", /*kMerged*/ "merged", - /*kFast*/ "fast"}}; + /*kFast*/ "fast", + /*kProjective*/ "projective"}}; /** * Base class to the simple, merged and fast TSDF integrators. The integrator @@ -84,6 +86,10 @@ class TsdfIntegratorBase { int clear_checks_every_n_frames = 1; /// fast integrator specific float max_integration_time_s = std::numeric_limits::max(); + // projective integrator specific + int sensor_horizontal_resolution = 0; + int sensor_vertical_resolution = 0; + double sensor_vertical_field_of_view_degrees = 0.0; std::string print() const; }; diff --git a/voxblox/src/integrator/esdf_integrator.cc b/voxblox/src/integrator/esdf_integrator.cc index c7f187aae..74277f7af 100644 --- a/voxblox/src/integrator/esdf_integrator.cc +++ b/voxblox/src/integrator/esdf_integrator.cc @@ -505,7 +505,7 @@ bool EsdfIntegrator::updateVoxelFromNeighbors(const GlobalIndex& global_index) { // Go through the neighbors and see if we can update any of them. for (unsigned int idx = 0u; idx < neighbor_indices.cols(); ++idx) { const GlobalIndex& neighbor_index = neighbor_indices.col(idx); - const FloatingPoint distance = Neighborhood<>::kDistances[idx]; + const FloatingPoint distance = Neighborhood<>::kDistances[idx] * voxel_size_; EsdfVoxel* neighbor_voxel = esdf_layer_->getVoxelPtrByGlobalIndex(neighbor_index); diff --git a/voxblox/src/integrator/tsdf_integrator.cc b/voxblox/src/integrator/tsdf_integrator.cc index 40bf72249..11213b23a 100644 --- a/voxblox/src/integrator/tsdf_integrator.cc +++ b/voxblox/src/integrator/tsdf_integrator.cc @@ -1,4 +1,5 @@ #include "voxblox/integrator/tsdf_integrator.h" +#include "voxblox/integrator/projective_tsdf_integrator.h" #include #include @@ -37,6 +38,11 @@ TsdfIntegratorBase::Ptr TsdfIntegratorFactory::create( case TsdfIntegratorType::kFast: return TsdfIntegratorBase::Ptr(new FastTsdfIntegrator(config, layer)); break; + case TsdfIntegratorType::kProjective: + return TsdfIntegratorBase::Ptr( + new ProjectiveTsdfIntegrator(config, + layer)); + break; default: LOG(FATAL) << "Unknown TSDF integrator type: " << static_cast(integrator_type); diff --git a/voxblox_ros/include/voxblox_ros/ros_params.h b/voxblox_ros/include/voxblox_ros/ros_params.h index 856a8aa61..ee7c417d5 100644 --- a/voxblox_ros/include/voxblox_ros/ros_params.h +++ b/voxblox_ros/include/voxblox_ros/ros_params.h @@ -68,6 +68,8 @@ inline TsdfIntegratorBase::Config getTsdfIntegratorConfigFromRosParam( double truncation_distance = integrator_config.default_truncation_distance; double max_weight = integrator_config.max_weight; + int integrator_threads = + static_cast(integrator_config.integrator_threads); nh_private.param("voxel_carving_enabled", integrator_config.voxel_carving_enabled, integrator_config.voxel_carving_enabled); @@ -107,10 +109,22 @@ inline TsdfIntegratorBase::Config getTsdfIntegratorConfigFromRosParam( nh_private.param("integration_order_mode", integrator_config.integration_order_mode, integrator_config.integration_order_mode); + nh_private.param("integrator_threads", integrator_threads, + integrator_threads); + nh_private.param("sensor_horizontal_resolution", + integrator_config.sensor_horizontal_resolution, + integrator_config.sensor_horizontal_resolution); + nh_private.param("sensor_vertical_resolution", + integrator_config.sensor_vertical_resolution, + integrator_config.sensor_vertical_resolution); + nh_private.param("sensor_vertical_field_of_view_degrees", + integrator_config.sensor_vertical_field_of_view_degrees, + integrator_config.sensor_vertical_field_of_view_degrees); integrator_config.default_truncation_distance = static_cast(truncation_distance); integrator_config.max_weight = static_cast(max_weight); + integrator_config.integrator_threads = integrator_threads; return integrator_config; } diff --git a/voxblox_ros/include/voxblox_ros/tsdf_server.h b/voxblox_ros/include/voxblox_ros/tsdf_server.h index 606cf8a61..736bd6e38 100644 --- a/voxblox_ros/include/voxblox_ros/tsdf_server.h +++ b/voxblox_ros/include/voxblox_ros/tsdf_server.h @@ -230,7 +230,7 @@ class TsdfServer { // Maps and integrators. std::shared_ptr tsdf_map_; - std::unique_ptr tsdf_integrator_; + TsdfIntegratorBase::Ptr tsdf_integrator_; /// ICP matcher std::shared_ptr icp_; diff --git a/voxblox_ros/launch/arche_dataset.launch b/voxblox_ros/launch/arche_dataset.launch new file mode 100644 index 000000000..8967b0f34 --- /dev/null +++ b/voxblox_ros/launch/arche_dataset.launch @@ -0,0 +1,62 @@ + + + + + + + + + + + + verbose: false + method: "projective" + sensor_horizontal_resolution: 1024 + sensor_vertical_resolution: 64 + sensor_vertical_field_of_view_degrees: 33.222 + color_mode: "normals" + world_frame: "mission" + tsdf_voxel_size: 0.20 + truncation_distance: 0.60 + pointcloud_queue_size: 1 + max_ray_length_m: 12.0 # 14 or 16m would be better, but for that we need better odometry. Otherwise the surface get too damaged. + min_ray_length_m: 1.0 + max_consecutive_ray_collisions: 1 + use_const_weight: true + + + + update_mesh_every_n_sec: 1.0 + integrator_threads: 1 + + + + + + + verbose: false + method: "fast" + color_mode: "normals" + world_frame: "mission" + tsdf_voxel_size: 0.15 + truncation_distance: 0.60 + pointcloud_queue_size: 1 + max_ray_length_m: 12.0 # 14 or 16m would be better, but for that we need better odometry. Otherwise the surface get too damaged. + min_ray_length_m: 1.0 + max_consecutive_ray_collisions: 1 + use_const_weight: true + + + + update_mesh_every_n_sec: 1.0 + + + + + + + + diff --git a/voxblox_ros/src/tsdf_server.cc b/voxblox_ros/src/tsdf_server.cc index 5d566e35d..ad3ea2dd8 100644 --- a/voxblox_ros/src/tsdf_server.cc +++ b/voxblox_ros/src/tsdf_server.cc @@ -2,6 +2,7 @@ #include #include +#include #include "voxblox_ros/conversions.h" #include "voxblox_ros/ros_params.h" @@ -91,19 +92,8 @@ TsdfServer::TsdfServer(const ros::NodeHandle& nh, std::string method("merged"); nh_private_.param("method", method, method); - if (method.compare("simple") == 0) { - tsdf_integrator_.reset(new SimpleTsdfIntegrator( - integrator_config, tsdf_map_->getTsdfLayerPtr())); - } else if (method.compare("merged") == 0) { - tsdf_integrator_.reset(new MergedTsdfIntegrator( - integrator_config, tsdf_map_->getTsdfLayerPtr())); - } else if (method.compare("fast") == 0) { - tsdf_integrator_.reset(new FastTsdfIntegrator( - integrator_config, tsdf_map_->getTsdfLayerPtr())); - } else { - tsdf_integrator_.reset(new SimpleTsdfIntegrator( - integrator_config, tsdf_map_->getTsdfLayerPtr())); - } + tsdf_integrator_ = TsdfIntegratorFactory::create( + method, integrator_config, tsdf_map_->getTsdfLayerPtr()); mesh_layer_.reset(new MeshLayer(tsdf_map_->block_size()));