TIKI-MINI로 시작하는 ROS2 실무
목차

4. 실기기 연동

4.4기본 구동과 상태 확인

이 장에서 로봇이 처음으로 움직입니다. 먼저 4.1장의 주행 전 점검표를 처음부터 확인하세요. 정지 명령을 입력해 둔 터미널 하나를 항상 열어 두는 것이 이 장의 전제입니다.

실행

터미널을 세 개 준비합니다. 모두 VM에서 열고 처음 둘은 ssh로 로봇에 접속합니다. 세 터미널의 ROS_DOMAIN_ID는 같아야 합니다(4.2장).

터미널위치용도
1로봇(ssh)launch 실행
2로봇(ssh) 또는 VM상태 확인 명령
3VM조종과 정지 명령

터미널 1에서 실행합니다. source ~/ros2_ws/install/setup.bash가 적용된 터미널이어야 합니다. ssh 접속이 끊기면 그 터미널에서 실행한 노드도 같이 종료됩니다. 이를 막으려면 로봇에서 tmux로 세션을 만들고 그 안에서 launch합니다.

tmux new -s ros
ros2 launch tiki_bringup tiki.launch.py

tmux 세션에서 빠져나올 때는 Ctrl+B를 누른 뒤 D를 누르고, 다시 들어갈 때는 tmux attach -t ros입니다.

LiDAR 없이 구동부만 시험하고 싶다면 인자를 줍니다. tiki.launch.py에 선언된 인자는 include_rplidar 하나이고 기본값은 True입니다.

ros2 launch tiki_bringup tiki.launch.py include_rplidar:=false
ros2 launch tiki_bringup tiki.launch.py --show-args

둘째 줄은 인자와 설명을 출력하고 실제로는 실행하지 않습니다.

시작 순서

tiki.launch.py는 세 부분을 시간차로 시작합니다. 2.9장에서 다룬 TimerAction입니다.

시각시작되는 것이유
0초tiki_description: robot_state_publisher(rsp:=True)URDF를 robot_description으로 공개
3초rplidar.launch.py: rplidar_node (include_rplidar가 참일 때)robot_state_publisher가 뜨는 동안 부하를 피함
7초tiki_control: ros2_control_node, spawner 두 개ros2 param get로 robot_description을 받으려면 robot_state_publisher가 먼저 떠 있어야 함

7초는 "robot_state_publisher가 그때쯤이면 떠 있을 것"이라는 시간 가정이지, 떴는지 확인하는 장치가 아닙니다. 보드가 느려서 7초 안에 떠 있지 않으면 컨트롤러 쪽이 실패합니다. 아래 문제 해결에서 다시 나옵니다.

각 단계에서 보이는 로그와 정상, 이상 신호를 한 단계씩 넘기며 확인하세요. 로그의 출처 라벨을 읽는 법은 컴포넌트 아래 설명에 있습니다.

0 s: launch 시작, robot_state_publisher

tiki_description.launch.py가 rsp:=True로 포함되어 robot_state_publisher가 바로 뜬다. 3초, 7초 타이머가 동시에 시작된다.

일반적[INFO] [launch]: All log files can be found below /home/<사용자>/.ros/log/...

일반적[robot_state_publisher-1]: process started with pid [...]

정상 신호

  • ros2 node list에 /robot_state_publisher
  • ros2 topic list에 /robot_description, /tf_static
ros2 node list && ros2 topic list

로그 앞 라벨은 출처입니다. 코드는 tiki 패키지 소스에서, 공식 소스는 ros2_control과 rplidar_ros 소스에서 문구를 확인했습니다. 일반적은 자주 보이는 형태일 뿐 문구를 확인하지 않았고, 줄 앞의 노드 번호(N)와 PID는 실행마다 다릅니다.

정상 상태 확인

launch가 도는 동안 터미널 2에서 확인합니다.

노드와 토픽

ros2 node list
ros2 topic list -t

launch 시작 후 약 10초(보드에 따라 다름) 지나면 아래가 보여야 합니다. 이 목록은 파일에서 도출한 것이며 실제 로봇의 출력과 일부 다릅니다. 예를 들어 spawner는 일을 마치고 종료하므로 노드 목록에 남지 않고, /rosout 같은 기본 토픽이 더 보입니다.

종류이름누가비고
노드/robot_state_publishertiki_description0초에 시작
노드/controller_managerros2_control_node7초에 시작, 50 Hz 루프
노드/diff_controllerspawner가 로드DiffDriveController
노드/joint_state_broadcasterspawner가 로드JointStateBroadcaster
노드/rplidar_noderplidar_ros3초에 시작
토픽/cmd_veldiff_controller가 구독geometry_msgs/msg/Twist(리매핑 결과)
토픽/odomdiff_controller가 발행nav_msgs/msg/Odometry, publish_rate 50.0
토픽/scanrplidar_node가 발행sensor_msgs/msg/LaserScan
토픽/joint_statesjoint_state_broadcaster바퀴 위치와 속도
토픽/tfdiff_controller, robot_state_publisherodom → base_footprint는 컨트롤러가 발행
토픽/tf_staticrobot_state_publisher고정 조인트
토픽/robot_descriptionrobot_state_publisherURDF 문자열

/cmd_vel은 tiki_control.launch.py의 리매핑으로 생깁니다. /diff_controller/cmd_vel_unstamped를 /cmd_vel로 바꾸므로 컨트롤러는 use_stamped_vel: false에 맞춰 타임스탬프 없는 Twist를 받습니다.

컨트롤러와 하드웨어

명령과 상태가 오가는 길로봇 안의 컴퓨터 (ros2_control)/cmd_velTwist(직진, 회전 속도)diff_controller속도를 바퀴 속도로엔코더로 위치 계산DiffDriveTiki하드웨어 플러그인AT 명령으로 대화모터 보드시리얼로 연결바퀴 모터, 엔코더바퀴 속도 명령바퀴 위치, 속도/odomOdometry, 50 Hz/joint_states바퀴 상태odom → base_footprint TF도diff_controller가 발행합니다실선: 명령점선: 돌아오는 상태
/cmd_vel이 모터까지 가는 길(실선)과 엔코더 값이 /odom으로 돌아오는 길(점선). 이 장에서 확인하는 노드와 토픽이 모두 이 안에 있습니다.
ros2 control list_controllers
ros2 control list_hardware_components
ros2 control list_hardware_interfaces

Humble의 ros2controlcli 소스에서 이 세 동사가 있고 출력 형식이 아래와 같은 것을 확인했습니다. 컨트롤러는 한 줄에 이름, 타입, 상태가 나옵니다.

joint_state_broadcaster joint_state_broadcaster/JointStateBroadcaster  active
diff_controller         diff_drive_controller/DiffDriveController      active

list_hardware_components는 하드웨어 컴포넌트마다 name, type, plugin name, state: id=3 label=active, 명령 인터페이스를 보여 줍니다. 여기에 plugin name: tiki_base/DiffDriveTiki와 이름 RealRobot(URDF의 ros2_control 이름)이 보여야 합니다. 상태 인터페이스까지 보려면 -v를 붙입니다.

list_hardware_interfaces에는 명령 인터페이스 left_wheel_joint/velocity, right_wheel_joint/velocity가 [available] [claimed]로, 상태 인터페이스로 두 바퀴의 position과 velocity가 나와야 합니다. [unavailable]이면 하드웨어 읽기나 쓰기가 실패했다는 뜻입니다. 소스에서 read()나 write()가 오류를 반환하면 그 컴포넌트의 인터페이스를 사용 가능 목록에서 빼도록 되어 있습니다.

주기 확인

ros2 topic hz /odom
ros2 topic hz /joint_states
ros2 topic hz /scan

/odom은 50 Hz 근처여야 합니다(publish_rate 50.0, update_rate 50). /scan은 LiDAR(RPLIDAR C1)의 스캔 주파수인 10 Hz 근처입니다(rplidar_ros의 scan_frequency 기본값도 10.0 Hz). 처음 측정한 값을 기록해 기준으로 삼으세요. 세 값이 모두 나오지 않으면 아래 문제 해결을 봅니다.

TF

ros2 run tf2_ros tf2_echo odom base_footprint
ros2 run tf2_tools view_frames

첫 명령은 odom에서 base_footprint까지의 변환을 계속 출력합니다. 로봇이 서 있으면 값이 거의 변하지 않습니다. 둘째 명령은 10초 가량 TF를 모아 frames_<날짜>.pdf 파일(Humble 소스에서 확인)로 트리를 저장합니다. 트리가 odom → base_footprint → base_link → 바퀴, lidar_mount → lidar_bottom → laser 모양인지 봅니다. odom 쪽 끝이 비어 있으면 diff_controller가 활성화되지 않은 것입니다.

TIKI-MINI의 TF 트리odombase_footprintbase_linkdiff_controller고정left_wheel/joint_states로 갱신right_wheel/joint_states로 갱신back_sidelidar_mountlidar_bottomlaseryaw π, x축이 뒤쪽실선: 고정 조인트 (/tf_static)점선: 바퀴 회전 (/tf)색 화살표: diff_controller (/tf)
정상 실행에서 보이는 TF 트리입니다. odom에서 base_footprint로 가는 변환은 diff_controller가, 나머지는 robot_state_publisher가 URDF를 바탕으로 발행합니다.

움직이기

키보드 조종

조종 프로그램은 VM에서 실행합니다. 로봇의 ssh 터미널에서 실행하면 지연 때문에 반응이 느려지므로 VM이 낫습니다. 패키지 이름과 실행 파일 이름은 teleop_twist_keyboard입니다(setup.py에서 확인).

ros2 run teleop_twist_keyboard teleop_twist_keyboard --ros-args -p speed:=0.05 -p turn:=0.3

speed와 turn은 이 프로그램이 읽기 전용 파라미터로 선언한 값이고 기본값은 0.5(m/s)와 1.0(rad/s)입니다. 시작할 때 -p로 넘기는 것이 검증된 설정 방법입니다. 위 예는 0.05 m/s, 0.3 rad/s로 시작합니다. 기본값 그대로 쓰면 0.5를 보내고 컨트롤러가 0.2 m/s로 잘라 내므로 키를 눌렀을 때 의도한 것보다 훨씬 빠르게 달립니다.

키동작
i전진
,후진
j / l제자리에서 왼쪽 / 오른쪽 회전
u / o전진하며 왼쪽 / 오른쪽
k 또는 그 밖의 아무 키정지
q / z속도와 회전을 함께 10% 올림 / 내림
w / x직진 속도만 10% 올림 / 내림
e / c회전 속도만 10% 올림 / 내림

이 프로그램의 소스를 읽으면 보이는 특징이 있습니다. 키를 눌렀을 때만 메시지를 한 번 발행합니다. 키를 누르고 있으면 키보드 반복으로 계속 발행되고, 손을 떼면 발행이 멈춥니다. 정지 메시지를 따로 보내지 않습니다. 그래서 손을 뗀 뒤 약 0.5초 뒤에 컨트롤러의 cmd_vel_timeout이 로봇을 멈춥니다. 확실히 멈추려면 k를 누릅니다. 종료는 Ctrl+C이고 이때는 영 속도를 한 번 보내고 끝납니다. 한 가지 더, 속도 키를 누르면 직전에 누른 이동 방향으로 새 속도를 바로 발행하므로 움직이는 중에 q를 누르면 빨라집니다.

직접 발행

조종 프로그램 대신 명령으로 정확한 값을 보냅니다. 터미널 3에서 낮은 속도로 직진합니다.

ros2 topic pub -r 10 /cmd_vel geometry_msgs/msg/Twist "{linear: {x: 0.05}}"

-r 10은 초당 10번 계속 발행하라는 뜻입니다. 로봇이 움직이는 것을 보고 Ctrl+C로 멈춥니다. 제자리 회전은 아래와 같습니다.

ros2 topic pub -r 10 /cmd_vel geometry_msgs/msg/Twist "{angular: {z: 0.3}}"

적지 않은 필드는 0입니다. 정지 명령은 4.1장의 영 Twist 명령입니다.

ros2 topic pub --once -w 1 /cmd_vel geometry_msgs/msg/Twist "{}"

--once로 한 번만 보낸 명령은 로봇을 최대 약 0.5초만 움직입니다. 이후에는 타임아웃이 영 속도로 바꿉니다. 이 성질을 이용해 짧게 "툭" 움직여 방향을 확인하는 데 씁니다. 예컨대 아래 명령은 낮은 속도의 짧은 직진입니다.

ros2 topic pub --once -w 1 /cmd_vel geometry_msgs/msg/Twist "{linear: {x: 0.05}}"

방향과 크기 확인

처음에는 바퀴를 띄운 상태에서 0.05 전진을 보내 두 바퀴가 같은 방향으로 도는지 봅니다. 바닥에 내린 뒤 아래를 확인합니다.

  • 전진 명령에서 로봇이 앞으로 가는가. 로봇의 앞쪽이 어느 쪽인지는 base_link의 x축이고, URDF에서 LiDAR(laser)는 yaw π로 달려 있어서 스캔 각도 0이 로봇의 뒤쪽을 향합니다.
  • j로 회전시켰을 때 위에서 봐서 반시계로 도는가(angular.z가 양수이면 왼쪽).
  • 한쪽 바퀴만 돌거나 반대로 도는가. 펌웨어는 AT+M의 오른쪽 값에 부호를 바꿔 적용합니다(두 모터가 서로 마주 보게 장착되어 있어서). 방향이 어긋나면 모터 전원 버튼과 배선을 확인하고, 필요하면 AT+ML과 AT+MR로 바퀴를 하나씩 시험합니다.

주행 중 /odom 확인

ros2 topic echo /odom --field twist.twist.linear.x
ros2 topic echo /odom --field pose.pose.position --once

첫 명령은 직진 속도를 계속 출력합니다. 0.05 m/s로 달리는 동안 0.05 근처 값이어야 합니다. 둘째 명령은 현재 위치를 한 번 출력합니다. 정확한지 보려면 pose.pose.position을 읽어 둔 뒤 줄자로 정해진 거리(예: 0.5 m)를 보내고 다시 읽어 차이를 비교합니다. 오차가 크면 wheel_radius, wheel_separation, 엔코더 틱 수(1170)가 실제와 맞는지 의심하세요. 이 값들은 각각 tiki_controllers.yaml과 diffdrive_tiki.cpp에 있고 이 장에서 바꾸지는 않습니다.

RViz2에서 보기

RViz2는 VM에서 실행합니다. VM의 ROS_DOMAIN_ID가 로봇과 같아야 합니다.

rviz2

tiki_description.rviz는 로봇의 tiki_description 패키지에 들어 있고, OVA의 VM에는 이 패키지가 없습니다. 이 설정을 쓰려면 로봇에서 파일을 VM으로 복사합니다. VM에서 이렇게 실행합니다.

scp <사용자>@<로봇 IP>:~/ros2_ws/install/tiki_description/share/tiki_description/rviz/tiki_description.rviz ~/
rviz2 -d ~/tiki_description.rviz

복사하지 않고 rviz2만 켠 뒤 디스플레이를 직접 추가해도 됩니다. 아래 순서대로 하면 같은 화면이 됩니다. 화면은 실제 로봇을 연결해 찍은 것입니다. 로봇의 bringup이 실행 중이고 VM이 로봇과 같은 네트워크, 같은 ROS_DOMAIN_ID인 상태에서 VM의 Tilix에 rviz2를 입력해 시작합니다.

처음 실행한 RViz2. Fixed Frame map과 Global Status 오류, Add 버튼에 번호 표시
  • ① Fixed Frame의 기본값은 map입니다.
  • ② Global Status가 빨간 Error이고 Frame [map] does not exist가 보입니다. 로봇이 map 프레임을 아직 발행하지 않았기 때문입니다(SLAM이 map을 발행합니다).
  • ③ Add로 디스플레이를 추가합니다. 먼저 TF를 추가합니다.
Fixed Frame을 odom으로 바꾸고 Global Status가 Ok가 된 화면
  • ① Fixed Frame을 odom으로 바꿉니다. odom은 로봇의 컨트롤러가 TF로 발행하는 프레임입니다.
  • ② Global Status가 초록 Ok로 바뀝니다.

다시 Add를 눌러 RobotModel을 추가합니다.

Add 창에서 RobotModel을 고르고 OK를 누르는 화면
  • ① 목록에서 RobotModel을 고릅니다.
  • ② OK를 누릅니다.
RobotModel의 Description Topic에 /robot_description을 입력하는 화면
  • ① RobotModel을 펼쳐 Description Topic 값 칸을 엽니다.
  • ② 목록에서 /robot_description을 고르거나 입력하고 Enter를 누릅니다. robot_state_publisher가 URDF를 이 토픽으로 발행합니다.
RobotModel이 표시된 RViz2 3D 화면. 로봇 모델과 RobotModel 항목에 번호 표시
  • ① 로봇 모양이 보이면 모델을 받은 것입니다. 축 표시(TF)가 함께 겹쳐 있습니다. 로봇의 바퀴를 살짝 움직이면 같은 바퀴가 RViz2에서도 움직입니다.
  • ② RobotModel 항목의 상태가 Ok입니다.

마지막으로 Add에서 LaserScan을 추가하고 Topic을 /scan으로 정합니다.

LaserScan Topic을 /scan으로 지정하자 라이다 점들이 3D 화면에 표시된 모습
  • ① LaserScan의 Topic을 /scan으로 입력합니다.
  • ② LiDAR가 읽은 점들이 로봇 주변에 색 점으로 나타납니다. 색은 반사 세기(intensity)입니다.

아래에서는 같은 내용을 설명으로 다시 정리합니다.

이 설정 파일은 부분적으로만 맞습니다. 그대로 쓰는 부분은 Fixed Frame base_footprint, RobotModel(/robot_description), TF 표시입니다. 파일에 적힌 링크 이름 중 front_left_wheel, rear_caster_*, left_motor 등은 이 로봇의 URDF에 없으니 무시하세요. 파일에는 LaserScan과 Odometry 표시가 없어서 직접 추가해야 합니다.

  1. 왼쪽 아래 Add → By topic에서 /scan의 LaserScan을 추가합니다.
  2. 움직임을 보려면 Fixed Frame을 odom으로 바꿉니다. base_footprint로 두면 로봇이 화면 중앙에 고정되고 주변이 움직입니다. odom은 diff_controller가 TF를 발행하는 동안만 나타납니다.
  3. 필요하면 Add에서 Odometry를 /odom으로 추가합니다.

RobotModel에 모델이 안 나타나면 robot_state_publisher가 robot_description을 transient_local로 발행한다는 점(Humble 소스에서 확인)을 떠올리세요. 그런데 위 설정 파일은 RobotModel의 Durability Policy를 Volatile로 두었습니다. Volatile 구독자는 구독하기 전에 발행된 메시지를 받지 못하므로 Durability Policy를 Transient Local로 바꿔 보세요.

스캔이 표시되지 않고 Message Filter dropping message ... frame 'laser' 같은 경고가 나온다면 base_footprint에서 laser로 가는 TF가 없거나 두 컴퓨터의 시계가 어긋났기 때문입니다(4.2장). VM에서 RViz2가 켜지자마자 종료되면 3D 가속 문제일 가능성이 큽니다. 일반적인 우회책은 LIBGL_ALWAYS_SOFTWARE=1 rviz2로 소프트웨어 렌더링을 쓰는 것입니다.

첫 실행 문제 해결

코드에서 직접 원인을 추적할 수 있는 순서대로 적습니다.

첫 실행 문제 해결 갈림길diff_controller active?ros2 control list_controllers하드웨어 컴포넌트가 있나?list_hardware_components/cmd_vel에 명령이 오나?topic info -v, topic echo아니오예7초 의존robot_description 빔인터페이스 확인[unavailable]이면시리얼 포트 절로없음있음구독자와 발행자타입이 Twist인지다른 발행이 섞였는지주기 정상?topic hz /joint_states아니오예시리얼 응답 대기하드웨어 루프 막힘전원, 배선 확인모터 전원 버튼아니오예
로봇이 움직이지 않을 때 확인 명령의 결과에 따라 어느 원인을 먼저 볼지 나눈 갈림길입니다. 각 칸의 확인 방법은 아래 절에 있습니다.

시리얼 포트가 열리지 않을 때

DiffDriveTiki::on_init는 포트를 열고, 실패하면 예외 메시지를 std::cout으로 출력한 뒤 OPEN! 또는 CLOSE!를 로그로 남깁니다. CLOSE!가 보이면 모터 컨트롤러와 통신이 불가능합니다.

포트는 launch가 시작될 때 한 번 엽니다. 원인을 고친 뒤에는 launch를 다시 시작합니다.

확인할 것은 ls -l /dev/ttyAMA1, groups(dialout), 다른 프로세스의 점유(sudo fuser -v /dev/ttyAMA1), 4.3장의 장치 활성화입니다. 포트는 열렸는데 AT+MODE=2 뒤에서 로그가 멈추면 모터 컨트롤러의 응답을 기다리는 중입니다. 모터 전원 버튼이 켜져 있는지와 배선을 확인합니다.

컨트롤러 매니저와 spawner 실패

spawner 로그에서 Failed loading controller, Failed to configure controller, Failed to activate controller가 나오면 ros2 control list_controllers로 상태를 봅니다. 이들 문구는 Humble의 spawner 소스에서 확인했습니다. 대표적인 단서는 이렇습니다.

  • 위 시리얼 문제로 하드웨어 인터페이스가 [unavailable]이면 diff_controller가 필요한 인터페이스를 얻지 못해 활성화에 실패할 수 있습니다.
  • ros2 control list_hardware_interfaces에서 left_wheel_joint/velocity가 없으면 URDF의 ros2_control 블록이 컨트롤러 매니저에 전달되지 않았습니다. 다음 항목을 봅니다.
  • tiki_control.launch.py는 joint_state_broadcaster spawner가 종료된 뒤(OnProcessExit) diff_controller spawner를 시작합니다. OnProcessExit는 성공 종료인지 실패 종료인지 가리지 않으므로, 첫 spawner가 실패해도 두 번째가 시작되어 오류 로그가 뒤섞입니다. 위에서부터 첫 오류를 찾으세요.

7초 의존과 TF 문제

tiki_control.launch.py는 ros2 param get --hide-type /robot_state_publisher robot_description 명령의 출력을 URDF로 씁니다. 그 시점에 robot_state_publisher가 아직 없으면 파라미터가 비거나 명령이 실패합니다. 비면 컨트롤러 매니저가 Subscribing to '~/robot_description' topic for robot description file. 로그를 남기고 아무도 발행하지 않는 토픽을 기다립니다. 이 경우 ros2 control list_hardware_components에 컴포넌트가 없고 TF의 odom 쪽도 비어 있습니다.

보드가 느려서 robot_state_publisher가 7초 안에 뜨지 못한 경우가 대표적입니다. launch를 다시 시작하면 보통 지나가지만 근본 해결은 7초를 늘리는 것입니다. 그리고 로그에는 [Deprecated] Passing the robot description parameter directly ... 경고가 정상 상태에서도 나옵니다. 이 방식이 Humble의 ros2_control에서 권장되지 않는다는 안내이고 동작을 막지 않습니다.

시작 직후 약 10초 동안은 RViz2와 Nav2에 TF 관련 경고가 나올 수 있습니다. 컨트롤러가 TF를 발행하기 전이기 때문이므로 list_controllers가 둘 다 active가 된 뒤에 확인하세요.

/scan이 없을 때

launch 로그에서 Error, cannot bind to the specified serial port /dev/ttyUSB0.가 나오면 rplidar_ros가 포트를 열지 못한 것입니다(rplidar_ros 소스의 문구). 4.3장의 ls -l /dev/ttyUSB0와 dialout, USB 이름 변경, 케이블을 확인합니다. 포트는 열리는데 /scan이 나오지 않거나 상태 확인에서 실패하면 보율이 맞지 않을 수 있습니다. rplidar.launch.py의 기본 보율은 460800이고 이 값은 RPLIDAR C1의 통신 속도(460800 bps)와 같으므로 바꾸지 않습니다. 로그의 RPLidar health status 줄이 OK인지 먼저 읽으세요. include_rplidar:=false로 실행했다면 /scan이 없는 것이 정상입니다.

로봇이 움직이지 않을 때

아래 순서로 좁힙니다.

  1. ros2 control list_controllers에서 diff_controller가 active인가.
  2. ros2 topic info /cmd_vel -v에서 구독자(diff_controller)가 있는가, 메시지 타입이 geometry_msgs/msg/Twist인가.
  3. ros2 topic echo /cmd_vel에 내 명령이 도착하는가. 다른 사람의 발행이나 영 속도를 계속 보내는 프로그램이 섞여 있지 않은가.
  4. 명령이 너무 작거나 짧지 않은가. --once로 보낸 명령은 약 0.5초 뒤에 영 속도가 됩니다. 속도 명령은 0.05 m/s 이상으로 시작합니다.
  5. ros2 topic hz /joint_states가 0이거나 매우 낮으면 하드웨어 루프가 막혀 있습니다. 시리얼 응답 대기(위)를 의심합니다.
  6. 명령은 정상인데 바퀴가 돌지 않으면 모터 전원 버튼, 배터리, 모터 컨트롤러 상태를 확인합니다. OLED에 저전압 충전 알림이 떠 있으면 펌웨어가 모터를 멈춘 것이고, 충전 중에는 주행이 되지 않습니다.

종료

종료 순서를 지킵니다. 정지 명령을 보내 바퀴가 멈춘 것을 눈으로 확인한 뒤 터미널 1에서 Ctrl+C로 launch를 끕니다. 4.1장에서 본 것처럼 플러그인이 종료 때 정지 명령을 보내지 않기 때문입니다.

한눈에 정리

  1. ros2 launch tiki_bringup tiki.launch.py는 0초에 robot_state_publisher, 3초에 rplidar_node, 7초에 ros2_control_node와 spawner를 시작한다. 인자는 include_rplidar(기본 True) 하나다.
  2. 정상은 노드 다섯 개, 토픽 /cmd_vel /odom /scan /joint_states /tf /tf_static /robot_description, 두 컨트롤러 active다.
  3. ros2 control list_controllers, list_hardware_components, list_hardware_interfaces로 컨트롤러와 하드웨어를 확인한다. 인터페이스가 [unavailable]이면 하드웨어 읽기·쓰기가 실패한 것이다.
  4. 키보드 조종은 --ros-args -p speed:=0.05 -p turn:=0.3으로 낮게 시작한다. 컨트롤러가 0.2 m/s, 0.85 rad/s로 자른다. 정지는 k나 영 Twist다.
  5. /odom은 50 Hz 근처이고, RViz2는 Fixed Frame을 odom으로 두면 움직임이 보인다. tiki_description.rviz는 LaserScan이 없고 이 로봇에 없는 링크 이름이 들어 있다.
  6. 첫 실행 문제는 시리얼 CLOSE!, spawner 실패, 7초 의존(robot_description이 빔), /scan 포트·보율, 명령 타임아웃 순으로 점검한다.

확인 문제

Q2. teleop_twist_keyboard를 기본값으로 실행하고 i를 눌렀습니다. 로봇은 몇 m/s로 달립니까? 왜 낮은 값으로 시작하라고 합니까?

기본 speed 0.5를 보내지만 컨트롤러가 linear.x 최대 0.2 m/s로 잘라 내므로 0.2 m/s로 달립니다. 작은 로봇에서 0.2 m/s도 빠르고 q로 속도를 올려도 변화가 없어 직관과 어긋나므로, -p speed:=0.05 같은 값으로 시작해 반응을 확인합니다.

Q3. ros2 topic pub --once -w 1 /cmd_vel geometry_msgs/msg/Twist 로 전진 명령을 한 번 보냈더니 로봇이 잠깐 가다가 섰습니다. 이유는?

diff_drive_controller의 cmd_vel_timeout(기본 0.5초)이 마지막 명령이 0.5초보다 오래되면 속도를 0으로 바꾸기 때문입니다. 계속 가게 하려면 -r 10처럼 반복 발행해야 합니다.

다음 장

4.5장에서는 2부의 시뮬레이션용 코드와 설정을 실기기로 옮길 때 무엇을 바꿔야 하는지 정리합니다. 그 전에 오늘 측정한 /scan 주기, /odom 주기, 0.5 m 직진 시험의 오차를 메모해 두세요. 나중에 시뮬레이션과 비교할 기준값이 됩니다.