rosparam 이 안 먹는 것처럼 보일 때 체크할 것들

대상: 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 파일의 최상위 키, 들여쓰기, 경로도 꼼꼼히 확인해야 합니다.

댓글 남기기