대상: ROS(특히 ROS1 Melodic/Noetic) 환경에서 파라미터가 적용되지 않거나 기본값으로만 동작하는 이유를 정확히 파악하고 싶은 개발자
환경: Ubuntu 20.04 / ROS Noetic / catkin_make
1. 문제/주제 요약
rosparam이나 YAML 파일로 파라미터를 설정했는데,
노드 실행 후 rosparam get으로 보면 값이 잘 들어가 있음에도
정작 코드에서는 반영되지 않는 경우가 있습니다.
대표적인 현상 👇
- “launch에서 param 넣었는데 코드에서 기본값으로 나옴”
- “rosparam load 했는데 노드가 읽질 않음”
- “YAML 올렸는데
/namespace/param이 아니라/param으로 들어감”
이 문제는 파라미터 네임스페이스(namespace) 와 로딩 순서,
NodeHandle의 스코프 차이 때문에 자주 발생합니다.
2. 원인 요약
| 원인 | 설명 |
|---|---|
| 🔹 네임스페이스 불일치 | launch 파일, NodeHandle, YAML에서 네임스페이스가 다름 |
| 🔹 파라미터 로드 순서 | rosparam load → node 실행 순서 반대 |
🔹 파라미터 스코프(~param) 혼동 | private / global param 구분 안 됨 |
| 🔹 rosparam 파일 위치 오류 | 파일 경로 또는 YAML 들여쓰기 문제 |
| 🔹 런타임 중 rosparam set | 노드가 이미 파라미터 읽은 뒤 수정 |
3. 체크리스트
✅ 1) 노드가 사용하는 네임스페이스 확인
C++ 예시:
ros::NodeHandle nh("~");
int rate;
nh.param("scan_rate", rate, 10);
이 코드는 ~ (private namespace) 기준이므로
실제 파라미터 키는 /node_name/scan_rate 로 접근해야 합니다.
즉, launch 파일에서 다음처럼 선언해야 합니다:
<node pkg="rplidar_ros" type="rplidarNode" name="lidar">
<param name="scan_rate" value="15"/> <!-- OK -->
</node>
만약 global param (/scan_rate)으로 넣으면 읽히지 않습니다.
확인 방법:
rosparam get /lidar/scan_rate
✅ 2) NodeHandle이 전역(ros::NodeHandle nh;)인지 확인
C++ 예시:
ros::NodeHandle nh; // 전역
ros::NodeHandle pnh("~"); // private
| 선언 방식 | 파라미터 경로 | launch 예시 |
|---|---|---|
ros::NodeHandle nh | /param_name | <param name="/param_name"/> |
ros::NodeHandle nh("~") | /node_name/param_name | <param name="param_name"/> |
💡 혼동 포인트:
~가 붙은 NodeHandle은 노드 이름 아래- 안 붙은 NodeHandle은 전역(/)
✅ 3) rosparam load 순서 확인
YAML 파일을 노드보다 먼저 로드해야 합니다.
<launch>
<!-- (1) 파라미터 먼저 로드 -->
<rosparam file="$(find my_robot_pkg)/config/lidar.yaml" command="load"/>
<!-- (2) 노드 실행 -->
<node pkg="rplidar_ros" type="rplidarNode" name="lidar" output="screen"/>
</launch>
파라미터를 노드보다 뒤에서 로드하면
이미 노드가 초기화 시 기본값으로 설정한 뒤라 적용되지 않습니다.
✅ 4) YAML의 들여쓰기 및 네임스페이스 구조 확인
YAML 예시:
lidar:
frame_id: "laser"
scan_rate: 10
launch에서 이렇게 로드하면:
<rosparam file="$(find my_robot_pkg)/config/lidar.yaml" command="load"/>
→ 실제 등록 결과:
/lidar/frame_id
/lidar/scan_rate
그런데 코드에서 ros::NodeHandle nh("~"); nh.param("scan_rate", rate, 10);
처럼 private param을 읽으면 /lidar_node/scan_rate 를 찾기 때문에 불일치.
✅ 해결:
rosparam로드 시ns지정<rosparam ns="lidar" file="$(find my_robot_pkg)/config/lidar.yaml" command="load"/>- 또는 YAML에서 최상위 키 제거
frame_id: "laser" scan_rate: 10
✅ 5) 실행 중 rosparam set은 즉시 반영되지 않음
C++ 코드에서 다음처럼 읽으면:
nh.param("scan_rate", rate, 10);
이 코드는 초기화 시 한 번만 읽음.
즉, 런타임 중 rosparam set /scan_rate 20 해도 자동으로 바뀌지 않습니다.
🔧 해결 방법:
- 주기적으로
getParam()호출 - 또는
dynamic_reconfigure사용
✅ 6) rosparam get으로 실제 등록 여부 확인
rosparam list | grep scan_rate
→ 아무것도 안 나오면 아직 등록되지 않은 것.
이때 YAML 경로 오류나 launch 파일에서 ns 잘못 지정 가능성이 높습니다.
✅ 7) rosparam load 실패 시 로그 확인
launch 실행 시 콘솔에 다음이 보이면:
[ WARN] cannot load YAML file: No such file or directory
→ 파일 경로나 들여쓰기 문제입니다.
확인:
rosparam load $(rospack find my_robot_pkg)/config/lidar.yaml
✅ 8) private param은 rosparam list에서 “node명” 포함
예시:
/lidar_node/scan_rate
/lidar_node/frame_id
이런 식이면 NodeHandle이 private임을 의미합니다.rosparam get /scan_rate로 조회하면 안 나오고rosparam get /lidar_node/scan_rate 로 봐야 합니다.
4. 빠른 점검 요약표
| 증상 | 원인 | 해결 |
|---|---|---|
| 코드에서 기본값만 읽힘 | 네임스페이스 불일치 | NodeHandle ~ 여부 확인 |
| rosparam load 했는데 반영 안 됨 | 로드 순서 문제 | YAML → node 순서로 변경 |
| rosparam set 했는데 반영 안 됨 | 초기화 시점만 읽음 | getParam() 반복 or dynamic_reconfigure |
| YAML 불러오는데 에러 | 경로 or 들여쓰기 | 절대경로 확인 + space 2칸 사용 |
| rosparam list에는 있는데 코드에서 못 읽음 | ns mismatch | / vs ~ 차이 확인 |
5. 실전 예시
<launch>
<!-- (1) YAML을 노드 네임스페이스에 맞게 로드 -->
<rosparam ns="lidar_node" file="$(find my_robot_pkg)/config/lidar.yaml" command="load"/>
<!-- (2) 노드 실행 -->
<node pkg="rplidar_ros" type="rplidarNode" name="lidar_node" output="screen"/>
</launch>
lidar.yaml
scan_rate: 10
frame_id: "laser"
이 구성이면 ✅ 완벽하게 일치합니다.
6. 정리
- 파라미터가 안 먹는 가장 흔한 이유는 네임스페이스(
~) 차이 - 항상 다음 세 가지를 순서대로 점검하세요: 1️⃣ NodeHandle이 global인지 private인지 확인
2️⃣ launch 파일의 param/rosparam 네임스페이스 확인
3️⃣ rosparam load → node 실행 순서 확인 - 추가로 YAML 파일의 최상위 키, 들여쓰기, 경로도 꼼꼼히 확인해야 합니다.