NavMap
Loading...
Searching...
No Matches
test_conversions.cpp File Reference
#include <cmath>
#include <functional>
#include <limits>
#include <gtest/gtest.h>
#include <nav_msgs/msg/occupancy_grid.hpp>
#include <pcl/point_cloud.h>
#include <pcl/point_types.h>
#include "navmap_ros_interfaces/msg/nav_map_layer.hpp"
#include "std_msgs/msg/header.hpp"
#include "navmap_ros/conversions.hpp"
#include "navmap_core/NavMap.hpp"
Include dependency graph for test_conversions.cpp:

Functions

navmap::NavMap from_occupancy_grid (const nav_msgs::msg::OccupancyGrid &grid, std_msgs::msg::Header &header)
 Build a navmap::NavMap from a nav_msgs::msg::OccupancyGrid using a regular triangular surface with shared vertices.
navmap::NavMap from_regular_grid (const pcl::PointCloud< pcl::PointXYZ > &grid_points, navmap_ros_interfaces::msg::NavMap &out_msg, BuildParams params)
 Build a NavMap surface from an organized (grid-shaped) PCL point cloud.
 TEST (FromRegularGrid, FlatGridProducesFullCoverageNoOverlap)
 TEST (FromRegularGrid, GentleSlopeUnderLimitStaysFullyCovered)
 TEST (FromRegularGrid, MatchesFromOccupancyGridWindingPattern)
 TEST (FromRegularGrid, NonFiniteVertexOnlySkipsItsOwnTriangles)
 TEST (FromRegularGrid, TooSmallGridReturnsEmpty)
 TEST (FromRegularGrid, TooSteepCellsAreSkippedNotTheWholeGrid)
 TEST (FromRegularGrid, UnorganizedCloudReturnsEmpty)
 TEST (NavMap_FullConversions, EmptyMap_RoundTrip)
 TEST (NavMap_FullConversions, RoundTrip_All)
 TEST (NavMap_LayerConversions, F32_RoundTrip)
 TEST (NavMap_LayerConversions, F64_RoundTrip)
 TEST (NavMap_LayerConversions, ToMsg_Throws_OnMissingLayer)
 TEST (NavMap_LayerConversions, U8_RoundTrip)
 TEST (TestConversions, RoundTrip_ExactEquality_4m_0p1)
 TEST (TestConversions, TriangleIndicesFollowPattern0)
nav_msgs::msg::OccupancyGrid to_occupancy_grid (const navmap::NavMap &nm, const std_msgs::msg::Header &header)
 Convert a navmap::NavMap back to nav_msgs::msg::OccupancyGrid.

Function Documentation

◆ from_occupancy_grid()

navmap::NavMap from_occupancy_grid ( const nav_msgs::msg::OccupancyGrid & grid,
std_msgs::msg::Header & header )

Build a navmap::NavMap from a nav_msgs::msg::OccupancyGrid using a regular triangular surface with shared vertices.

Parameters
[in]gridInput ROS OccupancyGrid (row-major, width×height, resolution and origin).
[out]headerHeader to assign to the resulting message.
Returns
A core navmap::NavMap with:
  • Vertices: (W+1) * (H+1) laid on the grid plane, with Z = grid.info.origin.position.z.
  • Triangles: 2 * W * H (two per cell), using diagonal pattern = 0.
  • One surface whose frame matches grid.header.frame_id, and grid metadata filled.
  • A per-NavCel layer named "occupancy" of type uint8, with values mapped as: -1 → 255 (unknown), 0..100 → 0..254 (linear scaling).
  • Vertex layout follows the grid indexation with shared vertices across adjacent cells.
  • Triangle winding and diagonal split are deterministic (pattern = 0).
  • If width == 0 or height == 0, the returned map contains no triangles.
Note
The grid origin pose may contain a rotation. The vertex Z is taken from the origin Z; handling of non-zero yaw/roll/pitch (if any) is implementation-defined in the builder.

◆ from_regular_grid()

navmap::NavMap from_regular_grid ( const pcl::PointCloud< pcl::PointXYZ > & grid_points,
navmap_ros_interfaces::msg::NavMap & out_msg,
BuildParams params )

Build a NavMap surface from an organized (grid-shaped) PCL point cloud.

Unlike navmap_ros::from_points – which discovers connectivity by neighbor search over an otherwise-unstructured point set, a heuristic that needs either a generous params.neighbor_radius (at real cost in redundant, overlapping triangles) or leaves gaps on an evenly-sampled surface even when every cell is individually navigable – this overload takes a cloud whose grid connectivity is already known (row-major, cloud.width x cloud.height, exactly as PCL's own "organized point cloud" convention) and builds the two triangles per grid cell directly from the (i, j) indices, the same deterministic scheme navmap_ros::from_occupancy_grid already uses. No neighbor search, no possibility of a meshing-artifact gap: the only triangles skipped are ones that fail the slope filter (params.max_slope_deg) or reference a non-finite vertex, i.e. every remaining hole is a real "not navigable here" gap, not a search-radius artifact.

Parameters
[in]grid_pointsOrganized point set (cloud.height must be > 1); row j, column i is at index j * cloud.width + i.
[out]out_msgOutput transport message mirroring the created NavMap.
[in]paramsOnly params.max_slope_deg and params.max_surfaces apply here; the neighbor-search/edge-length/angle fields are meaningless without a search step and are ignored.
Returns
The constructed navmap::NavMap; empty if grid_points is not organized (height <= 1) or is smaller than 2x2.

◆ TEST() [1/15]

TEST ( FromRegularGrid ,
FlatGridProducesFullCoverageNoOverlap  )

◆ TEST() [2/15]

TEST ( FromRegularGrid ,
GentleSlopeUnderLimitStaysFullyCovered  )

◆ TEST() [3/15]

TEST ( FromRegularGrid ,
MatchesFromOccupancyGridWindingPattern  )

◆ TEST() [4/15]

TEST ( FromRegularGrid ,
NonFiniteVertexOnlySkipsItsOwnTriangles  )

◆ TEST() [5/15]

TEST ( FromRegularGrid ,
TooSmallGridReturnsEmpty  )

◆ TEST() [6/15]

TEST ( FromRegularGrid ,
TooSteepCellsAreSkippedNotTheWholeGrid  )

◆ TEST() [7/15]

TEST ( FromRegularGrid ,
UnorganizedCloudReturnsEmpty  )

◆ TEST() [8/15]

TEST ( NavMap_FullConversions ,
EmptyMap_RoundTrip  )

◆ TEST() [9/15]

TEST ( NavMap_FullConversions ,
RoundTrip_All  )

◆ TEST() [10/15]

TEST ( NavMap_LayerConversions ,
F32_RoundTrip  )

◆ TEST() [11/15]

TEST ( NavMap_LayerConversions ,
F64_RoundTrip  )

◆ TEST() [12/15]

TEST ( NavMap_LayerConversions ,
ToMsg_Throws_OnMissingLayer  )

◆ TEST() [13/15]

TEST ( NavMap_LayerConversions ,
U8_RoundTrip  )

◆ TEST() [14/15]

TEST ( TestConversions ,
RoundTrip_ExactEquality_4m_0p1  )

◆ TEST() [15/15]

TEST ( TestConversions ,
TriangleIndicesFollowPattern0  )

◆ to_occupancy_grid()

nav_msgs::msg::OccupancyGrid to_occupancy_grid ( const navmap::NavMap & nm,
const std_msgs::msg::Header & header )

Convert a navmap::NavMap back to nav_msgs::msg::OccupancyGrid.

Parameters
[in]nmCore NavMap to be rasterized as an occupancy grid.
Returns
A ROS OccupancyGrid populated from nm.

Two paths are considered:

  • Fast exact path: If the first surface encodes valid grid metadata (GridMeta) and there is a per-NavCel "occupancy" layer of type U8 with size 2 * W * H, the function reconstructs an OccupancyGrid exactly (linear inverse mapping 0..254 → 0..100, 255 → -1).
  • Generic fallback: If the exact path is not applicable, the function samples cell centers via a navcel-locator (e.g., locate_navcel) and reads "occupancy" values to populate the grid.
Note
The fallback path assumes the presence of an "occupancy" layer. The precise sampling strategy (bounds, resolution, and handling of cells without a containing navcel) is implementation-defined.
Warning
If the map does not carry grid metadata or the "occupancy" layer is missing, the result may be incomplete or implementation-defined.