Elevation Mapping Manual
Elevation Mapping Manual 작성
- Elevation Mapping을 진행하기 위한, 기본 세팅 진행
# docker images
docker pull osrf/ros:humble-desktop
# X서버에 도커 컨테이너 접근 허용
xhost +local:docker
# docker 실행
docker run -it --name ys_test --network host \
--gpus all \
-e DISPLAY=$DISPLAY \
-v /tmp/.X11-unix:/tmp/.X11-unix \
osrf/ros:humble-desktop
# docker 실행
docker exec -it ys_test /bin/bash
# 패키지 목록 업데이트
apt update
# 저장소 활성화
apt install software-properties-common
add-apt-repository universe
apt update
# gedit 설치
apt install gedit
# ifconfig 설치
apt update && apt install -y net-tools
# ros2 설정
source /opt/ros/humble/setup.bash
export ROS_DOMAIN_ID=42
Elevation Mapping 설치
# 워크스페이스 생성
mkdir -p workspace/src
apt-get install libeigen3-dev
source /opt/ros/humble/setup.bash
# gridmap 설치
cd workspace/src
mkdir -p gridmap_dep/src
cd gridmap_dep
apt update && apt install -y wget
apt update && apt install -y curl
cd src
git clone https://github.com/ANYbotics/grid_map.git --branch humble
cd ..
rosdep update
rosdep install -y --ignore-src --from-paths src
# kindr 설치
cd /workspace/src
git clone https://github.com/ANYbotics/kindr.git
cd kindr
mkdir build
cd build
cmake .. -DUSE_CMAKE=true
make install
# kinr_ros 설치
cd /workspace.src
git clone https://github.com/SivertHavso/kindr_ros.git --branch galactic
## colcon build -> error 발생할꺼임 / 밑에 ### kind_ros 패키지 빌드 관련 에러 해결 참고
# Point Cloud Library 다운
apt install libpcl-dev
# grid map 테스트
source /workspace/install/setup.bash
ros2 launch grid_map_demos simple_demo_launch.py
# elevation_mapping git
cd /workspace/src
git clone https://github.com/Muhammad540/elevation_mapping.git
cd /worksapce
source /workspace/install/setup.bash
# elevation mapping 실행
ros2 launch elevation_mapping elevationMapping_launch.py
# Traversablility Estimation 설치
cd /workspace/src
git clone https://github.com/Muhammad540/traversability_estimation.git
## colcon build error 발생할꺼임 / 밑에 ### traversability_estimation 패키지 빌드 관련 에러 해결 참고
cd /workspace
colcon build
# Traversablility Estimation 실행
source /workspace/install/setup.bash
ros2 launch traversability_estimation traversability_estimation.launch.py
kind_ros 패키지 빌드 관련 에러 해결
# kind_msgs의 CmakeLists.txt 수정
cmake_minimum_required(VERSION 3.5.1)
project(kindr_msgs)
find_package(ament_cmake_auto)
ament_auto_find_build_dependencies()
rosidl_generate_interfaces(${PROJECT_NAME}
"msg/VectorAtPosition.msg"
DEPENDENCIES std_msgs geometry_msgs
ADD_LINTER_TESTS
)
if(BUILD_TESTING)
find_package(ament_lint_auto REQUIRED)
ament_lint_auto_find_test_dependencies()
endif()
ament_auto_package()
kind_msgs의 package.xml 수정
<?xml version="1.0"?>
<?xml-model href="http://download.ros.org/schema/package_format3.xsd" schematypens="http://www.w3.org/2001/XMLSchema"?>
<package format="3">
<name>kindr_msgs</name>
<version>0.3.4</version>
<description>Kindr common msgs</description>
<maintainer email="rdiethelm@anybotics.com">Remo Diethelm</maintainer>
<maintainer email="pleemann@anybotics.com">Philipp Leemann</maintainer>
<license>BSD</license>
<url type="website">https://github.com/anybotics/kindr_ros</url>
<author email="pfankhauser@anybotics.com">Peter Fankhauser</author>
<buildtool_depend>ament_cmake_auto</buildtool_depend>
<build_depend>rosidl_default_generators</build_depend>
<build_depend>geometry_msgs</build_depend>
<build_depend>std_msgs</build_depend>
<exec_depend>rosidl_default_runtime</exec_depend>
<exec_depend>geometry_msgs</exec_depend>
<exec_depend>std_msgs</exec_depend>
<test_depend>ament_lint_auto</test_depend>
<member_of_group>rosidl_interface_packages</member_of_group>
<export>
<build_type>ament_cmake</build_type>
</export>
</package>
kind_ros의 CmakeLists.txt 수정
cmake_minimum_required(VERSION 3.5)
project(kindr_ros)
# Use C++14 standard
if(NOT CMAKE_CXX_STANDARD)
set(CMAKE_CXX_STANDARD 14)
endif()
if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
add_compile_options(-Wall -Wextra -Wpedantic)
endif()
find_package(ament_cmake REQUIRED)
find_package(tf2 REQUIRED)
find_package(geometry_msgs REQUIRED)
find_package(kindr REQUIRED)
# 추가: kindr의 include 경로를 지정합니다.
if(NOT kindr_INCLUDE_DIRS)
set(kindr_INCLUDE_DIRS "/usr/local/include/kindr")
endif()
include_directories(${kindr_INCLUDE_DIRS})
find_package(eigen3_cmake_module REQUIRED)
find_package(Eigen3 REQUIRED)
set(dependencies
eigen3_cmake_module
Eigen3
tf2
geometry_msgs
)
install(DIRECTORY include/${PROJECT_NAME}/
DESTINATION include/${PROJECT_NAME})
if(BUILD_TESTING)
find_package(ament_lint_auto REQUIRED)
ament_lint_auto_find_test_dependencies()
find_package(ament_cmake_gtest REQUIRED)
ament_add_gtest(${PROJECT_NAME}-test
test/test_main.cpp
test/RosGeometryMsgPhysicalQuantitiesTest.cpp
test/RosGeometryMsgRotationTest.cpp
test/RosGeometryMsgPoseTest.cpp
test/RosTfPoseTest.cpp
test/TfConventionTest.cpp
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}/test
)
if(TARGET ${PROJECT_NAME}-test)
target_include_directories(${PROJECT_NAME}-test PUBLIC
include
${EIGEN3_INCLUDE_DIRS}
${kindr_INCLUDE_DIRS} # 테스트 타겟에도 추가
)
ament_target_dependencies(${PROJECT_NAME}-test
${dependencies}
)
endif()
endif()
ament_export_include_directories(include)
ament_export_dependencies(
${dependencies}
)
ament_package()
kinr_ros의 package.xml 수정
<?xml version="1.0"?>
<?xml-model href="http://download.ros.org/schema/package_format3.xsd" schematypens="http://www.w3.org/2001/XMLSchema"?>
<package format="3">
<name>kindr_ros</name>
<version>0.3.4</version>
<description>The kindr_ros package</description>
<maintainer email="rdiethelm@anybotics.com">Remo Diethelm</maintainer>
<maintainer email="pleemann@anybotics.com">Philipp Leemann</maintainer>
<license>BSD</license>
<url type="website">https://github.com/anybotics/kindr_ros</url>
<author email="cgehring@anybotics.com">Christian Gehring</author>
<buildtool_depend>ament_cmake</buildtool_depend>
<buildtool_depend>eigen3_cmake_module</buildtool_depend>
<buildtool_export_depend>eigen3_cmake_module</buildtool_export_depend>
<depend>kindr</depend>
<depend>geometry_msgs</depend>
<depend>tf2</depend>
<build_depend>eigen</build_depend>
<test_depend>ament_cmake_gtest</test_depend>
<test_depend>ament_lint_auto</test_depend>
<build_export_depend>eigen</build_export_depend>
<export>
<build_type>ament_cmake</build_type>
</export>
</package>
traversability 패키지 빌드 관련 에러 해결
gedit /worksapce/src/traversability_estimation/traversability_estimation/src/TraversabilityEstimation.cpp
# 239번째 ~ 240번째 주석처리
// response->header.frame_id = traversabilityMap_.getMapFrameId();
// response->header.stamp = nodeHandle_->now();
Go2- Elevation mapping 연동 진행
realsense 설치
- depth camera의 pointcloud를 받기 위해 설치
- sudo apt install ros-humble-librealsense2*
- sudo apt install ros-humble-realsense2-*
ROS 2 humble에서, pointcloud msg /camera/camera/depth/color/points 안나옴
버전, gpu, jetpack 등 다양하게 survey & local pc에서는 잘 나옴
depth image를 pointcloud로 변환해서, 진행
# 노드 작성 ros2 run realsense_pointcloud_converter depth_to_pc_node
elevation mapping 연동 진행 (미완성 : depth point가 너무 sparse함)
보안사항
- realsense node 최적화
- pointcloud 범위 한정 / voxelization
- elevation mapping test
- jeston orin에서 테스트 진행
파라미터 정리
- Postprocessor Pipeline 파라미터
postprocessor_pipeline: filter1: name: inpaint type: gridMapCv/InpaintFilter params: input_layer: elevation output_layer: elevation_inpainted radius: 0.05 filter2: name: surface_normals type: gridMapFilters/NormalVectorsFilter params: input_layer: elevation_inpainted output_layers_prefix: normal_vectors_ radius: 0.1 normal_vector_positive_axis: z
filter1 (inpaint)
type: gridMapCv/InpaintFilter
역할: Elevation Map에 “구멍(hole)”이 생긴 셀이나 NaN 영역을 보간(Interpolating)하여 매꿉니다.
매개변수
input_layer: elevation → 원본 레이어
output_layer: elevation_inpainted → 결과 레이어
radius: 0.05 → 인페인트(보간) 알고리즘이 주변 픽셀을 탐색할 때 사용하는 거리(단위 m).
filter2 (surface_normals)
type: gridMapFilters/NormalVectorsFilter
역할: 지도(elevation_inpainted)에서 각 셀의 표면 법선 벡터를 계산합니다.
매개변수
input_layer: elevation_inpainted → 인페인트된 고도 레이어 사용
output_layers_prefix: normal_vectors_ → 결과는 normal_vectors_x, normal_vectors_y, normal_vectors_z 등의 새 레이어들로 저장
radius: 0.1 → 주변 높이 정보를 사용해 표면 기울기/법선을 추정할 때 사용할 이웃 범위
normal_vector_positive_axis: z → 법선 벡터가 가능한 한 +Z 방향을 기준으로 계산되도록 설정
2. Sensor Processor 파라미터
sensor_processor:
ros__parameters:
type: structured_light
cutoff_min_depth: 0.2
cutoff_max_depth: 3.25
normal_factor_a: 0.000611
normal_factor_b: 0.003587
normal_factor_c: 0.3515
normal_factor_d: 0
normal_factor_e: 1
lateral_factor: 0.01576
type: structured_light
RealSense D435 같은 “Structured Light” 센서 특성(깊이 오차 모델)을 사용하는 프로세서로 설정.
cutoff_min_depth, cutoff_max_depth
센서에서 유효 범위를 벗어나는 깊이(너무 가깝거나 먼 포인트)를 무시합니다.
여기서는 0.2m보다 가까운 점, 3.25m보다 먼 점을 제거.
normal_factor_a, b, c, d, e, lateral_factor
Structured Light 센서의 노이즈(깊이 오차, 측방향 오차 등)를 모델링할 때 사용하는 파라미터들입니다.
대체로 A·B·C·D·E는 깊이에 따른 오차 함수를 구성하고, lateral_factor는 가로 방향(픽셀 x축)으로 증가하는 오차를 의미합니다.
3. Elevation Mapping 노드 파라미터
elevation_mapping:
ros__parameters:
min_update_rate: 1.0
time_tolerance: 0.5
sensor_processor/ignore_points_above: 0.4
robot_motion_map_update/covariance_scale_translation_x: 0.0
...
robot_motion_map_update/covariance_scale_rotation_z: 0.0
length_in_x: 10.0
length_in_y: 10.0
position_x: 0.0
position_y: 0.0
resolution: 0.1
min_variance: 0.0001
max_variance: 0.05
mahalanobis_distance_threshold: 2.5
multi_height_noise: 0.01
fused_map_publishing_rate: 5.0
enable_skip_lower_points: true
scanning_duration: 0.01
remove_penetrated_points_rate: 5.0
visibility_cleanup_rate: 10.0
enable_continuous_cleanup: false
min_update_rate (1.0)
Elevation Mapping 노드가 최소 몇 Hz로 업데이트되길 기대하는지 나타냅니다.
센서 입력이 너무 늦으면 경고를 내거나, 내부적으로 timeout 처리를 할 수 있습니다.
time_tolerance (0.5)
TF 변환을 요청할 때 허용되는 타임스탬프 오차(초).
센서 메시지와 TF가 완벽히 같은 시간을 갖지 않을 수 있으므로, 이 오차 내에서 보정해줍니다.
sensor_processor/ignore_points_above (0.4)
포인트 클라우드에서 특정 기준 이상(높이 차가 0.4m 이상)인 점들을 무시할 수 있습니다.
보통 센서 기준으로 너무 높게 뜬 노이즈 제거 목적으로 사용됩니다(세부 해석은 설정에 따라 다를 수 있음).
robot_motion_map_update/covariance_scale_* (모두 0.0)
로봇이 움직일 때, 지도 셀의 분산(variance)을 추가로 증가시키는 스케일 계수.
여기서 전부 0.0으로 설정되어 있어, “로봇 이동에 따른 추가 불확실도”를 고려하지 않는 상태입니다.
length_in_x, length_in_y (10.0)
Elevation Map의 X·Y 방향 크기(미터). 여기서는 10m x 10m 지도.
맵의 이동 윈도우(로봇 주변을 유지) 형태나 고정 지도 형태로 운용될 때 사용.
position_x, position_y (0.0)
맵의 중심 좌표를 world에서 어디로 잡을지 설정.
일반적으로 초기값 0.0, 0.0으로 두고, 로봇이 움직이면서 갱신할 수도 있음.
resolution (0.1)
지도 해상도(셀 크기). 0.1m → 1칸 = 10cm.
크기가 10m이고 해상도가 0.1m이면, 대략 100 x 100 셀 정도가 됩니다.
min_variance, max_variance
지도 셀 높이 추정치의 분산(variance) 최소·최대값 제한.
너무 확신이 높아져 분산이 0으로 수렴하지 않도록 하거나(최소값), 너무 커지지 않도록 최대값을 둠.
mahalanobis_distance_threshold (2.5)
새로 들어온 측정(포인트)이 현재 셀의 높이 통계와 비교했을 때, 어느 정도 차이가 나면 outlier로 처리할지 결정하는 임계값.
분산을 고려한 Mahalanobis distance를 사용.
multi_height_noise (0.01)
하나의 셀이 여러 다른 높이 레벨을 동시에 관측할 때(예: 책상 위+바닥), 추가로 노이즈(분산)를 늘릴지 결정하는 계수.
fused_map_publishing_rate (5.0)
최종 맵(융합된 Elevation Map)을 몇 Hz로 퍼블리시할지 설정. 5면 5Hz.
enable_skip_lower_points (true)
이미 지도에 기록된 높이보다 훨씬 낮은(즉 지면 아래) 포인트가 들어올 경우, 노이즈로 보고 무시할 수 있는 옵션.
scanning_duration (0.01)
센서가 들어오는 한 번의 콜백 내에서 포인트들을 처리하는 데 할당할 최대 시간.
실시간성 보장을 위해 짧게 잡으면, 한 주기에 다 못 처리한 점이 있으면 다음 cycle로 넘길 수 있습니다.
remove_penetrated_points_rate (5.0)
맵 상 표면보다 아래(관통)된 것으로 보이는 점들을 제거하는 주기(Hz).
5.0이면 1초에 5번 관통점 제거 작업을 수행.
visibility_cleanup_rate (10.0)
센서에서 보이지 않는 부분(장기간 미관측)이나 사라진 물체 등을 맵에서 정리(클린업)하는 주기(Hz).
enable_continuous_cleanup: false이므로, 여기서 설정된 Hz마다 한 번씩만 실행.
enable_continuous_cleanup (false)
true로 설정 시, 맵 정리(클린업)를 수시로(연속적으로) 진행. 여기서는 주기적(cleanup_rate)으로만 수행.
4. 최상위 Elevation Mapping 설정 및 Inputs
/**:
ros__parameters:
inputs: ['ground_truth_cloud']
ground_truth_cloud:
type: pointcloud
topic: /nvblox_node/back_projected_depth/front_stereo_camera_left_optical
queue_size: 10
publish_on_update: true
sensor_processor:
type: laser
frame_id: front_stereo_camera_left_optical
map_frame_id: "map"
robot_base_frame_id: "base_link"
robot_pose_with_covariance_topic: "/chassis/odom"
track_point_frame_id: "base_link"
track_point_x: 0.0
track_point_y: 0.0
track_point_z: 0.0
inputs: ['ground_truth_cloud']
Elevation Mapping 노드가 입력으로 사용할 센서(포인트클라우드) “이름” 리스트입니다.
ground_truth_cloud 세부
type: pointcloud → 이 입력은 PointCloud를 의미.
topic: /nvblox_node/back_projected_depth/front_stereo_camera_left_optical → 실제로 구독할 ROS 토픽 이름.
queue_size: 10 → 내부 구독 버퍼 크기.
publish_on_update: true → 이 센서로 업데이트가 발생할 때마다 맵을 갱신할지 여부.
sensor_processor.type: laser → 이 포인트클라우드에 대해 Laser 센서 모델을 적용(간단하게 처리)할 수 있음.
frame_id: front_stereo_camera_left_optical → 이 입력 데이터를 “front_stereo_camera_left_optical” 프레임 기준으로 해석.
map_frame_id: "map"
Elevation Mapping이 최종 지도를 표현할 좌표계(최상위 프레임) = "map".
robot_base_frame_id: "base_link"
로봇의 기준 프레임. Elevation Mapping은 TF를 통해 “map -> base_link” 변환을 lookup.
robot_pose_with_covariance_topic: "/chassis/odom"
로봇의 위치/자세 추정을 포함한 PoseWithCovarianceStamped(혹은 Odometry)를 구독하는 토픽.
내부적으로 TF lookup 시 참조할 수도 있고, 또는 속도·가속도 추정에 활용.
track_point_frame_id: "base_link" + track_point_x/y/z
맵을 로봇 중심 기준으로 이동 윈도우 형태로 운영할 때, “어느 점”을 기준으로 맵을 업데이트할지 결정.
여기서는 “base_link” 프레임의 (0,0,0) 지점을 트래킹.