Skip to content

Commit

Permalink
Improve surface cell selector and reorganize menu
Browse files Browse the repository at this point in the history
  • Loading branch information
victorreijgwart committed Oct 6, 2023
1 parent 76281ac commit 0915b7a
Show file tree
Hide file tree
Showing 6 changed files with 254 additions and 86 deletions.
6 changes: 4 additions & 2 deletions ros/wavemap_rviz_plugin/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@ set(CMAKE_AUTOMOC ON)
set(HEADERS_TO_MOC
include/wavemap_rviz_plugin/wavemap_map_display.h
include/wavemap_rviz_plugin/visuals/grid_visual.h
include/wavemap_rviz_plugin/visuals/slice_visual.h)
include/wavemap_rviz_plugin/visuals/slice_visual.h
include/wavemap_rviz_plugin/visuals/cell_selector.h)
if (rviz_QT_VERSION VERSION_LESS "5")
message(STATUS "Using Qt4 based on the rviz_QT_VERSION: ${rviz_QT_VERSION}")
find_package(Qt4 ${rviz_QT_VERSION} EXACT REQUIRED QtCore QtGui)
Expand Down Expand Up @@ -56,7 +57,8 @@ add_library(${PROJECT_NAME}
src/utils/listeners.cc
src/visuals/grid_visual.cc
src/visuals/slice_visual.cc
src/visuals/grid_layer.cpp
src/visuals/grid_layer.cc
src/visuals/cell_selector.cc
src/wavemap_map_display.cc
${QT_MOC})
target_link_libraries(${PROJECT_NAME} ${QT_LIBRARIES} ${catkin_LIBRARIES})
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
#ifndef WAVEMAP_RVIZ_PLUGIN_VISUALS_CELL_SELECTOR_H_
#define WAVEMAP_RVIZ_PLUGIN_VISUALS_CELL_SELECTOR_H_

#include <ros/console.h>
#include <rviz/properties/enum_property.h>
#include <rviz/properties/float_property.h>
#include <wavemap/config/type_selector.h>
#include <wavemap/data_structure/volumetric/hashed_wavelet_octree.h>

namespace wavemap::rviz_plugin {
struct CellSelectionMode : public TypeSelector<CellSelectionMode> {
using TypeSelector<CellSelectionMode>::TypeSelector;

enum Id : TypeId { kSurface, kBand };

static constexpr std::array names = {"Surface", "Band"};
};

class CellSelector : public QObject {
Q_OBJECT
public: // NOLINT
CellSelector(rviz::Property* submenu_root_property,
std::function<void()> redraw_map);

void initializePropertyMenu();

void setMap(const VolumetricDataStructureBase::ConstPtr& hashed_map);

bool shouldBeDrawn(const OctreeIndex& cell_index,
FloatingPoint cell_log_odds) const;
bool isUnknown(FloatingPoint log_odds) const {
return std::abs(log_odds) < unknown_occupancy_threshold_;
}
bool hasFreeNeighbor(const OctreeIndex& cell_index) const;

private Q_SLOTS: // NOLINT
// These Qt slots get connected to signals indicating changes in the
// user-editable properties
void cellSelectionModeUpdateCallback();
void thresholdUpdateCallback();

private:
std::function<void()> redraw_map_;
HashedWaveletOctree::ConstPtr hashed_map_;

// Selection mode and thresholds
CellSelectionMode cell_selection_mode_ = CellSelectionMode::kSurface;
FloatingPoint surface_occupancy_threshold_ = 1e-3f;
FloatingPoint band_min_occupancy_threshold_ = 1e-3f;
FloatingPoint band_max_occupancy_threshold_ = 1e6f;
FloatingPoint unknown_occupancy_threshold_ = 1e-4f;

// User-editable property variables, contained in the visual's submenu
rviz::EnumProperty cell_selection_mode_property_;
rviz::FloatProperty surface_occupancy_threshold_property_;
rviz::FloatProperty band_min_occupancy_threshold_property_;
rviz::FloatProperty band_max_occupancy_threshold_property_;
rviz::FloatProperty unknown_occupancy_threshold_property_;
};
} // namespace wavemap::rviz_plugin

#endif // WAVEMAP_RVIZ_PLUGIN_VISUALS_CELL_SELECTOR_H_
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,14 @@
#include <rviz/properties/property.h>
#include <rviz/view_manager.h>
#include <wavemap/config/type_selector.h>
#include <wavemap/data_structure/volumetric/hashed_wavelet_octree.h>
#include <wavemap/data_structure/volumetric/volumetric_data_structure_base.h>
#include <wavemap/indexing/index_hashes.h>
#include <wavemap/utils/time.h>

#include "wavemap_rviz_plugin/common.h"
#include "wavemap_rviz_plugin/utils/color_conversions.h"
#include "wavemap_rviz_plugin/utils/listeners.h"
#include "wavemap_rviz_plugin/visuals/cell_selector.h"
#include "wavemap_rviz_plugin/visuals/grid_layer.h"
#endif

Expand Down Expand Up @@ -64,9 +64,8 @@ class GridVisual : public QObject {
private Q_SLOTS: // NOLINT
// These Qt slots get connected to signals indicating changes in the
// user-editable properties
void thresholdUpdateCallback() { updateMap(true); }
void terminationHeightUpdateCallback() { force_lod_update_ = true; }
void visibilityUpdateCallback();
void terminationHeightUpdateCallback() { force_lod_update_ = true; }
void opacityUpdateCallback();
void colorModeUpdateCallback();
void flatColorUpdateCallback();
Expand All @@ -87,13 +86,16 @@ class GridVisual : public QObject {
Ogre::SceneNode* frame_node_;

// User-editable property variables, contained in the visual's submenu
// Grid visibility
rviz::BoolProperty visibility_property_;
rviz::FloatProperty min_occupancy_threshold_property_;
rviz::FloatProperty max_occupancy_threshold_property_;
// Cell selection
CellSelector cell_selector_;
rviz::IntProperty termination_height_property_;
// Colors
rviz::FloatProperty opacity_property_;
rviz::EnumProperty color_mode_property_;
rviz::ColorProperty flat_color_property_;
// Frame-rate stats
rviz::Property frame_rate_properties_;
rviz::IntProperty num_queued_blocks_indicator_;
rviz::IntProperty max_ms_per_frame_property_;
Expand All @@ -114,26 +116,12 @@ class GridVisual : public QObject {
FloatingPoint distance_to_cam, FloatingPoint min_cell_width,
NdtreeIndexElement min_height, NdtreeIndexElement max_height);

// Hidden cell pruning methods
const HashedWaveletOctree* hashed_map_;
static bool isOccupied(FloatingPoint min_occupancy_log_odds,
FloatingPoint max_occupancy_log_odds,
FloatingPoint cell_log_odds) {
return min_occupancy_log_odds < cell_log_odds &&
cell_log_odds < max_occupancy_log_odds;
}
bool hasFreeNeighbor(FloatingPoint min_occupancy_log_odds,
FloatingPoint max_occupancy_log_odds,
const OctreeIndex& cell_index);

// Drawing related methods
using GridLayerList = std::vector<std::vector<GridCell>>;
void getLeafCentersAndColors(int tree_height, FloatingPoint min_cell_width,
FloatingPoint min_occupancy_log_odds,
FloatingPoint max_occupancy_log_odds,
const OctreeIndex& cell_index,
FloatingPoint cell_log_odds,
GridLayerList& cells_per_level);
void appendLeafCenterAndColor(int tree_height, FloatingPoint min_cell_width,
const OctreeIndex& cell_index,
FloatingPoint cell_log_odds,
GridLayerList& cells_per_level);
void drawMultiResolutionGrid(IndexElement tree_height,
FloatingPoint min_cell_width,
const Index3D& block_index, FloatingPoint alpha,
Expand Down
154 changes: 154 additions & 0 deletions ros/wavemap_rviz_plugin/src/visuals/cell_selector.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
#include "wavemap_rviz_plugin/visuals/cell_selector.h"

#include <wavemap/iterator/grid_iterator.h>

namespace wavemap::rviz_plugin {
std::array<Index3D, 26> generateNeighborIndexOffsets() {
std::array<Index3D, 26> neighbor_offsets{};
size_t array_idx = 0u;
for (const Index3D& index : Grid<3>(-Index3D::Ones(), Index3D::Ones())) {
if (index != Index3D::Zero()) {
neighbor_offsets[array_idx] = index;
++array_idx;
}
}
std::sort(
neighbor_offsets.begin(), neighbor_offsets.end(),
[](const auto& lhs, const auto& rhs) { return lhs.norm() < rhs.norm(); });
return neighbor_offsets;
}
static const auto kNeighborOffsets = generateNeighborIndexOffsets();

CellSelector::CellSelector(rviz::Property* submenu_root_property,
std::function<void()> redraw_map)
: redraw_map_(std::move(redraw_map)),
cell_selection_mode_property_(
"Cell selector", "", "Mode determining what cells to draw.",
submenu_root_property, SLOT(cellSelectionModeUpdateCallback()), this),
surface_occupancy_threshold_property_(
"Log odds threshold", surface_occupancy_threshold_,
"Classification threshold above which a cell is considered occupied. "
"Ranges from -Inf to Inf.",
submenu_root_property, SLOT(thresholdUpdateCallback()), this),
band_min_occupancy_threshold_property_(
"Min log odds", band_min_occupancy_threshold_,
"Only show cells whose occupancy exceeds this threshold. "
"Ranges from -Inf to Inf.",
submenu_root_property, SLOT(thresholdUpdateCallback()), this),
band_max_occupancy_threshold_property_(
"Max log odds", band_max_occupancy_threshold_,
"Only show cells whose occupancy falls below this threshold. "
"Ranges from -Inf to Inf.",
submenu_root_property, SLOT(thresholdUpdateCallback()), this),
unknown_occupancy_threshold_property_(
"Unknown log odds", unknown_occupancy_threshold_,
"Hide cells whose absolute occupancy falls below this threshold, "
"considering them as unknown. Ranges from -Inf to Inf.",
submenu_root_property, SLOT(thresholdUpdateCallback()), this) {
// Initialize the property menu
initializePropertyMenu();
}

void CellSelector::initializePropertyMenu() {
cell_selection_mode_property_.clearOptions();
for (const auto& name : CellSelectionMode::names) {
cell_selection_mode_property_.addOption(name);
}
cell_selection_mode_property_.setStringStd(cell_selection_mode_.toStr());
surface_occupancy_threshold_property_.setHidden(cell_selection_mode_ !=
CellSelectionMode::kSurface);
band_min_occupancy_threshold_property_.setHidden(cell_selection_mode_ !=
CellSelectionMode::kBand);
band_max_occupancy_threshold_property_.setHidden(cell_selection_mode_ !=
CellSelectionMode::kBand);
}

void CellSelector::setMap(
const VolumetricDataStructureBase::ConstPtr& hashed_map) {
hashed_map_ =
std::dynamic_pointer_cast<const HashedWaveletOctree>(hashed_map);
if (!hashed_map_ && cell_selection_mode_ == CellSelectionMode::kSurface) {
ROS_WARN(
"Cell selection mode 'Surface' only supports HashedWaveletOctree maps. "
"Falling back to mode 'Band'.");
cell_selection_mode_ = CellSelectionMode::kBand;
initializePropertyMenu();
}
}

bool CellSelector::shouldBeDrawn(const OctreeIndex& cell_index,
FloatingPoint cell_log_odds) const {
switch (cell_selection_mode_.toTypeId()) {
case CellSelectionMode::kSurface:
// Skip free cells
if (cell_log_odds < surface_occupancy_threshold_ ||
isUnknown(cell_log_odds)) {
return false;
}
// Skip cells that are occluded by neighbors on all sides
if (!hasFreeNeighbor(cell_index)) {
return false;
}
break;
case CellSelectionMode::kBand:
// Skip cells that don't meet the occupancy threshold
if (cell_log_odds < band_min_occupancy_threshold_ ||
band_max_occupancy_threshold_ < cell_log_odds ||
isUnknown(cell_log_odds)) {
return false;
}
break;
}
return true;
}

bool CellSelector::hasFreeNeighbor(const OctreeIndex& cell_index) const {
for (const auto& offset : kNeighborOffsets) { // NOLINT
const OctreeIndex neighbor_index = {cell_index.height,
cell_index.position + offset};
const FloatingPoint neighbor_log_odds =
hashed_map_->getCellValue(neighbor_index);
// Check if the neighbor is free and observed
if (neighbor_log_odds < surface_occupancy_threshold_ &&
!isUnknown(neighbor_log_odds)) {
return true;
}
}
return false;
}

void CellSelector::cellSelectionModeUpdateCallback() {
// Update the cached cell selection mode value
const CellSelectionMode old_cell_selection_mode = cell_selection_mode_;
cell_selection_mode_ =
CellSelectionMode(cell_selection_mode_property_.getStdString());

// Show/hide properties that only affect certain modes
surface_occupancy_threshold_property_.setHidden(cell_selection_mode_ !=
CellSelectionMode::kSurface);
band_min_occupancy_threshold_property_.setHidden(cell_selection_mode_ !=
CellSelectionMode::kBand);
band_max_occupancy_threshold_property_.setHidden(cell_selection_mode_ !=
CellSelectionMode::kBand);

// Redraw the map if the color mode changed
if (cell_selection_mode_ != old_cell_selection_mode) {
std::invoke(redraw_map_);
}
}

void CellSelector::thresholdUpdateCallback() {
// Update the thresholds
surface_occupancy_threshold_ =
surface_occupancy_threshold_property_.getFloat();
band_min_occupancy_threshold_ =
band_min_occupancy_threshold_property_.getFloat();
band_max_occupancy_threshold_ =
band_max_occupancy_threshold_property_.getFloat();
unknown_occupancy_threshold_ =
unknown_occupancy_threshold_property_.getFloat();

// Redraw the map
std::invoke(redraw_map_);
}
} // namespace wavemap::rviz_plugin
Loading

0 comments on commit 0915b7a

Please sign in to comment.