<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>MakingRobot</title>
    <link>https://makingrobot.tistory.com/</link>
    <description>1인 1로봇을 꿈꾸며 지금까지 로봇 개발에 참여하고 있는 개발자 입니다. 교육과 현업에서 습득한 다양한 경험을 함께 공유하기 위해 이 블로그를 만들었습니다. 처음 계획했던 것만큼 성실하게 블로그를 관리할 수 없어 안타깝지만 앞으로도 가능한 제가 경험하거나 유용한 지식을 함께 공유하도록 노력하겠습니다.</description>
    <language>ko</language>
    <pubDate>Sat, 4 Jul 2026 03:22:41 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>MakingRobotWizard</managingEditor>
    <image>
      <title>MakingRobot</title>
      <url>https://tistory1.daumcdn.net/tistory/2923319/attach/74298de5362040d1a888daa4d931f97f</url>
      <link>https://makingrobot.tistory.com</link>
    </image>
    <item>
      <title>Odometry 프로그래밍</title>
      <link>https://makingrobot.tistory.com/443</link>
      <description>&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot; data-start=&quot;1333&quot; data-end=&quot;1357&quot;&gt;1. ROS 2 모바일 로봇 전체 흐름&lt;/h4&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;1359&quot; data-end=&quot;1394&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;1359&quot; data-end=&quot;1394&quot;&gt;차동구동 로봇에서 ROS 2 제어 흐름은 보통 다음과 같습니다.&lt;/p&gt;
&lt;div style=&quot;color: #333333; text-align: start;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;groovy&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot;&gt;&lt;code&gt;사용자 / Teleop / Nav2
        &amp;darr;
/cmd_vel
geometry_msgs/msg/Twist
        &amp;darr;
차동구동 역기구학
        &amp;darr;
왼쪽 바퀴 속도, 오른쪽 바퀴 속도
        &amp;darr;
모터 드라이버 / MCU / OpenCR / ros2_control
        &amp;darr;
바퀴 회전
        &amp;darr;
엔코더 피드백
        &amp;darr;
거리 변환
        &amp;darr;
Odometry 계산
        &amp;darr;
/odom
nav_msgs/msg/Odometry
        &amp;darr;
odom &amp;rarr; base_link TF
        &amp;darr;
RViz2 / Nav2 / SLAM / Localization&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;1755&quot; data-end=&quot;1788&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;1755&quot; data-end=&quot;1788&quot;&gt;먼저 아래와 같은 ROS 2 토픽을 이해해야 합니다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;1755&quot; data-end=&quot;1788&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div style=&quot;color: #333333; text-align: start;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;토픽&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;메시지 타입&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 의미
&lt;table style=&quot;border-collapse: collapse; width: 75.814%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-start=&quot;1790&quot; data-end=&quot;2203&quot;&gt;
&lt;tbody data-start=&quot;1825&quot; data-end=&quot;2203&quot;&gt;
&lt;tr data-start=&quot;1825&quot; data-end=&quot;1878&quot;&gt;
&lt;td style=&quot;width: 20%;&quot; data-start=&quot;1825&quot; data-end=&quot;1838&quot; data-col-size=&quot;sm&quot;&gt;/cmd_vel&lt;/td&gt;
&lt;td style=&quot;width: 29.4186%;&quot; data-start=&quot;1838&quot; data-end=&quot;1866&quot; data-col-size=&quot;sm&quot;&gt;geometry_msgs/msg/Twist&lt;/td&gt;
&lt;td style=&quot;width: 26.2791%;&quot; data-start=&quot;1866&quot; data-end=&quot;1878&quot; data-col-size=&quot;sm&quot;&gt;로봇 속도 명령&lt;/td&gt;
&lt;/tr&gt;
&lt;tr data-start=&quot;1879&quot; data-end=&quot;1933&quot;&gt;
&lt;td style=&quot;width: 20%;&quot; data-start=&quot;1879&quot; data-end=&quot;1889&quot; data-col-size=&quot;sm&quot;&gt;/odom&lt;/td&gt;
&lt;td style=&quot;width: 29.4186%;&quot; data-start=&quot;1889&quot; data-end=&quot;1915&quot; data-col-size=&quot;sm&quot;&gt;nav_msgs/msg/Odometry&lt;/td&gt;
&lt;td style=&quot;width: 26.2791%;&quot; data-start=&quot;1915&quot; data-end=&quot;1933&quot; data-col-size=&quot;sm&quot;&gt;로봇 위치/자세/속도 추정&lt;/td&gt;
&lt;/tr&gt;
&lt;tr data-start=&quot;1934&quot; data-end=&quot;1981&quot;&gt;
&lt;td style=&quot;width: 20%;&quot; data-start=&quot;1934&quot; data-end=&quot;1942&quot; data-col-size=&quot;sm&quot;&gt;/tf&lt;/td&gt;
&lt;td style=&quot;width: 29.4186%;&quot; data-start=&quot;1942&quot; data-end=&quot;1969&quot; data-col-size=&quot;sm&quot;&gt;tf2_msgs/msg/TFMessage&lt;/td&gt;
&lt;td style=&quot;width: 26.2791%;&quot; data-start=&quot;1969&quot; data-end=&quot;1981&quot; data-col-size=&quot;sm&quot;&gt;동적 좌표 변환&lt;/td&gt;
&lt;/tr&gt;
&lt;tr data-start=&quot;1982&quot; data-end=&quot;2036&quot;&gt;
&lt;td style=&quot;width: 20%;&quot; data-start=&quot;1982&quot; data-end=&quot;1997&quot; data-col-size=&quot;sm&quot;&gt;/tf_static&lt;/td&gt;
&lt;td style=&quot;width: 29.4186%;&quot; data-start=&quot;1997&quot; data-end=&quot;2024&quot; data-col-size=&quot;sm&quot;&gt;tf2_msgs/msg/TFMessage&lt;/td&gt;
&lt;td style=&quot;width: 26.2791%;&quot; data-start=&quot;2024&quot; data-end=&quot;2036&quot; data-col-size=&quot;sm&quot;&gt;고정 좌표 변환&lt;/td&gt;
&lt;/tr&gt;
&lt;tr data-start=&quot;2037&quot; data-end=&quot;2099&quot;&gt;
&lt;td style=&quot;width: 20%;&quot; data-start=&quot;2037&quot; data-end=&quot;2055&quot; data-col-size=&quot;sm&quot;&gt;/joint_states&lt;/td&gt;
&lt;td style=&quot;width: 29.4186%;&quot; data-start=&quot;2055&quot; data-end=&quot;2086&quot; data-col-size=&quot;sm&quot;&gt;sensor_msgs/msg/JointState&lt;/td&gt;
&lt;td style=&quot;width: 26.2791%;&quot; data-start=&quot;2086&quot; data-end=&quot;2099&quot; data-col-size=&quot;sm&quot;&gt;바퀴 조인트 상태&lt;/td&gt;
&lt;/tr&gt;
&lt;tr data-start=&quot;2100&quot; data-end=&quot;2153&quot;&gt;
&lt;td style=&quot;width: 20%;&quot; data-start=&quot;2100&quot; data-end=&quot;2110&quot; data-col-size=&quot;sm&quot;&gt;/scan&lt;/td&gt;
&lt;td style=&quot;width: 29.4186%;&quot; data-start=&quot;2110&quot; data-end=&quot;2140&quot; data-col-size=&quot;sm&quot;&gt;sensor_msgs/msg/LaserScan&lt;/td&gt;
&lt;td style=&quot;width: 26.2791%;&quot; data-start=&quot;2140&quot; data-end=&quot;2153&quot; data-col-size=&quot;sm&quot;&gt;LiDAR 데이터&lt;/td&gt;
&lt;/tr&gt;
&lt;tr data-start=&quot;2154&quot; data-end=&quot;2203&quot;&gt;
&lt;td style=&quot;width: 20%;&quot; data-start=&quot;2154&quot; data-end=&quot;2168&quot; data-col-size=&quot;sm&quot;&gt;/imu/data&lt;/td&gt;
&lt;td style=&quot;width: 29.4186%;&quot; data-start=&quot;2168&quot; data-end=&quot;2192&quot; data-col-size=&quot;sm&quot;&gt;sensor_msgs/msg/Imu&lt;/td&gt;
&lt;td style=&quot;width: 26.2791%;&quot; data-start=&quot;2192&quot; data-end=&quot;2203&quot; data-col-size=&quot;sm&quot;&gt;IMU 데이터&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;2205&quot; data-end=&quot;2402&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;2205&quot; data-end=&quot;2402&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;2205&quot; data-end=&quot;2402&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot; data-start=&quot;4129&quot; data-end=&quot;4164&quot;&gt;2. ROS 좌표계: odom, base_link, map&lt;/h4&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;4166&quot; data-end=&quot;4202&quot;&gt;ROS 2 모바일 로봇에서 가장 기본적인 TF(Transform, 좌표계 변환 시스템) 구조는 다음과 같습니다.&lt;/p&gt;
&lt;div style=&quot;color: #333333; text-align: start;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;cpp&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot;&gt;&lt;code&gt;map
 └── odom
      └── base_link
           ├── laser
           ├── imu_link
           └── wheel_link&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;4322&quot; data-end=&quot;4347&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;4322&quot; data-end=&quot;4347&quot;&gt;아래의 연결을 이해하는 것이 중요합니다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;4322&quot; data-end=&quot;4347&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div style=&quot;color: #333333; text-align: start;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;nginx&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot;&gt;&lt;code&gt;odom &amp;rarr; base_link&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size18&quot; data-start=&quot;4379&quot; data-end=&quot;4387&quot;&gt;odom&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;4389&quot; data-end=&quot;4433&quot;&gt;odom은 로봇이 출발한 지점 기준으로 부드럽게 이어지는 로컬 좌표계입니다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;4435&quot; data-end=&quot;4438&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;4435&quot; data-end=&quot;4438&quot;&gt;특징:&lt;/p&gt;
&lt;div style=&quot;color: #333333; text-align: start;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;erlang&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot;&gt;&lt;code&gt;연속적이다.
갑자기 튀면 안 된다.
시간이 지나면 drift가 생긴다.&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size18&quot; data-start=&quot;4493&quot; data-end=&quot;4506&quot;&gt;base_link&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;4508&quot; data-end=&quot;4537&quot;&gt;base_link는 로봇 본체 중심 좌표계입니다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;4539&quot; data-end=&quot;4567&quot;&gt;ROS 모바일 로봇의 기본 방향은 다음과 같습니다.&lt;/p&gt;
&lt;div style=&quot;color: #333333; text-align: start;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;http&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot;&gt;&lt;code&gt;x축: 로봇 전방
y축: 로봇 왼쪽
z축: 위쪽&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size18&quot; data-start=&quot;4609&quot; data-end=&quot;4616&quot;&gt;map&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;4618&quot; data-end=&quot;4676&quot;&gt;map은 전역 지도 좌표계입니다. SLAM 또는 AMCL이 map &amp;rarr; odom 변환을 보정합니다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;4678&quot; data-end=&quot;4683&quot;&gt;정리하면:&lt;/p&gt;
&lt;div style=&quot;color: #333333; text-align: start;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;ada&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot;&gt;&lt;code&gt;odom &amp;rarr; base_link : 엔코더/IMU 기반 로컬 오도메트리
map &amp;rarr; odom       : SLAM/AMCL 기반 전역 위치 보정&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;4778&quot; data-end=&quot;4807&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;4778&quot; data-end=&quot;4807&quot;&gt;이 구조를 깨면 Nav2가 제대로 동작하지 않습니다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;4778&quot; data-end=&quot;4807&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;4778&quot; data-end=&quot;4807&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;4778&quot; data-end=&quot;4807&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot; data-start=&quot;4814&quot; data-end=&quot;4835&quot;&gt;3. /cmd_vel 메시지 이해&lt;/h4&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;4837&quot; data-end=&quot;4883&quot;&gt;ROS 2에서 모바일 로봇 속도 명령은 보통 /cmd_vel 토픽으로 보냅니다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;4837&quot; data-end=&quot;4883&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;4885&quot; data-end=&quot;4899&quot;&gt;메시지 타입은 다음입니다.&lt;/p&gt;
&lt;div style=&quot;color: #333333; text-align: start;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;routeros&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot;&gt;&lt;code&gt;ros2 interface show geometry_msgs/msg/Twist&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;4958&quot; data-end=&quot;4971&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;4958&quot; data-end=&quot;4971&quot;&gt;구조는 다음과 같습니다.&lt;/p&gt;
&lt;div style=&quot;color: #333333; text-align: start;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;properties&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot;&gt;&lt;code&gt;Vector3 linear
Vector3 angular&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;5017&quot; data-end=&quot;5040&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;5017&quot; data-end=&quot;5040&quot;&gt;차동구동 로봇에서는 보통 두 값만 씁니다.&lt;/p&gt;
&lt;div style=&quot;color: #333333; text-align: start;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;groovy&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot;&gt;&lt;code&gt;linear.x   : 전진/후진 속도 [m/s]
angular.z  : 좌회전/우회전 각속도 [rad/s]&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;5116&quot; data-end=&quot;5122&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;5116&quot; data-end=&quot;5122&quot;&gt;예를 들어:&lt;/p&gt;
&lt;div style=&quot;color: #333333; text-align: start;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;properties&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot;&gt;&lt;code&gt;ros2 topic pub /cmd_vel geometry_msgs/msg/Twist &quot;{
  linear: {x: 0.2, y: 0.0, z: 0.0},
  angular: {x: 0.0, y: 0.0, z: 0.5}
}&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;5263&quot; data-end=&quot;5273&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;5263&quot; data-end=&quot;5273&quot;&gt;의미는 다음입니다.&lt;/p&gt;
&lt;div style=&quot;color: #333333; text-align: start;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;angelscript&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot;&gt;&lt;code&gt;전진 속도 v = 0.2 m/s
회전 속도 omega = 0.5 rad/s&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;5330&quot; data-end=&quot;5355&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;5330&quot; data-end=&quot;5355&quot;&gt;즉 로봇은 앞으로 가면서 왼쪽으로 회전합니다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;5357&quot; data-end=&quot;5546&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;5357&quot; data-end=&quot;5546&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;5357&quot; data-end=&quot;5546&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size20&quot; data-start=&quot;5357&quot; data-end=&quot;5546&quot;&gt;4. 엔코더 기반 Odometry 유도&lt;/h4&gt;
&lt;p data-end=&quot;1417&quot; data-start=&quot;1374&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;1417&quot; data-start=&quot;1374&quot; data-ke-size=&quot;size16&quot;&gt;이제&amp;nbsp;엔코더&amp;nbsp;tick에서&amp;nbsp;로봇&amp;nbsp;위치를&amp;nbsp;계산하는&amp;nbsp;과정을&amp;nbsp;보겠습니다. &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;1) tick을 거리로 변환 &lt;br /&gt;&lt;br /&gt;왼쪽과&amp;nbsp;오른쪽&amp;nbsp;엔코더&amp;nbsp;누적&amp;nbsp;tick이&amp;nbsp;있다고&amp;nbsp;가정합니다. &lt;br /&gt;&lt;br /&gt;$$ &lt;br /&gt;left\_ticks,\quad&amp;nbsp;right\_ticks &lt;br /&gt;$$ &lt;br /&gt;&lt;br /&gt;이전&amp;nbsp;주기의&amp;nbsp;tick과&amp;nbsp;비교해서&amp;nbsp;변화량을&amp;nbsp;구합니다. &lt;br /&gt;&lt;br /&gt;$$ &lt;br /&gt;\Delta&amp;nbsp;left\_ticks&amp;nbsp;=&amp;nbsp;left\_ticks&amp;nbsp;-&amp;nbsp;prev\_left\_ticks &lt;br /&gt;$$ &lt;br /&gt;&lt;br /&gt;$$ &lt;br /&gt;\Delta&amp;nbsp;right\_ticks&amp;nbsp;=&amp;nbsp;right\_ticks&amp;nbsp;-&amp;nbsp;prev\_right\_ticks &lt;br /&gt;$$ &lt;br /&gt;&lt;br /&gt;tick&amp;nbsp;하나당&amp;nbsp;이동&amp;nbsp;거리는&amp;nbsp;다음과&amp;nbsp;같습니다. &lt;br /&gt;&lt;br /&gt;$$ &lt;br /&gt;meter\_per\_tick&amp;nbsp;=&amp;nbsp;\frac{2\pi&amp;nbsp;r}{ticks\_per\_revolution} &lt;br /&gt;$$ &lt;br /&gt;&lt;br /&gt;왼쪽,&amp;nbsp;오른쪽&amp;nbsp;바퀴&amp;nbsp;이동&amp;nbsp;거리는&amp;nbsp;다음과&amp;nbsp;같습니다. &lt;br /&gt;&lt;br /&gt;$$ &lt;br /&gt;d_l&amp;nbsp;=&amp;nbsp;\Delta&amp;nbsp;left\_ticks&amp;nbsp;\times&amp;nbsp;meter\_per\_tick &lt;br /&gt;$$ &lt;br /&gt;&lt;br /&gt;$$ &lt;br /&gt;d_r&amp;nbsp;=&amp;nbsp;\Delta&amp;nbsp;right\_ticks&amp;nbsp;\times&amp;nbsp;meter\_per\_tick &lt;br /&gt;$$ &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;2) 로봇 중심 이동 거리 &lt;br /&gt;&lt;br /&gt;로봇&amp;nbsp;중심&amp;nbsp;이동&amp;nbsp;거리는&amp;nbsp;좌우&amp;nbsp;바퀴&amp;nbsp;이동&amp;nbsp;거리의&amp;nbsp;평균입니다. &lt;br /&gt;&lt;br /&gt;$$ &lt;br /&gt;d_{center}&amp;nbsp;=&amp;nbsp;\frac{d_r&amp;nbsp;+&amp;nbsp;d_l}{2} &lt;br /&gt;$$ &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;3) 방향 변화량 &lt;br /&gt;&lt;br /&gt;로봇의&amp;nbsp;yaw&amp;nbsp;변화량은&amp;nbsp;좌우&amp;nbsp;바퀴&amp;nbsp;이동&amp;nbsp;거리&amp;nbsp;차이를&amp;nbsp;바퀴&amp;nbsp;간&amp;nbsp;거리로&amp;nbsp;나눈&amp;nbsp;값입니다. &lt;br /&gt;&lt;br /&gt;$$ &lt;br /&gt;\Delta&amp;nbsp;\theta&amp;nbsp;=&amp;nbsp;\frac{d_r&amp;nbsp;-&amp;nbsp;d_l}{L} &lt;br /&gt;$$ &lt;br /&gt;&lt;br /&gt;오른쪽&amp;nbsp;바퀴가&amp;nbsp;더&amp;nbsp;많이&amp;nbsp;이동하면&amp;nbsp;다음과&amp;nbsp;같습니다. &lt;br /&gt;&lt;br /&gt;$$ &lt;br /&gt;d_r&amp;nbsp;&amp;gt;&amp;nbsp;d_l &lt;br /&gt;$$ &lt;br /&gt;&lt;br /&gt;$$ &lt;br /&gt;\Delta&amp;nbsp;\theta&amp;nbsp;&amp;gt;&amp;nbsp;0 &lt;br /&gt;$$ &lt;br /&gt;&lt;br /&gt;ROS&amp;nbsp;좌표계&amp;nbsp;기준으로&amp;nbsp;yaw가&amp;nbsp;증가하므로&amp;nbsp;반시계&amp;nbsp;방향,&amp;nbsp;즉&amp;nbsp;왼쪽&amp;nbsp;회전입니다. &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;4) $x$, $y$, $\theta$ 업데이트 &lt;br /&gt;&lt;br /&gt;현재&amp;nbsp;상태가&amp;nbsp;다음이라고&amp;nbsp;하겠습니다. &lt;br /&gt;&lt;br /&gt;$$ &lt;br /&gt;x,\quad&amp;nbsp;y,\quad&amp;nbsp;\theta &lt;br /&gt;$$ &lt;br /&gt;&lt;br /&gt;한&amp;nbsp;주기&amp;nbsp;동안&amp;nbsp;이동&amp;nbsp;후&amp;nbsp;상태는&amp;nbsp;다음처럼&amp;nbsp;갱신합니다. &lt;br /&gt;&lt;br /&gt;$$ &lt;br /&gt;x_{new}&amp;nbsp;=&amp;nbsp;x&amp;nbsp;+&amp;nbsp;d_{center}\cos\left(\theta&amp;nbsp;+&amp;nbsp;\frac{\Delta&amp;nbsp;\theta}{2}\right) &lt;br /&gt;$$ &lt;br /&gt;&lt;br /&gt;$$ &lt;br /&gt;y_{new}&amp;nbsp;=&amp;nbsp;y&amp;nbsp;+&amp;nbsp;d_{center}\sin\left(\theta&amp;nbsp;+&amp;nbsp;\frac{\Delta&amp;nbsp;\theta}{2}\right) &lt;br /&gt;$$ &lt;br /&gt;&lt;br /&gt;$$ &lt;br /&gt;\theta_{new}&amp;nbsp;=&amp;nbsp;\theta&amp;nbsp;+&amp;nbsp;\Delta&amp;nbsp;\theta &lt;br /&gt;$$ &lt;br /&gt;&lt;br /&gt;여기서&amp;nbsp;다음&amp;nbsp;항을&amp;nbsp;쓰는&amp;nbsp;이유가&amp;nbsp;중요합니다. &lt;br /&gt;&lt;br /&gt;$$ &lt;br /&gt;\theta&amp;nbsp;+&amp;nbsp;\frac{\Delta&amp;nbsp;\theta}{2} &lt;br /&gt;$$ &lt;br /&gt;&lt;br /&gt;로봇은&amp;nbsp;한&amp;nbsp;주기&amp;nbsp;동안&amp;nbsp;직선으로만&amp;nbsp;이동하지&amp;nbsp;않습니다.&amp;nbsp;회전하면서&amp;nbsp;조금씩&amp;nbsp;곡선을&amp;nbsp;그립니다.&amp;nbsp;시작&amp;nbsp;방향&amp;nbsp;$\theta$만&amp;nbsp;쓰면&amp;nbsp;오차가&amp;nbsp;커질&amp;nbsp;수&amp;nbsp;있습니다.&amp;nbsp;그래서&amp;nbsp;이동&amp;nbsp;중간&amp;nbsp;방향을&amp;nbsp;사용합니다. &lt;br /&gt;&lt;br /&gt;이&amp;nbsp;방식은&amp;nbsp;차동구동&amp;nbsp;odometry에서&amp;nbsp;가장&amp;nbsp;많이&amp;nbsp;쓰는&amp;nbsp;기본&amp;nbsp;적분&amp;nbsp;방식입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-end=&quot;2873&quot; data-start=&quot;2838&quot; data-section-id=&quot;18w4wuk&quot; data-ke-size=&quot;size20&quot;&gt;5. 인터페이스 패키지에 EncoderTicks 메시지 추가&lt;/h4&gt;
&lt;p data-end=&quot;3037&quot; data-start=&quot;2989&quot; data-ke-size=&quot;size16&quot;&gt;먼저&amp;nbsp; my_first_package_msgs에 다음 메시지를 추가합니다.&lt;/p&gt;
&lt;p data-end=&quot;3045&quot; data-start=&quot;3039&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;3045&quot; data-start=&quot;3039&quot; data-ke-size=&quot;size16&quot;&gt;파일 경로:&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;awk&quot;&gt;&lt;code&gt;~/ros2_study/src/my_first_package_msgs/msg/EncoderTicks.msg&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;3123&quot; data-start=&quot;3120&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;3123&quot; data-start=&quot;3120&quot; data-ke-size=&quot;size16&quot;&gt;내용:&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;int64 left_ticks
int64 right_ticks&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;3206&quot; data-start=&quot;3173&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;3206&quot; data-start=&quot;3173&quot; data-ke-size=&quot;size16&quot;&gt;package.xml에 메시지 빌드 의존성이 필요합니다. 이미 추가되어 있으면 생략합니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;xml&quot;&gt;&lt;code&gt;&amp;lt;buildtool_depend&amp;gt;ament_cmake&amp;lt;/buildtool_depend&amp;gt;

&amp;lt;build_depend&amp;gt;rosidl_default_generators&amp;lt;/build_depend&amp;gt;
&amp;lt;exec_depend&amp;gt;rosidl_default_runtime&amp;lt;/exec_depend&amp;gt;

&amp;lt;member_of_group&amp;gt;rosidl_interface_packages&amp;lt;/member_of_group&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;3466&quot; data-start=&quot;3437&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;3466&quot; data-start=&quot;3437&quot; data-ke-size=&quot;size16&quot;&gt;CMakeLists.txt에는 다음을 추가합니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;stylus&quot;&gt;&lt;code&gt;find_package(ament_cmake REQUIRED)
find_package(rosidl_default_generators REQUIRED)

rosidl_generate_interfaces(${PROJECT_NAME}
  &quot;msg/EncoderTicks.msg&quot;
)

ament_package()&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;3679&quot; data-start=&quot;3654&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;3679&quot; data-start=&quot;3654&quot; data-ke-size=&quot;size16&quot;&gt;빌드 후에는 다음 타입을 사용할 수 있습니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;awk&quot;&gt;&lt;code&gt;my_first_package_msgs/msg/EncoderTicks&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-end=&quot;3785&quot; data-start=&quot;3738&quot; data-section-id=&quot;8mbv9l&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span&gt;6. /cmd_vel을 좌우 바퀴 속도로 변환하는 Python 노드&lt;/span&gt;&lt;/h4&gt;
&lt;p data-end=&quot;3886&quot; data-start=&quot;3808&quot; data-ke-size=&quot;size16&quot;&gt;/cmd_vel은 로봇 중심 기준 속도 명령입니다.&lt;br /&gt;하지만 실제 모터 드라이버는 왼쪽 바퀴와 오른쪽 바퀴 명령을 따로 받아야 합니다.&lt;/p&gt;
&lt;p data-end=&quot;3912&quot; data-start=&quot;3888&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;3912&quot; data-start=&quot;3888&quot; data-ke-size=&quot;size16&quot;&gt;그래서 첫 번째로 해야 할 일은 cmd_vel을 좌우 바퀴 속도로 변환하는 것입니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;coq&quot;&gt;&lt;code&gt;/cmd_vel
   &amp;darr;
left wheel velocity
right wheel velocity&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;3988&quot; data-start=&quot;3982&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;p data-end=&quot;3988&quot; data-start=&quot;3982&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;3988&quot; data-start=&quot;3982&quot; data-ke-size=&quot;size16&quot;&gt;입력은&amp;nbsp;로봇의&amp;nbsp;목표&amp;nbsp;속도입니다.&lt;br /&gt;&lt;br /&gt;$$&lt;br /&gt;\text{입력}&amp;nbsp;=&amp;nbsp;v,\&amp;nbsp;\omega&lt;br /&gt;$$&lt;br /&gt;&lt;br /&gt;출력은&amp;nbsp;좌우&amp;nbsp;바퀴&amp;nbsp;속도입니다.&lt;br /&gt;&lt;br /&gt;$$&lt;br /&gt;\text{출력}&amp;nbsp;=&amp;nbsp;v_l,\&amp;nbsp;v_r&lt;br /&gt;$$&lt;br /&gt;&lt;br /&gt;차동&amp;nbsp;로봇의&amp;nbsp;기본&amp;nbsp;역기구학&amp;nbsp;식은&amp;nbsp;다음과&amp;nbsp;같습니다.&lt;br /&gt;&lt;br /&gt;$$&lt;br /&gt;v_r&amp;nbsp;=&amp;nbsp;v&amp;nbsp;+&amp;nbsp;\frac{\omega&amp;nbsp;L}{2}&lt;br /&gt;$$&lt;br /&gt;&lt;br /&gt;$$&lt;br /&gt;v_l&amp;nbsp;=&amp;nbsp;v&amp;nbsp;-&amp;nbsp;\frac{\omega&amp;nbsp;L}{2}&lt;br /&gt;$$&lt;br /&gt;&lt;br /&gt;바퀴&amp;nbsp;선속도가&amp;nbsp;아니라&amp;nbsp;모터&amp;nbsp;각속도가&amp;nbsp;필요하다면&amp;nbsp;다음처럼&amp;nbsp;바꿉니다.&lt;br /&gt;&lt;br /&gt;$$&lt;br /&gt;\omega_r&amp;nbsp;=&amp;nbsp;\frac{v_r}{r}&lt;br /&gt;$$&lt;br /&gt;&lt;br /&gt;$$&lt;br /&gt;\omega_l&amp;nbsp;=&amp;nbsp;\frac{v_l}{r}&lt;br /&gt;$$&lt;br /&gt;&lt;br /&gt;따라서&amp;nbsp;다음과&amp;nbsp;같이&amp;nbsp;정리할&amp;nbsp;수&amp;nbsp;있습니다.&lt;br /&gt;&lt;br /&gt;$$&lt;br /&gt;\omega_r&amp;nbsp;=&amp;nbsp;\frac{v&amp;nbsp;+&amp;nbsp;\frac{\omega&amp;nbsp;L}{2}}{r}&lt;br /&gt;$$&lt;br /&gt;&lt;br /&gt;$$&lt;br /&gt;\omega_l&amp;nbsp;=&amp;nbsp;\frac{v&amp;nbsp;-&amp;nbsp;\frac{\omega&amp;nbsp;L}{2}}{r}&lt;br /&gt;$$&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;3988&quot; data-start=&quot;3982&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;3988&quot; data-start=&quot;3982&quot; data-ke-size=&quot;size16&quot;&gt;파일 경로:&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;awk&quot;&gt;&lt;code&gt;~/ros2_study/src/my_first_package/my_first_package/cmd_vel_to_wheel.py&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;4077&quot; data-start=&quot;4074&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;4077&quot; data-start=&quot;4074&quot; data-ke-size=&quot;size16&quot;&gt;소스 코드:&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot;&gt;&lt;code&gt;import rclpy
from rclpy.node import Node

from geometry_msgs.msg import Twist
from std_msgs.msg import Float64MultiArray


class CmdVelToWheel(Node):
    def __init__(self):
        super().__init__('cmd_vel_to_wheel')

        self.declare_parameter('wheel_radius', 0.033)
        self.declare_parameter('wheel_separation', 0.30)

        self.wheel_radius = self.get_parameter('wheel_radius').value
        self.wheel_separation = self.get_parameter('wheel_separation').value

        self.sub_cmd_vel = self.create_subscription(
            Twist,
            '/cmd_vel',
            self.cmd_vel_callback,
            10
        )

        self.pub_wheel_velocity = self.create_publisher(
            Float64MultiArray,
            '/wheel_velocity',
            10
        )

        self.get_logger().info('cmd_vel_to_wheel node started')
        self.get_logger().info(f'wheel_radius: {self.wheel_radius} m')
        self.get_logger().info(f'wheel_separation: {self.wheel_separation} m')

    def cmd_vel_callback(self, msg: Twist):
        linear_x = msg.linear.x
        angular_z = msg.angular.z

        left_linear_velocity = (
            linear_x - angular_z * self.wheel_separation / 2.0
        )

        right_linear_velocity = (
            linear_x + angular_z * self.wheel_separation / 2.0
        )

        left_angular_velocity = left_linear_velocity / self.wheel_radius
        right_angular_velocity = right_linear_velocity / self.wheel_radius

        out = Float64MultiArray()
        out.data = [
            left_linear_velocity,
            right_linear_velocity,
            left_angular_velocity,
            right_angular_velocity
        ]

        self.pub_wheel_velocity.publish(out)

        self.get_logger().info(
            'cmd_vel '
            f'linear.x={linear_x:.3f} m/s, '
            f'angular.z={angular_z:.3f} rad/s | '
            f'left={left_linear_velocity:.3f} m/s, '
            f'right={right_linear_velocity:.3f} m/s | '
            f'left_w={left_angular_velocity:.3f} rad/s, '
            f'right_w={right_angular_velocity:.3f} rad/s'
        )


def main(args=None):
    rclpy.init(args=args)
    node = CmdVelToWheel()
    rclpy.spin(node)
    node.destroy_node()
    rclpy.shutdown()


if __name__ == '__main__':
    main()&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;6417&quot; data-start=&quot;6383&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;483&quot; data-start=&quot;392&quot; data-ke-size=&quot;size16&quot;&gt;/cmd_vel에서 받은 linear.x는 로봇의 전진 속도이고, angular.z는 회전 속도입니다. 이 값을 이용해 좌우 바퀴의 선속도를 계산합니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;ini&quot;&gt;&lt;code&gt;left_linear_velocity = linear_x - angular_z * wheel_separation / 2.0
right_linear_velocity = linear_x + angular_z * wheel_separation / 2.0&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;688&quot; data-start=&quot;639&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;688&quot; data-start=&quot;639&quot; data-ke-size=&quot;size16&quot;&gt;이후 각 바퀴의 선속도를 바퀴 반지름으로 나누어 바퀴의 각속도(rad/s)로 변환합니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;ini&quot;&gt;&lt;code&gt;left_angular_velocity = left_linear_velocity / wheel_radius
right_angular_velocity = right_linear_velocity / wheel_radius&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;874&quot; data-start=&quot;827&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;874&quot; data-start=&quot;827&quot; data-ke-size=&quot;size16&quot;&gt;최종적으로 /wheel_velocity 토픽에는 다음 순서로 데이터가 발행됩니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;json&quot;&gt;&lt;code&gt;[
    left_linear_velocity,
    right_linear_velocity,
    left_angular_velocity,
    right_angular_velocity
]&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-is-only-node=&quot;&quot; data-is-last-node=&quot;&quot; data-end=&quot;1138&quot; data-start=&quot;1002&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-is-only-node=&quot;&quot; data-is-last-node=&quot;&quot; data-end=&quot;1138&quot; data-start=&quot;1002&quot; data-ke-size=&quot;size16&quot;&gt;즉, 이 노드는 상위 제어기나 키보드 조종 노드에서 생성한 /cmd_vel 명령을 실제 좌우 바퀴 제어에 사용할 수 있는 속도 값으로 변환하는 역할을 합니다. 차동구동 모바일 로봇의 모터 제어 전단에서 사용하기 적합한 기본 변환 노드입니다.&lt;/p&gt;
&lt;p data-is-only-node=&quot;&quot; data-is-last-node=&quot;&quot; data-end=&quot;1138&quot; data-start=&quot;1002&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;6417&quot; data-start=&quot;6383&quot; data-ke-size=&quot;size16&quot;&gt;setup.py의 entry_points에 추가합니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;prolog&quot;&gt;&lt;code&gt;entry_points={
    'console_scripts': [
        'cmd_vel_to_wheel = my_first_package.cmd_vel_to_wheel:main',
    ],
},&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;6578&quot; data-start=&quot;6553&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;6578&quot; data-start=&quot;6553&quot; data-ke-size=&quot;size16&quot;&gt;예를 들어 다음 명령이 들어왔다고 가정합니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;ini&quot;&gt;&lt;code&gt;linear.x  = 0.3 m/s
angular.z = 0.5 rad/s
wheel_radius = 0.033 m
wheel_separation = 0.30 m&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;6701&quot; data-start=&quot;6684&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;6701&quot; data-start=&quot;6684&quot; data-ke-size=&quot;size16&quot;&gt;계산 결과는 다음과 비슷합니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;left_linear_velocity  &amp;asymp; 0.225 m/s
right_linear_velocity &amp;asymp; 0.375 m/s

left_angular_velocity  &amp;asymp; 6.818 rad/s
right_angular_velocity &amp;asymp; 11.364 rad/s&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;6890&quot; data-start=&quot;6860&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;6890&quot; data-start=&quot;6860&quot; data-ke-size=&quot;size16&quot;&gt;오른쪽 바퀴가 더 빠르므로 로봇은 왼쪽으로 회전합니다.&lt;/p&gt;
&lt;p data-end=&quot;6890&quot; data-start=&quot;6860&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;6890&quot; data-start=&quot;6860&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;6890&quot; data-start=&quot;6860&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;6890&quot; data-start=&quot;6860&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-end=&quot;6933&quot; data-start=&quot;6897&quot; data-section-id=&quot;xaedb4&quot; data-ke-size=&quot;size20&quot;&gt;7. 가상 Encoder Tick 발행 노드 만들기&lt;/h4&gt;
&lt;p data-end=&quot;7014&quot; data-start=&quot;6935&quot; data-ke-size=&quot;size16&quot;&gt;실제 로봇에서는 엔코더 tick이 MCU, 모터 드라이버, ros2_control hardware interface 등을 통해 들어옵니다.&lt;/p&gt;
&lt;p data-end=&quot;7014&quot; data-start=&quot;6935&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;7066&quot; data-start=&quot;7016&quot; data-ke-size=&quot;size16&quot;&gt;먼저 가상 엔코더 tick을 발행해서 odometry 원리를 이해하려고 합니다.&lt;/p&gt;
&lt;p data-end=&quot;7066&quot; data-start=&quot;7016&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;7078&quot; data-start=&quot;7068&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;jboss-cli&quot;&gt;&lt;code&gt;fake_encoder_node
        &amp;darr;
/encoder_ticks&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;7142&quot; data-start=&quot;7136&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;7142&quot; data-start=&quot;7136&quot; data-ke-size=&quot;size16&quot;&gt;파일 경로:&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;awk&quot;&gt;&lt;code&gt;~/ros2_study/src/my_first_package/my_first_package/fake_encoder_node.py&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;7232&quot; data-start=&quot;7229&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;7232&quot; data-start=&quot;7229&quot; data-ke-size=&quot;size16&quot;&gt;코드:&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot;&gt;&lt;code&gt;import rclpy
from rclpy.node import Node

from my_first_package_msgs.msg import EncoderTicks


class FakeEncoderNode(Node):
    def __init__(self):
        super().__init__('fake_encoder_node')

        self.publisher = self.create_publisher(
            EncoderTicks,
            '/encoder_ticks',
            10
        )

        self.left_ticks = 0
        self.right_ticks = 0

        self.declare_parameter('left_tick_step', 5)
        self.declare_parameter('right_tick_step', 5)
        self.declare_parameter('period', 0.05)

        self.left_tick_step = self.get_parameter('left_tick_step').value
        self.right_tick_step = self.get_parameter('right_tick_step').value
        self.period = self.get_parameter('period').value

        self.timer = self.create_timer(self.period, self.timer_callback)

        self.get_logger().info('fake_encoder_node started')

    def timer_callback(self):
        self.left_ticks += int(self.left_tick_step)
        self.right_ticks += int(self.right_tick_step)

        msg = EncoderTicks()
        msg.left_ticks = self.left_ticks
        msg.right_ticks = self.right_ticks

        self.publisher.publish(msg)

        self.get_logger().info(
            f'left_ticks={self.left_ticks}, '
            f'right_ticks={self.right_ticks}'
        )


def main(args=None):
    rclpy.init(args=args)
    node = FakeEncoderNode()
    rclpy.spin(node)
    node.destroy_node()
    rclpy.shutdown()


if __name__ == '__main__':
    main()&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;8750&quot; data-start=&quot;8732&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;593&quot; data-start=&quot;484&quot; data-ke-size=&quot;size16&quot;&gt;노드가 실행되면 내부 변수 left_ticks, right_ticks가 0에서 시작합니다. 이후 타이머가 period 주기마다 실행되며, 각 tick 값에 설정된 증가량을 더합니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;objectivec&quot;&gt;&lt;code&gt;self.left_ticks += int(self.left_tick_step)
self.right_ticks += int(self.right_tick_step)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;762&quot; data-start=&quot;700&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;762&quot; data-start=&quot;700&quot; data-ke-size=&quot;size16&quot;&gt;증가된 엔코더 값은 EncoderTicks 메시지에 담겨 /encoder_ticks 토픽으로 발행됩니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;ini&quot;&gt;&lt;code&gt;msg.left_ticks = self.left_ticks
msg.right_ticks = self.right_ticks&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-is-only-node=&quot;&quot; data-is-last-node=&quot;&quot; data-end=&quot;974&quot; data-start=&quot;847&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-is-only-node=&quot;&quot; data-is-last-node=&quot;&quot; data-end=&quot;974&quot; data-start=&quot;847&quot; data-ke-size=&quot;size16&quot;&gt;즉, 이 노드는 실제 엔코더 없이도 엔코더 데이터가 계속 들어오는 것처럼 테스트할 수 있게 해주는 가상 엔코더 발행 노드입니다. 주로 오도메트리 계산 노드, 속도 계산 노드, 바퀴 제어 알고리즘을 검증할 때 사용할 수 있습니다.&lt;/p&gt;
&lt;p data-end=&quot;8750&quot; data-start=&quot;8732&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;8750&quot; data-start=&quot;8732&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;8750&quot; data-start=&quot;8732&quot; data-ke-size=&quot;size16&quot;&gt;setup.py에 추가합니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;sml&quot;&gt;&lt;code&gt;entry_points={
    'console_scripts': [
        'cmd_vel_to_wheel = my_first_package.cmd_vel_to_wheel:main',
        'fake_encoder_node = my_first_package.fake_encoder_node:main',
    ],
},&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;8986&quot; data-start=&quot;8957&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;8986&quot; data-start=&quot;8957&quot; data-ke-size=&quot;size16&quot;&gt;기본값은 왼쪽과 오른쪽 tick이 똑같이 증가합니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;makefile&quot;&gt;&lt;code&gt;left_ticks  += 5
right_ticks += 5&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;9055&quot; data-start=&quot;9035&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;9055&quot; data-start=&quot;9035&quot; data-ke-size=&quot;size16&quot;&gt;이 경우 로봇은 직진하는 상황입니다.&lt;/p&gt;
&lt;p data-end=&quot;9055&quot; data-start=&quot;9035&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;9081&quot; data-start=&quot;9057&quot; data-ke-size=&quot;size16&quot;&gt;오른쪽을 더 빠르게 만들면 다음과 같습니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;makefile&quot;&gt;&lt;code&gt;left_ticks  += 3
right_ticks += 7&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;9168&quot; data-start=&quot;9130&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;9168&quot; data-start=&quot;9130&quot; data-ke-size=&quot;size16&quot;&gt;이 경우 오른쪽 바퀴 이동량이 더 크므로 로봇은 왼쪽으로 회전합니다.&lt;/p&gt;
&lt;p data-end=&quot;9187&quot; data-start=&quot;9170&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;9187&quot; data-start=&quot;9170&quot; data-ke-size=&quot;size16&quot;&gt;제자리 회전은 다음과 같습니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;left_ticks  -= 5
right_ticks += 5&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;9268&quot; data-start=&quot;9236&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;9268&quot; data-start=&quot;9236&quot; data-ke-size=&quot;size16&quot;&gt;이 경우 중심 이동거리는 거의 0이고 회전각만 증가합니다.&lt;/p&gt;
&lt;p data-end=&quot;9268&quot; data-start=&quot;9236&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;9268&quot; data-start=&quot;9236&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;9268&quot; data-start=&quot;9236&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-end=&quot;9318&quot; data-start=&quot;9275&quot; data-section-id=&quot;1fpqumg&quot; data-ke-size=&quot;size20&quot;&gt;8. Encoder Tick을 거리로 변환하는 Python 노드&lt;/h4&gt;
&lt;p data-end=&quot;9399&quot; data-start=&quot;9320&quot; data-ke-size=&quot;size16&quot;&gt;엔코더 tick은 그 자체로는 거리 단위가 아닙니다.&lt;/p&gt;
&lt;p data-end=&quot;9399&quot; data-start=&quot;9320&quot; data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;바퀴 반지름과 바퀴 1회전당 tick 수를 알아야 실제 이동거리로 바꿀 수 있습니다.&lt;/p&gt;
&lt;p data-end=&quot;9414&quot; data-start=&quot;9401&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;9414&quot; data-start=&quot;9401&quot; data-ke-size=&quot;size16&quot;&gt;바퀴 둘레는 다음 식으로 표현됩니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;ini&quot;&gt;&lt;code&gt;wheel_circumference = 2&amp;pi;r&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;9476&quot; data-start=&quot;9455&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;9476&quot; data-start=&quot;9455&quot; data-ke-size=&quot;size16&quot;&gt;tick 하나당 이동거리는 다음입니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;ini&quot;&gt;&lt;code&gt;meter_per_tick = 2&amp;pi;r / ticks_per_revolution&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;9558&quot; data-start=&quot;9535&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;9558&quot; data-start=&quot;9535&quot; data-ke-size=&quot;size16&quot;&gt;왼쪽, 오른쪽 바퀴 이동거리는 다음입니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;ini&quot;&gt;&lt;code&gt;d_left  = &amp;Delta;left_ticks  &amp;times; meter_per_tick
d_right = &amp;Delta;right_ticks &amp;times; meter_per_tick&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;9659&quot; data-start=&quot;9653&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;9659&quot; data-start=&quot;9653&quot; data-ke-size=&quot;size16&quot;&gt;파일 경로:&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;awk&quot;&gt;&lt;code&gt;~/ros2_study/src/my_first_package/my_first_package/tick_to_distance.py&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;9748&quot; data-start=&quot;9745&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;9748&quot; data-start=&quot;9745&quot; data-ke-size=&quot;size16&quot;&gt;코드:&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot;&gt;&lt;code&gt;import math

import rclpy
from rclpy.node import Node

from std_msgs.msg import Float64MultiArray
from my_first_package_msgs.msg import EncoderTicks


class TickToDistance(Node):
    def __init__(self):
        super().__init__('tick_to_distance')

        self.declare_parameter('wheel_radius', 0.033)
        self.declare_parameter('ticks_per_revolution', 2048)

        self.wheel_radius = self.get_parameter('wheel_radius').value
        self.ticks_per_revolution = self.get_parameter(
            'ticks_per_revolution'
        ).value

        self.distance_per_tick = (
            2.0 * math.pi * self.wheel_radius
            / float(self.ticks_per_revolution)
        )

        self.prev_left_ticks = None
        self.prev_right_ticks = None

        self.sub_encoder = self.create_subscription(
            EncoderTicks,
            '/encoder_ticks',
            self.encoder_callback,
            10
        )

        self.pub_wheel_distance = self.create_publisher(
            Float64MultiArray,
            '/wheel_distance',
            10
        )

        self.get_logger().info('tick_to_distance node started')
        self.get_logger().info(f'wheel_radius: {self.wheel_radius} m')
        self.get_logger().info(
            f'ticks_per_revolution: {self.ticks_per_revolution}'
        )
        self.get_logger().info(
            f'distance_per_tick: {self.distance_per_tick:.8f} m/tick'
        )

    def encoder_callback(self, msg: EncoderTicks):
        left_ticks = msg.left_ticks
        right_ticks = msg.right_ticks

        if self.prev_left_ticks is None:
            self.prev_left_ticks = left_ticks
            self.prev_right_ticks = right_ticks
            self.get_logger().info('First encoder data received')
            return

        delta_left_ticks = left_ticks - self.prev_left_ticks
        delta_right_ticks = right_ticks - self.prev_right_ticks

        self.prev_left_ticks = left_ticks
        self.prev_right_ticks = right_ticks

        left_distance = delta_left_ticks * self.distance_per_tick
        right_distance = delta_right_ticks * self.distance_per_tick

        out = Float64MultiArray()
        out.data = [
            float(delta_left_ticks),
            float(delta_right_ticks),
            left_distance,
            right_distance
        ]

        self.pub_wheel_distance.publish(out)

        self.get_logger().info(
            f'delta_ticks L={delta_left_ticks}, R={delta_right_ticks} | '
            f'distance L={left_distance:.5f} m, '
            f'R={right_distance:.5f} m'
        )


def main(args=None):
    rclpy.init(args=args)
    node = TickToDistance()
    rclpy.spin(node)
    node.destroy_node()
    rclpy.shutdown()


if __name__ == '__main__':
    main()&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;12533&quot; data-start=&quot;12515&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;516&quot; data-start=&quot;465&quot; data-ke-size=&quot;size16&quot;&gt;먼저 바퀴 한 바퀴의 둘레를 엔코더 해상도로 나누어 tick 1개당 이동 거리를 계산합니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;ini&quot;&gt;&lt;code&gt;distance_per_tick = 2.0 * math.pi * wheel_radius / ticks_per_revolution&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;670&quot; data-start=&quot;605&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;670&quot; data-start=&quot;605&quot; data-ke-size=&quot;size16&quot;&gt;엔코더 값은 누적 tick 값으로 들어오기 때문에, 현재 tick 값에서 이전 tick 값을 빼서 변화량을 구합니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;ini&quot;&gt;&lt;code&gt;delta_left_ticks = left_ticks - self.prev_left_ticks
delta_right_ticks = right_ticks - self.prev_right_ticks&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;853&quot; data-start=&quot;796&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;853&quot; data-start=&quot;796&quot; data-ke-size=&quot;size16&quot;&gt;이후 tick 변화량에 distance_per_tick을 곱해 좌우 바퀴의 이동 거리를 계산합니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;ini&quot;&gt;&lt;code&gt;left_distance = delta_left_ticks * self.distance_per_tick
right_distance = delta_right_ticks * self.distance_per_tick&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;1035&quot; data-start=&quot;988&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;1035&quot; data-start=&quot;988&quot; data-ke-size=&quot;size16&quot;&gt;최종적으로 /wheel_distance 토픽에는 다음 순서로 데이터가 발행됩니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;json&quot;&gt;&lt;code&gt;[
    delta_left_ticks,
    delta_right_ticks,
    left_distance,
    right_distance
]&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;1231&quot; data-start=&quot;1139&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;1231&quot; data-start=&quot;1139&quot; data-ke-size=&quot;size16&quot;&gt;첫 번째 엔코더 데이터는 이전 값이 없기 때문에 기준값으로만 저장하고 거리 계산은 하지 않습니다. 두 번째 데이터부터 실제 tick 변화량과 이동 거리를 계산합니다.&lt;/p&gt;
&lt;p data-end=&quot;1231&quot; data-start=&quot;1139&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-is-only-node=&quot;&quot; data-is-last-node=&quot;&quot; data-end=&quot;1340&quot; data-start=&quot;1233&quot; data-ke-size=&quot;size16&quot;&gt;즉, 이 노드는 엔코더의 누적 tick 값을 실제 바퀴 이동 거리로 변환하는 역할을 합니다. 차동구동 로봇에서 오도메트리 계산, 주행 거리 추정, 속도 계산 노드의 전단에 사용하기 적합합니다.&lt;/p&gt;
&lt;p data-end=&quot;12533&quot; data-start=&quot;12515&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;12533&quot; data-start=&quot;12515&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;12533&quot; data-start=&quot;12515&quot; data-ke-size=&quot;size16&quot;&gt;setup.py에 추가합니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;sml&quot;&gt;&lt;code&gt;entry_points={
    'console_scripts': [
        'cmd_vel_to_wheel = my_first_package.cmd_vel_to_wheel:main',
        'fake_encoder_node = my_first_package.fake_encoder_node:main',
        'tick_to_distance = my_first_package.tick_to_distance:main',
    ],
},&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;12830&quot; data-start=&quot;12809&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;12830&quot; data-start=&quot;12809&quot; data-ke-size=&quot;size16&quot;&gt;예를 들어 다음 조건이라고 가정합니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;ini&quot;&gt;&lt;code&gt;wheel_radius = 0.033 m
ticks_per_revolution = 2048
delta_ticks = 100&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;12930&quot; data-start=&quot;12914&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;12930&quot; data-start=&quot;12914&quot; data-ke-size=&quot;size16&quot;&gt;계산 결과는 다음과 같습니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;distance_per_tick &amp;asymp; 0.0001012 m/tick
100 ticks         &amp;asymp; 0.01012 m&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;13072&quot; data-start=&quot;13012&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;13072&quot; data-start=&quot;13012&quot; data-ke-size=&quot;size16&quot;&gt;좌우 이동거리가 같으면 직진입니다.&lt;/p&gt;
&lt;p data-end=&quot;13072&quot; data-start=&quot;13012&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;13072&quot; data-start=&quot;13012&quot; data-ke-size=&quot;size16&quot;&gt;오른쪽 이동거리가 더 크면 로봇은 왼쪽으로 회전한 것으로 해석합니다.&lt;/p&gt;
&lt;p data-end=&quot;13072&quot; data-start=&quot;13012&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;13072&quot; data-start=&quot;13012&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;13072&quot; data-start=&quot;13012&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-end=&quot;217&quot; data-start=&quot;179&quot; data-section-id=&quot;ijmicm&quot; data-ke-size=&quot;size20&quot;&gt;9. Python으로 Encoder Odometry 노드 구현하기&lt;/h4&gt;
&lt;p data-end=&quot;304&quot; data-start=&quot;219&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;304&quot; data-start=&quot;219&quot; data-ke-size=&quot;size16&quot;&gt;이번에는 my_first_package에 Python 노드를 만들고, /encoder_ticks를 받아서 /odom과 /tf를 발행합니다.&lt;/p&gt;
&lt;p data-end=&quot;323&quot; data-start=&quot;306&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;jboss-cli&quot;&gt;&lt;code&gt;/encoder_ticks
      &amp;darr;
encoder_odom_node
      &amp;darr;
/odom
/tf : odom &amp;rarr; base_link&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;435&quot; data-start=&quot;416&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;435&quot; data-start=&quot;416&quot; data-ke-size=&quot;size16&quot;&gt;파일 경로 예시는 다음과 같습니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;awk&quot;&gt;&lt;code&gt;~/ros2_study/src/my_first_package/my_first_package/encoder_odom_node.py&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;534&quot; data-start=&quot;522&quot; data-section-id=&quot;1atk1o9&quot; data-ke-size=&quot;size18&quot;&gt;1) Python 코드&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot;&gt;&lt;code&gt;import math

import rclpy
from rclpy.node import Node

from nav_msgs.msg import Odometry
from geometry_msgs.msg import TransformStamped
from tf2_ros import TransformBroadcaster

from my_first_package_msgs.msg import EncoderTicks


class EncoderOdomNode(Node):
    def __init__(self):
        super().__init__('encoder_odom_node')

        self.declare_parameter('wheel_radius', 0.033)
        self.declare_parameter('wheel_separation', 0.30)
        self.declare_parameter('ticks_per_revolution', 2048)
        self.declare_parameter('odom_frame_id', 'odom')
        self.declare_parameter('base_frame_id', 'base_link')
        self.declare_parameter('publish_tf', True)

        self.wheel_radius = self.get_parameter('wheel_radius').value
        self.wheel_separation = self.get_parameter('wheel_separation').value
        self.ticks_per_revolution = self.get_parameter(
            'ticks_per_revolution'
        ).value

        self.odom_frame_id = self.get_parameter('odom_frame_id').value
        self.base_frame_id = self.get_parameter('base_frame_id').value
        self.publish_tf = self.get_parameter('publish_tf').value

        self.distance_per_tick = (
            2.0 * math.pi * self.wheel_radius
            / float(self.ticks_per_revolution)
        )

        self.prev_left_ticks = 0
        self.prev_right_ticks = 0
        self.prev_time = None
        self.has_prev_ticks = False

        self.x = 0.0
        self.y = 0.0
        self.theta = 0.0

        self.odom_pub = self.create_publisher(
            Odometry,
            '/odom',
            10
        )

        self.tf_broadcaster = TransformBroadcaster(self)

        self.encoder_sub = self.create_subscription(
            EncoderTicks,
            '/encoder_ticks',
            self.encoder_callback,
            10
        )

        self.get_logger().info('encoder_odom_node started')
        self.get_logger().info(f'wheel_radius: {self.wheel_radius:.4f} m')
        self.get_logger().info(
            f'wheel_separation: {self.wheel_separation:.4f} m'
        )
        self.get_logger().info(
            f'ticks_per_revolution: {self.ticks_per_revolution}'
        )
        self.get_logger().info(
            f'distance_per_tick: {self.distance_per_tick:.8f} m/tick'
        )

    def encoder_callback(self, msg: EncoderTicks):
        now = self.get_clock().now()

        left_ticks = msg.left_ticks
        right_ticks = msg.right_ticks

        if not self.has_prev_ticks:
            self.prev_left_ticks = left_ticks
            self.prev_right_ticks = right_ticks
            self.prev_time = now
            self.has_prev_ticks = True

            self.get_logger().info('First encoder data received')
            return

        dt = (now - self.prev_time).nanoseconds / 1e9

        if dt &amp;lt;= 0.0:
            return

        delta_left_ticks = left_ticks - self.prev_left_ticks
        delta_right_ticks = right_ticks - self.prev_right_ticks

        self.prev_left_ticks = left_ticks
        self.prev_right_ticks = right_ticks
        self.prev_time = now

        d_left = float(delta_left_ticks) * self.distance_per_tick
        d_right = float(delta_right_ticks) * self.distance_per_tick

        d_center = (d_right + d_left) * 0.5
        d_theta = (d_right - d_left) / self.wheel_separation

        heading_mid = self.theta + d_theta * 0.5

        self.x += d_center * math.cos(heading_mid)
        self.y += d_center * math.sin(heading_mid)
        self.theta += d_theta

        self.theta = math.atan2(
            math.sin(self.theta),
            math.cos(self.theta)
        )

        linear_velocity = d_center / dt
        angular_velocity = d_theta / dt

        qx = 0.0
        qy = 0.0
        qz = math.sin(self.theta * 0.5)
        qw = math.cos(self.theta * 0.5)

        self.publish_odometry(
            now,
            qx,
            qy,
            qz,
            qw,
            linear_velocity,
            angular_velocity
        )

        if self.publish_tf:
            self.publish_transform(
                now,
                qx,
                qy,
                qz,
                qw
            )

        self.get_logger().info(
            f'x={self.x:.3f}, y={self.y:.3f}, '
            f'theta={self.theta:.3f} | '
            f'v={linear_velocity:.3f} m/s, '
            f'w={angular_velocity:.3f} rad/s'
        )

    def publish_odometry(
        self,
        now,
        qx,
        qy,
        qz,
        qw,
        linear_velocity,
        angular_velocity
    ):
        odom_msg = Odometry()

        odom_msg.header.stamp = now.to_msg()
        odom_msg.header.frame_id = self.odom_frame_id
        odom_msg.child_frame_id = self.base_frame_id

        odom_msg.pose.pose.position.x = self.x
        odom_msg.pose.pose.position.y = self.y
        odom_msg.pose.pose.position.z = 0.0

        odom_msg.pose.pose.orientation.x = qx
        odom_msg.pose.pose.orientation.y = qy
        odom_msg.pose.pose.orientation.z = qz
        odom_msg.pose.pose.orientation.w = qw

        odom_msg.twist.twist.linear.x = linear_velocity
        odom_msg.twist.twist.linear.y = 0.0
        odom_msg.twist.twist.angular.z = angular_velocity

        odom_msg.pose.covariance = [
            0.001, 0.0,   0.0,   0.0,   0.0,   0.0,
            0.0,   0.001, 0.0,   0.0,   0.0,   0.0,
            0.0,   0.0,   999.0, 0.0,   0.0,   0.0,
            0.0,   0.0,   0.0,   999.0, 0.0,   0.0,
            0.0,   0.0,   0.0,   0.0,   999.0, 0.0,
            0.0,   0.0,   0.0,   0.0,   0.0,   0.01
        ]

        odom_msg.twist.covariance = [
            0.001, 0.0,   0.0,   0.0,   0.0,   0.0,
            0.0,   0.001, 0.0,   0.0,   0.0,   0.0,
            0.0,   0.0,   999.0, 0.0,   0.0,   0.0,
            0.0,   0.0,   0.0,   999.0, 0.0,   0.0,
            0.0,   0.0,   0.0,   0.0,   999.0, 0.0,
            0.0,   0.0,   0.0,   0.0,   0.0,   0.01
        ]

        self.odom_pub.publish(odom_msg)

    def publish_transform(
        self,
        now,
        qx,
        qy,
        qz,
        qw
    ):
        tf_msg = TransformStamped()

        tf_msg.header.stamp = now.to_msg()
        tf_msg.header.frame_id = self.odom_frame_id
        tf_msg.child_frame_id = self.base_frame_id

        tf_msg.transform.translation.x = self.x
        tf_msg.transform.translation.y = self.y
        tf_msg.transform.translation.z = 0.0

        tf_msg.transform.rotation.x = qx
        tf_msg.transform.rotation.y = qy
        tf_msg.transform.rotation.z = qz
        tf_msg.transform.rotation.w = qw

        self.tf_broadcaster.sendTransform(tf_msg)


def main(args=None):
    rclpy.init(args=args)

    node = EncoderOdomNode()

    try:
        rclpy.spin(node)
    except KeyboardInterrupt:
        pass

    node.destroy_node()
    rclpy.shutdown()


if __name__ == '__main__':
    main()&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;7435&quot; data-start=&quot;7420&quot; data-section-id=&quot;4vz7rj&quot; data-ke-size=&quot;size18&quot;&gt;2) Python 패키지 설정&lt;/p&gt;
&lt;p data-end=&quot;7550&quot; data-start=&quot;7437&quot; data-ke-size=&quot;size16&quot;&gt;C++ 패키지에서는 CMakeLists.txt와 package.xml에 실행 파일과 의존성을 설정했지만, Python 패키지에서는 주로 setup.py, package.xml을 수정합니다.&lt;/p&gt;
&lt;p data-end=&quot;7550&quot; data-start=&quot;7437&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;7618&quot; data-start=&quot;7572&quot; data-ke-size=&quot;size16&quot;&gt;my_first_package/package.xml에 다음 의존성이 필요합니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;xml&quot;&gt;&lt;code&gt;&amp;lt;depend&amp;gt;rclpy&amp;lt;/depend&amp;gt;
&amp;lt;depend&amp;gt;nav_msgs&amp;lt;/depend&amp;gt;
&amp;lt;depend&amp;gt;geometry_msgs&amp;lt;/depend&amp;gt;
&amp;lt;depend&amp;gt;tf2_ros&amp;lt;/depend&amp;gt;
&amp;lt;depend&amp;gt;my_first_package_msgs&amp;lt;/depend&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;7813&quot; data-start=&quot;7776&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;7813&quot; data-start=&quot;7776&quot; data-ke-size=&quot;size16&quot;&gt;Python 패키지라면 export 부분에 아래 내용도 확인합니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;elm&quot;&gt;&lt;code&gt;&amp;lt;export&amp;gt;
  &amp;lt;build_type&amp;gt;ament_python&amp;lt;/build_type&amp;gt;
&amp;lt;/export&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;7905&quot; data-start=&quot;7891&quot; data-section-id=&quot;2wfsk&quot; data-ke-size=&quot;size18&quot;&gt;3) setup.py 설정&lt;/p&gt;
&lt;p data-end=&quot;7979&quot; data-start=&quot;7907&quot; data-ke-size=&quot;size16&quot;&gt;my_first_package/setup.py의 entry_points에 encoder_odom_node를 추가합니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;sml&quot;&gt;&lt;code&gt;entry_points={
    'console_scripts': [
        'fake_encoder_node = my_first_package.fake_encoder_node:main',
        'encoder_odom_node = my_first_package.encoder_odom_node:main',
    ],
},&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;8236&quot; data-start=&quot;8188&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;8236&quot; data-start=&quot;8188&quot; data-ke-size=&quot;size16&quot;&gt;launch 파일을 설치하려면 data_files에 launch 경로도 포함합니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;elm&quot;&gt;&lt;code&gt;import os
from glob import glob&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;8313&quot; data-start=&quot;8285&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;8313&quot; data-start=&quot;8285&quot; data-ke-size=&quot;size16&quot;&gt;그리고 data_files에 다음을 추가합니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;lua&quot;&gt;&lt;code&gt;(os.path.join('share', package_name, 'launch'), glob('launch/*.launch.py')),&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;8420&quot; data-start=&quot;8407&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;8420&quot; data-start=&quot;8407&quot; data-ke-size=&quot;size16&quot;&gt;예시는 다음과 같습니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;ceylon&quot;&gt;&lt;code&gt;data_files=[
    ('share/ament_index/resource_index/packages',
        ['resource/' + package_name]),
    ('share/' + package_name, ['package.xml']),
    (os.path.join('share', package_name, 'launch'), glob('launch/*.launch.py')),
],&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;8696&quot; data-start=&quot;8676&quot; data-section-id=&quot;1ntx5kx&quot; data-ke-size=&quot;size18&quot;&gt;4) Odometry 메시지 구조 이해&lt;/p&gt;
&lt;p data-end=&quot;8733&quot; data-start=&quot;8698&quot; data-ke-size=&quot;size16&quot;&gt;/odom 토픽은 일반적으로 다음 메시지 타입을 사용합니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;awk&quot;&gt;&lt;code&gt;nav_msgs/msg/Odometry&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;8786&quot; data-start=&quot;8770&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;8786&quot; data-start=&quot;8770&quot; data-ke-size=&quot;size16&quot;&gt;핵심 필드는 다음과 같습니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;stylus&quot;&gt;&lt;code&gt;header.frame_id       = &quot;odom&quot;
child_frame_id        = &quot;base_link&quot;

pose.pose.position.x
pose.pose.position.y
pose.pose.orientation

twist.twist.linear.x
twist.twist.angular.z

pose.covariance
twist.covariance&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;9027&quot; data-start=&quot;9011&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;9027&quot; data-start=&quot;9011&quot; data-ke-size=&quot;size16&quot;&gt;pose와 twist는&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;ada&quot;&gt;&lt;code&gt;pose  : header.frame_id 기준
twist : child_frame_id 기준&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;9118&quot; data-start=&quot;9095&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;9118&quot; data-start=&quot;9095&quot; data-ke-size=&quot;size16&quot;&gt;입니다.&amp;nbsp;즉, 다음처럼 해석합니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;ada&quot;&gt;&lt;code&gt;위치 pose  : odom 기준에서 base_link의 위치
속도 twist : base_link 기준에서 로봇의 속도&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;9225&quot; data-start=&quot;9206&quot; data-section-id=&quot;1o0k7ps&quot; data-ke-size=&quot;size18&quot;&gt;5) Odometry 계산 핵심 공식&lt;/p&gt;
&lt;p data-end=&quot;9247&quot; data-start=&quot;9227&quot; data-ke-size=&quot;size16&quot;&gt;엔코더 변화량은 다음처럼 계산합니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;ini&quot;&gt;&lt;code&gt;delta_left_ticks = left_ticks - self.prev_left_ticks
delta_right_ticks = right_ticks - self.prev_right_ticks&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;9388&quot; data-start=&quot;9373&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;9388&quot; data-start=&quot;9373&quot; data-ke-size=&quot;size16&quot;&gt;tick을 거리로 바꿉니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;ini&quot;&gt;&lt;code&gt;d_left = float(delta_left_ticks) * self.distance_per_tick
d_right = float(delta_right_ticks) * self.distance_per_tick&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;9546&quot; data-start=&quot;9523&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;9546&quot; data-start=&quot;9523&quot; data-ke-size=&quot;size16&quot;&gt;로봇 중심 이동거리와 회전량은 다음입니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;ini&quot;&gt;&lt;code&gt;d_center = (d_right + d_left) * 0.5
d_theta = (d_right - d_left) / self.wheel_separation&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;9693&quot; data-start=&quot;9652&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;9693&quot; data-start=&quot;9652&quot; data-ke-size=&quot;size16&quot;&gt;현재 자세가 x, y, theta일 때 위치 갱신은 다음입니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;gml&quot;&gt;&lt;code&gt;heading_mid = self.theta + d_theta * 0.5

self.x += d_center * math.cos(heading_mid)
self.y += d_center * math.sin(heading_mid)
self.theta += d_theta&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;9963&quot; data-start=&quot;9860&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;9963&quot; data-start=&quot;9860&quot; data-ke-size=&quot;size16&quot;&gt;heading_mid를 쓰는 이유는 로봇이 이동하면서 동시에 회전하기 때문입니다.&lt;/p&gt;
&lt;p data-end=&quot;9963&quot; data-start=&quot;9860&quot; data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;시작 방향이나 끝 방향 하나만 사용하는 것보다 중간 방향으로 적분하는 방식이 더 자연스럽습니다.&lt;/p&gt;
&lt;p data-end=&quot;10006&quot; data-start=&quot;9965&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;10006&quot; data-start=&quot;9965&quot; data-ke-size=&quot;size16&quot;&gt;각도 theta는 다음 코드로 -pi ~ pi 범위로 정규화합니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;lua&quot;&gt;&lt;code&gt;self.theta = math.atan2(
    math.sin(self.theta),
    math.cos(self.theta)
)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;&lt;br /&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;p data-end=&quot;1853&quot; data-start=&quot;1790&quot; data-ke-size=&quot;size16&quot;&gt;atan2(y, x)는&lt;br /&gt;점 (x, y)가 원점에서 볼 때 몇 도 방향인지를 알려주는 함수입니다.&lt;/p&gt;
&lt;p data-end=&quot;1859&quot; data-start=&quot;1855&quot; data-ke-size=&quot;size16&quot;&gt;여기서는&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;lisp&quot;&gt;&lt;code&gt;atan2(sin(theta), cos(theta))&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;1910&quot; data-start=&quot;1906&quot; data-ke-size=&quot;size16&quot;&gt;이므로,&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;1c&quot;&gt;&lt;code&gt;점 (cos(theta), sin(theta))를 보고
그 점이 가리키는 각도를 다시 구한다&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;1984&quot; data-start=&quot;1977&quot; data-ke-size=&quot;size16&quot;&gt;는 뜻입니다.&lt;/p&gt;
&lt;p data-end=&quot;1988&quot; data-start=&quot;1986&quot; data-ke-size=&quot;size16&quot;&gt;즉,&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-end=&quot;2071&quot; data-start=&quot;1990&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li data-end=&quot;2007&quot; data-start=&quot;1990&quot; data-section-id=&quot;z638cn&quot;&gt;원래 각도 theta를&lt;/li&gt;
&lt;li data-end=&quot;2050&quot; data-start=&quot;2008&quot; data-section-id=&quot;13u23tf&quot;&gt;원 위의 점 (cos(theta), sin(theta))로 바꾼 뒤&lt;/li&gt;
&lt;li data-end=&quot;2071&quot; data-start=&quot;2051&quot; data-section-id=&quot;j62pny&quot;&gt;그 점의 각도를 다시 구합니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-end=&quot;2121&quot; data-start=&quot;2073&quot; data-ke-size=&quot;size16&quot;&gt;그런데 atan2()는 결과를 항상 보통 -&amp;pi; ~ &amp;pi; 범위로 돌려줍니다.&lt;/p&gt;
&lt;p data-end=&quot;2142&quot; data-start=&quot;2123&quot; data-ke-size=&quot;size16&quot;&gt;그래서 자동으로 각도가 정리됩니다.&lt;/p&gt;
&lt;p data-end=&quot;2142&quot; data-start=&quot;2123&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;2422&quot; data-start=&quot;2402&quot; data-ke-size=&quot;size16&quot;&gt;점 P는 30도 방향에 있습니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;atan2(sin(30&amp;deg;), cos(30&amp;deg;)) = 30&amp;deg;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;2478&quot; data-start=&quot;2471&quot; data-ke-size=&quot;size16&quot;&gt;그대로입니다.&lt;/p&gt;
&lt;p data-end=&quot;2478&quot; data-start=&quot;2471&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;2544&quot; data-start=&quot;2510&quot; data-ke-size=&quot;size16&quot;&gt;390도는 한 바퀴(360도)를 돌고 다시 30도 방향입니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;390&amp;deg; = 360&amp;deg; + 30&amp;deg;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;2806&quot; data-start=&quot;2803&quot; data-ke-size=&quot;size16&quot;&gt;이때도&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;atan2(sin(390&amp;deg;), cos(390&amp;deg;)) = 30&amp;deg;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;2863&quot; data-start=&quot;2857&quot; data-ke-size=&quot;size16&quot;&gt;가 됩니다.&lt;/p&gt;
&lt;p data-end=&quot;2867&quot; data-start=&quot;2865&quot; data-ke-size=&quot;size16&quot;&gt;즉,&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;2918&quot; data-start=&quot;2869&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;2887&quot; data-start=&quot;2869&quot; data-section-id=&quot;8xu7xf&quot;&gt;390&amp;deg;라는 &amp;ldquo;긴 표현&amp;rdquo;을&lt;/li&gt;
&lt;li data-end=&quot;2918&quot; data-start=&quot;2888&quot; data-section-id=&quot;52w0s3&quot;&gt;30&amp;deg;라는 &amp;ldquo;정리된 표현&amp;rdquo;으로 바꾸는 것입니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-end=&quot;2992&quot; data-start=&quot;2950&quot; data-ke-size=&quot;size16&quot;&gt;190도는 &amp;pi;보다 큰 각도입니다.&lt;br /&gt;원 위에서는 왼쪽 아래쪽 방향입니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;3223&quot; data-start=&quot;3193&quot; data-ke-size=&quot;size16&quot;&gt;190도는 사실 방향상으로는 -170&amp;deg;와 같습니다.&lt;/p&gt;
&lt;p data-end=&quot;3230&quot; data-start=&quot;3225&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;3230&quot; data-start=&quot;3225&quot; data-ke-size=&quot;size16&quot;&gt;왜냐하면:&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;190&amp;deg; = -170&amp;deg; + 360&amp;deg;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;3276&quot; data-start=&quot;3265&quot; data-ke-size=&quot;size16&quot;&gt;즉 같은 방향입니다.&lt;/p&gt;
&lt;p data-end=&quot;3281&quot; data-start=&quot;3278&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;3281&quot; data-start=&quot;3278&quot; data-ke-size=&quot;size16&quot;&gt;그래서&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;atan2(sin(190&amp;deg;), cos(190&amp;deg;)) = -170&amp;deg;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;3340&quot; data-start=&quot;3334&quot; data-ke-size=&quot;size16&quot;&gt;가 됩니다.&lt;/p&gt;
&lt;p data-end=&quot;3388&quot; data-start=&quot;3342&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;3388&quot; data-start=&quot;3342&quot; data-ke-size=&quot;size16&quot;&gt;즉 atan2()는 &lt;b&gt;같은 방향을 더 짧고 표준적인 범위로 표현&lt;/b&gt;해 줍니다.&lt;/p&gt;
&lt;p data-end=&quot;3388&quot; data-start=&quot;3342&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;3559&quot; data-start=&quot;3492&quot; data-ke-size=&quot;size16&quot;&gt;로봇에서는 보통 -&amp;pi; ~ &amp;pi;를 많이 씁니다.&lt;br /&gt;이유는 &lt;b&gt;&amp;ldquo;좌회전/우회전&amp;rdquo; 해석이 직관적이기 때문&lt;/b&gt;입니다.&lt;/p&gt;
&lt;p data-end=&quot;3567&quot; data-start=&quot;3561&quot; data-ke-size=&quot;size16&quot;&gt;예를 들어,&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;3617&quot; data-start=&quot;3569&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;3593&quot; data-start=&quot;3569&quot; data-section-id=&quot;1lfq54v&quot;&gt;+0.2 rad &amp;rarr; 약간 반시계 방향&lt;/li&gt;
&lt;li data-end=&quot;3617&quot; data-start=&quot;3594&quot; data-section-id=&quot;16w02rl&quot;&gt;-0.2 rad &amp;rarr; 약간 시계 방향&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-end=&quot;3635&quot; data-start=&quot;3619&quot; data-ke-size=&quot;size16&quot;&gt;처럼 바로 해석하기 편합니다.&lt;/p&gt;
&lt;p data-end=&quot;3664&quot; data-start=&quot;3637&quot; data-ke-size=&quot;size16&quot;&gt;또한 각도 차이를 계산할 때도 더 자연스럽습니다.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;2142&quot; data-start=&quot;2123&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;10130&quot; data-start=&quot;10106&quot; data-section-id=&quot;1kua8a8&quot; data-ke-size=&quot;size18&quot;&gt;6) odom &amp;rarr; base_link TF 발행&lt;/p&gt;
&lt;p data-end=&quot;10217&quot; data-start=&quot;10132&quot; data-ke-size=&quot;size16&quot;&gt;/odom 토픽만 발행하면 위치와 속도 숫자는 확인할 수 있습니다.&lt;/p&gt;
&lt;p data-end=&quot;10217&quot; data-start=&quot;10132&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;10217&quot; data-start=&quot;10132&quot; data-ke-size=&quot;size16&quot;&gt;하지만 RViz2, Nav2, SLAM, 센서 시각화에서는 TF가 중요합니다.&lt;/p&gt;
&lt;p data-end=&quot;10248&quot; data-start=&quot;10219&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;10248&quot; data-start=&quot;10219&quot; data-ke-size=&quot;size16&quot;&gt;이번 Python 노드에서는 다음 TF를 발행합니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;nginx&quot;&gt;&lt;code&gt;odom &amp;rarr; base_link&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;10293&quot; data-start=&quot;10280&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;10293&quot; data-start=&quot;10280&quot; data-ke-size=&quot;size16&quot;&gt;의미는 다음과 같습니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;armasm&quot;&gt;&lt;code&gt;odom 좌표계 기준에서 base_link가 어디에 있는가?&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;10363&quot; data-start=&quot;10342&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;10363&quot; data-start=&quot;10342&quot; data-ke-size=&quot;size16&quot;&gt;TF 메시지는 다음 타입을 사용합니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;awk&quot;&gt;&lt;code&gt;geometry_msgs/msg/TransformStamped&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;10426&quot; data-start=&quot;10413&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;stylus&quot;&gt;&lt;code&gt;tf_msg.header.frame_id = self.odom_frame_id
tf_msg.child_frame_id = self.base_frame_id

tf_msg.transform.translation.x = self.x
tf_msg.transform.translation.y = self.y
tf_msg.transform.translation.z = 0.0&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;10689&quot; data-start=&quot;10648&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;10689&quot; data-start=&quot;10648&quot; data-ke-size=&quot;size16&quot;&gt;2D 로봇에서는 roll, pitch를 사용하지 않고 yaw만 사용합니다.&lt;/p&gt;
&lt;p data-end=&quot;10689&quot; data-start=&quot;10648&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;10724&quot; data-start=&quot;10691&quot; data-ke-size=&quot;size16&quot;&gt;yaw를 quaternion으로 바꾸는 기본식은 다음과 같습니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;ini&quot;&gt;&lt;code&gt;qx = 0.0
qy = 0.0
qz = math.sin(self.theta * 0.5)
qw = math.cos(self.theta * 0.5)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;7) covariance&lt;/div&gt;
&lt;div&gt;
&lt;p data-end=&quot;216&quot; data-start=&quot;175&quot; data-ke-size=&quot;size16&quot;&gt;covariance는 센서값이나 계산값의 불확실성을 의미합니다.&lt;/p&gt;
&lt;p data-end=&quot;226&quot; data-start=&quot;218&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;226&quot; data-start=&quot;218&quot; data-ke-size=&quot;size16&quot;&gt;값이 작을수록:&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;&quot;&gt;&lt;code&gt;이 값은 비교적 믿을 만하다&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;264&quot; data-start=&quot;257&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;264&quot; data-start=&quot;257&quot; data-ke-size=&quot;size16&quot;&gt;값이 클수록:&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;&quot;&gt;&lt;code&gt;이 값은 신뢰도가 낮다&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;301&quot; data-start=&quot;292&quot; data-ke-size=&quot;size16&quot;&gt;라는 의미입니다.&lt;/p&gt;
&lt;p data-end=&quot;301&quot; data-start=&quot;292&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;301&quot; data-start=&quot;292&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;301&quot; data-start=&quot;292&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;333&quot; data-start=&quot;308&quot; data-section-id=&quot;17qv89b&quot; data-ke-size=&quot;size18&quot;&gt;8) pose.covariance의 의미&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;ini&quot;&gt;&lt;code&gt;odom_msg.pose.covariance = [...]&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;419&quot; data-start=&quot;383&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;419&quot; data-start=&quot;383&quot; data-ke-size=&quot;size16&quot;&gt;이 부분은 로봇의 &lt;b&gt;위치와 자세&lt;/b&gt;에 대한 신뢰도를 설정합니다.&lt;/p&gt;
&lt;p data-end=&quot;458&quot; data-start=&quot;421&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;458&quot; data-start=&quot;421&quot; data-ke-size=&quot;size16&quot;&gt;pose는 다음 6개 값에 대한 covariance를 가집니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;gml&quot;&gt;&lt;code&gt;x, y, z, roll, pitch, yaw&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;512&quot; data-start=&quot;499&quot; data-ke-size=&quot;size16&quot;&gt;즉, 6x6 행렬입니다.&lt;/p&gt;
&lt;p data-end=&quot;512&quot; data-start=&quot;499&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;558&quot; data-start=&quot;514&quot; data-ke-size=&quot;size16&quot;&gt;Python 코드에서는 6x6 행렬을 한 줄짜리 리스트 36개 값으로 넣습니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;markdown&quot;&gt;&lt;code&gt;[0][0] = x 위치 신뢰도
[1][1] = y 위치 신뢰도
[2][2] = z 위치 신뢰도
[3][3] = roll 신뢰도
[4][4] = pitch 신뢰도
[5][5] = yaw 신뢰도&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;703&quot; data-start=&quot;681&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;703&quot; data-start=&quot;681&quot; data-ke-size=&quot;size16&quot;&gt;현재 코드에서는 대각선 값이 핵심입니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;ini&quot;&gt;&lt;code&gt;x     = 0.001
y     = 0.001
z     = 999.0
roll  = 999.0
pitch = 999.0
yaw   = 0.01&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;814&quot; data-start=&quot;801&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;814&quot; data-start=&quot;801&quot; data-ke-size=&quot;size16&quot;&gt;0.001은 비교적 신뢰, 999.0은 거의 사용하지 않음, 0.10은 어느 정도 신뢰를 의미합니다.&lt;/p&gt;
&lt;p data-end=&quot;1163&quot; data-start=&quot;1047&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;1163&quot; data-start=&quot;1047&quot; data-ke-size=&quot;size16&quot;&gt;차동구동 로봇은 보통 2D 평면에서 움직이므로 x, y, yaw가 중요합니다.&lt;/p&gt;
&lt;p data-end=&quot;1163&quot; data-start=&quot;1047&quot; data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;반대로 z, roll, pitch는 거의 사용하지 않기 때문에 큰 값을 넣어 신뢰도가 낮다고 표시합니다.&lt;/p&gt;
&lt;p data-end=&quot;1163&quot; data-start=&quot;1047&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;1163&quot; data-start=&quot;1047&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;1163&quot; data-start=&quot;1047&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;1196&quot; data-start=&quot;1170&quot; data-section-id=&quot;18500dm&quot; data-ke-size=&quot;size18&quot;&gt;9) twist.covariance의 의미&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;ini&quot;&gt;&lt;code&gt;odom_msg.twist.covariance = [...]&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;1279&quot; data-start=&quot;1247&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;1279&quot; data-start=&quot;1247&quot; data-ke-size=&quot;size16&quot;&gt;이 부분은 로봇의 &lt;b&gt;속도&lt;/b&gt;에 대한 신뢰도를 설정합니다.&lt;/p&gt;
&lt;p data-end=&quot;1316&quot; data-start=&quot;1281&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;1316&quot; data-start=&quot;1281&quot; data-ke-size=&quot;size16&quot;&gt;twist도 6개 값에 대한 covariance를 가집니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;css&quot;&gt;&lt;code&gt;linear.x, linear.y, linear.z, angular.x, angular.y, angular.z&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;1603&quot; data-start=&quot;1587&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;1603&quot; data-start=&quot;1587&quot; data-ke-size=&quot;size16&quot;&gt;현재 설정은 2D 이동 로봇에서 사용하는 전진 속도와 yaw 회전 속도는 비교적 신뢰하고, 3D 방향 속도나 roll/pitch 관련 속도는 신뢰하지 않는다는 뜻입니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;ini&quot;&gt;&lt;code&gt;linear.x   = 0.001
linear.y   = 0.001
linear.z   = 999.0
angular.x  = 999.0
angular.y  = 999.0
angular.z  = 0.01&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;2145&quot; data-start=&quot;2071&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h4 data-end=&quot;10851&quot; data-start=&quot;10828&quot; data-section-id=&quot;8redu6&quot; data-ke-size=&quot;size20&quot;&gt;10. Python용 Launch 파일 만들기&lt;/h4&gt;
&lt;p data-end=&quot;10888&quot; data-start=&quot;10853&quot; data-ke-size=&quot;size16&quot;&gt;두 노드를 한 번에 실행하기 위해 launch 파일을 만듭니다.&lt;/p&gt;
&lt;p data-end=&quot;10896&quot; data-start=&quot;10890&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;10896&quot; data-start=&quot;10890&quot; data-ke-size=&quot;size16&quot;&gt;파일 경로:&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;applescript&quot;&gt;&lt;code&gt;~/ros2_study/src/my_first_package/launch/odom_demo.launch.py&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;10975&quot; data-start=&quot;10972&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;10975&quot; data-start=&quot;10972&quot; data-ke-size=&quot;size16&quot;&gt;내용:&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;from launch import LaunchDescription
from launch_ros.actions import Node


def generate_launch_description():
    fake_encoder_node = Node(
        package='my_first_package',
        executable='fake_encoder_node',
        name='fake_encoder_node',
        output='screen',
        parameters=[
            {
                'left_tick_step': 5,
                'right_tick_step': 5,
                'period': 0.05
            }
        ]
    )

    encoder_odom_node = Node(
        package='my_first_package',
        executable='encoder_odom_node',
        name='encoder_odom_node',
        output='screen',
        parameters=[
            {
                'wheel_radius': 0.033,
                'wheel_separation': 0.30,
                'ticks_per_revolution': 2048,
                'odom_frame_id': 'odom',
                'base_frame_id': 'base_link',
                'publish_tf': True
            }
        ]
    )

    return LaunchDescription([
        fake_encoder_node,
        encoder_odom_node
    ])&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;12139&quot; data-start=&quot;12010&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h4 data-end=&quot;12197&quot; data-start=&quot;12188&quot; data-section-id=&quot;1of269g&quot; data-ke-size=&quot;size20&quot;&gt;11) 빌드 및 실행&lt;/h4&gt;
&lt;p data-end=&quot;12226&quot; data-start=&quot;12199&quot; data-ke-size=&quot;size16&quot;&gt;패키지 루트가 포함된 워크스페이스에서 빌드합니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;jboss-cli&quot;&gt;&lt;code&gt;cd ~/ros2_study
colcon build --packages-select my_first_package my_first_package_msgs
source install/setup.bash&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;12370&quot; data-start=&quot;12353&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;12370&quot; data-start=&quot;12353&quot; data-ke-size=&quot;size16&quot;&gt;launch 파일로 실행합니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;applescript&quot;&gt;&lt;code&gt;ros2 launch my_first_package odom_demo.launch.py&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;12447&quot; data-start=&quot;12434&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;12447&quot; data-start=&quot;12434&quot; data-ke-size=&quot;size16&quot;&gt;개별 실행도 가능합니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;dockerfile&quot;&gt;&lt;code&gt;ros2 run my_first_package fake_encoder_node&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;dockerfile&quot;&gt;&lt;code&gt;ros2 run my_first_package encoder_odom_node&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;12569&quot; data-start=&quot;12563&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;12569&quot; data-start=&quot;12563&quot; data-ke-size=&quot;size16&quot;&gt;토픽 확인:&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;jboss-cli&quot;&gt;&lt;code&gt;ros2 topic echo /encoder_ticks&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;jboss-cli&quot;&gt;&lt;code&gt;ros2 topic echo /odom&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;12656&quot; data-start=&quot;12650&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;12656&quot; data-start=&quot;12650&quot; data-ke-size=&quot;size16&quot;&gt;TF 확인:&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;dockerfile&quot;&gt;&lt;code&gt;ros2 run tf2_ros tf2_echo odom base_link&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-end=&quot;24194&quot; data-start=&quot;24173&quot; data-section-id=&quot;16dbq2j&quot; data-ke-size=&quot;size20&quot;&gt;12. RViz2에서 확인하는 방법&lt;/h4&gt;
&lt;p data-end=&quot;24215&quot; data-start=&quot;24196&quot; data-ke-size=&quot;size16&quot;&gt;RViz2 설정은 다음처럼 합니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;dockerfile&quot;&gt;&lt;code&gt;Fixed Frame : odom

Add &amp;rarr; TF
Add &amp;rarr; Odometry
Odometry Topic : /odom&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;24338&quot; data-start=&quot;24297&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;24338&quot; data-start=&quot;24297&quot; data-ke-size=&quot;size16&quot;&gt;정상이라면 base_link가 odom 기준으로 앞으로 이동합니다.&lt;/p&gt;
&lt;p data-end=&quot;24338&quot; data-start=&quot;24297&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;24346&quot; data-start=&quot;24340&quot; data-ke-size=&quot;size16&quot;&gt;직진 조건:&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;ini&quot;&gt;&lt;code&gt;left_tick_step  = 5
right_tick_step = 5&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;24407&quot; data-start=&quot;24401&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;24407&quot; data-start=&quot;24401&quot; data-ke-size=&quot;size16&quot;&gt;예상 결과:&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;properties&quot;&gt;&lt;code&gt;x 증가
y 거의 변화 없음
theta 거의 변화 없음&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;24462&quot; data-start=&quot;24453&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;24462&quot; data-start=&quot;24453&quot; data-ke-size=&quot;size16&quot;&gt;왼쪽 회전 조건:&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;ini&quot;&gt;&lt;code&gt;left_tick_step  = 3
right_tick_step = 7&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;24523&quot; data-start=&quot;24517&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;24523&quot; data-start=&quot;24517&quot; data-ke-size=&quot;size16&quot;&gt;예상 결과:&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;properties&quot;&gt;&lt;code&gt;오른쪽 바퀴 이동량 &amp;gt; 왼쪽 바퀴 이동량
d_theta &amp;gt; 0
theta 증가
로봇은 반시계 방향으로 회전&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;24608&quot; data-start=&quot;24598&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;24608&quot; data-start=&quot;24598&quot; data-ke-size=&quot;size16&quot;&gt;제자리 회전 조건:&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;ini&quot;&gt;&lt;code&gt;left_tick_step  = -5
right_tick_step = 5&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;24670&quot; data-start=&quot;24664&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;24670&quot; data-start=&quot;24664&quot; data-ke-size=&quot;size16&quot;&gt;예상 결과:&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;properties&quot;&gt;&lt;code&gt;d_center &amp;asymp; 0
d_theta 증가
로봇이 제자리에서 회전&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-end=&quot;25119&quot; data-start=&quot;25102&quot; data-section-id=&quot;bz7ooz&quot; data-ke-size=&quot;size20&quot;&gt;13. 실제 로봇 보정 절차&lt;/h4&gt;
&lt;p data-end=&quot;25145&quot; data-start=&quot;25121&quot; data-section-id=&quot;f57bec&quot; data-ke-size=&quot;size18&quot;&gt;1) Wheel Radius 보정&lt;/p&gt;
&lt;p data-end=&quot;25203&quot; data-start=&quot;25147&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;25203&quot; data-start=&quot;25147&quot; data-ke-size=&quot;size16&quot;&gt;실제 로봇을 1 m 직진시킵니다.&lt;br /&gt;그리고 실제 이동거리와 /odom의 x 이동량을 비교합니다.&lt;/p&gt;
&lt;p data-end=&quot;25207&quot; data-start=&quot;25205&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;25207&quot; data-start=&quot;25205&quot; data-ke-size=&quot;size16&quot;&gt;예:&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;ada&quot;&gt;&lt;code&gt;명령 거리 : 1.00 m
odom 거리 : 1.00 m
실제 거리 : 0.92 m&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;25325&quot; data-start=&quot;25269&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;25325&quot; data-start=&quot;25269&quot; data-ke-size=&quot;size16&quot;&gt;실제 로봇이 odom보다 덜 갔습니다.&lt;/p&gt;
&lt;p data-end=&quot;25325&quot; data-start=&quot;25269&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;25325&quot; data-start=&quot;25269&quot; data-ke-size=&quot;size16&quot;&gt;이 경우 설정된 wheel_radius가 너무 큽니다.&lt;/p&gt;
&lt;p data-end=&quot;25338&quot; data-start=&quot;25327&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;25338&quot; data-start=&quot;25327&quot; data-ke-size=&quot;size16&quot;&gt;보정식은 다음입니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;haxe&quot;&gt;&lt;code&gt;new_wheel_radius = old_wheel_radius &amp;times; 실제 이동 거리 / odom 이동 거리&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;25415&quot; data-start=&quot;25413&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;25415&quot; data-start=&quot;25413&quot; data-ke-size=&quot;size16&quot;&gt;예:&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;new_wheel_radius = 0.033 &amp;times; 0.92 / 1.00
                 = 0.03036 m&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;25561&quot; data-start=&quot;25498&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;25561&quot; data-start=&quot;25498&quot; data-ke-size=&quot;size16&quot;&gt;반대로 odom은 0.92m라고 나오는데 실제로는 1.0m를 갔다면, wheel radius를 키워야 합니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;new_wheel_radius = 0.033 &amp;times; 1.00 / 0.92
                 = 0.03587 m&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;25677&quot; data-start=&quot;25649&quot; data-section-id=&quot;jtujr&quot; data-ke-size=&quot;size18&quot;&gt;2) Wheel Separation 보정&lt;/p&gt;
&lt;p data-end=&quot;25701&quot; data-start=&quot;25679&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;25701&quot; data-start=&quot;25679&quot; data-ke-size=&quot;size16&quot;&gt;로봇을 제자리에서 360도 회전시킵니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;360도 = 2&amp;pi; rad&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;25732&quot; data-start=&quot;25730&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;25732&quot; data-start=&quot;25730&quot; data-ke-size=&quot;size16&quot;&gt;예:&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;odom은 360도 회전했다고 표시
실제 로봇은 330도만 회전&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;25858&quot; data-start=&quot;25783&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;25858&quot; data-start=&quot;25783&quot; data-ke-size=&quot;size16&quot;&gt;이 경우 실제 회전이 부족합니다.&lt;/p&gt;
&lt;p data-end=&quot;25858&quot; data-start=&quot;25783&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;25858&quot; data-start=&quot;25783&quot; data-ke-size=&quot;size16&quot;&gt;wheel_separation 설정, 마찰, 미끄러짐, 캐스터 휠 간섭 등을 의심해야 합니다.&lt;/p&gt;
&lt;p data-end=&quot;25870&quot; data-start=&quot;25860&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;25870&quot; data-start=&quot;25860&quot; data-ke-size=&quot;size16&quot;&gt;공식은 다음입니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;ini&quot;&gt;&lt;code&gt;d_theta = (d_right - d_left) / wheel_separation&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;26011&quot; data-start=&quot;25933&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;26011&quot; data-start=&quot;25933&quot; data-ke-size=&quot;size16&quot;&gt;wheel_separation이 작으면 회전각이 크게 계산됩니다.&lt;br /&gt;wheel_separation이 크면 회전각이 작게 계산됩니다.&lt;/p&gt;
&lt;p data-end=&quot;26054&quot; data-start=&quot;26013&quot; data-ke-size=&quot;size16&quot;&gt;그래서 회전 보정은 실제 회전 테스트를 반복하면서 맞추는 것이 정석입니다.&lt;/p&gt;
&lt;p data-end=&quot;26054&quot; data-start=&quot;26013&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;26054&quot; data-start=&quot;26013&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;26054&quot; data-start=&quot;26013&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;26054&quot; data-start=&quot;26013&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-end=&quot;26087&quot; data-start=&quot;26061&quot; data-section-id=&quot;9dw8hu&quot; data-ke-size=&quot;size20&quot;&gt;14. Odometry Drift 확인 실습&lt;/h4&gt;
&lt;p data-end=&quot;26139&quot; data-start=&quot;26089&quot; data-ke-size=&quot;size16&quot;&gt;Odometry drift는 시간이 지나면서 실제 위치와 추정 위치가 달라지는 현상입니다.&lt;/p&gt;
&lt;p data-end=&quot;26173&quot; data-start=&quot;26141&quot; data-section-id=&quot;1u3kq08&quot; data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;26173&quot; data-start=&quot;26141&quot; data-section-id=&quot;1u3kq08&quot; data-ke-size=&quot;size18&quot;&gt;1) 실습 1: wheel_radius 일부러 틀리게 넣기&lt;/p&gt;
&lt;p data-end=&quot;26215&quot; data-start=&quot;26175&quot; data-ke-size=&quot;size16&quot;&gt;실제 바퀴 반지름이 0.033m인데 코드에는 0.040m로 넣습니다.&lt;/p&gt;
&lt;p data-end=&quot;26220&quot; data-start=&quot;26217&quot; data-ke-size=&quot;size16&quot;&gt;결과:&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;ada&quot;&gt;&lt;code&gt;실제 이동거리       : 1.0 m
오도메트리 추정거리 : 약 1.2 m&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;26304&quot; data-start=&quot;26278&quot; data-ke-size=&quot;size16&quot;&gt;로봇이 실제보다 더 많이 이동했다고 추정합니다.&lt;/p&gt;
&lt;p data-end=&quot;26304&quot; data-start=&quot;26278&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;26304&quot; data-start=&quot;26278&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;26304&quot; data-start=&quot;26278&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;26347&quot; data-start=&quot;26311&quot; data-section-id=&quot;1f64ge3&quot; data-ke-size=&quot;size18&quot;&gt;2) 실습 2: wheel_separation 일부러 틀리게 넣기&lt;/p&gt;
&lt;p data-end=&quot;26382&quot; data-start=&quot;26349&quot; data-ke-size=&quot;size16&quot;&gt;wheel_separation을 실제보다 작게 넣습니다.&lt;/p&gt;
&lt;p data-end=&quot;26394&quot; data-start=&quot;26384&quot; data-ke-size=&quot;size16&quot;&gt;공식은 다음입니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;ini&quot;&gt;&lt;code&gt;d_theta = (d_right - d_left) / wheel_separation&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;26482&quot; data-start=&quot;26457&quot; data-ke-size=&quot;size16&quot;&gt;분모가 작아지면 d_theta가 커집니다.&lt;/p&gt;
&lt;p data-end=&quot;26482&quot; data-start=&quot;26457&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;26487&quot; data-start=&quot;26484&quot; data-ke-size=&quot;size16&quot;&gt;결과:&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;&quot;&gt;&lt;code&gt;실제보다 많이 회전했다고 추정
RViz2에서 방향이 과하게 돌아감&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;26572&quot; data-start=&quot;26544&quot; data-section-id=&quot;58yjtt&quot; data-ke-size=&quot;size18&quot;&gt;3) 실습 3: 한쪽 바퀴 tick만 다르게 만들기&lt;/p&gt;
&lt;p data-end=&quot;26604&quot; data-start=&quot;26574&quot; data-ke-size=&quot;size16&quot;&gt;가상 엔코더에서 오른쪽 tick만 조금 크게 만듭니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;ini&quot;&gt;&lt;code&gt;left_tick_step  = 5
right_tick_step = 6&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;26700&quot; data-start=&quot;26659&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;26700&quot; data-start=&quot;26659&quot; data-ke-size=&quot;size16&quot;&gt;로봇은 직진한다고 생각해도, odometry 계산상으로는 계속 회전합니다.&lt;/p&gt;
&lt;p data-end=&quot;26725&quot; data-start=&quot;26702&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;26725&quot; data-start=&quot;26702&quot; data-ke-size=&quot;size16&quot;&gt;실제 로봇에서도 이런 일이 많이 생깁니다. 따라서 로봇의 직진성이 훼손되는 이유입니다.&lt;/p&gt;
&lt;p data-end=&quot;26740&quot; data-start=&quot;26727&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;26740&quot; data-start=&quot;26727&quot; data-ke-size=&quot;size16&quot;&gt;원인은 다음과 같습니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;&quot;&gt;&lt;code&gt;좌우 바퀴 지름 차이
타이어 마모
모터 출력 차이
바닥 마찰 차이
엔코더 해상도 차이
기어 백래시
캐스터 휠 간섭&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-end=&quot;27570&quot; data-start=&quot;27539&quot; data-section-id=&quot;qfw0iz&quot; data-ke-size=&quot;size20&quot;&gt;15. Covariance를 잘못 넣으면 생기는 문제&lt;/h4&gt;
&lt;p data-end=&quot;27586&quot; data-start=&quot;27572&quot; data-section-id=&quot;13refjy&quot; data-ke-size=&quot;size18&quot;&gt;1) 너무 작게 넣는 경우&lt;/p&gt;
&lt;p data-end=&quot;27590&quot; data-start=&quot;27588&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;27590&quot; data-start=&quot;27588&quot; data-ke-size=&quot;size16&quot;&gt;예:&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;x covariance   = 0.000001
y covariance   = 0.000001
yaw covariance = 0.000001&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;27711&quot; data-start=&quot;27683&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;27711&quot; data-start=&quot;27683&quot; data-ke-size=&quot;size16&quot;&gt;이렇게 하면 필터가 엔코더 오도메트리를 과신합니다.&lt;/p&gt;
&lt;p data-end=&quot;27716&quot; data-start=&quot;27713&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;27716&quot; data-start=&quot;27713&quot; data-ke-size=&quot;size16&quot;&gt;문제:&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;properties&quot;&gt;&lt;code&gt;IMU 보정값을 무시
LiDAR 보정값을 무시
SLAM 또는 localization이 불안정
위치 추정이 천천히 망가짐&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;27812&quot; data-start=&quot;27798&quot; data-section-id=&quot;z6gcbn&quot; data-ke-size=&quot;size18&quot;&gt;2) 너무 크게 넣는 경우&lt;/p&gt;
&lt;p data-end=&quot;27816&quot; data-start=&quot;27814&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;27816&quot; data-start=&quot;27814&quot; data-ke-size=&quot;size16&quot;&gt;예:&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;x covariance   = 100
y covariance   = 100
yaw covariance = 100&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;27927&quot; data-start=&quot;27894&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;27927&quot; data-start=&quot;27894&quot; data-ke-size=&quot;size16&quot;&gt;이렇게 하면 필터가 엔코더 오도메트리를 거의 믿지 않습니다.&lt;/p&gt;
&lt;p data-end=&quot;27927&quot; data-start=&quot;27894&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;27932&quot; data-start=&quot;27929&quot; data-ke-size=&quot;size16&quot;&gt;문제:&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;gcode&quot;&gt;&lt;code&gt;속도 추정이 흔들림
센서 융합 결과가 느림
Nav2 경로 추종이 부드럽지 않음&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;28065&quot; data-start=&quot;27991&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;28065&quot; data-start=&quot;27991&quot; data-ke-size=&quot;size16&quot;&gt;실전에서는 샘플 데이터를 보고 조정해야 합니다.&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p data-end=&quot;28065&quot; data-start=&quot;27991&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;28065&quot; data-start=&quot;27991&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;28065&quot; data-start=&quot;27991&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-end=&quot;28095&quot; data-start=&quot;28072&quot; data-section-id=&quot;reuwxx&quot; data-ke-size=&quot;size20&quot;&gt;16. 자주 발생하는 문제와 해결 방향&lt;/h4&gt;
&lt;p data-end=&quot;28132&quot; data-start=&quot;28097&quot; data-section-id=&quot;mc7t8w&quot; data-ke-size=&quot;size18&quot;&gt;&lt;span&gt;1) 문제 1. /cmd_vel을 줬는데 로봇이 반대로 돈다&lt;/span&gt;&lt;/p&gt;
&lt;p data-end=&quot;28141&quot; data-start=&quot;28134&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;28141&quot; data-start=&quot;28134&quot; data-ke-size=&quot;size16&quot;&gt;가능한 원인:&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;stylus&quot;&gt;&lt;code&gt;왼쪽/오른쪽 모터 배선 반대
엔코더 방향 반대
좌우 바퀴 이름 반대
angular.z 부호 처리 반대&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;28219&quot; data-start=&quot;28213&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;28219&quot; data-start=&quot;28213&quot; data-ke-size=&quot;size16&quot;&gt;정상 기준:&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;ini&quot;&gt;&lt;code&gt;linear.x = 0.0
angular.z = 0.5&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;28302&quot; data-start=&quot;28265&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;28302&quot; data-start=&quot;28265&quot; data-ke-size=&quot;size16&quot;&gt;이 명령을 주면 ROS 표준 좌표계에서는 제자리 좌회전해야 합니다.&lt;/p&gt;
&lt;p data-end=&quot;28302&quot; data-start=&quot;28265&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;28302&quot; data-start=&quot;28265&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;28302&quot; data-start=&quot;28265&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;28339&quot; data-start=&quot;28309&quot; data-section-id=&quot;1crj1e0&quot; data-ke-size=&quot;size18&quot;&gt;&lt;span&gt;2) 문제 2. 직진하면 /odom이 많이 틀어진다&lt;/span&gt;&lt;/p&gt;
&lt;p data-end=&quot;28348&quot; data-start=&quot;28341&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;28348&quot; data-start=&quot;28341&quot; data-ke-size=&quot;size16&quot;&gt;가능한 원인:&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;&quot;&gt;&lt;code&gt;좌우 바퀴 반지름 차이
좌우 모터 속도 차이
엔코더 해상도 설정 오류
바퀴 미끄러짐
무게중심 불균형&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;28425&quot; data-start=&quot;28419&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;28425&quot; data-start=&quot;28419&quot; data-ke-size=&quot;size16&quot;&gt;해결 순서:&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;1. 좌우 tick 증가량 확인
2. 바퀴 지름 실측
3. ticks_per_revolution 확인
4. PID 속도 제어 적용
5. wheel_radius 보정&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;28562&quot; data-start=&quot;28537&quot; data-section-id=&quot;1jzy77v&quot; data-ke-size=&quot;size18&quot;&gt;3) 문제 3. 직진은 맞는데 회전이 틀어진다&lt;/p&gt;
&lt;p data-end=&quot;28571&quot; data-start=&quot;28564&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;28571&quot; data-start=&quot;28564&quot; data-ke-size=&quot;size16&quot;&gt;가능한 원인:&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;nginx&quot;&gt;&lt;code&gt;wheel_separation 설정 오류
바닥 마찰 차이
캐스터 휠 간섭
회전 중 미끄러짐&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;28643&quot; data-start=&quot;28637&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;28643&quot; data-start=&quot;28637&quot; data-ke-size=&quot;size16&quot;&gt;해결 순서:&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;1. 실제 좌우 바퀴 중심 간 거리 측정
2. 제자리 360도 회전 테스트
3. wheel_separation 보정
4. 저속 회전으로 테스트&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;28786&quot; data-start=&quot;28743&quot; data-section-id=&quot;1xbr700&quot; data-ke-size=&quot;size18&quot;&gt;4) 문제 4. encoder tick은 들어오는데 odometry가 이상하다&lt;/p&gt;
&lt;p data-end=&quot;28794&quot; data-start=&quot;28788&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;28794&quot; data-start=&quot;28788&quot; data-ke-size=&quot;size16&quot;&gt;확인할 것:&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;livecodeserver&quot;&gt;&lt;code&gt;tick 단위가 모터축 기준인지 바퀴축 기준인지
감속비가 반영되어 있는지
quadrature encoder의 x1, x2, x4 카운팅 방식
left/right 방향 부호
누적 tick overflow
시간 dt 계산&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;28976&quot; data-start=&quot;28931&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;28976&quot; data-start=&quot;28931&quot; data-ke-size=&quot;size16&quot;&gt;특히 감속기가 있는 DC 모터에서는 엔코더가 모터축에 붙어 있는 경우가 많습니다.&lt;/p&gt;
&lt;p data-end=&quot;29007&quot; data-start=&quot;28978&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;29007&quot; data-start=&quot;28978&quot; data-ke-size=&quot;size16&quot;&gt;이때 바퀴축 1회전당 tick은 다음처럼 계산합니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;makefile&quot;&gt;&lt;code&gt;wheel_ticks_per_revolution =
    motor_encoder_ticks_per_revolution
    &amp;times; gear_ratio
    &amp;times; quadrature_multiplier&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;29137&quot; data-start=&quot;29135&quot; data-ke-size=&quot;size16&quot;&gt;예:&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;makefile&quot;&gt;&lt;code&gt;motor_encoder_ticks_per_revolution = 11
gear_ratio = 90
quadrature_multiplier = 4

wheel_ticks_per_revolution = 11 &amp;times; 90 &amp;times; 4
                           = 3960&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;--&amp;gt; 4채배&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;29347&quot; data-start=&quot;29315&quot; data-section-id=&quot;19zr44q&quot; data-ke-size=&quot;size18&quot;&gt;&lt;span&gt;5) 문제 5. /odom은 나오는데 TF가 안 나온다&lt;/span&gt;&lt;/p&gt;
&lt;p data-end=&quot;29355&quot; data-start=&quot;29349&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;29355&quot; data-start=&quot;29349&quot; data-ke-size=&quot;size16&quot;&gt;확인할 것:&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;erlang&quot;&gt;&lt;code&gt;/tf 토픽이 발행되는가?
publish_tf 파라미터가 true인가?
sendTransform()이 실행되는가?
header.frame_id가 odom인가?
child_frame_id가 base_link인가?&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;29633&quot; data-start=&quot;29488&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;29633&quot; data-start=&quot;29488&quot; data-ke-size=&quot;size16&quot;&gt;같은 odom &amp;rarr; base_link TF를 여러 노드가 동시에 발행하면 안 됩니다.&lt;/p&gt;
&lt;p data-end=&quot;29633&quot; data-start=&quot;29488&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;29633&quot; data-start=&quot;29488&quot; data-ke-size=&quot;size16&quot;&gt;예를 들어 robot_localization이 TF를 발행한다면 encoder odometry 노드의 publish_tf는 false로 두는 것이 안전합니다.&lt;/p&gt;
&lt;p data-end=&quot;29633&quot; data-start=&quot;29488&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;29633&quot; data-start=&quot;29488&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;29633&quot; data-start=&quot;29488&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;29633&quot; data-start=&quot;29488&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-end=&quot;29667&quot; data-start=&quot;29640&quot; data-section-id=&quot;11c3fbj&quot; data-ke-size=&quot;size20&quot;&gt;17. 실전에서 권장하는 Odometry 구조&lt;/h4&gt;
&lt;p data-end=&quot;29696&quot; data-start=&quot;29669&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;29696&quot; data-start=&quot;29669&quot; data-ke-size=&quot;size16&quot;&gt;실제 모바일 로봇에서는 다음 구조가 안정적입니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;awk&quot;&gt;&lt;code&gt;Wheel Encoder
      &amp;darr;
/wheel/odom
      &amp;darr;
robot_localization + IMU
      &amp;darr;
/odometry/filtered
      &amp;darr;
Nav2 / SLAM / RViz2&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;29846&quot; data-start=&quot;29833&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;29846&quot; data-start=&quot;29833&quot; data-ke-size=&quot;size16&quot;&gt;TF 구조는 다음입니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;nginx&quot;&gt;&lt;code&gt;odom
 └── base_link&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;29894&quot; data-start=&quot;29881&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;29894&quot; data-start=&quot;29881&quot; data-ke-size=&quot;size16&quot;&gt;주의할 점은 다음입니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;crmsh&quot;&gt;&lt;code&gt;/odom을 발행하는 노드가 TF도 발행할지 결정해야 합니다.
robot_localization이 odom &amp;rarr; base_link를 발행한다면 encoder odom node는 TF를 꺼야 합니다.
같은 TF를 여러 노드가 동시에 발행하면 안 됩니다.&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h4 data-end=&quot;30880&quot; data-start=&quot;30866&quot; data-section-id=&quot;dqow6q&quot; data-ke-size=&quot;size20&quot;&gt;18. 요약&lt;/h4&gt;
&lt;p data-end=&quot;30897&quot; data-start=&quot;30882&quot; data-section-id=&quot;1njsf0u&quot; data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;30897&quot; data-start=&quot;30882&quot; data-section-id=&quot;1njsf0u&quot; data-ke-size=&quot;size18&quot;&gt;Wheel Radius&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;livecodeserver&quot;&gt;&lt;code&gt;바퀴 반지름
tick을 거리로 바꿀 때 핵심
직진 거리 정확도에 큰 영향&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;30972&quot; data-start=&quot;30953&quot; data-section-id=&quot;44573y&quot; data-ke-size=&quot;size18&quot;&gt;Wheel Separation&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;&quot;&gt;&lt;code&gt;좌우 구동 바퀴 중심 사이 거리
좌우 바퀴 이동거리 차이를 회전각으로 바꿀 때 핵심
회전 정확도에 큰 영향&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;31060&quot; data-start=&quot;31047&quot; data-section-id=&quot;1lofnts&quot; data-ke-size=&quot;size18&quot;&gt;&lt;span&gt;/cmd_vel&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;css&quot;&gt;&lt;code&gt;로봇 중심 속도 명령
linear.x는 전진 속도 [m/s]
angular.z는 회전 속도 [rad/s]&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;31151&quot; data-start=&quot;31134&quot; data-section-id=&quot;13mcptt&quot; data-ke-size=&quot;size18&quot;&gt;Wheel Velocity&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;ini&quot;&gt;&lt;code&gt;v_l = v - &amp;omega;L / 2
v_r = v + &amp;omega;L / 2&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;31215&quot; data-start=&quot;31200&quot; data-section-id=&quot;xdbfd0&quot; data-ke-size=&quot;size18&quot;&gt;Encoder Tick&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;makefile&quot;&gt;&lt;code&gt;바퀴 또는 모터 회전량
거리 변환 필요
distance = delta_ticks &amp;times; 2&amp;pi;r / ticks_per_revolution&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;31315&quot; data-start=&quot;31304&quot; data-section-id=&quot;1wv1n5i&quot; data-ke-size=&quot;size18&quot;&gt;Odometry&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;ini&quot;&gt;&lt;code&gt;d_center = (d_right + d_left) / 2
d_theta  = (d_right - d_left) / wheel_separation&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;31418&quot; data-start=&quot;31413&quot; data-section-id=&quot;1mnyt3&quot; data-ke-size=&quot;size18&quot;&gt;TF&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;nginx&quot;&gt;&lt;code&gt;odom &amp;rarr; base_link&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;31458&quot; data-start=&quot;31450&quot; data-section-id=&quot;xafmdk&quot; data-ke-size=&quot;size18&quot;&gt;Drift&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;&quot;&gt;&lt;code&gt;엔코더 기반 위치 추정 오차가 누적되는 현상
완전히 없앨 수는 없고 보정과 센서 융합으로 줄인다&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;31540&quot; data-start=&quot;31527&quot; data-section-id=&quot;1bzm7l8&quot; data-ke-size=&quot;size18&quot;&gt;Covariance&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;&quot;&gt;&lt;code&gt;센서 추정값의 불확실성
작으면 신뢰
크면 불신&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;</description>
      <category>강좌/ROS2</category>
      <category>odometry 프로그램</category>
      <author>MakingRobotWizard</author>
      <guid isPermaLink="true">https://makingrobot.tistory.com/443</guid>
      <comments>https://makingrobot.tistory.com/443#entry443comment</comments>
      <pubDate>Fri, 5 Jun 2026 00:18:10 +0900</pubDate>
    </item>
    <item>
      <title>강의자료 준비</title>
      <link>https://makingrobot.tistory.com/442</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #555555; text-align: left;&quot; data-ke-size=&quot;size18&quot;&gt;4)&amp;nbsp;&lt;a style=&quot;color: #222222;&quot; href=&quot;https://makingrobot.tistory.com/365&quot;&gt;TurtleBot3 Odometry 분석&lt;/a&gt;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #555555; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #555555; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #555555; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #555555; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;5)&amp;nbsp;&lt;a style=&quot;color: #222222;&quot; href=&quot;https://makingrobot.tistory.com/318&quot;&gt;RViz로 모바일 로봇 상태와 토픽 확인하기&lt;/a&gt;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #555555; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #555555; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #555555; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #555555; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;6)&amp;nbsp;&lt;a style=&quot;color: #222222;&quot; href=&quot;https://makingrobot.tistory.com/406&quot;&gt;TurtleBot3 Waffle 시뮬레이션에서 RViz와 rqt로 카메라 토픽 확인하기&lt;/a&gt;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #555555; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #555555; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #555555; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1.&amp;nbsp;&lt;a style=&quot;color: #222222;&quot; href=&quot;https://makingrobot.tistory.com/365&quot;&gt;Wheel Radius, Wheel Separation, /cmd_vel, Encoder Tick, Odometry 기초, Encoder Odometry 계산, /odom 발행, odom &amp;rarr; base_link TF, Drift 확인, Covariance 기초&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 좌&lt;a style=&quot;color: #222222;&quot; href=&quot;https://makingrobot.tistory.com/389&quot;&gt;표계와 Frame 개념, 모바일 로봇의 map, odom, base_link 구조 완전 이해&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3.&amp;nbsp;&lt;a style=&quot;color: #222222;&quot; href=&quot;https://makingrobot.tistory.com/423&quot;&gt;오도메트리(Odometry) 쉽게 이해하기&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4.&amp;nbsp;&lt;a style=&quot;color: #222222;&quot; href=&quot;https://makingrobot.tistory.com/352&quot;&gt;ROS 2 모바일 로봇 주행 원리, Differential Drive Kinematics&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;5.&amp;nbsp;&lt;a style=&quot;color: #222222;&quot; href=&quot;https://makingrobot.tistory.com/395&quot;&gt;Map / Odom / Base_link 관계 완전 정리&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1.&amp;nbsp;&lt;a style=&quot;color: #222222;&quot; href=&quot;https://makingrobot.tistory.com/312&quot;&gt;ROS 2 Humble에서 TurtleBot3 시뮬레이션(312)&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2.&amp;nbsp;&lt;a style=&quot;color: #222222;&quot; href=&quot;https://makingrobot.tistory.com/372&quot;&gt;차동 이동 로봇 기구학과 Odometry 쉽게 이해하기(373)&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. &lt;a style=&quot;color: #222222;&quot; href=&quot;https://makingrobot.tistory.com/443&quot;&gt;Odometry 프로그래밍(443)&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3-2 &lt;a style=&quot;color: #222222;&quot; href=&quot;https://makingrobot.tistory.com/373&quot;&gt;odometry 종합(373) &amp;lt;--위의 내용과 비교하여 다시 정리해야 함&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4.&amp;nbsp;&lt;a style=&quot;color: #222222;&quot; href=&quot;https://makingrobot.tistory.com/365&quot;&gt;TurtleBot3 Odometry 분석(365)&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;5.&amp;nbsp;&lt;a style=&quot;color: #222222;&quot; href=&quot;https://makingrobot.tistory.com/318&quot;&gt;RViz로 모바일 로봇 상태와 토픽 확인하기(318)&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;6.&amp;nbsp;&lt;a style=&quot;color: #222222;&quot; href=&quot;https://makingrobot.tistory.com/352&quot;&gt;URDF 이해(352)&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;7.&amp;nbsp;&lt;a style=&quot;color: #222222;&quot; href=&quot;https://makingrobot.tistory.com/329&quot;&gt;Xacro 기본 구조, Property, Macro, Include 실습(329)&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;8.&amp;nbsp;&lt;a style=&quot;color: #222222;&quot; href=&quot;https://makingrobot.tistory.com/389&quot;&gt;TF#1 : 좌표계와 Frame 개념, 모바일 로봇의 map, odom, base_link 구조 완전 이해(389)&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;9.&amp;nbsp;&lt;a style=&quot;color: #222222;&quot; href=&quot;https://makingrobot.tistory.com/405&quot;&gt;SLAM 기본 개념, Gazebo 기반 SLAM 실행(405)&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;10.&amp;nbsp;&lt;a style=&quot;color: #222222;&quot; href=&quot;https://makingrobot.tistory.com/438&quot;&gt;GIMP를 이용한 지도 파일 .pgm 수정(438)&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;11.&amp;nbsp;&lt;a style=&quot;color: #222222;&quot; href=&quot;https://makingrobot.tistory.com/440&quot;&gt;TurtleBot3 시뮬레이션으로 배우는 SLAM Toolbox(440)&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;extra1.&amp;nbsp;&lt;a style=&quot;color: #222222;&quot; href=&quot;https://makingrobot.tistory.com/340&quot;&gt;ROS 2를 이용한 로봇 개발 시 시스템 설계 방법: 실무자가 바로 써먹는 전체 구조 가이드&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1--&amp;gt;&amp;nbsp;&lt;a style=&quot;color: #222222;&quot; href=&quot;https://makingrobot.tistory.com/440&quot;&gt;TurtleBot3 시뮬레이션으로 배우는 SLAM Toolbox&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2--&amp;gt;&amp;nbsp;&lt;a style=&quot;color: #222222;&quot; href=&quot;https://makingrobot.tistory.com/395&quot;&gt;ROS 2 Humble TurtleBot3 시뮬레이션에서 Cartographer SLAM 실습하기&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;6.&amp;nbsp;&lt;a style=&quot;color: #222222;&quot; href=&quot;https://makingrobot.tistory.com/312&quot;&gt;ROS 2 Humble에서 TurtleBot3 시뮬레이션&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;7.&amp;nbsp;&lt;a style=&quot;color: #222222;&quot; href=&quot;https://makingrobot.tistory.com/358&quot;&gt;ROS 2 Python 서비스 서버와 클라이언트 실습&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;4.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;a style=&quot;color: #222222;&quot; href=&quot;https://makingrobot.tistory.com/385&quot;&gt;ROS 2 강의를 위한 Linux 터미널 기본 명령어 정리&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;5.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;a style=&quot;color: #222222;&quot; href=&quot;https://makingrobot.tistory.com/414&quot;&gt;ROS 2 Humble C++ 서비스 서버와 클라이언트 실습 : 모바일 로봇 주행 허용 및 모드 변경 제어&lt;/a&gt;&lt;/p&gt;
&lt;div style=&quot;background-color: #ffffff; color: #b3b3b3; text-align: center;&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div style=&quot;background-color: #ffffff; color: #b3b3b3; text-align: center;&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;6.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;a style=&quot;color: #222222;&quot; href=&quot;https://makingrobot.tistory.com/322&quot;&gt;ROS 2 C++ 패키지 설계 입문: 토픽, 서비스, 액션을 하나의 로봇 미션 시스템으로 연결하기&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;br /&gt;7.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;a style=&quot;color: #222222;&quot; href=&quot;https://makingrobot.tistory.com/396&quot;&gt;Python ROS 2 패키지 생성 정리&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;8.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;a style=&quot;color: #222222;&quot; href=&quot;https://makingrobot.tistory.com/358&quot;&gt;ROS 2 Python 서비스 서버와 클라이언트 실습&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;9.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;a style=&quot;color: #222222;&quot; href=&quot;https://makingrobot.tistory.com/427&quot;&gt;ROS2 Python 실습 강의: 토픽, 서비스, 액션으로 사칙연산 계산기 만들기&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;==&amp;gt;.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;a style=&quot;color: #222222;&quot; href=&quot;https://makingrobot.tistory.com/409&quot;&gt;로봇 상태 Topic 발행하기 : 추가된 내용 버전(수정해서 사용할 것)&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot; data-section-id=&quot;1kv2vgn&quot; data-start=&quot;241&quot; data-end=&quot;256&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot; data-section-id=&quot;1kv2vgn&quot; data-start=&quot;241&quot; data-end=&quot;256&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>강좌/강의준비</category>
      <author>MakingRobotWizard</author>
      <guid isPermaLink="true">https://makingrobot.tistory.com/442</guid>
      <comments>https://makingrobot.tistory.com/442#entry442comment</comments>
      <pubDate>Thu, 4 Jun 2026 11:01:25 +0900</pubDate>
    </item>
    <item>
      <title>10일차 강의</title>
      <link>https://makingrobot.tistory.com/441</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;1.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;a style=&quot;color: #222222;&quot; href=&quot;https://makingrobot.tistory.com/326&quot;&gt;ROS 2 C++ 파라미터 실습&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;a style=&quot;color: #222222;&quot; href=&quot;https://makingrobot.tistory.com/327&quot;&gt;ROS 2 C++ 실행 인자 사용하기&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;3.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;a style=&quot;color: #222222;&quot; href=&quot;https://makingrobot.tistory.com/415&quot;&gt;C++ Service Client 작성 실습 &amp;mdash; 모바일 로봇 긴급정지 요청 보내기&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4. &lt;a style=&quot;color: #222222;&quot; href=&quot;https://makingrobot.tistory.com/400&quot;&gt;ROS 2 에서 CMakeLists.txt 이해하기&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;5. &lt;a style=&quot;color: #222222;&quot; href=&quot;https://makingrobot.tistory.com/398&quot;&gt;ROS 2 package.xml 이해하기 : Python 패키지와 C++ 패키지 기준&lt;/a&gt;&lt;/p&gt;
&lt;div style=&quot;background-color: #ffffff; color: #b3b3b3; text-align: center;&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;6. &lt;a style=&quot;color: #222222;&quot; href=&quot;https://makingrobot.tistory.com/399&quot;&gt;ROS 2 Python 패키지의 setup.py 이해하기&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div style=&quot;background-color: #ffffff; color: #b3b3b3; text-align: center;&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>강좌/ROS2</category>
      <author>MakingRobotWizard</author>
      <guid isPermaLink="true">https://makingrobot.tistory.com/441</guid>
      <comments>https://makingrobot.tistory.com/441#entry441comment</comments>
      <pubDate>Sun, 31 May 2026 23:17:20 +0900</pubDate>
    </item>
    <item>
      <title>launch 파일에서 실행 인자 사용하기 #2</title>
      <link>https://makingrobot.tistory.com/439</link>
      <description>&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot; data-section-id=&quot;1wl8asr&quot; data-start=&quot;5882&quot; data-end=&quot;5913&quot;&gt;4. launch 파일에서 remapping 사용하기&lt;/h4&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;5915&quot; data-end=&quot;5950&quot;&gt;ROS 2에서 토픽 이름을 바꿔 연결해야 하는 경우가 많습니다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;5952&quot; data-end=&quot;5989&quot;&gt;이때 launch 파일에서 remapping을 사용할 수 있습니다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;5952&quot; data-end=&quot;5989&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;5991&quot; data-end=&quot;6085&quot;&gt;예를 들어 어떤 노드가 /cmd_vel 토픽을 구독하도록 만들어져 있는데, 실제 turtlesim은 /turtle1/cmd_vel을 사용한다고 가정해 보겠습니다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;5991&quot; data-end=&quot;6085&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;6087&quot; data-end=&quot;6127&quot;&gt;이 경우 launch 파일에서 다음처럼 remapping할 수 있습니다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;6087&quot; data-end=&quot;6127&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div style=&quot;color: #333333; text-align: start;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;routeros&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot;&gt;&lt;code&gt;Node(
    package='my_first_package',
    executable='my_publisher',
    output='screen',
    remappings=[
        ('/cmd_vel', '/turtle1/cmd_vel')
    ]
)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;6300&quot; data-end=&quot;6313&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;6300&quot; data-end=&quot;6313&quot;&gt;형식은 다음과 같습니다.&lt;/p&gt;
&lt;div style=&quot;color: #333333; text-align: start;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;maxima&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot;&gt;&lt;code&gt;remappings=[
    ('기존_토픽_이름', '변경할_토픽_이름')
]&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;6375&quot; data-end=&quot;6403&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;6375&quot; data-end=&quot;6403&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;6375&quot; data-end=&quot;6403&quot;&gt;먼저 패키지 폴더로 이동하여 새로운 노드 파일을 생성합니다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;6375&quot; data-end=&quot;6403&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1780060263732&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;cd ~/ros2_study/src/my_first_packages/my_first_packages

touch cmd_vel_publisher.py&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;6375&quot; data-end=&quot;6403&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;526&quot; data-start=&quot;514&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;580&quot; data-start=&quot;567&quot; data-ke-size=&quot;size16&quot;&gt;cmd_vel_publisher.py 을 열어 다음 코드를 작성합니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot;&gt;&lt;code&gt;import rclpy
from rclpy.node import Node
from geometry_msgs.msg import Twist


class CmdVelPublisher(Node):

    def __init__(self):
        super().__init__('cmd_vel_publisher')

        self.publisher_ = self.create_publisher(
            Twist,
            '/cmd_vel',
            10
        )

        self.timer = self.create_timer(1.0, self.timer_callback)

    def timer_callback(self):
        msg = Twist()

        msg.linear.x = 1.0
        msg.angular.z = 0.5

        self.publisher_.publish(msg)

        self.get_logger().info(
            'Publish velocity command to /cmd_vel'
        )


def main(args=None):
    rclpy.init(args=args)

    node = CmdVelPublisher()
    rclpy.spin(node)

    node.destroy_node()
    rclpy.shutdown()


if __name__ == '__main__':
    main()&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;1446&quot; data-start=&quot;1387&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;1446&quot; data-start=&quot;1387&quot; data-ke-size=&quot;size16&quot;&gt;이 노드는 /cmd_vel 토픽으로 geometry_msgs/msg/Twist 메시지를 발행합니다.&lt;/p&gt;
&lt;p data-end=&quot;1463&quot; data-start=&quot;1448&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;1463&quot; data-start=&quot;1448&quot; data-ke-size=&quot;size16&quot;&gt;코드의 주요부분은 아래와 같습니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;ruby&quot;&gt;&lt;code&gt;self.publisher_ = self.create_publisher(
    Twist,
    '/cmd_vel',
    10
)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;1595&quot; data-start=&quot;1557&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;1595&quot; data-start=&quot;1557&quot; data-ke-size=&quot;size16&quot;&gt;위의 소스는 /cmd_vel에 publish합니다.&lt;/p&gt;
&lt;p data-end=&quot;1636&quot; data-start=&quot;1597&quot; data-ke-size=&quot;size16&quot;&gt;나중에 launch 파일에서 이 토픽 이름을 바꿀 수 있습니다.&lt;/p&gt;
&lt;p data-end=&quot;1636&quot; data-start=&quot;1597&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;1636&quot; data-start=&quot;1597&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;1636&quot; data-start=&quot;1597&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;1689&quot; data-start=&quot;1672&quot; data-ke-size=&quot;size16&quot;&gt;상위 패키지 폴더로 이동합니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;jboss-cli&quot;&gt;&lt;code&gt;cd ~/ros2_study/src/my_first_packages&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;1761&quot; data-start=&quot;1742&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;1761&quot; data-start=&quot;1742&quot; data-ke-size=&quot;size16&quot;&gt;setup.py 파일을 엽니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;entry_points 부분에 cmd_vel_publisher를 추가합니다.&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;1855&quot; data-start=&quot;1838&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;1855&quot; data-start=&quot;1838&quot; data-ke-size=&quot;size16&quot;&gt;기존 코드가 다음과 비슷하다면,&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;아래를 추가합니다.&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot;&gt;&lt;code&gt;entry_points={
    'console_scripts': [
        'cmd_vel_publisher = my_first_package.cmd_vel_publisher:main',
    ],
},&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;2229&quot; data-start=&quot;2193&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;2229&quot; data-start=&quot;2193&quot; data-ke-size=&quot;size16&quot;&gt;이제 ROS 2에서 다음 명령으로 새 노드를 실행할 수 있습니다.&lt;/p&gt;
&lt;p data-end=&quot;2229&quot; data-start=&quot;2193&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;2229&quot; data-start=&quot;2193&quot; data-ke-size=&quot;size16&quot;&gt;컴파일하고 작업공간을 활성화하면 아래와 긑은 명령으로 실행할 수 있습니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;dockerfile&quot;&gt;&lt;code&gt;ros2 run my_first_package cmd_vel_publisher&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h1 data-end=&quot;2443&quot; data-start=&quot;2412&quot; data-section-id=&quot;1szkldz&quot;&gt;5. 새로운 remapping launch 파일 생성&lt;/h1&gt;
&lt;p data-end=&quot;2464&quot; data-start=&quot;2445&quot; data-ke-size=&quot;size16&quot;&gt;launch 파일을 새로 만듭니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot;&gt;&lt;code&gt;touch launch/cmd_vel_remap.launch.py&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;2528&quot; data-start=&quot;2515&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;2528&quot; data-start=&quot;2515&quot; data-ke-size=&quot;size16&quot;&gt;다음 내용을 작성합니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot;&gt;&lt;code&gt;from launch import LaunchDescription
from launch_ros.actions import Node


def generate_launch_description():

    cmd_vel_publisher_node = Node(
        package='my_first_package',
        executable='cmd_vel_publisher',
        output='screen',
        remappings=[
            ('/cmd_vel', '/turtle1/cmd_vel')
        ]
    )

    return LaunchDescription([
        cmd_vel_publisher_node
    ])&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;2956&quot; data-start=&quot;2944&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;2956&quot; data-start=&quot;2944&quot; data-ke-size=&quot;size16&quot;&gt;아래의 코드가 주요 부분입니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;ebnf&quot;&gt;&lt;code&gt;remappings=[
    ('/cmd_vel', '/turtle1/cmd_vel')
]&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;3037&quot; data-start=&quot;3025&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;3037&quot; data-start=&quot;3025&quot; data-ke-size=&quot;size16&quot;&gt;뜻은 다음과 같습니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;maxima&quot;&gt;&lt;code&gt;remappings=[
    ('기존_토픽_이름', '변경할_토픽_이름')
]&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;3184&quot; data-start=&quot;3099&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;3184&quot; data-start=&quot;3099&quot; data-ke-size=&quot;size16&quot;&gt;즉, cmd_vel_publisher 노드 안에서는 /cmd_vel을 사용하지만, 실제 실행할 때는 /turtle1/cmd_vel로 바뀝니다.&lt;/p&gt;
&lt;p data-end=&quot;3184&quot; data-start=&quot;3099&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;3184&quot; data-start=&quot;3099&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;3299&quot; data-start=&quot;3226&quot; data-ke-size=&quot;size16&quot;&gt;ros2 launch 명령으로 launch 파일을 실행하려면 setup.py에 launch 파일 설치 설정이 있어야 합니다.&lt;/p&gt;
&lt;p data-end=&quot;3337&quot; data-start=&quot;3301&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;3337&quot; data-start=&quot;3301&quot; data-ke-size=&quot;size16&quot;&gt;setup.py 상단에 다음 import가 있는지 확인합니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;elm&quot;&gt;&lt;code&gt;import os
from glob import glob
from setuptools import setup&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;3447&quot; data-start=&quot;3415&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;3447&quot; data-start=&quot;3415&quot; data-ke-size=&quot;size16&quot;&gt;그리고 data_files에 다음 줄이 있어야 합니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;lua&quot;&gt;&lt;code&gt;(os.path.join('share', package_name, 'launch'), glob('launch/*.launch.py')),&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;3554&quot; data-start=&quot;3541&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;3554&quot; data-start=&quot;3541&quot; data-ke-size=&quot;size16&quot;&gt;예시는 다음과 같습니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;ceylon&quot;&gt;&lt;code&gt;data_files=[
    ('share/ament_index/resource_index/packages',
        ['resource/' + package_name]),
    ('share/' + package_name, ['package.xml']),
    (os.path.join('share', package_name, 'launch'), glob('launch/*.launch.py')),
],&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;3815&quot; data-start=&quot;3805&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;3815&quot; data-start=&quot;3805&quot; data-ke-size=&quot;size16&quot;&gt;없다면 추가합니다.&lt;/p&gt;
&lt;p data-end=&quot;3815&quot; data-start=&quot;3805&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;3815&quot; data-start=&quot;3805&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;3850&quot; data-start=&quot;3833&quot; data-ke-size=&quot;size16&quot;&gt;워크스페이스 루트로 이동합니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;jboss-cli&quot;&gt;&lt;code&gt;cd ~/ros2_study&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;3887&quot; data-start=&quot;3881&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;3887&quot; data-start=&quot;3881&quot; data-ke-size=&quot;size16&quot;&gt;빌드합니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;armasm&quot;&gt;&lt;code&gt;colcon build --packages-select my_first_package&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;3966&quot; data-start=&quot;3950&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;3966&quot; data-start=&quot;3950&quot; data-ke-size=&quot;size16&quot;&gt;환경 설정을 다시 적용합니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;arduino&quot;&gt;&lt;code&gt;source install/setup.bash&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;4054&quot; data-start=&quot;4031&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;4054&quot; data-start=&quot;4031&quot; data-ke-size=&quot;size16&quot;&gt;새 터미널을 열고 다음 명령을 실행합니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;dockerfile&quot;&gt;&lt;code&gt;ros2 run turtlesim turtlesim_node&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;4156&quot; data-start=&quot;4103&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;4156&quot; data-start=&quot;4103&quot; data-ke-size=&quot;size16&quot;&gt;turtlesim_node는 기본적으로 /turtle1/cmd_vel 토픽을 구독합니다.&lt;/p&gt;
&lt;p data-end=&quot;4156&quot; data-start=&quot;4103&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;4211&quot; data-start=&quot;4189&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;4211&quot; data-start=&quot;4189&quot; data-ke-size=&quot;size16&quot;&gt;다른 터미널에서 다음 명령을 실행합니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;mel&quot;&gt;&lt;code&gt;cd ~/ros2_study
source install/setup.bash
ros2 launch my_first_package cmd_vel_remap.launch.py&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;4441&quot; data-start=&quot;4321&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;4441&quot; data-start=&quot;4321&quot; data-ke-size=&quot;size16&quot;&gt;그러면 cmd_vel_publisher 노드는 코드상으로는 /cmd_vel에 publish하지만, launch 파일의 remapping 때문에 실제로는&lt;/p&gt;
&lt;p data-end=&quot;4441&quot; data-start=&quot;4321&quot; data-ke-size=&quot;size16&quot;&gt;/turtle1/cmd_vel에 publish합니다.&lt;/p&gt;
&lt;p data-end=&quot;4441&quot; data-start=&quot;4321&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;4471&quot; data-start=&quot;4443&quot; data-ke-size=&quot;size16&quot;&gt;결과적으로 turtlesim의 거북이가 움직입니다.&lt;/p&gt;
&lt;p data-end=&quot;4471&quot; data-start=&quot;4443&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;4471&quot; data-start=&quot;4443&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;4504&quot; data-start=&quot;4491&quot; data-ke-size=&quot;size16&quot;&gt;토픽 목록을 확인합니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;applescript&quot;&gt;&lt;code&gt;ros2 topic list&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;4552&quot; data-start=&quot;4535&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;4552&quot; data-start=&quot;4535&quot; data-ke-size=&quot;size16&quot;&gt;다음 토픽이 보이면 정상입니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;awk&quot;&gt;&lt;code&gt;/turtle1/cmd_vel&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;4611&quot; data-start=&quot;4584&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;4611&quot; data-start=&quot;4584&quot; data-ke-size=&quot;size16&quot;&gt;메시지를 직접 확인하려면 다음 명령을 사용합니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;jboss-cli&quot;&gt;&lt;code&gt;ros2 topic echo /turtle1/cmd_vel&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;4675&quot; data-start=&quot;4659&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;4675&quot; data-start=&quot;4659&quot; data-ke-size=&quot;size16&quot;&gt;출력 예시는 다음과 같습니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;yaml&quot;&gt;&lt;code&gt;linear:
  x: 1.0
  y: 0.0
  z: 0.0
angular:
  x: 0.0
  y: 0.0
  z: 0.5&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;4832&quot; data-start=&quot;4793&quot; data-ke-size=&quot;size16&quot;&gt;이번에는 launch 파일을 사용하지 않고 노드를 직접 실행해 봅니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;dockerfile&quot;&gt;&lt;code&gt;ros2 run my_first_package cmd_vel_publisher&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;4919&quot; data-start=&quot;4891&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;4919&quot; data-start=&quot;4891&quot; data-ke-size=&quot;size16&quot;&gt;이 경우에는 remapping이 적용되지 않습니다.&lt;/p&gt;
&lt;p data-end=&quot;4959&quot; data-start=&quot;4921&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;4959&quot; data-start=&quot;4921&quot; data-ke-size=&quot;size16&quot;&gt;따라서 노드는 그대로 /cmd_vel 토픽에 메시지를 발행합니다.&lt;/p&gt;
&lt;p data-end=&quot;4967&quot; data-start=&quot;4961&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;4967&quot; data-start=&quot;4961&quot; data-ke-size=&quot;size16&quot;&gt;확인 명령:&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;jboss-cli&quot;&gt;&lt;code&gt;ros2 topic echo /cmd_vel&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;5033&quot; data-start=&quot;5007&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;5033&quot; data-start=&quot;5007&quot; data-ke-size=&quot;size16&quot;&gt;이 경우 turtlesim은 움직이지 않습니다.&lt;/p&gt;
&lt;p data-end=&quot;5033&quot; data-start=&quot;5007&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;5097&quot; data-start=&quot;5035&quot; data-ke-size=&quot;size16&quot;&gt;이유는 turtlesim이 /cmd_vel이 아니라 /turtle1/cmd_vel을 구독하기 때문입니다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;6375&quot; data-end=&quot;6403&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;6375&quot; data-end=&quot;6403&quot;&gt;실무에서 remapping은 매우 자주 사용됩니다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;6405&quot; data-end=&quot;6444&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;6405&quot; data-end=&quot;6444&quot;&gt;예를 들어 모바일 로봇에서는 다음처럼 토픽 이름이 달라질 수 있습니다.&lt;/p&gt;
&lt;div style=&quot;color: #333333; text-align: start;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;jboss-cli&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot;&gt;&lt;code&gt;/cmd_vel
/robot1/cmd_vel
/robot2/cmd_vel
/scan
/robot1/scan
/odom
/robot1/odom&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;6538&quot; data-end=&quot;6561&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;6538&quot; data-end=&quot;6561&quot;&gt;코드를 매번 수정하는 것은 좋지 않습니다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;6563&quot; data-end=&quot;6618&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;6563&quot; data-end=&quot;6618&quot;&gt;토픽 이름만 다른 경우에는 launch 파일에서 remapping으로 해결하는 것이 더 깔끔합니다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;6620&quot; data-end=&quot;6694&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;6620&quot; data-end=&quot;6694&quot;&gt;예를 들어 로봇 제어 노드는 /cmd_vel을 사용하도록 만들고, 실제 로봇마다 launch 파일에서 다음처럼 바꿀 수 있습니다.&lt;/p&gt;
&lt;div style=&quot;color: #333333; text-align: start;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;ebnf&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot;&gt;&lt;code&gt;remappings=[
    ('/cmd_vel', '/robot1/cmd_vel')
]&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;6762&quot; data-end=&quot;6798&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;6762&quot; data-end=&quot;6798&quot;&gt;이렇게 하면 같은 제어 노드를 여러 로봇에 재사용할 수 있습니다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;6762&quot; data-end=&quot;6798&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;6762&quot; data-end=&quot;6798&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;6762&quot; data-end=&quot;6798&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot; data-section-id=&quot;coxq6k&quot; data-start=&quot;6805&quot; data-end=&quot;6839&quot;&gt;5. launch 파일에서 namespace를 변수로 받기&lt;/h4&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;6841&quot; data-end=&quot;6879&quot;&gt;여러 대의 모바일 로봇을 운용할 때는 namespace가 중요합니다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;6841&quot; data-end=&quot;6879&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;6881&quot; data-end=&quot;6921&quot;&gt;예를 들어 모바일 로봇 1번과 모바일 로봇 2번이 있다고 가정하겠습니다.&lt;/p&gt;
&lt;div style=&quot;color: #333333; text-align: start;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;dts&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot;&gt;&lt;code&gt;/robot1/camera/image_raw
/robot1/scan
/robot1/odom
/robot1/cmd_vel
/robot1/navigation_state

/robot2/camera/image_raw
/robot2/scan
/robot2/odom
/robot2/cmd_vel
/robot2/navigation_state&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;7121&quot; data-end=&quot;7175&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;7121&quot; data-end=&quot;7175&quot;&gt;이런 구조를 만들려면 launch 파일에서 namespace를 외부 인자로 받는 방식이 좋습니다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;7121&quot; data-end=&quot;7175&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;7121&quot; data-end=&quot;7175&quot;&gt;먼저 namespace_test.launch.py 파일을 생성합니다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;7121&quot; data-end=&quot;7175&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1780064470133&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;cd ros2_study/src/my_first_package/launch/

touch namespace_test.launch.py

tree&lt;/code&gt;&lt;/pre&gt;
&lt;div style=&quot;color: #333333; text-align: start;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;새롭게 생성한 파일을 열어 아래의 내요을 작성합니다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;cpp&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot; data-ke-language=&quot;cpp&quot;&gt;&lt;code&gt;from launch import LaunchDescription
from launch.actions import DeclareLaunchArgument
from launch.substitutions import LaunchConfiguration
from launch_ros.actions import Node


def generate_launch_description():
    namespace = LaunchConfiguration('namespace')

    return LaunchDescription([
        DeclareLaunchArgument(
            'namespace',
            default_value='robot1',
            description='Robot namespace'
        ),

        Node(
            package='turtlesim',
            executable='turtlesim_node',
            namespace=namespace,
            output='screen'
        ),

        Node(
            package='my_first_package',
            executable='my_publisher',
            namespace=namespace,
            output='screen'
        )
    ])&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;7963&quot; data-end=&quot;7976&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-start=&quot;3881&quot; data-end=&quot;3887&quot; data-ke-size=&quot;size16&quot;&gt;빌드합니다.&lt;/p&gt;
&lt;div style=&quot;color: #333333; text-align: start;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;armasm&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot;&gt;&lt;code&gt;colcon build --packages-select my_first_package&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-start=&quot;3950&quot; data-end=&quot;3966&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-start=&quot;3950&quot; data-end=&quot;3966&quot; data-ke-size=&quot;size16&quot;&gt;환경 설정을 다시 적용합니다.&lt;/p&gt;
&lt;div style=&quot;color: #333333; text-align: start;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;arduino&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot;&gt;&lt;code&gt;source install/setup.bash&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-start=&quot;4031&quot; data-end=&quot;4054&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-start=&quot;4031&quot; data-end=&quot;4054&quot; data-ke-size=&quot;size16&quot;&gt;새 터미널을 열고 &lt;span style=&quot;letter-spacing: 0px;&quot;&gt;실행은 다음처럼 합니다.&lt;/span&gt;&lt;/p&gt;
&lt;div style=&quot;color: #333333; text-align: start;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;cpp&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot; data-ke-language=&quot;cpp&quot;&gt;&lt;code&gt;ros2 launch my_first_package namespace_test.launch.py namespace:=robot1&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;8063&quot; data-end=&quot;8090&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;8063&quot; data-end=&quot;8090&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;Screenshot from 2026-05-29 23-23-48.png&quot; data-origin-width=&quot;786&quot; data-origin-height=&quot;533&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b7fugZ/dJMcad3dmqJ/Bvi3UnogNXszeZZ0KAkRm0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b7fugZ/dJMcad3dmqJ/Bvi3UnogNXszeZZ0KAkRm0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b7fugZ/dJMcad3dmqJ/Bvi3UnogNXszeZZ0KAkRm0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb7fugZ%2FdJMcad3dmqJ%2FBvi3UnogNXszeZZ0KAkRm0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;786&quot; height=&quot;533&quot; data-filename=&quot;Screenshot from 2026-05-29 23-23-48.png&quot; data-origin-width=&quot;786&quot; data-origin-height=&quot;533&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;8063&quot; data-end=&quot;8090&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;8063&quot; data-end=&quot;8090&quot;&gt;다른 이름으로 실행하고 싶다면 다음처럼 바꿉니다.&lt;/p&gt;
&lt;div style=&quot;color: #333333; text-align: start;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;mel&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot;&gt;&lt;code&gt;ros2 launch my_first_package namespace_test.launch.py namespace:=robot2&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;Screenshot from 2026-05-29 23-24-06.png&quot; data-origin-width=&quot;786&quot; data-origin-height=&quot;533&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/KdHO9/dJMcabEnfw7/uNKdFYvk9K1kr8gSzKr4h1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/KdHO9/dJMcabEnfw7/uNKdFYvk9K1kr8gSzKr4h1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/KdHO9/dJMcabEnfw7/uNKdFYvk9K1kr8gSzKr4h1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FKdHO9%2FdJMcabEnfw7%2FuNKdFYvk9K1kr8gSzKr4h1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;786&quot; height=&quot;533&quot; data-filename=&quot;Screenshot from 2026-05-29 23-24-06.png&quot; data-origin-width=&quot;786&quot; data-origin-height=&quot;533&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;8177&quot; data-end=&quot;8204&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;8177&quot; data-end=&quot;8204&quot;&gt;이 방식은 다중 로봇 시스템에서 거의 필수입니다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;8177&quot; data-end=&quot;8204&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;8206&quot; data-end=&quot;8307&quot;&gt;특히 모바일 로봇, AMR, 물류 로봇, 서빙 로봇처럼 여러 대가 동시에 운용되는 시스템에서는 namespace 설계가 제대로 되어 있지 않으면 토픽이 섞이고 디버깅이 어려워집니다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;8206&quot; data-end=&quot;8307&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;8206&quot; data-end=&quot;8307&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;8206&quot; data-end=&quot;8307&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot; data-section-id=&quot;13927fi&quot; data-start=&quot;8314&quot; data-end=&quot;8339&quot;&gt;6. launch 파일에서 조건부 실행하기&lt;/h4&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;8341&quot; data-end=&quot;8367&quot;&gt;항상 모든 노드를 실행해야 하는 것은 아닙니다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;8341&quot; data-end=&quot;8367&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;8369&quot; data-end=&quot;8405&quot;&gt;예를 들어 카메라 노드는 필요할 때만 실행하고 싶을 수 있습니다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;8369&quot; data-end=&quot;8405&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;8407&quot; data-end=&quot;8432&quot;&gt;이럴 때는 조건부 실행을 사용할 수 있습니다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;8407&quot; data-end=&quot;8432&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;8407&quot; data-end=&quot;8432&quot;&gt;카메라 노드 파일을 생성합니다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;8407&quot; data-end=&quot;8432&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1780065575407&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;cd ~/ros2_study/src/my_first_package/my_first_package

touch camera_node.py&lt;/code&gt;&lt;/pre&gt;
&lt;div style=&quot;color: #333333; text-align: start;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;camera_node.py를 작성합니다.&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;
&lt;pre id=&quot;code_1780065632471&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import rclpy
from rclpy.node import Node


class CameraNode(Node):
    def __init__(self):
        super().__init__('camera_node')

        self.get_logger().info('camera_node has been started.')
        self.get_logger().info('This is a dummy camera node for launch condition test.')

        self.timer = self.create_timer(1.0, self.timer_callback)
        self.count = 0

    def timer_callback(self):
        self.count += 1
        self.get_logger().info(f'Dummy camera node is running... count: {self.count}')


def main(args=None):
    rclpy.init(args=args)

    node = CameraNode()

    try:
        rclpy.spin(node)
    except KeyboardInterrupt:
        node.get_logger().info('camera_node stopped by user.')
    finally:
        node.destroy_node()
        rclpy.shutdown()


if __name__ == '__main__':
    main()&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;
&lt;p data-end=&quot;1249&quot; data-start=&quot;1202&quot; data-ke-size=&quot;size16&quot;&gt;setup.py를 열고 entry_points 부분에 아래 내용을 추가합니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot;&gt;&lt;code&gt;entry_points={
    'console_scripts': [
        'camera_node = my_first_package.camera_node:main',
    ],
},&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;빌드하고 환경을 설정합니다.&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;
&lt;pre id=&quot;code_1780066292376&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;cd ~/ros2_study

colcon build --packages-select my_first_package
source install/setup.bash&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-end=&quot;7175&quot; data-start=&quot;7121&quot; data-ke-size=&quot;size16&quot;&gt;namespace_test.launch.py 파일을 생성합니다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-end=&quot;7175&quot; data-start=&quot;7121&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div style=&quot;color: #333333; text-align: start;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre id=&quot;code_1780065024006&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;cd ros2_study/src/my_first_package/launch/

touch camera_test.launch.py

tree&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;새롭게 생성한 파일을 열어 아래의 내요을 작성합니다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;cpp&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot; data-ke-language=&quot;cpp&quot;&gt;&lt;code&gt;from launch import LaunchDescription
from launch.actions import DeclareLaunchArgument
from launch.conditions import IfCondition
from launch.substitutions import LaunchConfiguration
from launch_ros.actions import Node


def generate_launch_description():
    use_camera = LaunchConfiguration('use_camera')

    return LaunchDescription([
        DeclareLaunchArgument(
            'use_camera',
            default_value='true',
            description='Whether to launch camera node'
        ),

        Node(
            package='my_first_package',
            executable='camera_node',
            output='screen',
            condition=IfCondition(use_camera)
        )
    ])&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;9129&quot; data-end=&quot;9152&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;9129&quot; data-end=&quot;9152&quot;&gt;카메라 노드를 실행하려면 다음처럼 합니다.&lt;/p&gt;
&lt;div style=&quot;color: #333333; text-align: start;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;cpp&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot; data-ke-language=&quot;cpp&quot;&gt;&lt;code&gt;ros2 launch my_first_package camera_test.launch.py use_camera:=true&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;9235&quot; data-end=&quot;9262&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;9235&quot; data-end=&quot;9262&quot;&gt;카메라 노드를 실행하지 않으려면 다음처럼 합니다.&lt;/p&gt;
&lt;div style=&quot;color: #333333; text-align: start;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;applescript&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot;&gt;&lt;code&gt;ros2 launch my_first_package camera_test.launch.py use_camera:=false&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;9346&quot; data-end=&quot;9381&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;107&quot; data-start=&quot;24&quot; data-ke-size=&quot;size16&quot;&gt;위의 실행결과 use_camera:=false로 실행했기 때문에 camera_node가 실행되지 않습니다. 그래서 아래처럼 launch 자체 로그만 나오고,&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;[INFO] [launch]: All log files can be found below ...
[INFO] [launch]: Default logging verbosity is set to INFO&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;270&quot; data-start=&quot;234&quot; data-ke-size=&quot;size16&quot;&gt;camera_node 관련 로그가 안 나오는 것이 정상입니다.&lt;/p&gt;
&lt;p data-end=&quot;270&quot; data-start=&quot;234&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;270&quot; data-start=&quot;234&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;9346&quot; data-end=&quot;9381&quot;&gt;모바일 로봇 시스템에서는 다음과 같은 조건부 실행이 유용합니다.&lt;/p&gt;
&lt;div style=&quot;color: #333333; text-align: start;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;gcode&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot;&gt;&lt;code&gt;use_lidar
use_camera
use_imu
use_nav2
use_slam
use_rviz
use_robot_state_publisher
use_logger
use_sim_time&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;9502&quot; data-end=&quot;9543&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;9502&quot; data-end=&quot;9543&quot;&gt;예를 들어 라이다만 테스트할 때는 카메라와 내비게이션 노드를 꺼도 됩니다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;9502&quot; data-end=&quot;9543&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;9545&quot; data-end=&quot;9626&quot;&gt;SLAM 테스트를 할 때는 use_slam:=true, 저장된 맵 기반 주행을 할 때는 use_slam:=false로 분리할 수 있습니다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;9545&quot; data-end=&quot;9626&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;9628&quot; data-end=&quot;9675&quot;&gt;개발 단계에서는 모든 기능을 한 번에 켜기보다 필요한 기능만 켜는 것이 안정적입니다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;9628&quot; data-end=&quot;9675&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;9628&quot; data-end=&quot;9675&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;9628&quot; data-end=&quot;9675&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot; data-section-id=&quot;131g6v6&quot; data-start=&quot;9682&quot; data-end=&quot;9704&quot;&gt;7. 다른 launch 파일 포함하기&lt;/h4&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;9706&quot; data-end=&quot;9754&quot;&gt;프로젝트가 커지면 launch 파일 하나에 모든 노드를 넣는 방식은 관리가 어렵습니다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;9706&quot; data-end=&quot;9754&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;9756&quot; data-end=&quot;9823&quot;&gt;이럴 때는 launch 파일을 기능별로 나누고, 상위 launch 파일에서 다른 launch 파일을 포함할 수 있습니다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;9825&quot; data-end=&quot;9849&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;9825&quot; data-end=&quot;9849&quot;&gt;예를 들어 다음과 같이 구성할 수 있습니다.&lt;/p&gt;
&lt;div style=&quot;color: #333333; text-align: start;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;stylus&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot;&gt;&lt;code&gt;my_first_package/
├── launch/
│   ├── bringup.launch.py
│   ├── sensor.launch.py
│   ├── navigation.launch.py
│   └── control.launch.py&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;10000&quot; data-end=&quot;10036&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;10000&quot; data-end=&quot;10036&quot;&gt;sensor.launch.py에는 센서 관련 노드를 넣습니다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;10038&quot; data-end=&quot;10085&quot;&gt;navigation.launch.py에는 경로 계획과 주행 관련 노드를 넣습니다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;10087&quot; data-end=&quot;10141&quot;&gt;control.launch.py에는 모터 제어, 속도 제어, 주행 명령 처리 노드를 넣습니다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;10143&quot; data-end=&quot;10178&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;10143&quot; data-end=&quot;10178&quot;&gt;그리고 bringup.launch.py에서 모두 포함합니다.&lt;/p&gt;
&lt;div style=&quot;color: #333333; text-align: start;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;cpp&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot; data-ke-language=&quot;cpp&quot;&gt;&lt;code&gt;import os

from ament_index_python.packages import get_package_share_directory

from launch import LaunchDescription
from launch.actions import IncludeLaunchDescription
from launch.launch_description_sources import PythonLaunchDescriptionSource


def generate_launch_description():
    package_dir = get_package_share_directory('my_first_package')

    dist_tutle_action_launch = IncludeLaunchDescription(
        PythonLaunchDescriptionSource(
            os.path.join(package_dir, 'launch', 'dist_turtle_action.launch.py')
        )
    )

    tutlesim_teleop_launch = IncludeLaunchDescription(
        PythonLaunchDescriptionSource(
            os.path.join(package_dir, 'launch', 'turtlesim_and_teleop.launch.py')
        )
    )

    return LaunchDescription([
        dist_tutle_action_launch,
        tutlesim_teleop_launch,
    ])&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;11175&quot; data-end=&quot;11190&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;11175&quot; data-end=&quot;11190&quot;&gt;실행은 하나만 하면 됩니다.&lt;/p&gt;
&lt;div style=&quot;color: #333333; text-align: start;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;applescript&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot;&gt;&lt;code&gt;ros2 launch my_first_package bringup.launch.py&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;11252&quot; data-end=&quot;11272&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;11252&quot; data-end=&quot;11272&quot;&gt;이 방식은 실무에서 많이 사용됩니다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;11274&quot; data-end=&quot;11308&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;11274&quot; data-end=&quot;11308&quot;&gt;특히 모바일 로봇 시스템이라면 다음처럼 나누는 것이 좋습니다.&lt;/p&gt;
&lt;div style=&quot;color: #333333; text-align: start;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;css&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot;&gt;&lt;code&gt;robot_description.launch.py
sensors.launch.py
slam.launch.py
navigation.launch.py
control.launch.py
localization.launch.py
rviz.launch.py
bringup.launch.py&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;11479&quot; data-end=&quot;11498&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;11479&quot; data-end=&quot;11498&quot;&gt;최종 실행은 다음처럼 단순해집니다.&lt;/p&gt;
&lt;div style=&quot;color: #333333; text-align: start;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;applescript&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot;&gt;&lt;code&gt;ros2 launch mobile_robot_bringup bringup.launch.py&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;11564&quot; data-end=&quot;11661&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;11564&quot; data-end=&quot;11661&quot;&gt;이렇게 구성하면 전체 시스템 실행은 bringup.launch.py 하나로 처리하고, 센서나 내비게이션만 따로 테스트할 때는 개별 launch 파일을 실행할 수 있습니다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;11564&quot; data-end=&quot;11661&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;11564&quot; data-end=&quot;11661&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;13777&quot; data-end=&quot;13824&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot; data-section-id=&quot;vwb5b6&quot; data-start=&quot;13831&quot; data-end=&quot;13860&quot;&gt;8. 모바일 로봇 시스템 예시 launch 구성&lt;/h4&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;13862&quot; data-end=&quot;13907&quot;&gt;모바일 로봇 시스템을 예로 들면 launch 파일은 다음처럼 구성할 수 있습니다.&lt;/p&gt;
&lt;div style=&quot;color: #333333; text-align: start;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;stylus&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot;&gt;&lt;code&gt;mobile_robot_bringup/
├── launch/
│   ├── bringup.launch.py
│   ├── robot_description.launch.py
│   ├── sensors.launch.py
│   ├── control.launch.py
│   ├── slam.launch.py
│   ├── localization.launch.py
│   ├── navigation.launch.py
│   └── rviz.launch.py
├── config/
│   ├── robot_params.yaml
│   ├── lidar_params.yaml
│   ├── controller_params.yaml
│   ├── slam_params.yaml
│   └── nav2_params.yaml
├── maps/
│   └── warehouse_map.yaml
└── urdf/
    └── mobile_robot.urdf.xacro&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;14400&quot; data-end=&quot;14426&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;14400&quot; data-end=&quot;14426&quot;&gt;각 launch 파일의 역할은 다음과 같습니다.&lt;/p&gt;
&lt;div style=&quot;color: #333333; text-align: start;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;markdown&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot;&gt;&lt;code&gt;robot_description.launch.py
- URDF 또는 Xacro 기반 로봇 모델 실행
- robot_state_publisher 실행
- joint_state_publisher 실행

sensors.launch.py
- 라이다 노드 실행
- 카메라 노드 실행
- IMU 노드 실행

control.launch.py
- 모터 제어 노드 실행
- cmd_vel 기반 속도 제어 노드 실행
- odom 발행 노드 실행

slam.launch.py
- SLAM 노드 실행
- 라이다 데이터를 이용한 지도 작성

localization.launch.py
- 저장된 map 파일 로드
- AMCL 또는 위치 추정 노드 실행

navigation.launch.py
- Nav2 관련 노드 실행
- global planner 실행
- local planner 실행
- behavior tree navigator 실행

rviz.launch.py
- RViz 실행
- 로봇 상태, 라이다, 지도, 경로 시각화

bringup.launch.py
- 전체 launch 파일을 하나로 묶어서 실행&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;14995&quot; data-end=&quot;15025&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;14995&quot; data-end=&quot;15025&quot;&gt;최종 실행 명령은 다음처럼 단순하게 만들 수 있습니다.&lt;/p&gt;
&lt;div style=&quot;color: #333333; text-align: start;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;go&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot;&gt;&lt;code&gt;ros2 launch mobile_robot_bringup bringup.launch.py robot_id:=robot1 use_lidar:=true use_camera:=false use_rviz:=true&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;15157&quot; data-end=&quot;15181&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;15157&quot; data-end=&quot;15181&quot;&gt;이런 구조가 되면 시스템 실행이 편해집니다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;15157&quot; data-end=&quot;15181&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;15183&quot; data-end=&quot;15223&quot;&gt;또한 문제가 생겼을 때 특정 기능만 따로 실행해서 디버깅할 수 있습니다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;15183&quot; data-end=&quot;15223&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;15225&quot; data-end=&quot;15256&quot;&gt;예를 들어 센서만 테스트하고 싶다면 다음처럼 실행합니다.&lt;/p&gt;
&lt;div style=&quot;color: #333333; text-align: start;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;applescript&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot;&gt;&lt;code&gt;ros2 launch mobile_robot_bringup sensors.launch.py&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;15322&quot; data-end=&quot;15350&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;15322&quot; data-end=&quot;15350&quot;&gt;제어 노드만 테스트하고 싶다면 다음처럼 실행합니다.&lt;/p&gt;
&lt;div style=&quot;color: #333333; text-align: start;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;mel&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot;&gt;&lt;code&gt;ros2 launch mobile_robot_bringup control.launch.py&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;15416&quot; data-end=&quot;15443&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;15416&quot; data-end=&quot;15443&quot;&gt;SLAM만 테스트하고 싶다면 다음처럼 실행합니다.&lt;/p&gt;
&lt;div style=&quot;color: #333333; text-align: start;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;applescript&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot;&gt;&lt;code&gt;ros2 launch mobile_robot_bringup slam.launch.py&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;15506&quot; data-end=&quot;15544&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;15506&quot; data-end=&quot;15544&quot;&gt;저장된 지도 기반 내비게이션만 테스트하고 싶다면 다음처럼 실행합니다.&lt;/p&gt;
&lt;div style=&quot;color: #333333; text-align: start;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;applescript&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot;&gt;&lt;code&gt;ros2 launch mobile_robot_bringup navigation.launch.py map:=warehouse_map.yaml&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;15637&quot; data-end=&quot;15689&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;15637&quot; data-end=&quot;15689&quot;&gt;이렇게 기능별로 launch 파일을 나누면 개발 속도가 빨라지고 문제 원인을 찾기 쉬워집니다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;15691&quot; data-end=&quot;15717&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;16482&quot; data-end=&quot;16546&quot; data-is-last-node=&quot;&quot; data-is-only-node=&quot;&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>강좌/ROS2</category>
      <category>roslaunch #2</category>
      <author>MakingRobotWizard</author>
      <guid isPermaLink="true">https://makingrobot.tistory.com/439</guid>
      <comments>https://makingrobot.tistory.com/439#entry439comment</comments>
      <pubDate>Fri, 29 May 2026 18:21:53 +0900</pubDate>
    </item>
    <item>
      <title>GIMP를 이용한 지도 파일 .pgm 수정</title>
      <link>https://makingrobot.tistory.com/438</link>
      <description>&lt;h4 data-end=&quot;210&quot; data-start=&quot;198&quot; data-section-id=&quot;lctxzq&quot; data-ke-size=&quot;size20&quot;&gt;1. GIMP 설치&lt;/h4&gt;
&lt;p data-end=&quot;235&quot; data-start=&quot;212&quot; data-section-id=&quot;oifo3p&quot; data-ke-size=&quot;size18&quot;&gt;1) Ubuntu에서 GIMP 설치&lt;/p&gt;
&lt;p data-end=&quot;284&quot; data-start=&quot;237&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;284&quot; data-start=&quot;237&quot; data-ke-size=&quot;size16&quot;&gt;다음 명령을 실행하여 GIMP를 설치합니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;properties&quot;&gt;&lt;code&gt;sudo apt update
sudo apt install gimp -y&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;346&quot; data-start=&quot;340&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;786&quot; data-origin-height=&quot;533&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/d7yrx5/dJMcabRYA4F/u5Slozsicl9QST5KC8frkk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/d7yrx5/dJMcabRYA4F/u5Slozsicl9QST5KC8frkk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/d7yrx5/dJMcabRYA4F/u5Slozsicl9QST5KC8frkk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fd7yrx5%2FdJMcabRYA4F%2Fu5Slozsicl9QST5KC8frkk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;786&quot; height=&quot;533&quot; data-origin-width=&quot;786&quot; data-origin-height=&quot;533&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-end=&quot;346&quot; data-start=&quot;340&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;346&quot; data-start=&quot;340&quot; data-ke-size=&quot;size16&quot;&gt;설치 확인:&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;ada&quot;&gt;&lt;code&gt;gimp --version&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;786&quot; data-origin-height=&quot;533&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cF5ouU/dJMcahSb4f4/yEugH0bkwtbYLeEzDCW7p1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cF5ouU/dJMcahSb4f4/yEugH0bkwtbYLeEzDCW7p1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cF5ouU/dJMcahSb4f4/yEugH0bkwtbYLeEzDCW7p1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcF5ouU%2FdJMcahSb4f4%2FyEugH0bkwtbYLeEzDCW7p1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;786&quot; height=&quot;533&quot; data-origin-width=&quot;786&quot; data-origin-height=&quot;533&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;384&quot; data-start=&quot;376&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;384&quot; data-start=&quot;376&quot; data-ke-size=&quot;size16&quot;&gt;GIMP 실행:&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;ebnf&quot;&gt;&lt;code&gt;gimp&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;426&quot; data-start=&quot;404&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1044&quot; data-origin-height=&quot;823&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dTFy5e/dJMcaci2OGI/fK7OC42zq4Q10JIrY4EOH0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dTFy5e/dJMcaci2OGI/fK7OC42zq4Q10JIrY4EOH0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dTFy5e/dJMcaci2OGI/fK7OC42zq4Q10JIrY4EOH0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdTFy5e%2FdJMcaci2OGI%2FfK7OC42zq4Q10JIrY4EOH0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1044&quot; height=&quot;823&quot; data-origin-width=&quot;1044&quot; data-origin-height=&quot;823&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-end=&quot;426&quot; data-start=&quot;404&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;426&quot; data-start=&quot;404&quot; data-ke-size=&quot;size16&quot;&gt;또는 지도 파일을 바로 열 수 있습니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;cpp&quot;&gt;&lt;code&gt;gimp map.pgm&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;630&quot; data-start=&quot;591&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-end=&quot;656&quot; data-start=&quot;637&quot; data-section-id=&quot;1jmqcoe&quot; data-ke-size=&quot;size20&quot;&gt;2. ROS 2 지도 파일 구조&lt;/h4&gt;
&lt;p data-end=&quot;671&quot; data-start=&quot;658&quot; data-section-id=&quot;171mtnm&quot; data-ke-size=&quot;size18&quot;&gt;1) PGM 파일&lt;/p&gt;
&lt;p data-end=&quot;694&quot; data-start=&quot;673&quot; data-ke-size=&quot;size16&quot;&gt;.pgm 파일은 지도 이미지입니다.&lt;/p&gt;
&lt;p data-end=&quot;694&quot; data-start=&quot;673&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;712&quot; data-start=&quot;696&quot; data-ke-size=&quot;size16&quot;&gt;색상 의미는 다음과 같습니다.&lt;/p&gt;
&lt;div&gt;&lt;br /&gt;
&lt;table style=&quot;border-collapse: collapse; width: 73.7209%;&quot; border=&quot;1&quot; data-end=&quot;842&quot; data-start=&quot;714&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody data-end=&quot;842&quot; data-start=&quot;745&quot;&gt;
&lt;tr data-end=&quot;776&quot; data-start=&quot;745&quot;&gt;
&lt;td style=&quot;width: 16.9767%;&quot; data-col-size=&quot;sm&quot; data-end=&quot;751&quot; data-start=&quot;745&quot;&gt;검정색&lt;/td&gt;
&lt;td style=&quot;width: 26.2791%;&quot; data-col-size=&quot;sm&quot; data-end=&quot;757&quot; data-start=&quot;751&quot;&gt;장애물&lt;/td&gt;
&lt;td style=&quot;width: 30.4651%;&quot; data-col-size=&quot;sm&quot; data-end=&quot;776&quot; data-start=&quot;757&quot;&gt;벽, 물체, 진입 금지 구역&lt;/td&gt;
&lt;/tr&gt;
&lt;tr data-end=&quot;807&quot; data-start=&quot;777&quot;&gt;
&lt;td style=&quot;width: 16.9767%;&quot; data-col-size=&quot;sm&quot; data-end=&quot;782&quot; data-start=&quot;777&quot;&gt;흰색&lt;/td&gt;
&lt;td style=&quot;width: 26.2791%;&quot; data-col-size=&quot;sm&quot; data-end=&quot;790&quot; data-start=&quot;782&quot;&gt;자유 공간&lt;/td&gt;
&lt;td style=&quot;width: 30.4651%;&quot; data-end=&quot;807&quot; data-start=&quot;790&quot; data-col-size=&quot;sm&quot;&gt;로봇이 이동 가능한 영역&lt;/td&gt;
&lt;/tr&gt;
&lt;tr data-end=&quot;842&quot; data-start=&quot;808&quot;&gt;
&lt;td style=&quot;width: 16.9767%;&quot; data-col-size=&quot;sm&quot; data-end=&quot;813&quot; data-start=&quot;808&quot;&gt;회색&lt;/td&gt;
&lt;td style=&quot;width: 26.2791%;&quot; data-end=&quot;822&quot; data-start=&quot;813&quot; data-col-size=&quot;sm&quot;&gt;미확인 영역&lt;/td&gt;
&lt;td style=&quot;width: 30.4651%;&quot; data-end=&quot;842&quot; data-start=&quot;822&quot; data-col-size=&quot;sm&quot;&gt;SLAM이 확인하지 못한 영역&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;p data-end=&quot;864&quot; data-start=&quot;844&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;864&quot; data-start=&quot;844&quot; data-ke-size=&quot;size16&quot;&gt;일반적인 픽셀 값은 다음과 같습니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;검정색: 0
흰색: 254 또는 255
회색: 약 205&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;937&quot; data-start=&quot;911&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;937&quot; data-start=&quot;911&quot; data-ke-size=&quot;size16&quot;&gt;즉, GIMP에서 수정할 때 기준은 단순합니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;&quot;&gt;&lt;code&gt;검정색으로 칠하면 장애물
흰색으로 칠하면 이동 가능 공간
회색으로 칠하면 미확인 영역&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;1019&quot; data-start=&quot;1005&quot; data-section-id=&quot;1q0063m&quot; data-ke-size=&quot;size18&quot;&gt;2) YAML 파일&lt;/p&gt;
&lt;p data-end=&quot;1024&quot; data-start=&quot;1021&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;1024&quot; data-start=&quot;1021&quot; data-ke-size=&quot;size16&quot;&gt;예시:&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot;&gt;&lt;code&gt;image: turtlebot3_map.pgm
mode: trinary
resolution: 0.05
origin: [-1.21, -2.4, 0]
negate: 0
occupied_thresh: 0.65
free_thresh: 0.25&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;1177&quot; data-start=&quot;1163&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;343&quot; data-start=&quot;310&quot; data-section-id=&quot;v4613o&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;a. image: turtlebot3_map.pgm&lt;/span&gt;&lt;/p&gt;
&lt;p data-end=&quot;361&quot; data-start=&quot;345&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;361&quot; data-start=&quot;345&quot; data-ke-size=&quot;size16&quot;&gt;지도 이미지 파일 이름입니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;arduino&quot;&gt;&lt;code&gt;image: turtlebot3_map.pgm&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;448&quot; data-start=&quot;402&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;448&quot; data-start=&quot;402&quot; data-ke-size=&quot;size16&quot;&gt;turtlebot3_map.pgm 파일을 실제 맵 이미지로 사용한다는 뜻입니다.&amp;nbsp;PGM 이미지는 흑백 이미지입니다.&lt;/p&gt;
&lt;p data-end=&quot;595&quot; data-start=&quot;550&quot; data-ke-size=&quot;size16&quot;&gt;이 이미지를 기반으로 로봇이 갈 수 있는 곳과 갈 수 없는 곳을 판단합니다.&lt;/p&gt;
&lt;p data-end=&quot;595&quot; data-start=&quot;550&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;595&quot; data-start=&quot;550&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;623&quot; data-start=&quot;602&quot; data-section-id=&quot;m1uga3&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;2. mode: trinary&lt;/span&gt;&lt;/p&gt;
&lt;p data-end=&quot;648&quot; data-start=&quot;625&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;648&quot; data-start=&quot;625&quot; data-ke-size=&quot;size16&quot;&gt;이미지를 지도 값으로 변환하는 방식입니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;avrasm&quot;&gt;&lt;code&gt;mode: trinary&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;706&quot; data-start=&quot;677&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;706&quot; data-start=&quot;677&quot; data-ke-size=&quot;size16&quot;&gt;trinary는 맵을 세 가지 값으로만 나눕니다.&lt;/p&gt;
&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;상태&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;Occupancy Grid 값&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 의미
&lt;table style=&quot;border-collapse: collapse; width: 69.0698%;&quot; border=&quot;1&quot; data-end=&quot;831&quot; data-start=&quot;708&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody data-end=&quot;831&quot; data-start=&quot;754&quot;&gt;
&lt;tr data-end=&quot;776&quot; data-start=&quot;754&quot;&gt;
&lt;td style=&quot;width: 20.814%;&quot; data-col-size=&quot;sm&quot; data-end=&quot;761&quot; data-start=&quot;754&quot;&gt;Free&lt;/td&gt;
&lt;td style=&quot;width: 30.2065%;&quot; data-col-size=&quot;sm&quot; data-end=&quot;767&quot; data-start=&quot;761&quot;&gt;0&lt;/td&gt;
&lt;td style=&quot;width: 22.0098%;&quot; data-col-size=&quot;sm&quot; data-end=&quot;776&quot; data-start=&quot;767&quot;&gt;이동 가능&lt;/td&gt;
&lt;/tr&gt;
&lt;tr data-end=&quot;803&quot; data-start=&quot;777&quot;&gt;
&lt;td style=&quot;width: 20.814%;&quot; data-col-size=&quot;sm&quot; data-end=&quot;788&quot; data-start=&quot;777&quot;&gt;Occupied&lt;/td&gt;
&lt;td style=&quot;width: 30.2065%;&quot; data-end=&quot;796&quot; data-start=&quot;788&quot; data-col-size=&quot;sm&quot;&gt;100&lt;/td&gt;
&lt;td style=&quot;width: 22.0098%;&quot; data-end=&quot;803&quot; data-start=&quot;796&quot; data-col-size=&quot;sm&quot;&gt;장애물&lt;/td&gt;
&lt;/tr&gt;
&lt;tr data-end=&quot;831&quot; data-start=&quot;804&quot;&gt;
&lt;td style=&quot;width: 20.814%;&quot; data-col-size=&quot;sm&quot; data-end=&quot;814&quot; data-start=&quot;804&quot;&gt;Unknown&lt;/td&gt;
&lt;td style=&quot;width: 30.2065%;&quot; data-col-size=&quot;sm&quot; data-end=&quot;821&quot; data-start=&quot;814&quot;&gt;-1&lt;/td&gt;
&lt;td style=&quot;width: 22.0098%;&quot; data-col-size=&quot;sm&quot; data-end=&quot;831&quot; data-start=&quot;821&quot;&gt;알 수 없음&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;p data-end=&quot;897&quot; data-start=&quot;833&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;897&quot; data-start=&quot;833&quot; data-ke-size=&quot;size16&quot;&gt;즉, 애매한 회색 값도 임계값 기준으로 &lt;b&gt;free / occupied / unknown&lt;/b&gt; 중 하나로 분류합니다.&lt;/p&gt;
&lt;p data-end=&quot;897&quot; data-start=&quot;833&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;931&quot; data-start=&quot;899&quot; data-ke-size=&quot;size16&quot;&gt;ROS Navigation에서 가장 흔히 쓰는 방식입니다.&lt;/p&gt;
&lt;p data-end=&quot;931&quot; data-start=&quot;899&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;931&quot; data-start=&quot;899&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;931&quot; data-start=&quot;899&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;962&quot; data-start=&quot;938&quot; data-section-id=&quot;ph3v9z&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;3. resolution: 0.05&lt;/span&gt;&lt;/p&gt;
&lt;p data-end=&quot;1000&quot; data-start=&quot;964&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;1000&quot; data-start=&quot;964&quot; data-ke-size=&quot;size16&quot;&gt;지도 이미지의 픽셀 하나가 실제 세계에서 몇 미터인지 나타냅니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;yaml&quot;&gt;&lt;code&gt;resolution: 0.05&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;1035&quot; data-start=&quot;1032&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;1035&quot; data-start=&quot;1032&quot; data-ke-size=&quot;size16&quot;&gt;뜻은:&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;basic&quot;&gt;&lt;code&gt;1 pixel = 0.05 m&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;1069&quot; data-start=&quot;1067&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;1069&quot; data-start=&quot;1067&quot; data-ke-size=&quot;size16&quot;&gt;즉,&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;basic&quot;&gt;&lt;code&gt;1 pixel = 5 cm&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;1142&quot; data-start=&quot;1099&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;1142&quot; data-start=&quot;1099&quot; data-ke-size=&quot;size16&quot;&gt;예를 들어 이미지 크기가 400 x 400 pixel이면 실제 맵 크기는:&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;basic&quot;&gt;&lt;code&gt;400 &amp;times; 0.05 = 20 m&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;1189&quot; data-start=&quot;1175&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;1189&quot; data-start=&quot;1175&quot; data-ke-size=&quot;size16&quot;&gt;따라서 실제 공간 크기는:&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;basic&quot;&gt;&lt;code&gt;20 m &amp;times; 20 m&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;1220&quot; data-start=&quot;1216&quot; data-ke-size=&quot;size16&quot;&gt;입니다.&lt;/p&gt;
&lt;p data-end=&quot;1251&quot; data-start=&quot;1222&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;1251&quot; data-start=&quot;1222&quot; data-ke-size=&quot;size16&quot;&gt;해상도가 작을수록 정밀하지만, 맵 데이터가 커집니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;resolution&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;의미
&lt;table style=&quot;border-collapse: collapse; width: 54.4186%;&quot; border=&quot;1&quot; data-end=&quot;1392&quot; data-start=&quot;1253&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody data-end=&quot;1392&quot; data-start=&quot;1284&quot;&gt;
&lt;tr data-end=&quot;1313&quot; data-start=&quot;1284&quot;&gt;
&lt;td style=&quot;width: 15.3488%;&quot; data-col-size=&quot;sm&quot; data-end=&quot;1293&quot; data-start=&quot;1284&quot;&gt;0.01&lt;/td&gt;
&lt;td style=&quot;width: 38.9535%;&quot; data-end=&quot;1313&quot; data-start=&quot;1293&quot; data-col-size=&quot;sm&quot;&gt;1픽셀 = 1cm, 매우 정밀&lt;/td&gt;
&lt;/tr&gt;
&lt;tr data-end=&quot;1355&quot; data-start=&quot;1314&quot;&gt;
&lt;td style=&quot;width: 15.3488%;&quot; data-col-size=&quot;sm&quot; data-end=&quot;1323&quot; data-start=&quot;1314&quot;&gt;0.05&lt;/td&gt;
&lt;td style=&quot;width: 38.9535%;&quot; data-end=&quot;1355&quot; data-start=&quot;1323&quot; data-col-size=&quot;sm&quot;&gt;1픽셀 = 5cm, 일반적인 TurtleBot3 맵&lt;/td&gt;
&lt;/tr&gt;
&lt;tr data-end=&quot;1392&quot; data-start=&quot;1356&quot;&gt;
&lt;td style=&quot;width: 15.3488%;&quot; data-col-size=&quot;sm&quot; data-end=&quot;1365&quot; data-start=&quot;1356&quot;&gt;0.10&lt;/td&gt;
&lt;td style=&quot;width: 38.9535%;&quot; data-end=&quot;1392&quot; data-start=&quot;1365&quot; data-col-size=&quot;sm&quot;&gt;1픽셀 = 10cm, 덜 정밀하지만 가벼움&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;1431&quot; data-start=&quot;1399&quot; data-section-id=&quot;5c06ur&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;4. origin: [-1.21, -2.4, 0]&lt;/span&gt;&lt;/p&gt;
&lt;p data-end=&quot;1470&quot; data-start=&quot;1433&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;1470&quot; data-start=&quot;1433&quot; data-ke-size=&quot;size16&quot;&gt;지도 이미지의 원점이 실제 좌표계에서 어디에 위치하는지 나타냅니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;origin: [-1.21, -2.4, 0]&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;1523&quot; data-start=&quot;1510&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;1523&quot; data-start=&quot;1510&quot; data-ke-size=&quot;size16&quot;&gt;형식은 다음과 같습니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;gml&quot;&gt;&lt;code&gt;origin: [x, y, yaw]&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;1567&quot; data-start=&quot;1558&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;1725&quot; data-start=&quot;1688&quot; data-ke-size=&quot;size16&quot;&gt;이 맵의 왼쪽 아래 픽셀 위치가 실제 /map 좌표계에서:&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;ini&quot;&gt;&lt;code&gt;x = -1.21 m
y = -2.4 m
yaw = 0 rad&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;1787&quot; data-start=&quot;1775&quot; data-ke-size=&quot;size16&quot;&gt;에 놓인다는 뜻입니다.&lt;/p&gt;
&lt;p data-end=&quot;1787&quot; data-start=&quot;1775&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;1893&quot; data-start=&quot;1789&quot; data-ke-size=&quot;size16&quot;&gt;중요한 점은 origin은 보통 &lt;b&gt;이미지의 왼쪽 아래 모서리 기준&lt;/b&gt;입니다.&lt;/p&gt;
&lt;p data-end=&quot;1893&quot; data-start=&quot;1789&quot; data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;PGM 이미지는 화면상으로는 왼쪽 위부터 보이지만, ROS 좌표계에서는 왼쪽 아래를 기준으로 봅니다.&lt;/p&gt;
&lt;p data-end=&quot;1893&quot; data-start=&quot;1789&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;1893&quot; data-start=&quot;1789&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;1893&quot; data-start=&quot;1789&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;1917&quot; data-start=&quot;1900&quot; data-section-id=&quot;g9er3c&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;5. negate: 0&lt;/span&gt;&lt;/p&gt;
&lt;p data-end=&quot;1942&quot; data-start=&quot;1919&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;1942&quot; data-start=&quot;1919&quot; data-ke-size=&quot;size16&quot;&gt;이미지의 흑백 의미를 반전할지 여부입니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;yaml&quot;&gt;&lt;code&gt;negate: 0&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;1983&quot; data-start=&quot;1967&quot; data-ke-size=&quot;size16&quot;&gt;0이면 반전하지 않습니다.&lt;/p&gt;
&lt;p data-end=&quot;1994&quot; data-start=&quot;1985&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;1994&quot; data-start=&quot;1985&quot; data-ke-size=&quot;size16&quot;&gt;일반적인 해석은:&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 색상&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;의미
&lt;table style=&quot;border-collapse: collapse; width: 44.5349%;&quot; border=&quot;1&quot; data-end=&quot;2046&quot; data-start=&quot;1996&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody data-end=&quot;2046&quot; data-start=&quot;2018&quot;&gt;
&lt;tr data-end=&quot;2031&quot; data-start=&quot;2018&quot;&gt;
&lt;td style=&quot;width: 20.1163%;&quot; data-col-size=&quot;sm&quot; data-end=&quot;2024&quot; data-start=&quot;2018&quot;&gt;검은색&lt;/td&gt;
&lt;td style=&quot;width: 24.3023%;&quot; data-end=&quot;2031&quot; data-start=&quot;2024&quot; data-col-size=&quot;sm&quot;&gt;장애물&lt;/td&gt;
&lt;/tr&gt;
&lt;tr data-end=&quot;2046&quot; data-start=&quot;2032&quot;&gt;
&lt;td style=&quot;width: 20.1163%;&quot; data-col-size=&quot;sm&quot; data-end=&quot;2037&quot; data-start=&quot;2032&quot;&gt;흰색&lt;/td&gt;
&lt;td style=&quot;width: 24.3023%;&quot; data-end=&quot;2046&quot; data-start=&quot;2037&quot; data-col-size=&quot;sm&quot;&gt;자유 공간&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;2075&quot; data-start=&quot;2048&quot; data-ke-size=&quot;size16&quot;&gt;만약 negate: 1이면 반대로 해석됩니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 색상&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 의미
&lt;table style=&quot;border-collapse: collapse; width: 45.5814%;&quot; border=&quot;1&quot; data-end=&quot;2127&quot; data-start=&quot;2077&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody data-end=&quot;2127&quot; data-start=&quot;2099&quot;&gt;
&lt;tr data-end=&quot;2114&quot; data-start=&quot;2099&quot;&gt;
&lt;td style=&quot;width: 21.1628%;&quot; data-col-size=&quot;sm&quot; data-end=&quot;2105&quot; data-start=&quot;2099&quot;&gt;검은색&lt;/td&gt;
&lt;td style=&quot;width: 24.3023%;&quot; data-col-size=&quot;sm&quot; data-end=&quot;2114&quot; data-start=&quot;2105&quot;&gt;자유 공간&lt;/td&gt;
&lt;/tr&gt;
&lt;tr data-end=&quot;2127&quot; data-start=&quot;2115&quot;&gt;
&lt;td style=&quot;width: 21.1628%;&quot; data-col-size=&quot;sm&quot; data-end=&quot;2120&quot; data-start=&quot;2115&quot;&gt;흰색&lt;/td&gt;
&lt;td style=&quot;width: 24.3023%;&quot; data-end=&quot;2127&quot; data-start=&quot;2120&quot; data-col-size=&quot;sm&quot;&gt;장애물&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;2167&quot; data-start=&quot;2129&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;2167&quot; data-start=&quot;2129&quot; data-ke-size=&quot;size16&quot;&gt;대부분의 SLAM으로 생성된 맵은 negate: 0을 사용합니다.&lt;/p&gt;
&lt;p data-end=&quot;2167&quot; data-start=&quot;2129&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;2167&quot; data-start=&quot;2129&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;2167&quot; data-start=&quot;2129&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;2203&quot; data-start=&quot;2174&quot; data-section-id=&quot;mq0aon&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;6. occupied_thresh: 0.65&lt;/span&gt;&lt;/p&gt;
&lt;p data-end=&quot;2203&quot; data-start=&quot;2174&quot; data-section-id=&quot;mq0aon&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;2222&quot; data-start=&quot;2205&quot; data-ke-size=&quot;size16&quot;&gt;장애물로 판단하는 임계값입니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;yaml&quot;&gt;&lt;code&gt;occupied_thresh: 0.65&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;2300&quot; data-start=&quot;2259&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;2300&quot; data-start=&quot;2259&quot; data-ke-size=&quot;size16&quot;&gt;픽셀의 occupancy 확률이 0.65 이상이면 장애물로 판단합니다.&lt;/p&gt;
&lt;p data-end=&quot;2300&quot; data-start=&quot;2259&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;occupancy &amp;gt;= 0.65 &amp;rarr; Occupied&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;2378&quot; data-start=&quot;2344&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;2378&quot; data-start=&quot;2344&quot; data-ke-size=&quot;size16&quot;&gt;즉, 장애물일 확률이 65% 이상이면 해당 셀은 장애물입니다.&lt;/p&gt;
&lt;p data-end=&quot;2378&quot; data-start=&quot;2344&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;2422&quot; data-start=&quot;2380&quot; data-ke-size=&quot;size16&quot;&gt;Occupancy Grid에서는 보통 장애물 셀이 100으로 표현됩니다.&lt;/p&gt;
&lt;p data-end=&quot;2422&quot; data-start=&quot;2380&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;1053&quot; data-start=&quot;1022&quot; data-ke-size=&quot;size16&quot;&gt;negate: 0일 때 occupancy 확률은 아래의 식으로 구할 수 있습니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;occupancy = (255 - pixel_value) / 255&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;2422&quot; data-start=&quot;2380&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;2422&quot; data-start=&quot;2380&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;2422&quot; data-start=&quot;2380&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;2454&quot; data-start=&quot;2429&quot; data-section-id=&quot;jur6uc&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;7. free_thresh: 0.25&lt;/span&gt;&lt;/p&gt;
&lt;p data-end=&quot;2480&quot; data-start=&quot;2456&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;2480&quot; data-start=&quot;2456&quot; data-ke-size=&quot;size16&quot;&gt;이동 가능한 공간으로 판단하는 임계값입니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;yaml&quot;&gt;&lt;code&gt;free_thresh: 0.25&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;2557&quot; data-start=&quot;2513&quot; data-ke-size=&quot;size16&quot;&gt;픽셀의 occupancy 확률이 0.25 이하이면 자유 공간으로 판단합니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;occupancy &amp;lt;= 0.25 &amp;rarr; Free&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;2631&quot; data-start=&quot;2597&quot; data-ke-size=&quot;size16&quot;&gt;즉, 장애물일 확률이 25% 이하이면 이동 가능한 공간입니다.&lt;/p&gt;
&lt;p data-end=&quot;2631&quot; data-start=&quot;2597&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;2673&quot; data-start=&quot;2633&quot; data-ke-size=&quot;size16&quot;&gt;Occupancy Grid에서는 보통 자유 공간이 0으로 표현됩니다.&lt;/p&gt;
&lt;p data-end=&quot;2673&quot; data-start=&quot;2633&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;2673&quot; data-start=&quot;2633&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;2673&quot; data-start=&quot;2633&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;2723&quot; data-start=&quot;2680&quot; data-section-id=&quot;170wszz&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;8. occupied_thresh와 free_thresh 사이 값&lt;/span&gt;&lt;/p&gt;
&lt;p data-end=&quot;2753&quot; data-start=&quot;2725&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;2753&quot; data-start=&quot;2725&quot; data-ke-size=&quot;size16&quot;&gt;두 임계값 사이의 값은 미확인 영역으로 처리됩니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;0.25 &amp;lt; occupancy &amp;lt; 0.65 &amp;rarr; Unknown&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;2804&quot; data-start=&quot;2802&quot; data-ke-size=&quot;size16&quot;&gt;즉:&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;occupancy 값결과
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-end=&quot;2919&quot; data-start=&quot;2806&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody data-end=&quot;2919&quot; data-start=&quot;2838&quot;&gt;
&lt;tr data-end=&quot;2862&quot; data-start=&quot;2838&quot;&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;2854&quot; data-start=&quot;2838&quot;&gt;0.00 ~ 0.25&lt;/td&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;2862&quot; data-start=&quot;2854&quot;&gt;Free&lt;/td&gt;
&lt;/tr&gt;
&lt;tr data-end=&quot;2890&quot; data-start=&quot;2863&quot;&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;2879&quot; data-start=&quot;2863&quot;&gt;0.25 ~ 0.65&lt;/td&gt;
&lt;td data-end=&quot;2890&quot; data-start=&quot;2879&quot; data-col-size=&quot;sm&quot;&gt;Unknown&lt;/td&gt;
&lt;/tr&gt;
&lt;tr data-end=&quot;2919&quot; data-start=&quot;2891&quot;&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;2907&quot; data-start=&quot;2891&quot;&gt;0.65 ~ 1.00&lt;/td&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;2919&quot; data-start=&quot;2907&quot;&gt;Occupied&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;1493&quot; data-start=&quot;1441&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;1493&quot; data-start=&quot;1441&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;1493&quot; data-start=&quot;1441&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-end=&quot;1516&quot; data-start=&quot;1500&quot; data-section-id=&quot;1gw0g5w&quot; data-ke-size=&quot;size20&quot;&gt;3. GIMP로 지도 열기&lt;/h4&gt;
&lt;p data-end=&quot;1527&quot; data-start=&quot;1518&quot; data-ke-size=&quot;size16&quot;&gt;터미널에서 실행:&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;cpp&quot;&gt;&lt;code&gt;gimp map.pgm&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;1571&quot; data-start=&quot;1555&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;1571&quot; data-start=&quot;1555&quot; data-ke-size=&quot;size16&quot;&gt;또는 GIMP에서 직접 열기:&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;vhdl&quot;&gt;&lt;code&gt;File &amp;rarr; Open &amp;rarr; map.pgm&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;1633&quot; data-start=&quot;1608&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1028&quot; data-origin-height=&quot;745&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/buDT7g/dJMcaa6Gz0i/fDEOP5SDxE2KWLGlrxGkLK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/buDT7g/dJMcaa6Gz0i/fDEOP5SDxE2KWLGlrxGkLK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/buDT7g/dJMcaa6Gz0i/fDEOP5SDxE2KWLGlrxGkLK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbuDT7g%2FdJMcaa6Gz0i%2FfDEOP5SDxE2KWLGlrxGkLK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1028&quot; height=&quot;745&quot; data-origin-width=&quot;1028&quot; data-origin-height=&quot;745&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-end=&quot;1633&quot; data-start=&quot;1608&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1044&quot; data-origin-height=&quot;823&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ZZsa7/dJMcaftk4K2/1PAWXj3pbQz1FgZjq3VLLK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ZZsa7/dJMcaftk4K2/1PAWXj3pbQz1FgZjq3VLLK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ZZsa7/dJMcaftk4K2/1PAWXj3pbQz1FgZjq3VLLK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FZZsa7%2FdJMcaftk4K2%2F1PAWXj3pbQz1FgZjq3VLLK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1044&quot; height=&quot;823&quot; data-origin-width=&quot;1044&quot; data-origin-height=&quot;823&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-end=&quot;1633&quot; data-start=&quot;1608&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;1633&quot; data-start=&quot;1608&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;1633&quot; data-start=&quot;1608&quot; data-ke-size=&quot;size16&quot;&gt;파일을 연 후 먼저 이미지 모드를 확인합니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;mathematica&quot;&gt;&lt;code&gt;Image &amp;rarr; Mode &amp;rarr; Grayscale&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;1716&quot; data-start=&quot;1673&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1026&quot; data-origin-height=&quot;805&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/EiSqw/dJMcabkelGY/WfcIORG7na9mNR6sodPkh0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/EiSqw/dJMcabkelGY/WfcIORG7na9mNR6sodPkh0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/EiSqw/dJMcabkelGY/WfcIORG7na9mNR6sodPkh0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FEiSqw%2FdJMcabkelGY%2FWfcIORG7na9mNR6sodPkh0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1026&quot; height=&quot;805&quot; data-origin-width=&quot;1026&quot; data-origin-height=&quot;805&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-end=&quot;1716&quot; data-start=&quot;1673&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;1716&quot; data-start=&quot;1673&quot; data-ke-size=&quot;size16&quot;&gt;ROS 2 지도는 일반적으로 흑백 Grayscale 이미지로 유지해야 합니다.&lt;/p&gt;
&lt;p data-end=&quot;1716&quot; data-start=&quot;1673&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;1716&quot; data-start=&quot;1673&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;1716&quot; data-start=&quot;1673&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-end=&quot;1735&quot; data-start=&quot;1723&quot; data-section-id=&quot;258mjl&quot; data-ke-size=&quot;size20&quot;&gt;4. 수정 전 백업&lt;/h4&gt;
&lt;p data-end=&quot;1769&quot; data-start=&quot;1737&quot; data-ke-size=&quot;size16&quot;&gt;원본을 바로 수정하면 안 됩니다. 먼저 복사본을 만듭니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot;&gt;&lt;code&gt;cp turtlebot3_map.pgm turtlebot3_map_origin.pgm
mv turtlebot3_map.pgm turtlebot3_map_modified.pgm&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;2001&quot; data-start=&quot;1970&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;2001&quot; data-start=&quot;1970&quot; data-ke-size=&quot;size16&quot;&gt;이후에는 map_modified.pgm만 수정합니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;arcade&quot;&gt;&lt;code&gt;gimp ~/maps/edit/map_modified.pgm&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1044&quot; data-origin-height=&quot;823&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/uVwWn/dJMcaci2ONq/VIbN6bKbNjFHhfPE6Oq1l0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/uVwWn/dJMcaci2ONq/VIbN6bKbNjFHhfPE6Oq1l0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/uVwWn/dJMcaci2ONq/VIbN6bKbNjFHhfPE6Oq1l0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FuVwWn%2FdJMcaci2ONq%2FVIbN6bKbNjFHhfPE6Oq1l0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1044&quot; height=&quot;823&quot; data-origin-width=&quot;1044&quot; data-origin-height=&quot;823&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-end=&quot;2077&quot; data-start=&quot;2055&quot; data-section-id=&quot;k0u1fn&quot; data-ke-size=&quot;size20&quot;&gt;5. GIMP에서 주로 사용하는 도구&lt;/h4&gt;
&lt;p data-end=&quot;2100&quot; data-start=&quot;2079&quot; data-section-id=&quot;11elv73&quot; data-ke-size=&quot;size18&quot;&gt;1) Pencil Tool 사용&lt;/p&gt;
&lt;p data-end=&quot;2136&quot; data-start=&quot;2102&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;2136&quot; data-start=&quot;2102&quot; data-ke-size=&quot;size16&quot;&gt;지도 수정에는 Brush보다 Pencil Tool이 좋습니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;nginx&quot;&gt;&lt;code&gt;Tools &amp;rarr; Paint Tools &amp;rarr; Pencil&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;2184&quot; data-start=&quot;2180&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1339&quot; data-origin-height=&quot;1047&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bKp1yo/dJMcagTlkha/9rDlNwOunDpk2nEVR5Wo81/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bKp1yo/dJMcagTlkha/9rDlNwOunDpk2nEVR5Wo81/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bKp1yo/dJMcagTlkha/9rDlNwOunDpk2nEVR5Wo81/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbKp1yo%2FdJMcagTlkha%2F9rDlNwOunDpk2nEVR5Wo81%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1339&quot; height=&quot;1047&quot; data-origin-width=&quot;1339&quot; data-origin-height=&quot;1047&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-end=&quot;2184&quot; data-start=&quot;2180&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;2184&quot; data-start=&quot;2180&quot; data-ke-size=&quot;size16&quot;&gt;단축키:&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;ebnf&quot;&gt;&lt;code&gt;N&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;2207&quot; data-start=&quot;2201&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;2207&quot; data-start=&quot;2201&quot; data-ke-size=&quot;size16&quot;&gt;권장 설정:&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;yaml&quot;&gt;&lt;code&gt;Opacity: 100%
Hardness: 100%&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;2294&quot; data-start=&quot;2251&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;2294&quot; data-start=&quot;2251&quot; data-ke-size=&quot;size16&quot;&gt;Pencil Tool은 가장자리를 흐리게 만들지 않아 지도 수정에 적합합니다.&lt;/p&gt;
&lt;p data-end=&quot;2294&quot; data-start=&quot;2251&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;2294&quot; data-start=&quot;2251&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;2294&quot; data-start=&quot;2251&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;2317&quot; data-start=&quot;2301&quot; data-section-id=&quot;10df9x9&quot; data-ke-size=&quot;size18&quot;&gt;2) 색상별 수정 기준&lt;/p&gt;
&lt;div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 50.6977%;&quot; border=&quot;1&quot; data-end=&quot;2453&quot; data-start=&quot;2319&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody data-end=&quot;2453&quot; data-start=&quot;2348&quot;&gt;
&lt;tr data-end=&quot;2362&quot; data-start=&quot;2348&quot;&gt;
&lt;td style=&quot;width: 28.1395%;&quot; data-col-size=&quot;sm&quot; data-end=&quot;2355&quot; data-start=&quot;2348&quot;&gt;벽 추가&lt;/td&gt;
&lt;td style=&quot;width: 22.5582%;&quot; data-col-size=&quot;sm&quot; data-end=&quot;2362&quot; data-start=&quot;2355&quot;&gt;검정색&lt;/td&gt;
&lt;/tr&gt;
&lt;tr data-end=&quot;2380&quot; data-start=&quot;2363&quot;&gt;
&lt;td style=&quot;width: 28.1395%;&quot; data-col-size=&quot;sm&quot; data-end=&quot;2373&quot; data-start=&quot;2363&quot;&gt;가상 벽 추가&lt;/td&gt;
&lt;td style=&quot;width: 22.5582%;&quot; data-col-size=&quot;sm&quot; data-end=&quot;2380&quot; data-start=&quot;2373&quot;&gt;검정색&lt;/td&gt;
&lt;/tr&gt;
&lt;tr data-end=&quot;2396&quot; data-start=&quot;2381&quot;&gt;
&lt;td style=&quot;width: 28.1395%;&quot; data-col-size=&quot;sm&quot; data-end=&quot;2390&quot; data-start=&quot;2381&quot;&gt;노이즈 제거&lt;/td&gt;
&lt;td style=&quot;width: 22.5582%;&quot; data-end=&quot;2396&quot; data-start=&quot;2390&quot; data-col-size=&quot;sm&quot;&gt;흰색&lt;/td&gt;
&lt;/tr&gt;
&lt;tr data-end=&quot;2416&quot; data-start=&quot;2397&quot;&gt;
&lt;td style=&quot;width: 28.1395%;&quot; data-col-size=&quot;sm&quot; data-end=&quot;2410&quot; data-start=&quot;2397&quot;&gt;잘못 생긴 벽 제거&lt;/td&gt;
&lt;td style=&quot;width: 22.5582%;&quot; data-col-size=&quot;sm&quot; data-end=&quot;2416&quot; data-start=&quot;2410&quot;&gt;흰색&lt;/td&gt;
&lt;/tr&gt;
&lt;tr data-end=&quot;2434&quot; data-start=&quot;2417&quot;&gt;
&lt;td style=&quot;width: 28.1395%;&quot; data-col-size=&quot;sm&quot; data-end=&quot;2428&quot; data-start=&quot;2417&quot;&gt;지도 외곽 정리&lt;/td&gt;
&lt;td style=&quot;width: 22.5582%;&quot; data-end=&quot;2434&quot; data-start=&quot;2428&quot; data-col-size=&quot;sm&quot;&gt;회색&lt;/td&gt;
&lt;/tr&gt;
&lt;tr data-end=&quot;2453&quot; data-start=&quot;2435&quot;&gt;
&lt;td style=&quot;width: 28.1395%;&quot; data-col-size=&quot;sm&quot; data-end=&quot;2447&quot; data-start=&quot;2435&quot;&gt;미확인 영역 복원&lt;/td&gt;
&lt;td style=&quot;width: 22.5582%;&quot; data-col-size=&quot;sm&quot; data-end=&quot;2453&quot; data-start=&quot;2447&quot;&gt;회색&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1357&quot; data-origin-height=&quot;1063&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/brGDvf/dJMcabxGQp5/ZOrR3oQBFoD0H48jDEJtHk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/brGDvf/dJMcabxGQp5/ZOrR3oQBFoD0H48jDEJtHk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/brGDvf/dJMcabxGQp5/ZOrR3oQBFoD0H48jDEJtHk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbrGDvf%2FdJMcabxGQp5%2FZOrR3oQBFoD0H48jDEJtHk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1357&quot; height=&quot;1063&quot; data-origin-width=&quot;1357&quot; data-origin-height=&quot;1063&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-end=&quot;2478&quot; data-start=&quot;2460&quot; data-section-id=&quot;1urlcli&quot; data-ke-size=&quot;size20&quot;&gt;6. 대표적인 지도 수정 작업&lt;/h4&gt;
&lt;p data-end=&quot;2498&quot; data-start=&quot;2480&quot; data-section-id=&quot;o1wa6v&quot; data-ke-size=&quot;size18&quot;&gt;1) SLAM 노이즈 제거&lt;/p&gt;
&lt;p data-end=&quot;2538&quot; data-start=&quot;2500&quot; data-ke-size=&quot;size16&quot;&gt;SLAM 후 지도에 작은 검은 점이나 이상한 선이 생길 수 있습니다.&lt;/p&gt;
&lt;p data-end=&quot;2568&quot; data-start=&quot;2540&quot; data-ke-size=&quot;size16&quot;&gt;이런 노이즈는 로봇이 장애물로 인식할 수 있습니다.&lt;/p&gt;
&lt;p data-end=&quot;2568&quot; data-start=&quot;2540&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;2576&quot; data-start=&quot;2570&quot; data-ke-size=&quot;size16&quot;&gt;수정 방법:&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;1. Pencil Tool 선택
2. 흰색 선택
3. 검은 노이즈를 흰색으로 칠함
4. 저장&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;2666&quot; data-start=&quot;2648&quot; data-section-id=&quot;1gcqkct&quot; data-ke-size=&quot;size18&quot;&gt;2) 잘못 생성된 벽 제거&lt;/p&gt;
&lt;p data-end=&quot;2716&quot; data-start=&quot;2668&quot; data-ke-size=&quot;size16&quot;&gt;사람, 임시 물체, 센서 오류 때문에 복도 중간에 벽처럼 생긴 선이 생길 수 있습니다.&lt;/p&gt;
&lt;p data-end=&quot;2716&quot; data-start=&quot;2668&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;2724&quot; data-start=&quot;2718&quot; data-ke-size=&quot;size16&quot;&gt;수정 방법:&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;1. 흰색 선택
2. 잘못된 검은 선을 흰색으로 지움
3. 실제 벽은 지우지 않도록 주의&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;2825&quot; data-start=&quot;2789&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;2825&quot; data-start=&quot;2789&quot; data-ke-size=&quot;size16&quot;&gt;실제 벽을 지우면 로봇이 벽을 통과하는 경로를 만들 수 있습니다.&lt;/p&gt;
&lt;p data-end=&quot;2825&quot; data-start=&quot;2789&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;2825&quot; data-start=&quot;2789&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;2825&quot; data-start=&quot;2789&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;2846&quot; data-start=&quot;2832&quot; data-section-id=&quot;1esinae&quot; data-ke-size=&quot;size18&quot;&gt;3) 가상 벽 추가&lt;/p&gt;
&lt;p data-end=&quot;2882&quot; data-start=&quot;2848&quot; data-ke-size=&quot;size16&quot;&gt;로봇이 들어가면 안 되는 구역은 검은색으로 막을 수 있습니다.&lt;/p&gt;
&lt;p data-end=&quot;2882&quot; data-start=&quot;2848&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;2886&quot; data-start=&quot;2884&quot; data-ke-size=&quot;size16&quot;&gt;예:&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;&quot;&gt;&lt;code&gt;계단
위험 구역
사람 전용 공간
유리문 근처
좁은 통로&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;2938&quot; data-start=&quot;2932&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;2938&quot; data-start=&quot;2932&quot; data-ke-size=&quot;size16&quot;&gt;수정 방법:&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;1. 검정색 선택
2. Pencil Tool 또는 Rectangle Select Tool 사용
3. 진입 금지 구역 앞에 검정색 선 추가&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;3036&quot; data-start=&quot;3030&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;3036&quot; data-start=&quot;3030&quot; data-ke-size=&quot;size16&quot;&gt;권장 두께:&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;3~10 pixel 정도&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;3108&quot; data-start=&quot;3065&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;3108&quot; data-start=&quot;3065&quot; data-ke-size=&quot;size16&quot;&gt;너무 얇으면 Nav2 costmap에서 안정적으로 반영되지 않을 수 있습니다.&lt;/p&gt;
&lt;p data-end=&quot;3108&quot; data-start=&quot;3065&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1357&quot; data-origin-height=&quot;1063&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/EMZjN/dJMcaayP1qv/jPF6CfTYnj3oxvQiJaXG41/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/EMZjN/dJMcaayP1qv/jPF6CfTYnj3oxvQiJaXG41/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/EMZjN/dJMcaayP1qv/jPF6CfTYnj3oxvQiJaXG41/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FEMZjN%2FdJMcaayP1qv%2FjPF6CfTYnj3oxvQiJaXG41%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1357&quot; height=&quot;1063&quot; data-origin-width=&quot;1357&quot; data-origin-height=&quot;1063&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-end=&quot;3108&quot; data-start=&quot;3065&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;3108&quot; data-start=&quot;3065&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;3108&quot; data-start=&quot;3065&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;3130&quot; data-start=&quot;3115&quot; data-section-id=&quot;6cdzo1&quot; data-ke-size=&quot;size18&quot;&gt;4) 지도 외곽 정리&lt;/p&gt;
&lt;p data-end=&quot;3172&quot; data-start=&quot;3132&quot; data-ke-size=&quot;size16&quot;&gt;지도 바깥이나 탐색하지 않은 영역은 흰색으로 만들지 않는 것이 좋습니다.&lt;/p&gt;
&lt;p data-end=&quot;3172&quot; data-start=&quot;3132&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;3177&quot; data-start=&quot;3174&quot; data-ke-size=&quot;size16&quot;&gt;권장:&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;fix&quot;&gt;&lt;code&gt;지도 외곽 = 회색&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;3244&quot; data-start=&quot;3203&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;3244&quot; data-start=&quot;3203&quot; data-ke-size=&quot;size16&quot;&gt;흰색으로 칠하면 로봇이 지도 밖을 이동 가능 영역으로 판단할 수 있습니다.&lt;/p&gt;
&lt;p data-end=&quot;3244&quot; data-start=&quot;3203&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;3244&quot; data-start=&quot;3203&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;3244&quot; data-start=&quot;3203&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;3244&quot; data-start=&quot;3203&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;3261&quot; data-start=&quot;3251&quot; data-section-id=&quot;1dak0au&quot; data-ke-size=&quot;size18&quot;&gt;7. 저장 방법&lt;/p&gt;
&lt;p data-end=&quot;3261&quot; data-start=&quot;3251&quot; data-section-id=&quot;1dak0au&quot; data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;3284&quot; data-start=&quot;3263&quot; data-ke-size=&quot;size16&quot;&gt;수정 후에는 Export로 저장합니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;delphi&quot;&gt;&lt;code&gt;File &amp;rarr; Export As&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1028&quot; data-origin-height=&quot;768&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/btfiIB/dJMcacDq6m3/YNMOxqViXTFffCILQJCL5k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/btfiIB/dJMcacDq6m3/YNMOxqViXTFffCILQJCL5k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/btfiIB/dJMcacDq6m3/YNMOxqViXTFffCILQJCL5k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbtfiIB%2FdJMcacDq6m3%2FYNMOxqViXTFffCILQJCL5k%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1028&quot; height=&quot;768&quot; data-origin-width=&quot;1028&quot; data-origin-height=&quot;768&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;3322&quot; data-start=&quot;3316&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1339&quot; data-origin-height=&quot;1047&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cyYuBi/dJMcacpS82w/vq0uIieHtsw50IYy2Ucnkk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cyYuBi/dJMcacpS82w/vq0uIieHtsw50IYy2Ucnkk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cyYuBi/dJMcacpS82w/vq0uIieHtsw50IYy2Ucnkk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcyYuBi%2FdJMcacpS82w%2Fvq0uIieHtsw50IYy2Ucnkk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1339&quot; height=&quot;1047&quot; data-origin-width=&quot;1339&quot; data-origin-height=&quot;1047&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-end=&quot;3322&quot; data-start=&quot;3316&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;3322&quot; data-start=&quot;3316&quot; data-ke-size=&quot;size16&quot;&gt;파일명 예:&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;css&quot;&gt;&lt;code&gt;map_modified.pgm&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;3372&quot; data-start=&quot;3354&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;3372&quot; data-start=&quot;3354&quot; data-ke-size=&quot;size16&quot;&gt;가능하면 다음 상태를 유지합니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;Grayscale
8-bit
PGM&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;3430&quot; data-start=&quot;3407&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;3430&quot; data-start=&quot;3407&quot; data-ke-size=&quot;size16&quot;&gt;레이어를 사용했다면 저장 전에 병합합니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;mathematica&quot;&gt;&lt;code&gt;Image &amp;rarr; Flatten Image&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1014&quot; data-origin-height=&quot;781&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bqRVYg/dJMcaiKkizl/AlgQvrMkqCy07V0TERNVlk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bqRVYg/dJMcaiKkizl/AlgQvrMkqCy07V0TERNVlk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bqRVYg/dJMcaiKkizl/AlgQvrMkqCy07V0TERNVlk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbqRVYg%2FdJMcaiKkizl%2FAlgQvrMkqCy07V0TERNVlk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1014&quot; height=&quot;781&quot; data-origin-width=&quot;1014&quot; data-origin-height=&quot;781&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h4 data-end=&quot;3487&quot; data-start=&quot;3472&quot; data-section-id=&quot;s5bwvo&quot; data-ke-size=&quot;size20&quot;&gt;8. YAML 파일 수정&lt;/h4&gt;
&lt;p data-end=&quot;3533&quot; data-start=&quot;3489&quot; data-ke-size=&quot;size16&quot;&gt;PGM 파일명을 바꿨다면 YAML 파일의 image 항목도 수정해야 합니다.&lt;/p&gt;
&lt;p data-end=&quot;3533&quot; data-start=&quot;3489&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;3533&quot; data-start=&quot;3489&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;3540&quot; data-start=&quot;3535&quot; data-ke-size=&quot;size16&quot;&gt;수정 전:&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot;&gt;&lt;code&gt;image: turtlebot3_map_origin.pgm
mode: trinary
resolution: 0.05
origin: [-1.21, -2.4, 0]
negate: 0
occupied_thresh: 0.65
free_thresh: 0.25&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;3684&quot; data-start=&quot;3679&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;3684&quot; data-start=&quot;3679&quot; data-ke-size=&quot;size16&quot;&gt;수정 후:&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot;&gt;&lt;code&gt;image: turtlebot3_map_modified.pgm
mode: trinary
resolution: 0.05
origin: [-1.21, -2.4, 0]
negate: 0
occupied_thresh: 0.65
free_thresh: 0.25&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;3838&quot; data-start=&quot;3832&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;890&quot; data-origin-height=&quot;547&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bF1R0D/dJMcaaFC3xR/wdCjLJBdkaPPl41PbHNuok/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bF1R0D/dJMcaaFC3xR/wdCjLJBdkaPPl41PbHNuok/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bF1R0D/dJMcaaFC3xR/wdCjLJBdkaPPl41PbHNuok/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbF1R0D%2FdJMcaaFC3xR%2FwdCjLJBdkaPPl41PbHNuok%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;890&quot; height=&quot;547&quot; data-origin-width=&quot;890&quot; data-origin-height=&quot;547&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-end=&quot;3838&quot; data-start=&quot;3832&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;952&quot; data-origin-height=&quot;799&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/YRix1/dJMcacXGM91/hZ3R8DK7klCMMeavd4f6o1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/YRix1/dJMcacXGM91/hZ3R8DK7klCMMeavd4f6o1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/YRix1/dJMcacXGM91/hZ3R8DK7klCMMeavd4f6o1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FYRix1%2FdJMcacXGM91%2FhZ3R8DK7klCMMeavd4f6o1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;952&quot; height=&quot;799&quot; data-origin-width=&quot;952&quot; data-origin-height=&quot;799&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-end=&quot;3838&quot; data-start=&quot;3832&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;3838&quot; data-start=&quot;3832&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;3838&quot; data-start=&quot;3832&quot; data-ke-size=&quot;size16&quot;&gt;주의할 점:&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;maxima&quot;&gt;&lt;code&gt;resolution 변경 금지
origin 변경 금지
이미지 크기 변경 금지&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;3935&quot; data-start=&quot;3896&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;3935&quot; data-start=&quot;3896&quot; data-ke-size=&quot;size16&quot;&gt;이 값들이 바뀌면 RViz에서 로봇 위치와 지도가 어긋날 수 있습니다.&lt;/p&gt;
&lt;p data-end=&quot;3935&quot; data-start=&quot;3896&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;3935&quot; data-start=&quot;3896&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;3935&quot; data-start=&quot;3896&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;3935&quot; data-start=&quot;3896&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-end=&quot;3956&quot; data-start=&quot;3942&quot; data-section-id=&quot;o1mfft&quot; data-ke-size=&quot;size20&quot;&gt;9. 수정한 지도 실행&lt;/h4&gt;
&lt;p data-end=&quot;3979&quot; data-start=&quot;3958&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;3979&quot; data-start=&quot;3958&quot; data-ke-size=&quot;size16&quot;&gt;Nav2에서 수정한 지도를 사용할 때:&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot;&gt;&lt;code&gt;ros2 launch turtlebot3_navigation2 navigation2.launch.py use_sim_time:=True \
  map:=$HOME/maps/turtlebot3_map_modified.yaml&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1630&quot; data-origin-height=&quot;948&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/LrUyD/dJMb99UbVol/YsoPWLXNWI8HKCU7sKvuf0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/LrUyD/dJMb99UbVol/YsoPWLXNWI8HKCU7sKvuf0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/LrUyD/dJMb99UbVol/YsoPWLXNWI8HKCU7sKvuf0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FLrUyD%2FdJMb99UbVol%2FYsoPWLXNWI8HKCU7sKvuf0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1630&quot; height=&quot;948&quot; data-origin-width=&quot;1630&quot; data-origin-height=&quot;948&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;새롭게 작성한 지도 위에서 Nav2 Goal을 이용하여 주행을 시작합니다. 다양한 위치를 목표지점으로 정하고 주행하면서 주행성능을 확인하시기 바랍니다.&lt;/p&gt;</description>
      <category>강좌/ROS2</category>
      <category>GIMP 사용 지도 수정</category>
      <author>MakingRobotWizard</author>
      <guid isPermaLink="true">https://makingrobot.tistory.com/438</guid>
      <comments>https://makingrobot.tistory.com/438#entry438comment</comments>
      <pubDate>Fri, 29 May 2026 00:18:20 +0900</pubDate>
    </item>
    <item>
      <title>Cancel 테스트용 Action Client 만들기</title>
      <link>https://makingrobot.tistory.com/436</link>
      <description>&lt;h4 data-end=&quot;118&quot; data-start=&quot;97&quot; data-section-id=&quot;gzn47k&quot; data-ke-size=&quot;size20&quot;&gt;1. Cancel 기능 실습 개요&lt;/h4&gt;
&lt;p data-end=&quot;167&quot; data-start=&quot;120&quot; data-ke-size=&quot;size16&quot;&gt;이번 실습에서는 실행 중인 Action Goal을 중간에 취소하는 방법을 확인합니다.&lt;/p&gt;
&lt;p data-end=&quot;267&quot; data-start=&quot;169&quot; data-ke-size=&quot;size16&quot;&gt;ROS 2 Action은 Client가 Server에 Goal을 보내고, Server는 작업을 수행하면서 Feedback을 보내다가 마지막에 Result를 반환하는 구조입니다.&lt;/p&gt;
&lt;p data-end=&quot;315&quot; data-start=&quot;269&quot; data-ke-size=&quot;size16&quot;&gt;여기서 Cancel 기능은 이미 실행 중인 Goal을 중간에 취소할 때 사용합니다.&lt;/p&gt;
&lt;p data-end=&quot;315&quot; data-start=&quot;269&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;401&quot; data-start=&quot;317&quot; data-ke-size=&quot;size16&quot;&gt;주의할 점은 일반적인 ROS 2 CLI 환경에서는 실행 중인 Action Goal을 직접 취소하는 다음 명령을 사용할 수 없는 경우가 많다는 것입니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;fortran&quot;&gt;&lt;code&gt;ros2 action cancel /dist_turtle&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;501&quot; data-start=&quot;448&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;501&quot; data-start=&quot;448&quot; data-ke-size=&quot;size16&quot;&gt;따라서 이번 실습에서는 별도의 Action Client를 작성해서 Cancel 요청을 보냅니다.&lt;/p&gt;
&lt;p data-end=&quot;527&quot; data-start=&quot;503&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;527&quot; data-start=&quot;503&quot; data-ke-size=&quot;size16&quot;&gt;Cancel 요청의 핵심 코드는 다음입니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;crystal&quot;&gt;&lt;code&gt;self._cancel_future = self.goal_handle.cancel_goal_async()&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;702&quot; data-start=&quot;603&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;702&quot; data-start=&quot;603&quot; data-ke-size=&quot;size16&quot;&gt;이 코드는 현재 Client가 보낸 Goal에 대해 Action Server로 Cancel 요청을 전송합니다.&lt;/p&gt;
&lt;p data-end=&quot;702&quot; data-start=&quot;603&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;702&quot; data-start=&quot;603&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;702&quot; data-start=&quot;603&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-end=&quot;747&quot; data-start=&quot;709&quot; data-section-id=&quot;sawui1&quot; data-ke-size=&quot;size20&quot;&gt;2. Cancel 테스트용 Action Client 파일 만들기&lt;/h4&gt;
&lt;p data-end=&quot;793&quot; data-start=&quot;749&quot; data-ke-size=&quot;size16&quot;&gt;먼저 Cancel 요청을 보내는 Action Client 파일을 새로 만듭니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;awk&quot;&gt;&lt;code&gt;cd ~/ros2_study/src/my_first_package/my_first_package
touch dist_turtle_action_client_cancel.py&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;920&quot; data-start=&quot;904&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;920&quot; data-start=&quot;904&quot; data-ke-size=&quot;size16&quot;&gt;파일 이름은 다음과 같습니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;css&quot;&gt;&lt;code&gt;dist_turtle_action_client_cancel.py&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;1051&quot; data-start=&quot;971&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;1051&quot; data-start=&quot;971&quot; data-ke-size=&quot;size16&quot;&gt;이 파일은 기존 Action Client와 비슷하지만, Goal을 보낸 뒤 일정 시간이 지나면 자동으로 Cancel 요청을 보내도록 작성합니다.&lt;/p&gt;
&lt;p data-end=&quot;1051&quot; data-start=&quot;971&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;1051&quot; data-start=&quot;971&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;1051&quot; data-start=&quot;971&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-end=&quot;1095&quot; data-start=&quot;1058&quot; data-section-id=&quot;grkfzs&quot; data-ke-size=&quot;size20&quot;&gt;3. Cancel 테스트용 Action Client 전체 코드&lt;/h4&gt;
&lt;p data-end=&quot;1152&quot; data-start=&quot;1097&quot; data-ke-size=&quot;size16&quot;&gt;dist_turtle_action_client_cancel.py 파일에 다음 코드를 작성합니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot;&gt;&lt;code&gt;import rclpy as rp
from rclpy.action import ActionClient
from rclpy.node import Node

from my_first_package_msgs.action import DistTurtle


class DistTurtleCancelClient(Node):

    def __init__(self):
        super().__init__('dist_turtle_action_client_cancel')

        self._action_client = ActionClient(
            self,
            DistTurtle,
            'dist_turtle'
        )

        self.goal_handle = None
        self.timer = None

    def send_goal(self):
        goal_msg = DistTurtle.Goal()
        goal_msg.linear_x = 1.0
        goal_msg.angular_z = 0.0
        goal_msg.dist = 10.0

        self._action_client.wait_for_server()

        self.get_logger().info('Sending goal')

        self._send_goal_future = self._action_client.send_goal_async(
            goal_msg,
            feedback_callback=self.feedback_callback
        )

        self._send_goal_future.add_done_callback(
            self.goal_response_callback
        )

    def goal_response_callback(self, future):
        self.goal_handle = future.result()

        if not self.goal_handle.accepted:
            self.get_logger().info('Goal rejected')
            return

        self.get_logger().info('Goal accepted')

        self._get_result_future = self.goal_handle.get_result_async()
        self._get_result_future.add_done_callback(
            self.get_result_callback
        )

        self.timer = self.create_timer(2.0, self.cancel_goal)

    def feedback_callback(self, feedback_msg):
        feedback = feedback_msg.feedback

        self.get_logger().info(
            f'Received feedback: remained_dist = {feedback.remained_dist}'
        )

    def cancel_goal(self):
        self.get_logger().info('Sending cancel request')

        self.timer.cancel()

        self._cancel_future = self.goal_handle.cancel_goal_async()
        self._cancel_future.add_done_callback(
            self.cancel_done_callback
        )

    def cancel_done_callback(self, future):
        cancel_response = future.result()

        if len(cancel_response.goals_canceling) &amp;gt; 0:
            self.get_logger().info('Cancel request accepted')
        else:
            self.get_logger().info('Cancel request rejected')

    def get_result_callback(self, future):
        result = future.result().result
        status = future.result().status

        self.get_logger().info(f'Action finished with status: {status}')
        self.get_logger().info(f'Result distance: {result.result_dist}')

        rp.shutdown()


def main(args=None):
    rp.init(args=args)

    action_client = DistTurtleCancelClient()
    action_client.send_goal()

    rp.spin(action_client)


if __name__ == '__main__':
    main()&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-end=&quot;3870&quot; data-start=&quot;3852&quot; data-section-id=&quot;1kaskdj&quot; data-ke-size=&quot;size20&quot;&gt;4. import 부분 설명&lt;/h4&gt;
&lt;p data-end=&quot;3892&quot; data-start=&quot;3872&quot; data-ke-size=&quot;size16&quot;&gt;먼저 코드의 import 부분입니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;elm&quot;&gt;&lt;code&gt;import rclpy as rp
from rclpy.action import ActionClient
from rclpy.node import Node

from my_first_package_msgs.action import DistTurtle&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;다음 코드는 Action Client를 사용하기 위해 필요합니다.&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;from rclpy.action import ActionClient&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;4475&quot; data-start=&quot;4384&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;4475&quot; data-start=&quot;4384&quot; data-ke-size=&quot;size16&quot;&gt;ActionClient는 Action Server에 Goal을 보내고, Feedback과 Result를 받으며, Cancel 요청도 보낼 수 있는 클래스입니다.&lt;/p&gt;
&lt;p data-end=&quot;4514&quot; data-start=&quot;4477&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;4736&quot; data-start=&quot;4693&quot; data-ke-size=&quot;size16&quot;&gt;마지막 import는 직접 만든 Action 인터페이스를 가져오는 부분입니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;from my_first_package_msgs.action import DistTurtle&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;4840&quot; data-start=&quot;4805&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;4840&quot; data-start=&quot;4805&quot; data-ke-size=&quot;size16&quot;&gt;DistTurtle은 앞에서 만든 Action 메시지입니다.&lt;/p&gt;
&lt;p data-end=&quot;4870&quot; data-start=&quot;4842&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;4870&quot; data-start=&quot;4842&quot; data-ke-size=&quot;size16&quot;&gt;이 안에는 다음 세 가지 타입이 포함되어 있습니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;css&quot;&gt;&lt;code&gt;DistTurtle.Goal
DistTurtle.Feedback
DistTurtle.Result&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;5025&quot; data-start=&quot;4939&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;5025&quot; data-start=&quot;4939&quot; data-ke-size=&quot;size16&quot;&gt;이번 Client에서는 DistTurtle.Goal()을 만들어 Server로 보내고, Server가 보내는 Feedback과 Result를 받습니다.&lt;/p&gt;
&lt;p data-end=&quot;5025&quot; data-start=&quot;4939&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;5025&quot; data-start=&quot;4939&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h4 data-end=&quot;5345&quot; data-start=&quot;5320&quot; data-section-id=&quot;v65517&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span&gt;6. 생성자 __init__() 설명&lt;/span&gt;&lt;/h4&gt;
&lt;p data-end=&quot;5361&quot; data-start=&quot;5347&quot; data-ke-size=&quot;size16&quot;&gt;다음은 생성자 부분입니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot;&gt;&lt;code&gt;def __init__(self):
    super().__init__('dist_turtle_action_client_cencel')

    self._action_client = ActionClient(
        self,
        DistTurtle,
        'dist_turtle'
    )

    self.goal_handle = None
    self.timer = None&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;5627&quot; data-start=&quot;5602&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;5627&quot; data-start=&quot;5602&quot; data-ke-size=&quot;size16&quot;&gt;먼저 다음 코드는 Node 이름을 설정합니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot;&gt;&lt;code&gt;super().__init__('dist_turtle_action_client_cancel')&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;5742&quot; data-start=&quot;5690&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;5742&quot; data-start=&quot;5690&quot; data-ke-size=&quot;size16&quot;&gt;이 Client Node의 이름은 dist_turtle_cancel_client가 됩니다.&lt;/p&gt;
&lt;p data-end=&quot;5766&quot; data-start=&quot;5744&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;5766&quot; data-start=&quot;5744&quot; data-ke-size=&quot;size16&quot;&gt;실행 로그에서는 이 이름으로 출력됩니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot;&gt;&lt;code&gt;[INFO] [dist_turtle_action_client_cencel]: Sending goal&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;5858&quot; data-start=&quot;5830&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;5858&quot; data-start=&quot;5830&quot; data-ke-size=&quot;size16&quot;&gt;다음 코드는 Action Client를 생성합니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;ruby&quot;&gt;&lt;code&gt;self._action_client = ActionClient(
    self,
    DistTurtle,
    'dist_turtle'
)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;5976&quot; data-start=&quot;5957&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;5976&quot; data-start=&quot;5957&quot; data-ke-size=&quot;size16&quot;&gt;각 인자의 의미는 다음과 같습니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;crmsh&quot;&gt;&lt;code&gt;self          &amp;rarr; 현재 Node
DistTurtle    &amp;rarr; 사용할 Action 타입
'dist_turtle' &amp;rarr; 접속할 Action 이름&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;6135&quot; data-start=&quot;6075&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;6135&quot; data-start=&quot;6075&quot; data-ke-size=&quot;size16&quot;&gt;여기서 'dist_turtle'은 Action Server에서 사용한 Action 이름과 같아야 합니다.&lt;/p&gt;
&lt;p data-end=&quot;6194&quot; data-start=&quot;6137&quot; data-ke-size=&quot;size16&quot;&gt;Server도 같은 이름으로 Action Server를 열고 있어야 Client가 연결할 수 있습니다.&lt;/p&gt;
&lt;p data-end=&quot;6226&quot; data-start=&quot;6196&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;6226&quot; data-start=&quot;6196&quot; data-ke-size=&quot;size16&quot;&gt;다음 코드는 Goal Handle을 저장할 변수입니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;ini&quot;&gt;&lt;code&gt;self.goal_handle = None&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;6311&quot; data-start=&quot;6267&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;6311&quot; data-start=&quot;6267&quot; data-ke-size=&quot;size16&quot;&gt;Goal Handle은 Client가 보낸 Goal을 제어하기 위한 객체입니다.&lt;/p&gt;
&lt;p data-end=&quot;6350&quot; data-start=&quot;6313&quot; data-ke-size=&quot;size16&quot;&gt;Cancel 요청을 보낼 때 이 Goal Handle이 필요합니다.&lt;/p&gt;
&lt;p data-end=&quot;6379&quot; data-start=&quot;6352&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;6379&quot; data-start=&quot;6352&quot; data-ke-size=&quot;size16&quot;&gt;다음 코드는 Timer 객체를 저장할 변수입니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;ini&quot;&gt;&lt;code&gt;self.timer = None&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;6470&quot; data-start=&quot;6414&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;6470&quot; data-start=&quot;6414&quot; data-ke-size=&quot;size16&quot;&gt;이번 실습에서는 Goal을 보낸 뒤 2초 후 Cancel 요청을 보내기 위해 Timer를 사용합니다.&lt;/p&gt;
&lt;p data-end=&quot;6470&quot; data-start=&quot;6414&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;6470&quot; data-start=&quot;6414&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;6470&quot; data-start=&quot;6414&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-end=&quot;6502&quot; data-start=&quot;6477&quot; data-section-id=&quot;1wpz0h6&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span&gt;7. send_goal() 함수 설명&lt;/span&gt;&lt;/h4&gt;
&lt;p data-end=&quot;6542&quot; data-start=&quot;6504&quot; data-ke-size=&quot;size16&quot;&gt;다음 함수는 Action Server로 Goal을 보내는 함수입니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;ruby&quot;&gt;&lt;code&gt;def send_goal(self):
    goal_msg = DistTurtle.Goal()
    goal_msg.linear_x = 0.0
    goal_msg.angular_z = 0.0
    goal_msg.dist = 10.0

    self._action_client.wait_for_server()

    self.get_logger().info('Sending goal')

    self._send_goal_future = self._action_client.send_goal_async(
        goal_msg,
        feedback_callback=self.feedback_callback
    )

    self._send_goal_future.add_done_callback(
        self.goal_response_callback
    )&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;7030&quot; data-start=&quot;7011&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;7030&quot; data-start=&quot;7011&quot; data-ke-size=&quot;size16&quot;&gt;먼저 Goal 메시지를 생성합니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;ini&quot;&gt;&lt;code&gt;goal_msg = DistTurtle.Goal()&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;7122&quot; data-start=&quot;7076&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;7122&quot; data-start=&quot;7076&quot; data-ke-size=&quot;size16&quot;&gt;DistTurtle.Goal()은 Action Server에 보낼 목표값입니다.&lt;/p&gt;
&lt;p data-end=&quot;7149&quot; data-start=&quot;7124&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;7149&quot; data-start=&quot;7124&quot; data-ke-size=&quot;size16&quot;&gt;그다음 Goal 메시지 안의 값을 설정합니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;ini&quot;&gt;&lt;code&gt;goal_msg.linear_x = 0.0
goal_msg.angular_z = 0.0
goal_msg.dist = 10.0&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;7270&quot; data-start=&quot;7236&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;7270&quot; data-start=&quot;7236&quot; data-ke-size=&quot;size16&quot;&gt;각 값은 Action 정의 파일에 작성한 Goal 필드입니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;properties&quot;&gt;&lt;code&gt;linear_x  &amp;rarr; 직선 속도 값
angular_z &amp;rarr; 회전 속도 값
dist      &amp;rarr; 목표 거리 값&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;7397&quot; data-start=&quot;7345&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;7397&quot; data-start=&quot;7345&quot; data-ke-size=&quot;size16&quot;&gt;이번 실습에서는 Cancel 기능 확인이 목적이므로 dist를 10.0으로 설정합니다.&lt;/p&gt;
&lt;p data-end=&quot;7435&quot; data-start=&quot;7399&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;7435&quot; data-start=&quot;7399&quot; data-ke-size=&quot;size16&quot;&gt;다음 코드는 Action Server가 실행될 때까지 기다립니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;reasonml&quot;&gt;&lt;code&gt;self._action_client.wait_for_server()&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;7538&quot; data-start=&quot;7490&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;7538&quot; data-start=&quot;7490&quot; data-ke-size=&quot;size16&quot;&gt;Server가 실행되지 않은 상태에서 Goal을 보내면 정상적으로 처리할 수 없습니다.&lt;/p&gt;
&lt;p data-end=&quot;7577&quot; data-start=&quot;7540&quot; data-ke-size=&quot;size16&quot;&gt;그래서 Client는 먼저 Server가 준비될 때까지 대기합니다.&lt;/p&gt;
&lt;p data-end=&quot;7577&quot; data-start=&quot;7540&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;7606&quot; data-start=&quot;7579&quot; data-ke-size=&quot;size16&quot;&gt;다음 코드는 Goal을 비동기 방식으로 보냅니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;crystal&quot;&gt;&lt;code&gt;self._send_goal_future = self._action_client.send_goal_async(
    goal_msg,
    feedback_callback=self.feedback_callback
)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;7793&quot; data-start=&quot;7746&quot; data-ke-size=&quot;size16&quot;&gt;send_goal_async()는 Goal을 보내고 바로 다음 코드로 넘어갑니다.&lt;/p&gt;
&lt;p data-end=&quot;7793&quot; data-start=&quot;7746&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;7825&quot; data-start=&quot;7795&quot; data-ke-size=&quot;size16&quot;&gt;작업 결과를 기다리는 동안 프로그램이 멈추지 않습니다.&lt;/p&gt;
&lt;p data-end=&quot;7825&quot; data-start=&quot;7795&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;7885&quot; data-start=&quot;7827&quot; data-ke-size=&quot;size16&quot;&gt;여기서 feedback_callback은 Server가 Feedback을 보낼 때 실행될 함수입니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;ini&quot;&gt;&lt;code&gt;feedback_callback=self.feedback_callback&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;7974&quot; data-start=&quot;7943&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;7974&quot; data-start=&quot;7943&quot; data-ke-size=&quot;size16&quot;&gt;마지막으로 Goal 요청 결과를 받을 콜백을 등록합니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;css&quot;&gt;&lt;code&gt;self._send_goal_future.add_done_callback(
    self.goal_response_callback
)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;8137&quot; data-start=&quot;8067&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;8137&quot; data-start=&quot;8067&quot; data-ke-size=&quot;size16&quot;&gt;Server가 Goal을 수락했는지 거부했는지 결과가 오면 goal_response_callback() 함수가 실행됩니다.&lt;/p&gt;
&lt;p data-end=&quot;8137&quot; data-start=&quot;8067&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;8137&quot; data-start=&quot;8067&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;8137&quot; data-start=&quot;8067&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-end=&quot;8182&quot; data-start=&quot;8144&quot; data-section-id=&quot;1pz2qbw&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span&gt;8. goal_response_callback() 함수 설명&lt;/span&gt;&lt;/h4&gt;
&lt;p data-end=&quot;8222&quot; data-start=&quot;8184&quot; data-ke-size=&quot;size16&quot;&gt;다음 함수는 Server가 Goal을 수락했는지 확인하는 함수입니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;ruby&quot;&gt;&lt;code&gt;def goal_response_callback(self, future):
    self.goal_handle = future.result()

    if not self.goal_handle.accepted:
        self.get_logger().info('Goal rejected')
        return

    self.get_logger().info('Goal accepted')

    self._get_result_future = self.goal_handle.get_result_async()
    self._get_result_future.add_done_callback(
        self.get_result_callback
    )

    self.timer = self.create_timer(2.0, self.cancel_goal)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;8701&quot; data-start=&quot;8679&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;8701&quot; data-start=&quot;8679&quot; data-ke-size=&quot;size16&quot;&gt;먼저 Goal Handle을 가져옵니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;ini&quot;&gt;&lt;code&gt;self.goal_handle = future.result()&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;8793&quot; data-start=&quot;8753&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;8793&quot; data-start=&quot;8753&quot; data-ke-size=&quot;size16&quot;&gt;이 Goal Handle은 이후 Cancel 요청을 보낼 때 사용합니다.&lt;/p&gt;
&lt;p data-end=&quot;8821&quot; data-start=&quot;8795&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;8821&quot; data-start=&quot;8795&quot; data-ke-size=&quot;size16&quot;&gt;다음 코드는 Goal이 거부되었는지 확인합니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;ruby&quot;&gt;&lt;code&gt;if not self.goal_handle.accepted:
    self.get_logger().info('Goal rejected')
    return&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;8970&quot; data-start=&quot;8927&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;8970&quot; data-start=&quot;8927&quot; data-ke-size=&quot;size16&quot;&gt;Server가 Goal을 거부했다면 더 이상 진행하지 않고 함수를 종료합니다.&lt;/p&gt;
&lt;p data-end=&quot;9002&quot; data-start=&quot;8972&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;9002&quot; data-start=&quot;8972&quot; data-ke-size=&quot;size16&quot;&gt;Goal이 정상적으로 수락되면 다음 로그가 출력됩니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;less&quot;&gt;&lt;code&gt;self.get_logger().info('Goal accepted')&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;9087&quot; data-start=&quot;9059&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;9087&quot; data-start=&quot;9059&quot; data-ke-size=&quot;size16&quot;&gt;그다음 Result를 받기 위한 요청을 등록합니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;armasm&quot;&gt;&lt;code&gt;self._get_result_future = self.goal_handle.get_result_async()
self._get_result_future.add_done_callback(
    self.get_result_callback
)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;9296&quot; data-start=&quot;9240&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;9296&quot; data-start=&quot;9240&quot; data-ke-size=&quot;size16&quot;&gt;get_result_async()는 Action이 끝났을 때 Result를 받기 위해 사용합니다.&lt;/p&gt;
&lt;p data-end=&quot;9327&quot; data-start=&quot;9298&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;9327&quot; data-start=&quot;9298&quot; data-ke-size=&quot;size16&quot;&gt;마지막 줄이 Cancel 실습에서 중요한 부분입니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;crystal&quot;&gt;&lt;code&gt;self.timer = self.create_timer(2.0, self.cancel_goal)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;9446&quot; data-start=&quot;9398&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;9446&quot; data-start=&quot;9398&quot; data-ke-size=&quot;size16&quot;&gt;이 코드는 2초마다 cancel_goal() 함수를 실행하는 Timer를 만듭니다.&lt;/p&gt;
&lt;p data-end=&quot;9525&quot; data-start=&quot;9448&quot; data-ke-size=&quot;size16&quot;&gt;하지만 cancel_goal() 함수 안에서 바로 Timer를 취소하기 때문에 실제로는 2초 후 한 번만 Cancel 요청을 보냅니다.&lt;/p&gt;
&lt;p data-end=&quot;9525&quot; data-start=&quot;9448&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;9525&quot; data-start=&quot;9448&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;9525&quot; data-start=&quot;9448&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-end=&quot;9565&quot; data-start=&quot;9532&quot; data-section-id=&quot;j2g6e5&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span&gt;9. feedback_callback() 함수 설명&lt;/span&gt;&lt;/h4&gt;
&lt;p data-end=&quot;9606&quot; data-start=&quot;9567&quot; data-ke-size=&quot;size16&quot;&gt;다음 함수는 Server에서 Feedback을 보낼 때마다 실행됩니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;ruby&quot;&gt;&lt;code&gt;def feedback_callback(self, feedback_msg):
    feedback = feedback_msg.feedback

    self.get_logger().info(
        f'Received feedback: remained_dist = {feedback.remained_dist}'
    )&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;9868&quot; data-start=&quot;9809&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;9868&quot; data-start=&quot;9809&quot; data-ke-size=&quot;size16&quot;&gt;feedback_msg.feedback에는 Server가 보낸 Feedback 데이터가 들어 있습니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;ini&quot;&gt;&lt;code&gt;feedback = feedback_msg.feedback&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;9964&quot; data-start=&quot;9918&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;9964&quot; data-start=&quot;9918&quot; data-ke-size=&quot;size16&quot;&gt;이번 예제에서는 남은 거리를 의미하는 remained_dist 값을 출력합니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;python&quot;&gt;&lt;code&gt;f'Received feedback: remained_dist = {feedback.remained_dist}'&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;10112&quot; data-start=&quot;10044&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;10112&quot; data-start=&quot;10044&quot; data-ke-size=&quot;size16&quot;&gt;Action Server가 작업 중 Feedback을 계속 보내면 Client는 이 함수를 통해 값을 확인할 수 있습니다.&lt;/p&gt;
&lt;p data-end=&quot;10112&quot; data-start=&quot;10044&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;10112&quot; data-start=&quot;10044&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;10112&quot; data-start=&quot;10044&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-end=&quot;10147&quot; data-start=&quot;10119&quot; data-section-id=&quot;1aqpleu&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span&gt;10. cancel_goal() 함수 설명&lt;/span&gt;&lt;/h4&gt;
&lt;p data-end=&quot;10181&quot; data-start=&quot;10149&quot; data-ke-size=&quot;size16&quot;&gt;다음 함수는 실제로 Cancel 요청을 보내는 함수입니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;ruby&quot;&gt;&lt;code&gt;def cancel_goal(self):
    self.get_logger().info('Sending cancel request')

    self.timer.cancel()

    self._cancel_future = self.goal_handle.cancel_goal_async()
    self._cancel_future.add_done_callback(
        self.cancel_done_callback
    )&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;10475&quot; data-start=&quot;10446&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;10475&quot; data-start=&quot;10446&quot; data-ke-size=&quot;size16&quot;&gt;먼저 Cancel 요청을 보낸다는 로그를 출력합니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;less&quot;&gt;&lt;code&gt;self.get_logger().info('Sending cancel request')&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;10561&quot; data-start=&quot;10541&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;10561&quot; data-start=&quot;10541&quot; data-ke-size=&quot;size16&quot;&gt;다음 코드는 Timer를 중지합니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;css&quot;&gt;&lt;code&gt;self.timer.cancel()&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;10669&quot; data-start=&quot;10598&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;10669&quot; data-start=&quot;10598&quot; data-ke-size=&quot;size16&quot;&gt;create_timer(2.0, self.cancel_goal)로 만든 Timer는 원래 2초마다 계속 실행될 수 있습니다.&lt;/p&gt;
&lt;p data-end=&quot;10715&quot; data-start=&quot;10671&quot; data-ke-size=&quot;size16&quot;&gt;하지만 Cancel 요청은 한 번만 보내면 되므로 Timer를 바로 중지합니다.&lt;/p&gt;
&lt;p data-end=&quot;10734&quot; data-start=&quot;10717&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;10734&quot; data-start=&quot;10717&quot; data-ke-size=&quot;size16&quot;&gt;가장 중요한 코드는 다음입니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;crystal&quot;&gt;&lt;code&gt;self._cancel_future = self.goal_handle.cancel_goal_async()&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;10847&quot; data-start=&quot;10810&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;10847&quot; data-start=&quot;10810&quot; data-ke-size=&quot;size16&quot;&gt;이 코드가 Action Server로 Cancel 요청을 보냅니다.&lt;/p&gt;
&lt;p data-end=&quot;10883&quot; data-start=&quot;10849&quot; data-ke-size=&quot;size16&quot;&gt;여기서 goal_handle을 사용한다는 점이 중요합니다.&lt;/p&gt;
&lt;p data-end=&quot;10957&quot; data-start=&quot;10885&quot; data-ke-size=&quot;size16&quot;&gt;Cancel 요청은 Action 이름만으로 보내는 것이 아니라, Client가 보낸 Goal의 Handle을 통해 보내야 합니다.&lt;/p&gt;
&lt;p data-end=&quot;10957&quot; data-start=&quot;10885&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;10994&quot; data-start=&quot;10959&quot; data-ke-size=&quot;size16&quot;&gt;마지막 코드는 Cancel 요청 결과를 받을 콜백을 등록합니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;css&quot;&gt;&lt;code&gt;self._cancel_future.add_done_callback(
    self.cancel_done_callback
)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;11155&quot; data-start=&quot;11082&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;11155&quot; data-start=&quot;11082&quot; data-ke-size=&quot;size16&quot;&gt;Server가 Cancel 요청을 허용했는지 거부했는지 결과가 오면 cancel_done_callback() 함수가 실행됩니다.&lt;/p&gt;
&lt;p data-end=&quot;11155&quot; data-start=&quot;11082&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;11155&quot; data-start=&quot;11082&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;11155&quot; data-start=&quot;11082&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-end=&quot;11199&quot; data-start=&quot;11162&quot; data-section-id=&quot;lpjo1g&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span&gt;11. cancel_done_callback() 함수 설명&lt;/span&gt;&lt;/h4&gt;
&lt;p data-end=&quot;11233&quot; data-start=&quot;11201&quot; data-ke-size=&quot;size16&quot;&gt;다음 함수는 Cancel 요청 결과를 확인하는 함수입니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;ruby&quot;&gt;&lt;code&gt;def cancel_done_callback(self, future):
    cancel_response = future.result()

    if len(cancel_response.goals_canceling) &amp;gt; 0:
        self.get_logger().info('Cancel request accepted')
    else:
        self.get_logger().info('Cancel request rejected')&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;11527&quot; data-start=&quot;11504&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;11527&quot; data-start=&quot;11504&quot; data-ke-size=&quot;size16&quot;&gt;먼저 Cancel 요청 결과를 가져옵니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;ini&quot;&gt;&lt;code&gt;cancel_response = future.result()&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;11610&quot; data-start=&quot;11578&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;11610&quot; data-start=&quot;11578&quot; data-ke-size=&quot;size16&quot;&gt;다음 코드는 취소 처리 중인 Goal이 있는지 확인합니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot;&gt;&lt;code&gt;if len(cancel_response.goals_canceling) &amp;gt; 0:&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;11732&quot; data-start=&quot;11672&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;11732&quot; data-start=&quot;11672&quot; data-ke-size=&quot;size16&quot;&gt;goals_canceling 안에 값이 하나라도 있으면 Server가 Cancel 요청을 받아들였다는 의미입니다.&lt;/p&gt;
&lt;p data-end=&quot;11752&quot; data-start=&quot;11734&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;11752&quot; data-start=&quot;11734&quot; data-ke-size=&quot;size16&quot;&gt;이 경우 다음 로그를 출력합니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;less&quot;&gt;&lt;code&gt;self.get_logger().info('Cancel request accepted')&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;11886&quot; data-start=&quot;11819&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;11886&quot; data-start=&quot;11819&quot; data-ke-size=&quot;size16&quot;&gt;반대로 goals_canceling이 비어 있으면 Cancel 요청이 거부되었거나 취소할 Goal이 없는 상태입니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;less&quot;&gt;&lt;code&gt;self.get_logger().info('Cancel request rejected')&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-end=&quot;11994&quot; data-start=&quot;11958&quot; data-section-id=&quot;787bi&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span&gt;12. get_result_callback() 함수 설명&lt;/span&gt;&lt;/h4&gt;
&lt;p data-end=&quot;12028&quot; data-start=&quot;11996&quot; data-ke-size=&quot;size16&quot;&gt;다음 함수는 Action이 최종 종료되었을 때 실행됩니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;oxygene&quot;&gt;&lt;code&gt;def get_result_callback(self, future):
    result = future.result().result
    status = future.result().status

    self.get_logger().info(f'Action finished with status: {status}')
    self.get_logger().info(f'Result distance: {result.result_dist}')

    rp.shutdown()&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;12333&quot; data-start=&quot;12314&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;12333&quot; data-start=&quot;12314&quot; data-ke-size=&quot;size16&quot;&gt;먼저 Result 값을 가져옵니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;applescript&quot;&gt;&lt;code&gt;result = future.result().result&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;12405&quot; data-start=&quot;12382&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;12405&quot; data-start=&quot;12382&quot; data-ke-size=&quot;size16&quot;&gt;그리고 Action 상태 값을 가져옵니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;fortran&quot;&gt;&lt;code&gt;status = future.result().status&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;12492&quot; data-start=&quot;12454&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;12492&quot; data-start=&quot;12454&quot; data-ke-size=&quot;size16&quot;&gt;Cancel이 정상 처리되면 보통 다음과 같은 상태 값이 출력됩니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;fortran&quot;&gt;&lt;code&gt;Action finished with status: 5&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;12578&quot; data-start=&quot;12538&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;12578&quot; data-start=&quot;12538&quot; data-ke-size=&quot;size16&quot;&gt;일반적으로 status: 5는 CANCELED 상태를 의미합니다.&lt;/p&gt;
&lt;p data-end=&quot;12613&quot; data-start=&quot;12580&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;12613&quot; data-start=&quot;12580&quot; data-ke-size=&quot;size16&quot;&gt;다음 코드는 Result에 들어 있는 거리 값을 출력합니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;less&quot;&gt;&lt;code&gt;self.get_logger().info(f'Result distance: {result.result_dist}')&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;12717&quot; data-start=&quot;12695&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;12717&quot; data-start=&quot;12695&quot; data-ke-size=&quot;size16&quot;&gt;마지막으로 ROS 2 노드를 종료합니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;arduino&quot;&gt;&lt;code&gt;rp.shutdown()&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-end=&quot;12774&quot; data-start=&quot;12753&quot; data-section-id=&quot;9487iq&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span&gt;13. main() 함수 설명&lt;/span&gt;&lt;/h4&gt;
&lt;p data-end=&quot;12791&quot; data-start=&quot;12776&quot; data-ke-size=&quot;size16&quot;&gt;마지막은 실행 진입점입니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;isbl&quot;&gt;&lt;code&gt;def main(args=None):
    rp.init(args=args)

    action_client = DistTurtleCancelClient()
    action_client.send_goal()

    rp.spin(action_client)


if __name__ == '__main__':
    main()&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;13026&quot; data-start=&quot;12996&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;그다음 Cancel Client 객체를 생성합니다.&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;ini&quot;&gt;&lt;code&gt;action_client = DistTurtleCancelClient()&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;13167&quot; data-start=&quot;13148&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;13167&quot; data-start=&quot;13148&quot; data-ke-size=&quot;size16&quot;&gt;다음 코드로 Goal을 전송합니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;css&quot;&gt;&lt;code&gt;action_client.send_goal()&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;13245&quot; data-start=&quot;13210&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;13245&quot; data-start=&quot;13210&quot; data-ke-size=&quot;size16&quot;&gt;마지막으로 Node를 계속 실행하면서 콜백이 처리되도록 합니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;css&quot;&gt;&lt;code&gt;rp.spin(action_client)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;13347&quot; data-start=&quot;13285&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;13347&quot; data-start=&quot;13285&quot; data-ke-size=&quot;size16&quot;&gt;rp.spin(action_client)가 실행 중이기 때문에 다음 콜백들이 정상적으로 동작할 수 있습니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;stylus&quot;&gt;&lt;code&gt;goal_response_callback()
feedback_callback()
cancel_goal()
cancel_done_callback()
get_result_callback()&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-end=&quot;13498&quot; data-start=&quot;13471&quot; data-section-id=&quot;165p353&quot; data-ke-size=&quot;size20&quot;&gt;14. setup.py에 실행 파일 등록하기&lt;/h4&gt;
&lt;p data-end=&quot;13560&quot; data-start=&quot;13500&quot; data-ke-size=&quot;size16&quot;&gt;새로 만든 Python 파일을 ros2 run 명령으로 실행하려면 setup.py에 등록해야 합니다.&lt;/p&gt;
&lt;p data-end=&quot;13581&quot; data-start=&quot;13562&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;13581&quot; data-start=&quot;13562&quot; data-ke-size=&quot;size16&quot;&gt;setup.py 파일을 엽니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;jboss-cli&quot;&gt;&lt;code&gt;cd ~/ros2_study/src/my_first_package
gedit setup.py&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;13680&quot; data-start=&quot;13648&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;13680&quot; data-start=&quot;13648&quot; data-ke-size=&quot;size16&quot;&gt;또는 VS Code를 사용한다면 다음처럼 열 수 있습니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;arduino&quot;&gt;&lt;code&gt;code setup.py&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;13756&quot; data-start=&quot;13709&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;13756&quot; data-start=&quot;13709&quot; data-ke-size=&quot;size16&quot;&gt;entry_points의 console_scripts에 다음 줄을 추가합니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;sml&quot;&gt;&lt;code&gt;'dist_turtle_action_client_cancel = my_first_package.dist_turtle_action_client_cancel:main',&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;13879&quot; data-start=&quot;13866&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;13879&quot; data-start=&quot;13866&quot; data-ke-size=&quot;size16&quot;&gt;예시는 다음과 같습니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;sml&quot;&gt;&lt;code&gt;entry_points={
    'console_scripts': [
        'dist_turtle_action_server = my_first_package.dist_turtle_action_server:main',
        'dist_turtle_action_client_cancel = my_first_package.dist_turtle_action_client_cancel:main',
    ],
},&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;14348&quot; data-start=&quot;14325&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;14365&quot; data-start=&quot;14350&quot; data-ke-size=&quot;size16&quot;&gt;따라서 다음 명령을 실행하면&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;dockerfile&quot;&gt;&lt;code&gt;ros2 run my_first_package dist_turtle_action_client_cancel&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;14478&quot; data-start=&quot;14439&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;14478&quot; data-start=&quot;14439&quot; data-ke-size=&quot;size16&quot;&gt;ROS 2는 내부적으로 다음 파일의 main() 함수를 실행합니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;vim&quot;&gt;&lt;code&gt;my_first_package/dist_turtle_action_client_cancel.py&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-end=&quot;16712&quot; data-start=&quot;16701&quot; data-section-id=&quot;vvyol1&quot; data-ke-size=&quot;size20&quot;&gt;15. 빌드하기&lt;/h4&gt;
&lt;p data-end=&quot;16734&quot; data-start=&quot;16714&quot; data-ke-size=&quot;size16&quot;&gt;코드를 수정했으므로 다시 빌드합니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;properties&quot;&gt;&lt;code&gt;cd ~/ros2_study
colcon build
source install/setup.bash&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;16838&quot; data-start=&quot;16804&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;16838&quot; data-start=&quot;16804&quot; data-ke-size=&quot;size16&quot;&gt;빌드가 완료되면 새로 등록한 실행 파일을 사용할 수 있습니다.&lt;/p&gt;
&lt;p data-end=&quot;16838&quot; data-start=&quot;16804&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;16838&quot; data-start=&quot;16804&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-end=&quot;16870&quot; data-start=&quot;16845&quot; data-section-id=&quot;1ggr0jg&quot; data-ke-size=&quot;size20&quot;&gt;16. Action Server 실행하기&lt;/h4&gt;
&lt;p data-end=&quot;16904&quot; data-start=&quot;16872&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;16904&quot; data-start=&quot;16872&quot; data-ke-size=&quot;size16&quot;&gt;첫 번째 터미널에서 Action Server를 실행합니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;properties&quot;&gt;&lt;code&gt;cd ~/ros2_study
source install/setup.bash
ros2 run my_first_package dist_turtle_action_server&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;17056&quot; data-start=&quot;17013&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;17056&quot; data-start=&quot;17013&quot; data-ke-size=&quot;size16&quot;&gt;Action Server가 실행되면 Client의 Goal 요청을 기다립니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-end=&quot;17100&quot; data-start=&quot;17063&quot; data-section-id=&quot;1ppbj6m&quot; data-ke-size=&quot;size20&quot;&gt;17. Cancel 테스트용 Action Client 실행하기&lt;/h4&gt;
&lt;p data-end=&quot;17148&quot; data-start=&quot;17102&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;17148&quot; data-start=&quot;17102&quot; data-ke-size=&quot;size16&quot;&gt;두 번째 터미널을 열고 Cancel 테스트용 Action Client를 실행합니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;properties&quot;&gt;&lt;code&gt;cd ~/ros2_study
source install/setup.bash
ros2 run my_first_package dist_turtle_action_client_cancel&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;17313&quot; data-start=&quot;17264&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;17313&quot; data-start=&quot;17264&quot; data-ke-size=&quot;size16&quot;&gt;이 Client는 Goal을 보낸 뒤 약 2초 후 자동으로 Cancel 요청을 보냅니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-end=&quot;17337&quot; data-start=&quot;17320&quot; data-section-id=&quot;ja5hyl&quot; data-ke-size=&quot;size20&quot;&gt;18. 실행 결과 확인하기&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;17362&quot; data-start=&quot;17339&quot; data-ke-size=&quot;size16&quot;&gt;Client 쪽 출력은 다음과 비슷합니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot;&gt;&lt;code&gt;[INFO] [dist_turtle_action_client_cancel]: Sending goal
[INFO] [dist_turtle_action_client_cancel]: Goal accepted
[INFO] [dist_turtle_action_client_cancel]: Received feedback: remained_dist = 10.0
[INFO] [dist_turtle_action_client_cancel]: Received feedback: remained_dist = 9.0
[INFO] [dist_turtle_action_client_cancel]: Sending cancel request
[INFO] [dist_turtle_action_client_cancel]: Cancel request accepted
[INFO] [dist_turtle_action_client_cancel]: Action finished with status: 5
[INFO] [dist_turtle_action_client_cancel]: Result distance: 2.0&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;17893&quot; data-start=&quot;17870&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;17893&quot; data-start=&quot;17870&quot; data-ke-size=&quot;size16&quot;&gt;Server 쪽 출력은 다음과 비슷합니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;markdown&quot;&gt;&lt;code&gt;[INFO] [dist_turtle_action_server]: Goal received
[INFO] [dist_turtle_action_server]: Feedback: remained_dist = 10.0
[INFO] [dist_turtle_action_server]: Feedback: remained_dist = 9.0
[INFO] [dist_turtle_action_server]: Cancel request received
[INFO] [dist_turtle_action_server]: Goal canceled&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;18253&quot; data-start=&quot;18201&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;18253&quot; data-start=&quot;18201&quot; data-ke-size=&quot;size16&quot;&gt;Client에서 다음 로그가 출력되면 Cancel 요청이 Server에 의해 허용된 것입니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;ebnf&quot;&gt;&lt;code&gt;Cancel request accepted&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;18340&quot; data-start=&quot;18292&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;18340&quot; data-start=&quot;18292&quot; data-ke-size=&quot;size16&quot;&gt;Server에서 다음 로그가 출력되면 Server가 Cancel 요청을 받은 것입니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;ebnf&quot;&gt;&lt;code&gt;Cancel request received&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;18425&quot; data-start=&quot;18379&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;18425&quot; data-start=&quot;18379&quot; data-ke-size=&quot;size16&quot;&gt;Server에서 다음 로그가 출력되면 실행 중이던 Goal이 취소 처리된 것입니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;coq&quot;&gt;&lt;code&gt;Goal canceled&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;18499&quot; data-start=&quot;18454&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;18499&quot; data-start=&quot;18454&quot; data-ke-size=&quot;size16&quot;&gt;Client에서 다음 로그가 출력되면 Action이 취소 상태로 종료된 것입니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;fortran&quot;&gt;&lt;code&gt;Action finished with status: 5&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;Screenshot from 2026-05-26 23-49-46.png&quot; data-origin-width=&quot;1630&quot; data-origin-height=&quot;986&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/oCUcZ/dJMcaffIoBt/8yYPp9OBxcFJuaf5WEXmR0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/oCUcZ/dJMcaffIoBt/8yYPp9OBxcFJuaf5WEXmR0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/oCUcZ/dJMcaffIoBt/8yYPp9OBxcFJuaf5WEXmR0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FoCUcZ%2FdJMcaffIoBt%2F8yYPp9OBxcFJuaf5WEXmR0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1630&quot; height=&quot;986&quot; data-filename=&quot;Screenshot from 2026-05-26 23-49-46.png&quot; data-origin-width=&quot;1630&quot; data-origin-height=&quot;986&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>강좌/ROS2</category>
      <category>Action Client</category>
      <author>MakingRobotWizard</author>
      <guid isPermaLink="true">https://makingrobot.tistory.com/436</guid>
      <comments>https://makingrobot.tistory.com/436#entry436comment</comments>
      <pubDate>Tue, 26 May 2026 23:22:20 +0900</pubDate>
    </item>
    <item>
      <title>ROS 2 Python Topic 실습 : RobotStatus 메시지로 로봇 상태 주고받기</title>
      <link>https://makingrobot.tistory.com/435</link>
      <description>&lt;h4 data-end=&quot;488&quot; data-start=&quot;477&quot; data-section-id=&quot;lpgo3a&quot; data-ke-size=&quot;size20&quot;&gt;1. 최종 목표&lt;/h4&gt;
&lt;p data-end=&quot;514&quot; data-start=&quot;490&quot; data-ke-size=&quot;size16&quot;&gt;이번 실습에서 만들 구조는 다음과 같습니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;css&quot;&gt;&lt;code&gt;ros2_lab_ws
└── src
    ├── robot_interfaces
    │   └── msg
    │       └── RobotStatus.msg
    │
    └── topic_practice
        └── topic_practice
            ├── robot_status_pub.py
            └── robot_status_sub.py&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;769&quot; data-start=&quot;750&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;769&quot; data-start=&quot;750&quot; data-ke-size=&quot;size16&quot;&gt;전체 동작 흐름은 다음과 같습니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;jboss-cli&quot;&gt;&lt;code&gt;robot_status_pub
        &amp;darr;
/robot_status Topic
        &amp;darr;
robot_status_sub&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;881&quot; data-start=&quot;858&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;881&quot; data-start=&quot;858&quot; data-ke-size=&quot;size16&quot;&gt;Publisher는 로봇 상태를 보냅니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;yaml&quot;&gt;&lt;code&gt;robot_id: R-001
mode: AUTO
battery_percent: 87.5
emergency_stop: false&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;996&quot; data-start=&quot;967&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;996&quot; data-start=&quot;967&quot; data-ke-size=&quot;size16&quot;&gt;Subscriber는 이 메시지를 받아서 출력합니다.&lt;/p&gt;
&lt;p data-end=&quot;996&quot; data-start=&quot;967&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;996&quot; data-start=&quot;967&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;996&quot; data-start=&quot;967&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-end=&quot;1017&quot; data-start=&quot;1003&quot; data-section-id=&quot;ojavsq&quot; data-ke-size=&quot;size20&quot;&gt;2. 워크스페이스 생성&lt;/h4&gt;
&lt;p data-end=&quot;1041&quot; data-start=&quot;1019&quot; data-ke-size=&quot;size16&quot;&gt;먼저 ROS 2 워크스페이스를 만듭니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;jboss-cli&quot;&gt;&lt;code&gt;mkdir -p ~/ros2_lab_ws/src
cd ~/ros2_lab_ws/src&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;1119&quot; data-start=&quot;1104&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;1119&quot; data-start=&quot;1104&quot; data-ke-size=&quot;size16&quot;&gt;현재 구조는 이렇게 됩니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;haml&quot;&gt;&lt;code&gt;~/ros2_lab_ws
└── src&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-end=&quot;1464&quot; data-start=&quot;1450&quot; data-section-id=&quot;1kowm3t&quot; data-ke-size=&quot;size20&quot;&gt;3. msg 폴더 생성&lt;/h4&gt;
&lt;p data-end=&quot;1506&quot; data-start=&quot;1466&quot; data-ke-size=&quot;size16&quot;&gt;RobotStatus.msg 파일을 넣을 msg 폴더를 만듭니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;dos&quot;&gt;&lt;code&gt;cd ~/ros2_lab_ws/src/robot_interfaces
mkdir msg&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000; font-size: 1.25em; letter-spacing: -1px;&quot;&gt;4. RobotStatus.msg 작성&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;1609&quot; data-start=&quot;1599&quot; data-ke-size=&quot;size16&quot;&gt;파일을 생성합니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot;&gt;&lt;code&gt;touch msg/RobotStatus.msg&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;1666&quot; data-start=&quot;1649&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;1666&quot; data-start=&quot;1649&quot; data-ke-size=&quot;size16&quot;&gt;내용은 다음과 같이 작성합니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;string robot_id
string mode
float32 battery_percent
bool emergency_stop&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;1759&quot; data-start=&quot;1753&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;각 필드 의미는 다음과 같습니다.&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;필드&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;타입&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;의미&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-end=&quot;1999&quot; data-start=&quot;1818&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody data-end=&quot;1999&quot; data-start=&quot;1849&quot;&gt;
&lt;tr data-end=&quot;1882&quot; data-start=&quot;1849&quot;&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;1862&quot; data-start=&quot;1849&quot;&gt;robot_id&lt;/td&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;1873&quot; data-start=&quot;1862&quot;&gt;string&lt;/td&gt;
&lt;td data-end=&quot;1882&quot; data-start=&quot;1873&quot; data-col-size=&quot;sm&quot;&gt;로봇 ID&lt;/td&gt;
&lt;/tr&gt;
&lt;tr data-end=&quot;1915&quot; data-start=&quot;1883&quot;&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;1892&quot; data-start=&quot;1883&quot;&gt;mode&lt;/td&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;1903&quot; data-start=&quot;1892&quot;&gt;string&lt;/td&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;1915&quot; data-start=&quot;1903&quot;&gt;현재 동작 모드&lt;/td&gt;
&lt;/tr&gt;
&lt;tr data-end=&quot;1958&quot; data-start=&quot;1916&quot;&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;1936&quot; data-start=&quot;1916&quot;&gt;battery_percent&lt;/td&gt;
&lt;td data-end=&quot;1948&quot; data-start=&quot;1936&quot; data-col-size=&quot;sm&quot;&gt;float32&lt;/td&gt;
&lt;td data-end=&quot;1958&quot; data-start=&quot;1948&quot; data-col-size=&quot;sm&quot;&gt;배터리 잔량&lt;/td&gt;
&lt;/tr&gt;
&lt;tr data-end=&quot;1999&quot; data-start=&quot;1959&quot;&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;1978&quot; data-start=&quot;1959&quot;&gt;emergency_stop&lt;/td&gt;
&lt;td data-end=&quot;1987&quot; data-start=&quot;1978&quot; data-col-size=&quot;sm&quot;&gt;bool&lt;/td&gt;
&lt;td data-end=&quot;1999&quot; data-start=&quot;1987&quot; data-col-size=&quot;sm&quot;&gt;비상 정지 상태&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000;&quot; data-section-id=&quot;85k6yd&quot; data-start=&quot;3690&quot; data-end=&quot;3716&quot; data-ke-size=&quot;size20&quot;&gt;5. topic_practice 패키지 생성&lt;/h4&gt;
&lt;p data-start=&quot;3718&quot; data-end=&quot;3765&quot; data-ke-size=&quot;size16&quot;&gt;이제 Publisher와 Subscriber를 만들 Python 패키지를 생성합니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;cpp&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot; data-ke-language=&quot;cpp&quot;&gt;&lt;code&gt;cd ~/ros2_lab_ws/src

ros2 pkg create topic_practice --build-type ament_python --dependencies rclpy robot_interfaces&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-start=&quot;3905&quot; data-end=&quot;3926&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-start=&quot;3905&quot; data-end=&quot;3926&quot; data-ke-size=&quot;size16&quot;&gt;생성 후 구조는 대략 다음과 같습니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;routeros&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot;&gt;&lt;code&gt;topic_practice
├── package.xml
├── setup.py
├── setup.cfg
├── resource
│   └── topic_practice
└── topic_practice
    └── __init__.py&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000;&quot; data-section-id=&quot;1aobd93&quot; data-start=&quot;4079&quot; data-end=&quot;4099&quot; data-ke-size=&quot;size20&quot;&gt;6. Publisher 코드 작성&lt;/h4&gt;
&lt;p data-start=&quot;4101&quot; data-end=&quot;4120&quot; data-ke-size=&quot;size16&quot;&gt;Publisher 파일을 만듭니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;awk&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot;&gt;&lt;code&gt;cd ~/ros2_lab_ws/src/topic_practice/topic_practice
nano robot_status_pub.py&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-start=&quot;4211&quot; data-end=&quot;4224&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-start=&quot;4211&quot; data-end=&quot;4224&quot; data-ke-size=&quot;size16&quot;&gt;아래 코드를 작성합니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;cpp&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot; data-ke-language=&quot;cpp&quot;&gt;&lt;code&gt;import rclpy
from rclpy.node import Node

from robot_interfaces.msg import RobotStatus


class RobotStatusPublisher(Node):
    def __init__(self):
        super().__init__('robot_status_pub')

        self.publisher_ = self.create_publisher(
            RobotStatus,
            '/robot_status',
            10
        )

        self.timer = self.create_timer(1.0, self.timer_callback)

        self.count = 0
        self.modes = ['IDLE', 'MANUAL', 'AUTO', 'ERROR']

    def timer_callback(self):
        self.count += 1

        msg = RobotStatus()
        msg.robot_id = f'R-{self.count:03d}'
        msg.mode = self.modes[self.count % len(self.modes)]
        msg.battery_percent = max(0.0, 100.0 - self.count * 1.25)
        msg.emergency_stop = msg.mode == 'ERROR'

        self.publisher_.publish(msg)

        self.get_logger().info(
            f'Publish: robot_id={msg.robot_id}, '
            f'mode={msg.mode}, '
            f'battery={msg.battery_percent:.2f}, '
            f'emergency={msg.emergency_stop}'
        )


def main(args=None):
    rclpy.init(args=args)

    node = RobotStatusPublisher()

    try:
        rclpy.spin(node)
    except KeyboardInterrupt:
        pass

    node.destroy_node()
    rclpy.shutdown()


if __name__ == '__main__':
    main()&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000;&quot; data-section-id=&quot;1ge6h17&quot; data-start=&quot;5513&quot; data-end=&quot;5535&quot; data-ke-size=&quot;size20&quot;&gt;7. Subscriber 코드 작성&lt;/h4&gt;
&lt;p data-start=&quot;5537&quot; data-end=&quot;5557&quot; data-ke-size=&quot;size16&quot;&gt;Subscriber 파일을 만듭니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;css&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot;&gt;&lt;code&gt;nano robot_status_sub.py&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-start=&quot;5597&quot; data-end=&quot;5610&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-start=&quot;5597&quot; data-end=&quot;5610&quot; data-ke-size=&quot;size16&quot;&gt;아래 코드를 작성합니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;python&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot;&gt;&lt;code&gt;import rclpy
from rclpy.node import Node

from robot_interfaces.msg import RobotStatus


class RobotStatusSubscriber(Node):
    def __init__(self):
        super().__init__('robot_status_sub')

        self.subscription = self.create_subscription(
            RobotStatus,
            '/robot_status',
            self.listener_callback,
            10
        )

    def listener_callback(self, msg):
        if msg.emergency_stop:
            self.get_logger().error(
                f'Emergency detected: {msg.robot_id} mode={msg.mode}'
            )
        else:
            self.get_logger().info(
                f'Receive: {msg.robot_id} | '
                f'{msg.mode} | '
                f'battery={msg.battery_percent:.2f} | '
                f'emergency={msg.emergency_stop}'
            )


def main(args=None):
    rclpy.init(args=args)

    node = RobotStatusSubscriber()

    try:
        rclpy.spin(node)
    except KeyboardInterrupt:
        pass

    node.destroy_node()
    rclpy.shutdown()


if __name__ == '__main__':
    main()&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-end=&quot;2042&quot; data-start=&quot;2006&quot; data-section-id=&quot;1r33o70&quot; data-ke-size=&quot;size20&quot;&gt;8. robot_interfaces/package.xml 수정&lt;/h4&gt;
&lt;p data-end=&quot;2080&quot; data-start=&quot;2044&quot; data-ke-size=&quot;size16&quot;&gt;robot_interfaces/package.xml을 엽니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;아래 내용을 추가합니다.&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;xml&quot;&gt;&lt;code&gt;&amp;lt;buildtool_depend&amp;gt;rosidl_default_generators&amp;lt;/buildtool_depend&amp;gt;
&amp;lt;exec_depend&amp;gt;rosidl_default_runtime&amp;lt;/exec_depend&amp;gt;
&amp;lt;member_of_group&amp;gt;rosidl_interface_packages&amp;lt;/member_of_group&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;2335&quot; data-start=&quot;2313&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;2335&quot; data-start=&quot;2313&quot; data-ke-size=&quot;size16&quot;&gt;전체에서 중요한 부분은 이런 형태입니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;xml&quot;&gt;&lt;code&gt;&amp;lt;?xml version=&quot;1.0&quot;?&amp;gt;
&amp;lt;package format=&quot;3&quot;&amp;gt;
  &amp;lt;name&amp;gt;robot_interfaces&amp;lt;/name&amp;gt;
  &amp;lt;version&amp;gt;0.0.0&amp;lt;/version&amp;gt;
  &amp;lt;description&amp;gt;Custom interfaces for robot examples&amp;lt;/description&amp;gt;
  &amp;lt;maintainer email=&quot;user@example.com&quot;&amp;gt;user&amp;lt;/maintainer&amp;gt;
  &amp;lt;license&amp;gt;Apache-2.0&amp;lt;/license&amp;gt;

  &amp;lt;buildtool_depend&amp;gt;ament_cmake&amp;lt;/buildtool_depend&amp;gt;

  &amp;lt;buildtool_depend&amp;gt;rosidl_default_generators&amp;lt;/buildtool_depend&amp;gt;
  &amp;lt;exec_depend&amp;gt;rosidl_default_runtime&amp;lt;/exec_depend&amp;gt;

  &amp;lt;member_of_group&amp;gt;rosidl_interface_packages&amp;lt;/member_of_group&amp;gt;

  &amp;lt;test_depend&amp;gt;ament_lint_auto&amp;lt;/test_depend&amp;gt;
  &amp;lt;test_depend&amp;gt;ament_lint_common&amp;lt;/test_depend&amp;gt;

  &amp;lt;export&amp;gt;
    &amp;lt;build_type&amp;gt;ament_cmake&amp;lt;/build_type&amp;gt;
  &amp;lt;/export&amp;gt;
&amp;lt;/package&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;3027&quot; data-start=&quot;3009&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;3027&quot; data-start=&quot;3009&quot; data-ke-size=&quot;size16&quot;&gt;여기서 중요 포인트는 이것입니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;xml&quot;&gt;&lt;code&gt;&amp;lt;member_of_group&amp;gt;rosidl_interface_packages&amp;lt;/member_of_group&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;3137&quot; data-start=&quot;3102&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;3137&quot; data-start=&quot;3102&quot; data-ke-size=&quot;size16&quot;&gt;이게 빠지면 인터페이스 패키지 빌드에서 문제가 날 수 있습니다.&lt;/p&gt;
&lt;p data-end=&quot;3137&quot; data-start=&quot;3102&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;3137&quot; data-start=&quot;3102&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;3137&quot; data-start=&quot;3102&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-end=&quot;3183&quot; data-start=&quot;3144&quot; data-section-id=&quot;b1pavq&quot; data-ke-size=&quot;size20&quot;&gt;9. robot_interfaces/CMakeLists.txt 수정&lt;/h4&gt;
&lt;p data-end=&quot;3207&quot; data-start=&quot;3185&quot; data-ke-size=&quot;size16&quot;&gt;CMakeLists.txt를 엽니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;내용을 다음처럼 정리합니다.&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;stylus&quot;&gt;&lt;code&gt;cmake_minimum_required(VERSION 3.8)
project(robot_interfaces)

if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES &quot;Clang&quot;)
  add_compile_options(-Wall -Wextra -Wpedantic)
endif()

find_package(ament_cmake REQUIRED)
find_package(rosidl_default_generators REQUIRED)

rosidl_generate_interfaces(${PROJECT_NAME}
  &quot;msg/RobotStatus.msg&quot;
)

ament_export_dependencies(rosidl_default_runtime)

ament_package()&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-end=&quot;6701&quot; data-start=&quot;6684&quot; data-section-id=&quot;yuzjk5&quot; data-ke-size=&quot;size20&quot;&gt;10. setup.py 수정&lt;/h4&gt;
&lt;p data-end=&quot;6750&quot; data-start=&quot;6703&quot; data-ke-size=&quot;size16&quot;&gt;ros2 run으로 실행하려면 setup.py에 실행 파일을 등록해야 합니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;entry_points 부분을 다음처럼 수정합니다.&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;sml&quot;&gt;&lt;code&gt;entry_points={
    'console_scripts': [
        'robot_status_pub = topic_practice.robot_status_pub:main',
        'robot_status_sub = topic_practice.robot_status_sub:main',
    ],
},&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;7062&quot; data-start=&quot;7046&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;7062&quot; data-start=&quot;7046&quot; data-ke-size=&quot;size16&quot;&gt;전체 예시는 다음과 같습니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;from setuptools import find_packages, setup

package_name = 'topic_practice'

setup(
    name=package_name,
    version='0.0.0',
    packages=find_packages(exclude=['test']),
    data_files=[
        ('share/ament_index/resource_index/packages',
            ['resource/' + package_name]),
        ('share/' + package_name, ['package.xml']),
    ],
    install_requires=['setuptools'],
    zip_safe=True,
    maintainer='user',
    maintainer_email='user@example.com',
    description='ROS 2 topic practice package',
    license='Apache-2.0',
    tests_require=['pytest'],
    entry_points={
        'console_scripts': [
            'robot_status_pub = topic_practice.robot_status_pub:main',
            'robot_status_sub = topic_practice.robot_status_sub:main',
        ],
    },
)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-end=&quot;7901&quot; data-start=&quot;7866&quot; data-section-id=&quot;rlogjl&quot; data-ke-size=&quot;size20&quot;&gt;11. topic_practice/package.xml 확인&lt;/h4&gt;
&lt;p data-end=&quot;7956&quot; data-start=&quot;7903&quot; data-ke-size=&quot;size16&quot;&gt;topic_practice는 rclpy와 robot_interfaces를 사용합니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;아래 의존성이 있는지 확인합니다.&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;xml&quot;&gt;&lt;code&gt;&amp;lt;depend&amp;gt;rclpy&amp;lt;/depend&amp;gt;
&amp;lt;depend&amp;gt;robot_interfaces&amp;lt;/depend&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;8090&quot; data-start=&quot;8077&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;8090&quot; data-start=&quot;8077&quot; data-ke-size=&quot;size16&quot;&gt;예시는 다음과 같습니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;xml&quot;&gt;&lt;code&gt;&amp;lt;?xml version=&quot;1.0&quot;?&amp;gt;
&amp;lt;package format=&quot;3&quot;&amp;gt;
  &amp;lt;name&amp;gt;topic_practice&amp;lt;/name&amp;gt;
  &amp;lt;version&amp;gt;0.0.0&amp;lt;/version&amp;gt;
  &amp;lt;description&amp;gt;ROS 2 topic practice package&amp;lt;/description&amp;gt;
  &amp;lt;maintainer email=&quot;user@example.com&quot;&amp;gt;user&amp;lt;/maintainer&amp;gt;
  &amp;lt;license&amp;gt;Apache-2.0&amp;lt;/license&amp;gt;

  &amp;lt;depend&amp;gt;rclpy&amp;lt;/depend&amp;gt;
  &amp;lt;depend&amp;gt;robot_interfaces&amp;lt;/depend&amp;gt;

  &amp;lt;test_depend&amp;gt;ament_copyright&amp;lt;/test_depend&amp;gt;
  &amp;lt;test_depend&amp;gt;ament_flake8&amp;lt;/test_depend&amp;gt;
  &amp;lt;test_depend&amp;gt;ament_pep257&amp;lt;/test_depend&amp;gt;
  &amp;lt;test_depend&amp;gt;python3-pytest&amp;lt;/test_depend&amp;gt;

  &amp;lt;export&amp;gt;
    &amp;lt;build_type&amp;gt;ament_python&amp;lt;/build_type&amp;gt;
  &amp;lt;/export&amp;gt;
&amp;lt;/package&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h4 data-end=&quot;8679&quot; data-start=&quot;8669&quot; data-section-id=&quot;h71cs2&quot; data-ke-size=&quot;size20&quot;&gt;12. 빌드하기&lt;/h4&gt;
&lt;p data-end=&quot;8698&quot; data-start=&quot;8681&quot; data-ke-size=&quot;size16&quot;&gt;워크스페이스 루트로 이동합니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;jboss-cli&quot;&gt;&lt;code&gt;cd ~/ros2_lab_ws&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;8736&quot; data-start=&quot;8730&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;8736&quot; data-start=&quot;8730&quot; data-ke-size=&quot;size16&quot;&gt;빌드합니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;ada&quot;&gt;&lt;code&gt;colcon build --symlink-install&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;8803&quot; data-start=&quot;8782&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;8803&quot; data-start=&quot;8782&quot; data-ke-size=&quot;size16&quot;&gt;빌드가 끝나면 환경 설정을 적용합니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;arduino&quot;&gt;&lt;code&gt;source install/setup.bash&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;8925&quot; data-start=&quot;8844&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;8925&quot; data-start=&quot;8844&quot; data-ke-size=&quot;size16&quot;&gt;매우 중요합니다.&lt;br /&gt;빌드 후 source install/setup.bash를 하지 않으면 새 메시지나 실행 파일을 ROS 2가 못 찾습니다.&lt;/p&gt;
&lt;p data-end=&quot;8925&quot; data-start=&quot;8844&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;8925&quot; data-start=&quot;8844&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;8925&quot; data-start=&quot;8844&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-end=&quot;8947&quot; data-start=&quot;8932&quot; data-section-id=&quot;1adoqxw&quot; data-ke-size=&quot;size20&quot;&gt;13. 메시지 생성 확인&lt;/h4&gt;
&lt;p data-end=&quot;8977&quot; data-start=&quot;8949&quot; data-ke-size=&quot;size16&quot;&gt;사용자 정의 메시지가 정상 등록되었는지 확인합니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;ros2 interface show robot_interfaces/msg/RobotStatus&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;9062&quot; data-start=&quot;9045&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;9062&quot; data-start=&quot;9045&quot; data-ke-size=&quot;size16&quot;&gt;정상이라면 다음처럼 출력됩니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;string robot_id
string mode
float32 battery_percent
bool emergency_stop&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h4 data-end=&quot;9172&quot; data-start=&quot;9154&quot; data-section-id=&quot;3zwvzj&quot; data-ke-size=&quot;size20&quot;&gt;14. Publisher 실행&lt;/h4&gt;
&lt;p data-end=&quot;9191&quot; data-start=&quot;9174&quot; data-ke-size=&quot;size16&quot;&gt;첫 번째 터미널에서 실행합니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;properties&quot;&gt;&lt;code&gt;cd ~/ros2_lab_ws
source install/setup.bash
ros2 run topic_practice robot_status_pub&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;9309&quot; data-start=&quot;9290&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;9309&quot; data-start=&quot;9290&quot; data-ke-size=&quot;size16&quot;&gt;정상 출력 예시는 다음과 같습니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;[INFO] [robot_status_pub]: Publish: robot_id=R-001, mode=MANUAL, battery=98.75, emergency=False
[INFO] [robot_status_pub]: Publish: robot_id=R-001, mode=AUTO, battery=97.50, emergency=False
[INFO] [robot_status_pub]: Publish: robot_id=R-001, mode=ERROR, battery=96.25, emergency=True
[INFO] [robot_status_pub]: Publish: robot_id=R-001, mode=IDLE, battery=95.00, emergency=False&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;9708&quot; data-start=&quot;9702&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;9708&quot; data-start=&quot;9702&quot; data-ke-size=&quot;size16&quot;&gt;확인할 것:&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;mercury&quot;&gt;&lt;code&gt;mode가 계속 바뀐다.
battery가 계속 줄어든다.
mode가 ERROR일 때 emergency_stop이 True가 된다.&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-end=&quot;9820&quot; data-start=&quot;9801&quot; data-section-id=&quot;1juzd7c&quot; data-ke-size=&quot;size20&quot;&gt;15. Subscriber 실행&lt;/h4&gt;
&lt;p data-end=&quot;9836&quot; data-start=&quot;9822&quot; data-ke-size=&quot;size16&quot;&gt;두 번째 터미널을 엽니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;properties&quot;&gt;&lt;code&gt;cd ~/ros2_lab_ws
source install/setup.bash
ros2 run topic_practice robot_status_sub&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;9954&quot; data-start=&quot;9935&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;9954&quot; data-start=&quot;9935&quot; data-ke-size=&quot;size16&quot;&gt;정상 출력 예시는 다음과 같습니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;[INFO] [robot_status_sub]: Receive: R-001 | MANUAL | battery=98.75 | emergency=False
[INFO] [robot_status_sub]: Receive: R-001 | AUTO | battery=97.50 | emergency=False
[ERROR] [robot_status_sub]: Emergency detected: R-001 mode=ERROR
[INFO] [robot_status_sub]: Receive: R-001 | IDLE | battery=95.00 | emergency=False&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;10299&quot; data-start=&quot;10285&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;10299&quot; data-start=&quot;10285&quot; data-ke-size=&quot;size16&quot;&gt;여기서 핵심은 이것입니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;mode=ERROR이면 Subscriber 로그가 [ERROR]로 출력된다.&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;10411&quot; data-start=&quot;10357&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;10411&quot; data-start=&quot;10357&quot; data-ke-size=&quot;size16&quot;&gt;즉, Subscriber가 단순 출력만 하는 게 아니라 메시지 내용을 보고 조건 판단까지 합니다.&lt;/p&gt;
&lt;p data-end=&quot;10411&quot; data-start=&quot;10357&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;10411&quot; data-start=&quot;10357&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;10411&quot; data-start=&quot;10357&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-end=&quot;10437&quot; data-start=&quot;10418&quot; data-section-id=&quot;fa7ak8&quot; data-ke-size=&quot;size20&quot;&gt;16. CLI로 Topic 확인&lt;/h4&gt;
&lt;p data-end=&quot;10472&quot; data-start=&quot;10439&quot; data-ke-size=&quot;size16&quot;&gt;Publisher가 실행 중인 상태에서 새 터미널을 엽니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;bash&quot;&gt;&lt;code&gt;cd ~/ros2_lab_ws
source install/setup.bash&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;10542&quot; data-start=&quot;10530&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;10542&quot; data-start=&quot;10530&quot; data-ke-size=&quot;size16&quot;&gt;Topic 목록 확인:&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;applescript&quot;&gt;&lt;code&gt;ros2 topic list&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;10604&quot; data-start=&quot;10573&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;10604&quot; data-start=&quot;10573&quot; data-ke-size=&quot;size16&quot;&gt;정상이라면 /robot_status가 보여야 합니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;jboss-cli&quot;&gt;&lt;code&gt;/robot_status
/parameter_events
/rosout&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;10672&quot; data-start=&quot;10659&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;10672&quot; data-start=&quot;10659&quot; data-ke-size=&quot;size16&quot;&gt;Topic 데이터 확인:&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;jboss-cli&quot;&gt;&lt;code&gt;ros2 topic echo /robot_status&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;10723&quot; data-start=&quot;10717&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;10723&quot; data-start=&quot;10717&quot; data-ke-size=&quot;size16&quot;&gt;출력 예시:&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;yaml&quot;&gt;&lt;code&gt;robot_id: R-001
mode: AUTO
battery_percent: 97.5
emergency_stop: false
---
robot_id: R-001
mode: ERROR
battery_percent: 96.25
emergency_stop: true
---&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;10901&quot; data-start=&quot;10889&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;10901&quot; data-start=&quot;10889&quot; data-ke-size=&quot;size16&quot;&gt;Topic 주기 확인:&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;jboss-cli&quot;&gt;&lt;code&gt;ros2 topic hz /robot_status&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;10972&quot; data-start=&quot;10944&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;10972&quot; data-start=&quot;10944&quot; data-ke-size=&quot;size16&quot;&gt;1초마다 발행하므로 약 1Hz가 나와야 합니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;yaml&quot;&gt;&lt;code&gt;average rate: 1.000&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;12766&quot; data-start=&quot;12746&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-end=&quot;12841&quot; data-start=&quot;12827&quot; data-section-id=&quot;4voi4r&quot; data-ke-size=&quot;size20&quot;&gt;17. 실습 확장 과제&lt;/h4&gt;
&lt;p data-end=&quot;12896&quot; data-start=&quot;12871&quot; data-section-id=&quot;3h58lw&quot; data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;12896&quot; data-start=&quot;12871&quot; data-section-id=&quot;3h58lw&quot; data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;과제 1. 배터리 20% 이하 경고 추가&lt;/b&gt;&lt;/p&gt;
&lt;p data-end=&quot;12896&quot; data-start=&quot;12871&quot; data-section-id=&quot;3h58lw&quot; data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;12946&quot; data-start=&quot;12898&quot; data-ke-size=&quot;size16&quot;&gt;Subscriber의 listener_callback()에 아래 조건을 추가합니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;nginx&quot;&gt;&lt;code&gt;if msg.battery_percent &amp;lt;= 20.0:
    self.get_logger().warn(
        f'Low battery: {msg.robot_id} battery={msg.battery_percent:.2f}'
    )&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;13129&quot; data-start=&quot;13107&quot; data-section-id=&quot;dy0bue&quot; data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;과제 2. 로봇 ID 여러 개 사용&lt;/b&gt;&lt;/p&gt;
&lt;p data-end=&quot;13160&quot; data-start=&quot;13131&quot; data-ke-size=&quot;size16&quot;&gt;Publisher에서 로봇 ID를 리스트로 만듭니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot;&gt;&lt;code&gt;self.robot_ids = ['R-001', 'R-002', 'R-003']&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;13247&quot; data-start=&quot;13222&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;13247&quot; data-start=&quot;13222&quot; data-ke-size=&quot;size16&quot;&gt;그리고 callback에서 바꿔가며 넣습니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot;&gt;&lt;code&gt;msg.robot_id = self.robot_ids[self.count % len(self.robot_ids)]&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;13355&quot; data-start=&quot;13333&quot; data-section-id=&quot;1k21ffg&quot; data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;과제 3. mode를 숫자로 바꾸기&lt;/b&gt;&lt;/p&gt;
&lt;p data-end=&quot;13388&quot; data-start=&quot;13357&quot; data-ke-size=&quot;size16&quot;&gt;실무에서는 문자열보다 숫자 상수를 쓰는 경우가 많습니다.&lt;/p&gt;
&lt;p data-end=&quot;13388&quot; data-start=&quot;13357&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;13424&quot; data-start=&quot;13390&quot; data-ke-size=&quot;size16&quot;&gt;RobotStatus.msg를 다음처럼 바꿀 수 있습니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;uint8 MODE_IDLE=0
uint8 MODE_MANUAL=1
uint8 MODE_AUTO=2
uint8 MODE_ERROR=3

string robot_id
uint8 mode
float32 battery_percent
bool emergency_stop&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;13620&quot; data-start=&quot;13586&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;641&quot; data-start=&quot;620&quot; data-section-id=&quot;1r5bhm6&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Publisher 예제 수정&lt;/b&gt;&lt;/p&gt;
&lt;p data-end=&quot;669&quot; data-start=&quot;643&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;669&quot; data-start=&quot;643&quot; data-ke-size=&quot;size16&quot;&gt;기존에는 문자열로 이렇게 작성했을 수 있습니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;ini&quot;&gt;&lt;code&gt;msg.mode = &quot;AUTO&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;741&quot; data-start=&quot;704&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;741&quot; data-start=&quot;704&quot; data-ke-size=&quot;size16&quot;&gt;이제는 RobotStatus.msg에 정의한 상수를 사용합니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;ini&quot;&gt;&lt;code&gt;msg.mode = RobotStatus.MODE_AUTO&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;807&quot; data-start=&quot;791&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;807&quot; data-start=&quot;791&quot; data-ke-size=&quot;size16&quot;&gt;전체 예시는 다음과 같습니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot;&gt;&lt;code&gt;import rclpy
from rclpy.node import Node

from my_robot_interfaces.msg import RobotStatus


class RobotStatusPublisher(Node):

    def __init__(self):
        super().__init__('robot_status_publisher')

        self.publisher = self.create_publisher(
            RobotStatus,
            'robot_status',
            10
        )
        
        self.robot_ids = ['R-001', 'R-002', 'R-003']

        self.timer = self.create_timer(1.0, self.publish_status)

    def publish_status(self):
        msg = RobotStatus()

        msg.robot_id = self.robot_ids[self.count % len(self.robot_ids)]
        msg.mode = RobotStatus.MODE_AUTO
        msg.battery_percent = 87.5
        msg.emergency_stop = False

        self.publisher.publish(msg)

        self.get_logger().info(
            f'Publish: robot_id={msg.robot_id}, '
            f'mode={msg.mode}, '
            f'battery={msg.battery_percent}, '
            f'emergency_stop={msg.emergency_stop}'
        )


def main(args=None):
    rclpy.init(args=args)

    node = RobotStatusPublisher()
    rclpy.spin(node)

    node.destroy_node()
    rclpy.shutdown()


if __name__ == '__main__':
    main()&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;1902&quot; data-start=&quot;1880&quot; data-section-id=&quot;rbagkb&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Subscriber 예제 수정&lt;/b&gt;&lt;/p&gt;
&lt;p data-end=&quot;1955&quot; data-start=&quot;1904&quot; data-ke-size=&quot;size16&quot;&gt;Subscriber에서는 숫자 값을 직접 비교하지 말고, 메시지에 정의된 상수를 사용합니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;isbl&quot;&gt;&lt;code&gt;if msg.mode == RobotStatus.MODE_AUTO:
    print(&quot;자동 주행 모드입니다.&quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;2052&quot; data-start=&quot;2036&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;2052&quot; data-start=&quot;2036&quot; data-ke-size=&quot;size16&quot;&gt;전체 예시는 다음과 같습니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;python&quot;&gt;&lt;code&gt;import rclpy
from rclpy.node import Node

from my_robot_interfaces.msg import RobotStatus


class RobotStatusSubscriber(Node):

    def __init__(self):
        super().__init__('robot_status_subscriber')

        self.subscription = self.create_subscription(
            RobotStatus,
            'robot_status',
            self.status_callback,
            10
        )

    def status_callback(self, msg):
        if msg.mode == RobotStatus.MODE_IDLE:
            mode_text = 'IDLE'

        elif msg.mode == RobotStatus.MODE_MANUAL:
            mode_text = 'MANUAL'

        elif msg.mode == RobotStatus.MODE_AUTO:
            mode_text = 'AUTO'

        elif msg.mode == RobotStatus.MODE_ERROR:
            mode_text = 'ERROR'

        else:
            mode_text = 'UNKNOWN'

        self.get_logger().info(
            f'Receive: robot_id={msg.robot_id}, '
            f'mode={mode_text}, '
            f'battery={msg.battery_percent}, '
            f'emergency_stop={msg.emergency_stop}'
        )


def main(args=None):
    rclpy.init(args=args)

    node = RobotStatusSubscriber()
    rclpy.spin(node)

    node.destroy_node()
    rclpy.shutdown()


if __name__ == '__main__':
    main()&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-end=&quot;13642&quot; data-start=&quot;13627&quot; data-section-id=&quot;tsnw1m&quot; data-ke-size=&quot;size20&quot;&gt;18. 전체 명령어 요약&lt;/h4&gt;
&lt;p data-end=&quot;13668&quot; data-start=&quot;13644&quot; data-ke-size=&quot;size16&quot;&gt;처음부터 한 번에 정리하면 다음과 같습니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot;&gt;&lt;code&gt;mkdir -p ~/ros2_lab_ws/src
cd ~/ros2_lab_ws/src

ros2 pkg create robot_interfaces --build-type ament_cmake

cd ~/ros2_lab_ws/src/robot_interfaces
mkdir msg
touch msg/RobotStatus.msg&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;13882&quot; data-start=&quot;13864&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;13882&quot; data-start=&quot;13864&quot; data-ke-size=&quot;size16&quot;&gt;RobotStatus.msg:&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;string robot_id
string mode
float32 battery_percent
bool emergency_stop&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;13976&quot; data-start=&quot;13969&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;13976&quot; data-start=&quot;13969&quot; data-ke-size=&quot;size16&quot;&gt;패키지 생성:&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;jboss-cli&quot;&gt;&lt;code&gt;cd ~/ros2_lab_ws/src

ros2 pkg create topic_practice \
  --build-type ament_python \
  --dependencies rclpy robot_interfaces&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;14129&quot; data-start=&quot;14116&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;14129&quot; data-start=&quot;14116&quot; data-ke-size=&quot;size16&quot;&gt;Publisher 작성:&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot;&gt;&lt;code&gt;cd ~/ros2_lab_ws/src/topic_practice/topic_practice
gedit robot_status_pub.py&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;14234&quot; data-start=&quot;14220&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;14234&quot; data-start=&quot;14220&quot; data-ke-size=&quot;size16&quot;&gt;Subscriber 작성:&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot;&gt;&lt;code&gt;gedit robot_status_sub.py&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;14277&quot; data-start=&quot;14274&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;14277&quot; data-start=&quot;14274&quot; data-ke-size=&quot;size16&quot;&gt;빌드:&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;jboss-cli&quot;&gt;&lt;code&gt;cd ~/ros2_lab_ws
colcon build --symlink-install
source install/setup.bash&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;14373&quot; data-start=&quot;14366&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;14373&quot; data-start=&quot;14366&quot; data-ke-size=&quot;size16&quot;&gt;메시지 확인:&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;ros2 interface show robot_interfaces/msg/RobotStatus&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;14454&quot; data-start=&quot;14441&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;14454&quot; data-start=&quot;14441&quot; data-ke-size=&quot;size16&quot;&gt;Publisher 실행:&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;dockerfile&quot;&gt;&lt;code&gt;ros2 run topic_practice robot_status_pub&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;14524&quot; data-start=&quot;14510&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;14524&quot; data-start=&quot;14510&quot; data-ke-size=&quot;size16&quot;&gt;Subscriber 실행:&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;dockerfile&quot;&gt;&lt;code&gt;ros2 run topic_practice robot_status_sub&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;14589&quot; data-start=&quot;14580&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;14589&quot; data-start=&quot;14580&quot; data-ke-size=&quot;size16&quot;&gt;Topic 확인:&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;jboss-cli&quot;&gt;&lt;code&gt;ros2 topic list
ros2 topic echo /robot_status
ros2 topic hz /robot_status&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-is-only-node=&quot;&quot; data-is-last-node=&quot;&quot; data-end=&quot;15136&quot; data-start=&quot;15066&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>강좌/ROS2</category>
      <category>python 토픽 실습 #2</category>
      <author>MakingRobotWizard</author>
      <guid isPermaLink="true">https://makingrobot.tistory.com/435</guid>
      <comments>https://makingrobot.tistory.com/435#entry435comment</comments>
      <pubDate>Tue, 26 May 2026 00:48:53 +0900</pubDate>
    </item>
    <item>
      <title>Python 기본 타입 메시지 Publisher / Subscriber 예제</title>
      <link>https://makingrobot.tistory.com/434</link>
      <description>&lt;p data-end=&quot;300&quot; data-start=&quot;237&quot; data-ke-size=&quot;size16&quot;&gt;이번 실습에서는 직접 만든 메시지 타입을 사용해서 Publisher와 Subscriber가 통신하도록 구성합니다.&lt;/p&gt;
&lt;p data-end=&quot;323&quot; data-start=&quot;302&quot; data-ke-size=&quot;size16&quot;&gt;사용할 메시지 구조는 다음과 같습니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;int32 id
float32 temperature
bool enabled
string name&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;411&quot; data-start=&quot;392&quot; data-ke-size=&quot;size16&quot;&gt;최종 실행 구조는 다음과 같습니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;armasm&quot;&gt;&lt;code&gt;basic_types_pub 노드
        &amp;darr;
/basic_types 토픽
        &amp;darr;
basic_types_sub 노드&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;hr data-end=&quot;503&quot; data-start=&quot;500&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h4 data-end=&quot;519&quot; data-start=&quot;505&quot; data-section-id=&quot;rbz5zt&quot; data-ke-size=&quot;size20&quot;&gt;1. 워크스페이스 생성&lt;/h4&gt;
&lt;p data-end=&quot;543&quot; data-start=&quot;521&quot; data-ke-size=&quot;size16&quot;&gt;먼저 ROS 2 워크스페이스를 만듭니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;jboss-cli&quot;&gt;&lt;code&gt;mkdir -p ~/ros2_lab_ws/src
cd ~/ros2_lab_ws/src&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;619&quot; data-start=&quot;606&quot; data-ke-size=&quot;size16&quot;&gt;구조는 다음과 같습니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;arcade&quot;&gt;&lt;code&gt;~/ros2_lab_ws/
└── src/&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;Screenshot from 2026-05-27 00-12-42.png&quot; data-origin-width=&quot;786&quot; data-origin-height=&quot;533&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/baMrP3/dJMcacJ3E21/kMIBlZph7eB56j7lQp3jUK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/baMrP3/dJMcacJ3E21/kMIBlZph7eB56j7lQp3jUK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/baMrP3/dJMcacJ3E21/kMIBlZph7eB56j7lQp3jUK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbaMrP3%2FdJMcacJ3E21%2FkMIBlZph7eB56j7lQp3jUK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;786&quot; height=&quot;533&quot; data-filename=&quot;Screenshot from 2026-05-27 00-12-42.png&quot; data-origin-width=&quot;786&quot; data-origin-height=&quot;533&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-end=&quot;680&quot; data-start=&quot;663&quot; data-section-id=&quot;4vdasa&quot; data-ke-size=&quot;size20&quot;&gt;2. 인터페이스 패키지 생성&lt;/h4&gt;
&lt;p data-end=&quot;740&quot; data-start=&quot;682&quot; data-ke-size=&quot;size16&quot;&gt;사용자 정의 메시지는 일반 Python 패키지가 아니라 별도의 인터페이스 패키지에 두는 것이 정석입니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot;&gt;&lt;code&gt;cd ~/ros2_lab_ws/src

ros2 pkg create robot_interfaces --build-type ament_cmake&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;860&quot; data-start=&quot;839&quot; data-ke-size=&quot;size16&quot;&gt;생성 후 구조는 대략 다음과 같습니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;crmsh&quot;&gt;&lt;code&gt;ros2_lab_ws/src/
└── robot_interfaces/
    ├── CMakeLists.txt
    ├── package.xml
    └── include/&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;Screenshot from 2026-05-27 00-14-12.png&quot; data-origin-width=&quot;786&quot; data-origin-height=&quot;533&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bjSc6S/dJMcai4s8It/pEJLOGmMCexsIm1KefBWJk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bjSc6S/dJMcai4s8It/pEJLOGmMCexsIm1KefBWJk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bjSc6S/dJMcai4s8It/pEJLOGmMCexsIm1KefBWJk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbjSc6S%2FdJMcai4s8It%2FpEJLOGmMCexsIm1KefBWJk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;786&quot; height=&quot;533&quot; data-filename=&quot;Screenshot from 2026-05-27 00-14-12.png&quot; data-origin-width=&quot;786&quot; data-origin-height=&quot;533&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;Screenshot from 2026-05-27 00-14-17.png&quot; data-origin-width=&quot;786&quot; data-origin-height=&quot;533&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cEy7lv/dJMcagFGXB3/IKHacNZFCKAk59jeCSN760/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cEy7lv/dJMcagFGXB3/IKHacNZFCKAk59jeCSN760/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cEy7lv/dJMcagFGXB3/IKHacNZFCKAk59jeCSN760/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcEy7lv%2FdJMcagFGXB3%2FIKHacNZFCKAk59jeCSN760%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;786&quot; height=&quot;533&quot; data-filename=&quot;Screenshot from 2026-05-27 00-14-17.png&quot; data-origin-width=&quot;786&quot; data-origin-height=&quot;533&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h4 data-end=&quot;993&quot; data-start=&quot;979&quot; data-section-id=&quot;asb3bj&quot; data-ke-size=&quot;size20&quot;&gt;3. 메시지 파일 생성&lt;/h4&gt;
&lt;p data-end=&quot;1036&quot; data-start=&quot;995&quot; data-ke-size=&quot;size16&quot;&gt;robot_interfaces 패키지 안에 msg 폴더를 만듭니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;awk&quot;&gt;&lt;code&gt;mkdir -p ~/ros2_lab_ws/src/robot_interfaces/msg&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;Screenshot from 2026-05-27 00-15-37.png&quot; data-origin-width=&quot;786&quot; data-origin-height=&quot;533&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bwMCi9/dJMcaaZITon/rDKS7MkKah5IJxnCCIcRX0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bwMCi9/dJMcaaZITon/rDKS7MkKah5IJxnCCIcRX0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bwMCi9/dJMcaaZITon/rDKS7MkKah5IJxnCCIcRX0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbwMCi9%2FdJMcaaZITon%2FrDKS7MkKah5IJxnCCIcRX0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;786&quot; height=&quot;533&quot; data-filename=&quot;Screenshot from 2026-05-27 00-15-37.png&quot; data-origin-width=&quot;786&quot; data-origin-height=&quot;533&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;1113&quot; data-start=&quot;1099&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;1113&quot; data-start=&quot;1099&quot; data-ke-size=&quot;size16&quot;&gt;메시지 파일을 생성합니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot;&gt;&lt;code&gt;touch ~/ros2_lab_ws/src/robot_interfaces/msg/BasicTypes.msg&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;Screenshot from 2026-05-27 00-21-12.png&quot; data-origin-width=&quot;786&quot; data-origin-height=&quot;533&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cD3yIp/dJMcaayGPZD/fxz4PrbMSBKYaASd9IJ7Tk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cD3yIp/dJMcaayGPZD/fxz4PrbMSBKYaASd9IJ7Tk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cD3yIp/dJMcaayGPZD/fxz4PrbMSBKYaASd9IJ7Tk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcD3yIp%2FdJMcaayGPZD%2Ffxz4PrbMSBKYaASd9IJ7Tk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;786&quot; height=&quot;533&quot; data-filename=&quot;Screenshot from 2026-05-27 00-21-12.png&quot; data-origin-width=&quot;786&quot; data-origin-height=&quot;533&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;1209&quot; data-start=&quot;1188&quot; data-ke-size=&quot;size16&quot;&gt;또는 VS Code를 사용하면 됩니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;awk&quot;&gt;&lt;code&gt;code ~/ros2_lab_ws/src/robot_interfaces/msg/BasicTypes.msg&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;1296&quot; data-start=&quot;1283&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;1296&quot; data-start=&quot;1283&quot; data-ke-size=&quot;size16&quot;&gt;다음 내용을 작성합니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot;&gt;&lt;code&gt;int32 id
float32 temperature
bool enabled
string name&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;1383&quot; data-start=&quot;1365&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;1383&quot; data-start=&quot;1365&quot; data-ke-size=&quot;size16&quot;&gt;각 필드 의미는 다음과 같습니다.&lt;/p&gt;
&lt;p data-end=&quot;1383&quot; data-start=&quot;1365&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 필드&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 타입&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 의미
&lt;table style=&quot;border-collapse: collapse; width: 81.6279%;&quot; border=&quot;1&quot; data-end=&quot;1572&quot; data-start=&quot;1385&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody data-end=&quot;1572&quot; data-start=&quot;1416&quot;&gt;
&lt;tr data-end=&quot;1450&quot; data-start=&quot;1416&quot;&gt;
&lt;td style=&quot;width: 27.3256%;&quot; data-col-size=&quot;sm&quot; data-end=&quot;1423&quot; data-start=&quot;1416&quot;&gt;id&lt;/td&gt;
&lt;td style=&quot;width: 17.4419%;&quot; data-col-size=&quot;sm&quot; data-end=&quot;1433&quot; data-start=&quot;1423&quot;&gt;int32&lt;/td&gt;
&lt;td style=&quot;width: 36.8605%;&quot; data-col-size=&quot;sm&quot; data-end=&quot;1450&quot; data-start=&quot;1433&quot;&gt;로봇 번호, 데이터 순번&lt;/td&gt;
&lt;/tr&gt;
&lt;tr data-end=&quot;1501&quot; data-start=&quot;1451&quot;&gt;
&lt;td style=&quot;width: 27.3256%;&quot; data-col-size=&quot;sm&quot; data-end=&quot;1467&quot; data-start=&quot;1451&quot;&gt;temperature&lt;/td&gt;
&lt;td style=&quot;width: 17.4419%;&quot; data-col-size=&quot;sm&quot; data-end=&quot;1479&quot; data-start=&quot;1467&quot;&gt;float32&lt;/td&gt;
&lt;td style=&quot;width: 36.8605%;&quot; data-col-size=&quot;sm&quot; data-end=&quot;1501&quot; data-start=&quot;1479&quot;&gt;온도, 거리, 전압 같은 실수 값&lt;/td&gt;
&lt;/tr&gt;
&lt;tr data-end=&quot;1533&quot; data-start=&quot;1502&quot;&gt;
&lt;td style=&quot;width: 27.3256%;&quot; data-col-size=&quot;sm&quot; data-end=&quot;1514&quot; data-start=&quot;1502&quot;&gt;enabled&lt;/td&gt;
&lt;td style=&quot;width: 17.4419%;&quot; data-col-size=&quot;sm&quot; data-end=&quot;1523&quot; data-start=&quot;1514&quot;&gt;bool&lt;/td&gt;
&lt;td style=&quot;width: 36.8605%;&quot; data-col-size=&quot;sm&quot; data-end=&quot;1533&quot; data-start=&quot;1523&quot;&gt;활성화 여부&lt;/td&gt;
&lt;/tr&gt;
&lt;tr data-end=&quot;1572&quot; data-start=&quot;1534&quot;&gt;
&lt;td style=&quot;width: 27.3256%;&quot; data-col-size=&quot;sm&quot; data-end=&quot;1543&quot; data-start=&quot;1534&quot;&gt;name&lt;/td&gt;
&lt;td style=&quot;width: 17.4419%;&quot; data-col-size=&quot;sm&quot; data-end=&quot;1554&quot; data-start=&quot;1543&quot;&gt;string&lt;/td&gt;
&lt;td style=&quot;width: 36.8605%;&quot; data-col-size=&quot;sm&quot; data-end=&quot;1572&quot; data-start=&quot;1554&quot;&gt;로봇 이름 또는 상태 이름&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-end=&quot;1603&quot; data-start=&quot;1579&quot; data-section-id=&quot;1vjxk80&quot; data-ke-size=&quot;size20&quot;&gt;4. robot_interfaces 설정&lt;/h4&gt;
&lt;p data-end=&quot;1627&quot; data-start=&quot;1605&quot; data-section-id=&quot;jbq1sz&quot; data-ke-size=&quot;size18&quot;&gt;1) package.xml 수정&lt;/p&gt;
&lt;p data-end=&quot;1637&quot; data-start=&quot;1629&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;1637&quot; data-start=&quot;1629&quot; data-ke-size=&quot;size16&quot;&gt;파일을 엽니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;gradle&quot;&gt;&lt;code&gt;gedit ~/ros2_lab_ws/src/robot_interfaces/package.xml&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;1719&quot; data-start=&quot;1705&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;1719&quot; data-start=&quot;1705&quot; data-ke-size=&quot;size16&quot;&gt;아래 의존성을 추가합니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot;&gt;&lt;code&gt;&amp;lt;build_depend&amp;gt;rosidl_default_generators&amp;lt;/build_depend&amp;gt;
&amp;lt;exec_depend&amp;gt;rosidl_default_runtime&amp;lt;/exec_depend&amp;gt;

&amp;lt;member_of_group&amp;gt;rosidl_interface_packages&amp;lt;/member_of_group&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;1975&quot; data-start=&quot;1950&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;1975&quot; data-start=&quot;1950&quot; data-ke-size=&quot;size16&quot;&gt;전체 구조에서 중요한 부분은 다음과 같습니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;xml&quot;&gt;&lt;code&gt;&amp;lt;package format=&quot;3&quot;&amp;gt;
  &amp;lt;name&amp;gt;robot_interfaces&amp;lt;/name&amp;gt;
  &amp;lt;version&amp;gt;0.0.0&amp;lt;/version&amp;gt;
  &amp;lt;description&amp;gt;Custom interfaces for ROS 2 practice&amp;lt;/description&amp;gt;
  &amp;lt;maintainer email=&quot;user@example.com&quot;&amp;gt;user&amp;lt;/maintainer&amp;gt;
  &amp;lt;license&amp;gt;Apache-2.0&amp;lt;/license&amp;gt;

  &amp;lt;buildtool_depend&amp;gt;ament_cmake&amp;lt;/buildtool_depend&amp;gt;

  &amp;lt;build_depend&amp;gt;rosidl_default_generators&amp;lt;/build_depend&amp;gt;
  &amp;lt;exec_depend&amp;gt;rosidl_default_runtime&amp;lt;/exec_depend&amp;gt;

  &amp;lt;member_of_group&amp;gt;rosidl_interface_packages&amp;lt;/member_of_group&amp;gt;

  &amp;lt;export&amp;gt;
    &amp;lt;build_type&amp;gt;ament_cmake&amp;lt;/build_type&amp;gt;
  &amp;lt;/export&amp;gt;
&amp;lt;/package&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;2539&quot; data-start=&quot;2526&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;2539&quot; data-start=&quot;2526&quot; data-ke-size=&quot;size16&quot;&gt;여기서 특히 중요합니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;xml&quot;&gt;&lt;code&gt;&amp;lt;member_of_group&amp;gt;rosidl_interface_packages&amp;lt;/member_of_group&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;2649&quot; data-start=&quot;2614&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;2649&quot; data-start=&quot;2614&quot; data-ke-size=&quot;size16&quot;&gt;이게 빠지면 인터페이스 패키지 빌드에서 문제가 날 수 있습니다.&lt;/p&gt;
&lt;p data-end=&quot;2649&quot; data-start=&quot;2614&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;Screenshot from 2026-05-27 00-23-17.png&quot; data-origin-width=&quot;1560&quot; data-origin-height=&quot;959&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b8HSil/dJMcacJ3Fdj/BrV0XbIJX8PqkcIq2PyJ91/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b8HSil/dJMcacJ3Fdj/BrV0XbIJX8PqkcIq2PyJ91/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b8HSil/dJMcacJ3Fdj/BrV0XbIJX8PqkcIq2PyJ91/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb8HSil%2FdJMcacJ3Fdj%2FBrV0XbIJX8PqkcIq2PyJ91%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1560&quot; height=&quot;959&quot; data-filename=&quot;Screenshot from 2026-05-27 00-23-17.png&quot; data-origin-width=&quot;1560&quot; data-origin-height=&quot;959&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-end=&quot;2649&quot; data-start=&quot;2614&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;2649&quot; data-start=&quot;2614&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;2649&quot; data-start=&quot;2614&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;2649&quot; data-start=&quot;2614&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;2681&quot; data-start=&quot;2656&quot; data-section-id=&quot;axd6a3&quot; data-ke-size=&quot;size18&quot;&gt;2) CMakeLists.txt 수정&lt;/p&gt;
&lt;p data-end=&quot;2681&quot; data-start=&quot;2656&quot; data-section-id=&quot;axd6a3&quot; data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;2691&quot; data-start=&quot;2683&quot; data-ke-size=&quot;size16&quot;&gt;파일을 엽니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;awk&quot;&gt;&lt;code&gt;gedit ~/ros2_lab_ws/src/robot_interfaces/CMakeLists.txt&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;2773&quot; data-start=&quot;2762&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;2773&quot; data-start=&quot;2762&quot; data-ke-size=&quot;size16&quot;&gt;아래처럼 수정합니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot;&gt;&lt;code&gt;cmake_minimum_required(VERSION 3.8)
project(robot_interfaces)

if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES &quot;Clang&quot;)
  add_compile_options(-Wall -Wextra -Wpedantic)
endif()

find_package(ament_cmake REQUIRED)
find_package(rosidl_default_generators REQUIRED)

rosidl_generate_interfaces(${PROJECT_NAME}
  &quot;msg/BasicTypes.msg&quot;
)

ament_package()&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;3161&quot; data-start=&quot;3149&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;3161&quot; data-start=&quot;3149&quot; data-ke-size=&quot;size16&quot;&gt;핵심은 이 부분입니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;awk&quot;&gt;&lt;code&gt;rosidl_generate_interfaces(${PROJECT_NAME}
  &quot;msg/BasicTypes.msg&quot;
)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;3298&quot; data-start=&quot;3245&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;3298&quot; data-start=&quot;3245&quot; data-ke-size=&quot;size16&quot;&gt;이 설정이 있어야 ROS 2가 BasicTypes.msg를 실제 메시지 타입으로 생성합니다.&lt;/p&gt;
&lt;p data-end=&quot;3298&quot; data-start=&quot;3245&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;Screenshot from 2026-05-27 00-25-07.png&quot; data-origin-width=&quot;1560&quot; data-origin-height=&quot;959&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ba4Op9/dJMcadIPEaX/lVkwR36zNt6uCoKmhZra00/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ba4Op9/dJMcadIPEaX/lVkwR36zNt6uCoKmhZra00/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ba4Op9/dJMcadIPEaX/lVkwR36zNt6uCoKmhZra00/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fba4Op9%2FdJMcadIPEaX%2FlVkwR36zNt6uCoKmhZra00%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1560&quot; height=&quot;959&quot; data-filename=&quot;Screenshot from 2026-05-27 00-25-07.png&quot; data-origin-width=&quot;1560&quot; data-origin-height=&quot;959&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-end=&quot;3298&quot; data-start=&quot;3245&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;3298&quot; data-start=&quot;3245&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;3298&quot; data-start=&quot;3245&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;3298&quot; data-start=&quot;3245&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-end=&quot;3331&quot; data-start=&quot;3305&quot; data-section-id=&quot;1epl8ig&quot; data-ke-size=&quot;size20&quot;&gt;5. topic_practice 패키지 생성&lt;/h4&gt;
&lt;p data-end=&quot;3380&quot; data-start=&quot;3333&quot; data-ke-size=&quot;size16&quot;&gt;이제 Publisher와 Subscriber를 작성할 Python 패키지를 만듭니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot;&gt;&lt;code&gt;cd ~/ros2_lab_ws/src

ros2 pkg create topic_practice --build-type ament_python --dependencies rclpy robot_interfaces&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;3538&quot; data-start=&quot;3520&quot; data-ke-size=&quot;size16&quot;&gt;생성 후 구조는 다음과 같습니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;crmsh&quot;&gt;&lt;code&gt;ros2_lab_ws/src/
├── robot_interfaces/
└── topic_practice/
    ├── package.xml
    ├── setup.py
    ├── resource/
    ├── test/
    └── topic_practice/
        └── __init__.py&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;Screenshot from 2026-05-27 00-27-04.png&quot; data-origin-width=&quot;786&quot; data-origin-height=&quot;533&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Gn8PG/dJMcageAj7H/WDszoakpcrIQjhlKWlfa30/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Gn8PG/dJMcageAj7H/WDszoakpcrIQjhlKWlfa30/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Gn8PG/dJMcageAj7H/WDszoakpcrIQjhlKWlfa30/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FGn8PG%2FdJMcageAj7H%2FWDszoakpcrIQjhlKWlfa30%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;786&quot; height=&quot;533&quot; data-filename=&quot;Screenshot from 2026-05-27 00-27-04.png&quot; data-origin-width=&quot;786&quot; data-origin-height=&quot;533&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;Screenshot from 2026-05-27 00-27-15.png&quot; data-origin-width=&quot;786&quot; data-origin-height=&quot;533&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/XQI0g/dJMcageAj7G/G74bv1qXNbm2dV2QpxKU90/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/XQI0g/dJMcageAj7G/G74bv1qXNbm2dV2QpxKU90/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/XQI0g/dJMcageAj7G/G74bv1qXNbm2dV2QpxKU90/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FXQI0g%2FdJMcageAj7G%2FG74bv1qXNbm2dV2QpxKU90%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;786&quot; height=&quot;533&quot; data-filename=&quot;Screenshot from 2026-05-27 00-27-15.png&quot; data-origin-width=&quot;786&quot; data-origin-height=&quot;533&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-end=&quot;3754&quot; data-start=&quot;3734&quot; data-section-id=&quot;x9i8qg&quot; data-ke-size=&quot;size20&quot;&gt;6. Publisher 코드 작성&lt;/h4&gt;
&lt;p data-end=&quot;3766&quot; data-start=&quot;3756&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;3766&quot; data-start=&quot;3756&quot; data-ke-size=&quot;size16&quot;&gt;파일을 생성합니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;awk&quot;&gt;&lt;code&gt;cd ~/ros2_lab_ws/src/topic_practice/topic_practice
touch basic_types_pub.py&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;Screenshot from 2026-05-27 00-29-06.png&quot; data-origin-width=&quot;786&quot; data-origin-height=&quot;533&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cg0IwB/dJMcagTch4J/6h8hxRGEytQpT3Cd586120/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cg0IwB/dJMcagTch4J/6h8hxRGEytQpT3Cd586120/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cg0IwB/dJMcagTch4J/6h8hxRGEytQpT3Cd586120/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fcg0IwB%2FdJMcagTch4J%2F6h8hxRGEytQpT3Cd586120%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;786&quot; height=&quot;533&quot; data-filename=&quot;Screenshot from 2026-05-27 00-29-06.png&quot; data-origin-width=&quot;786&quot; data-origin-height=&quot;533&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-end=&quot;3865&quot; data-start=&quot;3857&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;3865&quot; data-start=&quot;3857&quot; data-ke-size=&quot;size16&quot;&gt;파일을 엽니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;css&quot;&gt;&lt;code&gt;gedit basic_types_pub.py&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;3918&quot; data-start=&quot;3905&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;Screenshot from 2026-05-27 00-29-30.png&quot; data-origin-width=&quot;786&quot; data-origin-height=&quot;533&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dqvY2N/dJMcaaFtwvn/xk3Djh2KAEWFPTvcQRRq5K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dqvY2N/dJMcaaFtwvn/xk3Djh2KAEWFPTvcQRRq5K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dqvY2N/dJMcaaFtwvn/xk3Djh2KAEWFPTvcQRRq5K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdqvY2N%2FdJMcaaFtwvn%2Fxk3Djh2KAEWFPTvcQRRq5K%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;786&quot; height=&quot;533&quot; data-filename=&quot;Screenshot from 2026-05-27 00-29-30.png&quot; data-origin-width=&quot;786&quot; data-origin-height=&quot;533&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-end=&quot;3918&quot; data-start=&quot;3905&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;3918&quot; data-start=&quot;3905&quot; data-ke-size=&quot;size16&quot;&gt;아래 코드를 작성합니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot;&gt;&lt;code&gt;import rclpy
from rclpy.node import Node

from robot_interfaces.msg import BasicTypes


class BasicTypesPublisher(Node):
    def __init__(self):
        super().__init__('basic_types_pub')

        self.publisher_ = self.create_publisher(
            BasicTypes,
            '/basic_types',
            10
        )

        self.timer = self.create_timer(1.0, self.timer_callback)
        self.count = 0

    def timer_callback(self):
        self.count += 1

        msg = BasicTypes()
        msg.id = self.count
        msg.temperature = 25.0 + self.count * 0.5
        msg.enabled = self.count % 2 == 1
        msg.name = f'robot_{self.count}'

        self.publisher_.publish(msg)

        self.get_logger().info(
            f'Publish: id={msg.id}, '
            f'temp={msg.temperature:.2f}, '
            f'enabled={msg.enabled}, '
            f'name={msg.name}'
        )


def main(args=None):
    rclpy.init(args=args)

    node = BasicTypesPublisher()

    rclpy.spin(node)

    node.destroy_node()
    rclpy.shutdown()


if __name__ == '__main__':
    main()&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;5031&quot; data-start=&quot;5013&quot; data-section-id=&quot;rj7k62&quot; data-ke-size=&quot;size18&quot;&gt;1) Publisher 코드 핵심&lt;/p&gt;
&lt;p data-end=&quot;5031&quot; data-start=&quot;5013&quot; data-section-id=&quot;rj7k62&quot; data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;5048&quot; data-start=&quot;5033&quot; data-section-id=&quot;nngj9j&quot; data-ke-size=&quot;size16&quot;&gt;메시지 타입 가져오기&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;from robot_interfaces.msg import BasicTypes&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;5169&quot; data-start=&quot;5109&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;5169&quot; data-start=&quot;5109&quot; data-ke-size=&quot;size16&quot;&gt;robot_interfaces 패키지에 만든 BasicTypes.msg를 Python에서 가져옵니다.&lt;/p&gt;
&lt;p data-end=&quot;5169&quot; data-start=&quot;5109&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;5169&quot; data-start=&quot;5109&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;5169&quot; data-start=&quot;5109&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;5192&quot; data-start=&quot;5176&quot; data-section-id=&quot;s09eh0&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;5192&quot; data-start=&quot;5176&quot; data-section-id=&quot;s09eh0&quot; data-ke-size=&quot;size18&quot;&gt;2) Publisher 생성&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;armasm&quot;&gt;&lt;code&gt;self.publisher_ = self.create_publisher(
    BasicTypes,
    '/basic_types',
    10
)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;5308&quot; data-start=&quot;5295&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;5308&quot; data-start=&quot;5295&quot; data-ke-size=&quot;size16&quot;&gt;의미는 다음과 같습니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;armasm&quot;&gt;&lt;code&gt;BasicTypes 메시지를
/basic_types 토픽으로
큐 크기 10으로 발행한다&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;5392&quot; data-start=&quot;5377&quot; data-section-id=&quot;1cjctvy&quot; data-ke-size=&quot;size18&quot;&gt;3) 1초마다 메시지 발행&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;crystal&quot;&gt;&lt;code&gt;self.timer = self.create_timer(1.0, self.timer_callback)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;5500&quot; data-start=&quot;5466&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;5500&quot; data-start=&quot;5466&quot; data-ke-size=&quot;size16&quot;&gt;1초마다 timer_callback() 함수가 실행됩니다.&lt;/p&gt;
&lt;p data-end=&quot;5500&quot; data-start=&quot;5466&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;5500&quot; data-start=&quot;5466&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;5500&quot; data-start=&quot;5466&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;5519&quot; data-start=&quot;5507&quot; data-section-id=&quot;exx68p&quot; data-ke-size=&quot;size18&quot;&gt;4) 메시지 값 대입&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;ini&quot;&gt;&lt;code&gt;msg.id = self.count
msg.temperature = 25.0 + self.count * 0.5
msg.enabled = self.count % 2 == 1
msg.name = f'robot_{self.count}'&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;5704&quot; data-start=&quot;5665&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;5704&quot; data-start=&quot;5665&quot; data-ke-size=&quot;size16&quot;&gt;BasicTypes.msg에 작성한 필드 이름을 그대로 사용합니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;css&quot;&gt;&lt;code&gt;BasicTypes.msg의 id          &amp;rarr; msg.id
BasicTypes.msg의 temperature &amp;rarr; msg.temperature
BasicTypes.msg의 enabled     &amp;rarr; msg.enabled
BasicTypes.msg의 name        &amp;rarr; msg.name&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;5902&quot; data-start=&quot;5883&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;5902&quot; data-start=&quot;5883&quot; data-ke-size=&quot;size16&quot;&gt;필드 이름이 다르면 에러가 납니다.&lt;/p&gt;
&lt;p data-end=&quot;5966&quot; data-start=&quot;5904&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;5966&quot; data-start=&quot;5904&quot; data-ke-size=&quot;size16&quot;&gt;예를 들어 BasicTypes.msg에는 temperature가 있는데 코드에서 이렇게 쓰면 안 됩니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;ini&quot;&gt;&lt;code&gt;msg.temp = 25.5&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;6013&quot; data-start=&quot;5999&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;6013&quot; data-start=&quot;5999&quot; data-ke-size=&quot;size16&quot;&gt;올바른 코드는 다음입니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;ini&quot;&gt;&lt;code&gt;msg.temperature = 25.5&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;Screenshot from 2026-05-27 00-30-33.png&quot; data-origin-width=&quot;1560&quot; data-origin-height=&quot;959&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cOasUg/dJMcafms3tQ/blLwMcAMPTEUFpjw2OiR4K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cOasUg/dJMcafms3tQ/blLwMcAMPTEUFpjw2OiR4K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cOasUg/dJMcafms3tQ/blLwMcAMPTEUFpjw2OiR4K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcOasUg%2FdJMcafms3tQ%2FblLwMcAMPTEUFpjw2OiR4K%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1560&quot; height=&quot;959&quot; data-filename=&quot;Screenshot from 2026-05-27 00-30-33.png&quot; data-origin-width=&quot;1560&quot; data-origin-height=&quot;959&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-end=&quot;6079&quot; data-start=&quot;6058&quot; data-section-id=&quot;1xqsdbh&quot; data-ke-size=&quot;size20&quot;&gt;7. Subscriber 코드 작성&lt;/h4&gt;
&lt;p data-end=&quot;6091&quot; data-start=&quot;6081&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;6091&quot; data-start=&quot;6081&quot; data-ke-size=&quot;size16&quot;&gt;파일을 생성합니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;awk&quot;&gt;&lt;code&gt;cd ~/ros2_lab_ws/src/topic_practice/topic_practice
touch basic_types_sub.py&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;6190&quot; data-start=&quot;6182&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;Screenshot from 2026-05-27 00-33-33.png&quot; data-origin-width=&quot;786&quot; data-origin-height=&quot;533&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bsXQcO/dJMcahLkBaA/BqotN27zf2FQYXt1QPIJw0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bsXQcO/dJMcahLkBaA/BqotN27zf2FQYXt1QPIJw0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bsXQcO/dJMcahLkBaA/BqotN27zf2FQYXt1QPIJw0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbsXQcO%2FdJMcahLkBaA%2FBqotN27zf2FQYXt1QPIJw0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;786&quot; height=&quot;533&quot; data-filename=&quot;Screenshot from 2026-05-27 00-33-33.png&quot; data-origin-width=&quot;786&quot; data-origin-height=&quot;533&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-end=&quot;6190&quot; data-start=&quot;6182&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;6190&quot; data-start=&quot;6182&quot; data-ke-size=&quot;size16&quot;&gt;파일을 엽니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;css&quot;&gt;&lt;code&gt;gedit basic_types_sub.py&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;6243&quot; data-start=&quot;6230&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;6243&quot; data-start=&quot;6230&quot; data-ke-size=&quot;size16&quot;&gt;아래 코드를 작성합니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot;&gt;&lt;code&gt;import rclpy
from rclpy.node import Node

from robot_interfaces.msg import BasicTypes


class BasicTypesSubscriber(Node):
    def __init__(self):
        super().__init__('basic_types_sub')

        self.subscription = self.create_subscription(
            BasicTypes,
            '/basic_types',
            self.listener_callback,
            10
        )

    def listener_callback(self, msg):
        self.get_logger().info(
            f'Receive: id={msg.id}, '
            f'temp={msg.temperature:.2f}, '
            f'enabled={msg.enabled}, '
            f'name={msg.name}'
        )


def main(args=None):
    rclpy.init(args=args)

    node = BasicTypesSubscriber()

    rclpy.spin(node)

    node.destroy_node()
    rclpy.shutdown()


if __name__ == '__main__':
    main()&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;Screenshot from 2026-05-27 00-34-25.png&quot; data-origin-width=&quot;1560&quot; data-origin-height=&quot;959&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c1fayG/dJMcag6H8yg/JtR3vGDObNVDwkdbogrKsk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c1fayG/dJMcag6H8yg/JtR3vGDObNVDwkdbogrKsk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c1fayG/dJMcag6H8yg/JtR3vGDObNVDwkdbogrKsk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc1fayG%2FdJMcag6H8yg%2FJtR3vGDObNVDwkdbogrKsk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1560&quot; height=&quot;959&quot; data-filename=&quot;Screenshot from 2026-05-27 00-34-25.png&quot; data-origin-width=&quot;1560&quot; data-origin-height=&quot;959&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;7067&quot; data-start=&quot;7048&quot; data-section-id=&quot;1nwd10u&quot; data-ke-size=&quot;size18&quot;&gt;1) Subscriber 코드 핵심&lt;/p&gt;
&lt;p data-end=&quot;7086&quot; data-start=&quot;7069&quot; data-section-id=&quot;1ke6mz4&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;7086&quot; data-start=&quot;7069&quot; data-section-id=&quot;1ke6mz4&quot; data-ke-size=&quot;size16&quot;&gt;Subscriber 생성&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;armasm&quot;&gt;&lt;code&gt;self.subscription = self.create_subscription(
    BasicTypes,
    '/basic_types',
    self.listener_callback,
    10
)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;7235&quot; data-start=&quot;7222&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;7235&quot; data-start=&quot;7222&quot; data-ke-size=&quot;size16&quot;&gt;의미는 다음과 같습니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;armasm&quot;&gt;&lt;code&gt;/basic_types 토픽에서
BasicTypes 메시지를 받으면
listener_callback 함수를 실행한다&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;7333&quot; data-start=&quot;7320&quot; data-section-id=&quot;12mfltz&quot; data-ke-size=&quot;size18&quot;&gt;2) 수신 데이터 확인&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;python&quot;&gt;&lt;code&gt;def listener_callback(self, msg):
    self.get_logger().info(
        f'Receive: id={msg.id}, '
        f'temp={msg.temperature:.2f}, '
        f'enabled={msg.enabled}, '
        f'name={msg.name}'
    )&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;7589&quot; data-start=&quot;7554&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;7589&quot; data-start=&quot;7554&quot; data-ke-size=&quot;size16&quot;&gt;Publisher가 보낸 메시지는 msg 변수로 들어옵니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-end=&quot;7612&quot; data-start=&quot;7596&quot; data-section-id=&quot;p6980s&quot; data-ke-size=&quot;size20&quot;&gt;8. setup.py 등록&lt;/h4&gt;
&lt;p data-end=&quot;7661&quot; data-start=&quot;7614&quot; data-ke-size=&quot;size16&quot;&gt;ros2 run으로 실행하려면 setup.py에 실행 파일을 등록해야 합니다.&lt;/p&gt;
&lt;p data-end=&quot;7671&quot; data-start=&quot;7663&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;7671&quot; data-start=&quot;7663&quot; data-ke-size=&quot;size16&quot;&gt;파일을 엽니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;awk&quot;&gt;&lt;code&gt;gedit ~/ros2_lab_ws/src/topic_practice/setup.py&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;7764&quot; data-start=&quot;7734&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;7764&quot; data-start=&quot;7734&quot; data-ke-size=&quot;size16&quot;&gt;entry_points 부분을 아래처럼 수정합니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot;&gt;&lt;code&gt;entry_points={
    'console_scripts': [
        'basic_types_pub = topic_practice.basic_types_pub:main',
        'basic_types_sub = topic_practice.basic_types_sub:main',
    ],
},&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;Screenshot from 2026-05-27 00-36-06.png&quot; data-origin-width=&quot;1560&quot; data-origin-height=&quot;959&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/beIg7u/dJMcaiQYwe3/9mHwI74GgmEVoeCKM7DSwK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/beIg7u/dJMcaiQYwe3/9mHwI74GgmEVoeCKM7DSwK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/beIg7u/dJMcaiQYwe3/9mHwI74GgmEVoeCKM7DSwK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbeIg7u%2FdJMcaiQYwe3%2F9mHwI74GgmEVoeCKM7DSwK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1560&quot; height=&quot;959&quot; data-filename=&quot;Screenshot from 2026-05-27 00-36-06.png&quot; data-origin-width=&quot;1560&quot; data-origin-height=&quot;959&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;7978&quot; data-start=&quot;7961&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;7978&quot; data-start=&quot;7961&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;7978&quot; data-start=&quot;7961&quot; data-ke-size=&quot;size16&quot;&gt;전체 예시는 다음과 비슷합니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;from setuptools import setup

package_name = 'topic_practice'

setup(
    name=package_name,
    version='0.0.0',
    packages=[package_name],
    data_files=[
        ('share/ament_index/resource_index/packages',
            ['resource/' + package_name]),
        ('share/' + package_name, ['package.xml']),
    ],
    install_requires=['setuptools'],
    zip_safe=True,
    maintainer='user',
    maintainer_email='user@example.com',
    description='ROS 2 topic practice package',
    license='Apache-2.0',
    tests_require=['pytest'],
    entry_points={
        'console_scripts': [
            'basic_types_pub = topic_practice.basic_types_pub:main',
            'basic_types_sub = topic_practice.basic_types_sub:main',
        ],
    },
)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-end=&quot;8780&quot; data-start=&quot;8746&quot; data-section-id=&quot;7t0cr8&quot; data-ke-size=&quot;size20&quot;&gt;9. topic_practice package.xml 확인&lt;/h4&gt;
&lt;p data-end=&quot;8790&quot; data-start=&quot;8782&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;8790&quot; data-start=&quot;8782&quot; data-ke-size=&quot;size16&quot;&gt;파일을 엽니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;gradle&quot;&gt;&lt;code&gt;gedit ~/ros2_lab_ws/src/topic_practice/package.xml&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;8875&quot; data-start=&quot;8856&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;8875&quot; data-start=&quot;8856&quot; data-ke-size=&quot;size16&quot;&gt;아래 의존성이 들어 있어야 합니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;xml&quot;&gt;&lt;code&gt;&amp;lt;depend&amp;gt;rclpy&amp;lt;/depend&amp;gt;
&amp;lt;depend&amp;gt;robot_interfaces&amp;lt;/depend&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;8959&quot; data-start=&quot;8946&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;8959&quot; data-start=&quot;8946&quot; data-ke-size=&quot;size16&quot;&gt;예시는 다음과 같습니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;xml&quot;&gt;&lt;code&gt;&amp;lt;package format=&quot;3&quot;&amp;gt;
  &amp;lt;name&amp;gt;topic_practice&amp;lt;/name&amp;gt;
  &amp;lt;version&amp;gt;0.0.0&amp;lt;/version&amp;gt;
  &amp;lt;description&amp;gt;ROS 2 topic practice package&amp;lt;/description&amp;gt;
  &amp;lt;maintainer email=&quot;user@example.com&quot;&amp;gt;user&amp;lt;/maintainer&amp;gt;
  &amp;lt;license&amp;gt;Apache-2.0&amp;lt;/license&amp;gt;

  &amp;lt;depend&amp;gt;rclpy&amp;lt;/depend&amp;gt;
  &amp;lt;depend&amp;gt;robot_interfaces&amp;lt;/depend&amp;gt;

  &amp;lt;test_depend&amp;gt;ament_copyright&amp;lt;/test_depend&amp;gt;
  &amp;lt;test_depend&amp;gt;ament_flake8&amp;lt;/test_depend&amp;gt;
  &amp;lt;test_depend&amp;gt;ament_pep257&amp;lt;/test_depend&amp;gt;
  &amp;lt;test_depend&amp;gt;python3-pytest&amp;lt;/test_depend&amp;gt;

  &amp;lt;export&amp;gt;
    &amp;lt;build_type&amp;gt;ament_python&amp;lt;/build_type&amp;gt;
  &amp;lt;/export&amp;gt;
&amp;lt;/package&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;Screenshot from 2026-05-27 00-37-09.png&quot; data-origin-width=&quot;1560&quot; data-origin-height=&quot;959&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c36kcB/dJMcacpJFq9/JS9VKUPOYERjsAzblWI9oK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c36kcB/dJMcacpJFq9/JS9VKUPOYERjsAzblWI9oK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c36kcB/dJMcacpJFq9/JS9VKUPOYERjsAzblWI9oK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc36kcB%2FdJMcacpJFq9%2FJS9VKUPOYERjsAzblWI9oK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1560&quot; height=&quot;959&quot; data-filename=&quot;Screenshot from 2026-05-27 00-37-09.png&quot; data-origin-width=&quot;1560&quot; data-origin-height=&quot;959&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h4 data-end=&quot;9526&quot; data-start=&quot;9516&quot; data-section-id=&quot;419zld&quot; data-ke-size=&quot;size20&quot;&gt;10. 빌드하기&lt;/h4&gt;
&lt;p data-end=&quot;9545&quot; data-start=&quot;9528&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;9545&quot; data-start=&quot;9528&quot; data-ke-size=&quot;size16&quot;&gt;워크스페이스 루트로 이동합니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;jboss-cli&quot;&gt;&lt;code&gt;cd ~/ros2_lab_ws&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;9583&quot; data-start=&quot;9577&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;9583&quot; data-start=&quot;9577&quot; data-ke-size=&quot;size16&quot;&gt;빌드합니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;ada&quot;&gt;&lt;code&gt;colcon build --symlink-install&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;9647&quot; data-start=&quot;9629&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;9647&quot; data-start=&quot;9629&quot; data-ke-size=&quot;size16&quot;&gt;빌드 후 환경 설정을 적용합니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;arduino&quot;&gt;&lt;code&gt;source install/setup.bash&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;9721&quot; data-start=&quot;9688&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;Screenshot from 2026-05-27 00-39-07.png&quot; data-origin-width=&quot;786&quot; data-origin-height=&quot;533&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/rpqOl/dJMcaaZITyY/vSSYXvpAukwmFsyWoNXyQk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/rpqOl/dJMcaaZITyY/vSSYXvpAukwmFsyWoNXyQk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/rpqOl/dJMcaaZITyY/vSSYXvpAukwmFsyWoNXyQk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FrpqOl%2FdJMcaaZITyY%2FvSSYXvpAukwmFsyWoNXyQk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;786&quot; height=&quot;533&quot; data-filename=&quot;Screenshot from 2026-05-27 00-39-07.png&quot; data-origin-width=&quot;786&quot; data-origin-height=&quot;533&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-end=&quot;9721&quot; data-start=&quot;9688&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;9721&quot; data-start=&quot;9688&quot; data-ke-size=&quot;size16&quot;&gt;확실하게 하려면 메시지 인터페이스가 생성되었는지 확인합니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;ros2 interface show robot_interfaces/msg/BasicTypes&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;9804&quot; data-start=&quot;9788&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;9804&quot; data-start=&quot;9788&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;9804&quot; data-start=&quot;9788&quot; data-ke-size=&quot;size16&quot;&gt;정상 출력은 다음과 같습니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;int32 id
float32 temperature
bool enabled
string name&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;Screenshot from 2026-05-27 00-39-53.png&quot; data-origin-width=&quot;786&quot; data-origin-height=&quot;533&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/des4E6/dJMcagZUAKn/3e6oT6JvvZ9uXnKQpzUZ1k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/des4E6/dJMcagZUAKn/3e6oT6JvvZ9uXnKQpzUZ1k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/des4E6/dJMcagZUAKn/3e6oT6JvvZ9uXnKQpzUZ1k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fdes4E6%2FdJMcagZUAKn%2F3e6oT6JvvZ9uXnKQpzUZ1k%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;786&quot; height=&quot;533&quot; data-filename=&quot;Screenshot from 2026-05-27 00-39-53.png&quot; data-origin-width=&quot;786&quot; data-origin-height=&quot;533&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h4 data-end=&quot;9888&quot; data-start=&quot;9878&quot; data-section-id=&quot;1qvfl59&quot; data-ke-size=&quot;size20&quot;&gt;11. 실행하기&lt;/h4&gt;
&lt;p data-end=&quot;9915&quot; data-start=&quot;9890&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;9915&quot; data-start=&quot;9890&quot; data-ke-size=&quot;size16&quot;&gt;터미널을 3개 열어서 확인하는 것이 좋습니다.&lt;/p&gt;
&lt;p data-end=&quot;9915&quot; data-start=&quot;9890&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;9915&quot; data-start=&quot;9890&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;9915&quot; data-start=&quot;9890&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;9944&quot; data-start=&quot;9922&quot; data-section-id=&quot;1eszw5&quot; data-ke-size=&quot;size18&quot;&gt;1) 터미널 1: Publisher 실행&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;properties&quot;&gt;&lt;code&gt;cd ~/ros2_lab_ws
source install/setup.bash
ros2 run topic_practice basic_types_pub&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;10048&quot; data-start=&quot;10042&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;10048&quot; data-start=&quot;10042&quot; data-ke-size=&quot;size16&quot;&gt;예상 출력:&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;[INFO] [basic_types_pub]: Publish: id=1, temp=25.50, enabled=True, name=robot_1
[INFO] [basic_types_pub]: Publish: id=2, temp=26.00, enabled=False, name=robot_2
[INFO] [basic_types_pub]: Publish: id=3, temp=26.50, enabled=True, name=robot_3&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;10332&quot; data-start=&quot;10309&quot; data-section-id=&quot;wiv6rm&quot; data-ke-size=&quot;size18&quot;&gt;2) 터미널 2: Subscriber 실행&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;properties&quot;&gt;&lt;code&gt;cd ~/ros2_lab_ws
source install/setup.bash
ros2 run topic_practice basic_types_sub&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;10436&quot; data-start=&quot;10430&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;10436&quot; data-start=&quot;10430&quot; data-ke-size=&quot;size16&quot;&gt;예상 출력:&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;[INFO] [basic_types_sub]: Receive: id=1, temp=25.50, enabled=True, name=robot_1
[INFO] [basic_types_sub]: Receive: id=2, temp=26.00, enabled=False, name=robot_2
[INFO] [basic_types_sub]: Receive: id=3, temp=26.50, enabled=True, name=robot_3&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;10739&quot; data-start=&quot;10692&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;10739&quot; data-start=&quot;10692&quot; data-ke-size=&quot;size16&quot;&gt;Publisher에서 보낸 값과 Subscriber에서 받은 값이 같으면 정상입니다.&lt;/p&gt;
&lt;p data-end=&quot;10739&quot; data-start=&quot;10692&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;Screenshot from 2026-05-27 00-48-05.png&quot; data-origin-width=&quot;786&quot; data-origin-height=&quot;533&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/vBy0H/dJMcaciTPk1/UxhjizFMVaw5fgobwgL761/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/vBy0H/dJMcaciTPk1/UxhjizFMVaw5fgobwgL761/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/vBy0H/dJMcaciTPk1/UxhjizFMVaw5fgobwgL761/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FvBy0H%2FdJMcaciTPk1%2FUxhjizFMVaw5fgobwgL761%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;786&quot; height=&quot;533&quot; data-filename=&quot;Screenshot from 2026-05-27 00-48-05.png&quot; data-origin-width=&quot;786&quot; data-origin-height=&quot;533&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;Screenshot from 2026-05-27 00-48-07.png&quot; data-origin-width=&quot;786&quot; data-origin-height=&quot;533&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/oBuYk/dJMcaciTPk2/hStDjERyOTlF8UHK12CEok/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/oBuYk/dJMcaciTPk2/hStDjERyOTlF8UHK12CEok/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/oBuYk/dJMcaciTPk2/hStDjERyOTlF8UHK12CEok/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FoBuYk%2FdJMcaciTPk2%2FhStDjERyOTlF8UHK12CEok%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;786&quot; height=&quot;533&quot; data-filename=&quot;Screenshot from 2026-05-27 00-48-07.png&quot; data-origin-width=&quot;786&quot; data-origin-height=&quot;533&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-end=&quot;10739&quot; data-start=&quot;10692&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;10739&quot; data-start=&quot;10692&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;10739&quot; data-start=&quot;10692&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;10763&quot; data-start=&quot;10746&quot; data-section-id=&quot;1htkrn&quot; data-ke-size=&quot;size18&quot;&gt;3) 터미널 3: CLI로 확인&lt;/p&gt;
&lt;p data-end=&quot;10774&quot; data-start=&quot;10765&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;10774&quot; data-start=&quot;10765&quot; data-ke-size=&quot;size16&quot;&gt;토픽 목록 확인:&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;properties&quot;&gt;&lt;code&gt;cd ~/ros2_lab_ws
source install/setup.bash
ros2 topic list&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;10870&quot; data-start=&quot;10848&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;10870&quot; data-start=&quot;10848&quot; data-ke-size=&quot;size16&quot;&gt;출력 목록에 아래 토픽이 있어야 합니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;elm&quot;&gt;&lt;code&gt;/basic_types&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;10908&quot; data-start=&quot;10898&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;Screenshot from 2026-05-27 00-50-54.png&quot; data-origin-width=&quot;786&quot; data-origin-height=&quot;533&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/wt6fG/dJMb99T28dU/2rPv0yLX76dk87xLVIoia1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/wt6fG/dJMb99T28dU/2rPv0yLX76dk87xLVIoia1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/wt6fG/dJMb99T28dU/2rPv0yLX76dk87xLVIoia1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fwt6fG%2FdJMb99T28dU%2F2rPv0yLX76dk87xLVIoia1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;786&quot; height=&quot;533&quot; data-filename=&quot;Screenshot from 2026-05-27 00-50-54.png&quot; data-origin-width=&quot;786&quot; data-origin-height=&quot;533&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-end=&quot;10908&quot; data-start=&quot;10898&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;10908&quot; data-start=&quot;10898&quot; data-ke-size=&quot;size16&quot;&gt;토픽 데이터 확인:&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;jboss-cli&quot;&gt;&lt;code&gt;ros2 topic echo /basic_types&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;10958&quot; data-start=&quot;10952&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;10958&quot; data-start=&quot;10952&quot; data-ke-size=&quot;size16&quot;&gt;예상 출력:&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;yaml&quot;&gt;&lt;code&gt;id: 1
temperature: 25.5
enabled: true
name: robot_1
---
id: 2
temperature: 26.0
enabled: false
name: robot_2
---&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;11095&quot; data-start=&quot;11086&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;Screenshot from 2026-05-27 00-51-07.png&quot; data-origin-width=&quot;786&quot; data-origin-height=&quot;533&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/d9bCxS/dJMcabddWUI/daqicvOSBJjiOuK9faYVz1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/d9bCxS/dJMcabddWUI/daqicvOSBJjiOuK9faYVz1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/d9bCxS/dJMcabddWUI/daqicvOSBJjiOuK9faYVz1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fd9bCxS%2FdJMcabddWUI%2FdaqicvOSBJjiOuK9faYVz1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;786&quot; height=&quot;533&quot; data-filename=&quot;Screenshot from 2026-05-27 00-51-07.png&quot; data-origin-width=&quot;786&quot; data-origin-height=&quot;533&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-end=&quot;11095&quot; data-start=&quot;11086&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;11095&quot; data-start=&quot;11086&quot; data-ke-size=&quot;size16&quot;&gt;토픽 정보 확인:&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;nginx&quot;&gt;&lt;code&gt;ros2 topic info /basic_types&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;11145&quot; data-start=&quot;11139&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;11145&quot; data-start=&quot;11139&quot; data-ke-size=&quot;size16&quot;&gt;예상 출력:&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;yaml&quot;&gt;&lt;code&gt;Type: robot_interfaces/msg/BasicTypes
Publisher count: 1
Subscription count: 1&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;11259&quot; data-start=&quot;11239&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;Screenshot from 2026-05-27 00-52-44.png&quot; data-origin-width=&quot;786&quot; data-origin-height=&quot;533&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/m7hOC/dJMcaiKbs1A/73pf9k38bUH8zOnwE4ifA1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/m7hOC/dJMcaiKbs1A/73pf9k38bUH8zOnwE4ifA1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/m7hOC/dJMcaiKbs1A/73pf9k38bUH8zOnwE4ifA1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fm7hOC%2FdJMcaiKbs1A%2F73pf9k38bUH8zOnwE4ifA1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;786&quot; height=&quot;533&quot; data-filename=&quot;Screenshot from 2026-05-27 00-52-44.png&quot; data-origin-width=&quot;786&quot; data-origin-height=&quot;533&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-end=&quot;11259&quot; data-start=&quot;11239&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;11259&quot; data-start=&quot;11239&quot; data-ke-size=&quot;size16&quot;&gt;여기서 봐야 할 것은 세 가지입니다.&lt;/p&gt;
&lt;p data-end=&quot;11259&quot; data-start=&quot;11239&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;11259&quot; data-start=&quot;11239&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;11259&quot; data-start=&quot;11239&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;h4 data-end=&quot;11405&quot; data-start=&quot;11391&quot; data-section-id=&quot;5jogp3&quot; data-ke-size=&quot;size20&quot;&gt;12. 전체 폴더 구조&lt;/h4&gt;
&lt;p data-end=&quot;11427&quot; data-start=&quot;11407&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;11427&quot; data-start=&quot;11407&quot; data-ke-size=&quot;size16&quot;&gt;최종 구조는 다음과 비슷해야 합니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;stylus&quot;&gt;&lt;code&gt;~/ros2_lab_ws/
└── src/
    ├── robot_interfaces/
    │   ├── CMakeLists.txt
    │   ├── package.xml
    │   └── msg/
    │       └── BasicTypes.msg
    │
    └── topic_practice/
        ├── package.xml
        ├── setup.py
        ├── resource/
        │   └── topic_practice
        └── topic_practice/
            ├── __init__.py
            ├── basic_types_pub.py
            └── basic_types_sub.py&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;Screenshot from 2026-05-27 00-54-05.png&quot; data-origin-width=&quot;786&quot; data-origin-height=&quot;569&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/KaGLV/dJMcagMsoSD/eMyeO3LN4nfVrMeJXY7GZ0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/KaGLV/dJMcagMsoSD/eMyeO3LN4nfVrMeJXY7GZ0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/KaGLV/dJMcagMsoSD/eMyeO3LN4nfVrMeJXY7GZ0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FKaGLV%2FdJMcagMsoSD%2FeMyeO3LN4nfVrMeJXY7GZ0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;786&quot; height=&quot;569&quot; data-filename=&quot;Screenshot from 2026-05-27 00-54-05.png&quot; data-origin-width=&quot;786&quot; data-origin-height=&quot;569&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;13833&quot; data-start=&quot;13790&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-end=&quot;13851&quot; data-start=&quot;13840&quot; data-section-id=&quot;1d8iif1&quot; data-ke-size=&quot;size20&quot;&gt;13. 실습 과제&lt;/h4&gt;
&lt;p data-end=&quot;13877&quot; data-start=&quot;13853&quot; data-section-id=&quot;srpul8&quot; data-ke-size=&quot;size18&quot;&gt;과제 1. voltage 필드 추가하기&lt;/p&gt;
&lt;p data-end=&quot;13908&quot; data-start=&quot;13879&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;13908&quot; data-start=&quot;13879&quot; data-ke-size=&quot;size16&quot;&gt;BasicTypes.msg를 아래처럼 수정합니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;int32 id
float32 temperature
bool enabled
string name
float32 voltage&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;14010&quot; data-start=&quot;13993&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;14010&quot; data-start=&quot;13993&quot; data-ke-size=&quot;size16&quot;&gt;Publisher에 추가합니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;msg.voltage = 12.0 + self.count * 0.1&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;14078&quot; data-start=&quot;14065&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;14078&quot; data-start=&quot;14065&quot; data-ke-size=&quot;size16&quot;&gt;로그 출력도 수정합니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;python&quot;&gt;&lt;code&gt;self.get_logger().info(
    f'Publish: id={msg.id}, '
    f'temp={msg.temperature:.2f}, '
    f'enabled={msg.enabled}, '
    f'name={msg.name}, '
    f'voltage={msg.voltage:.2f}'
)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;14294&quot; data-start=&quot;14276&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;14294&quot; data-start=&quot;14276&quot; data-ke-size=&quot;size16&quot;&gt;Subscriber도 수정합니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;python&quot;&gt;&lt;code&gt;self.get_logger().info(
    f'Receive: id={msg.id}, '
    f'temp={msg.temperature:.2f}, '
    f'enabled={msg.enabled}, '
    f'name={msg.name}, '
    f'voltage={msg.voltage:.2f}'
)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;14510&quot; data-start=&quot;14492&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;14510&quot; data-start=&quot;14492&quot; data-ke-size=&quot;size16&quot;&gt;수정 후 반드시 다시 빌드합니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;jboss-cli&quot;&gt;&lt;code&gt;cd ~/ros2_lab_ws
colcon build --symlink-install
source install/setup.bash&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;14639&quot; data-start=&quot;14604&quot; data-section-id=&quot;tze5ip&quot; data-ke-size=&quot;size18&quot;&gt;과제 2. enabled 값에 따라 name 다르게 만들기&lt;/p&gt;
&lt;p data-end=&quot;14688&quot; data-start=&quot;14641&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;14688&quot; data-start=&quot;14641&quot; data-ke-size=&quot;size16&quot;&gt;Publisher의 timer_callback() 안에서 아래 코드를 사용합니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;stylus&quot;&gt;&lt;code&gt;if msg.enabled:
    msg.name = f'active_robot_{self.count}'
else:
    msg.name = f'inactive_robot_{self.count}'&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;14823&quot; data-start=&quot;14817&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;14823&quot; data-start=&quot;14817&quot; data-ke-size=&quot;size16&quot;&gt;예상 결과:&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;id=1, enabled=True, name=active_robot_1
id=2, enabled=False, name=inactive_robot_2
id=3, enabled=True, name=active_robot_3
id=4, enabled=False, name=inactive_robot_4&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-end=&quot;15023&quot; data-start=&quot;15009&quot; data-section-id=&quot;1y46kgm&quot; data-ke-size=&quot;size20&quot;&gt;14. 최종 핵심 정리&lt;/h4&gt;
&lt;p data-end=&quot;15047&quot; data-start=&quot;15025&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;1. 사용자 정의 메시지는 robot_interfaces에 만든다.
2. Publisher와 Subscriber는 같은 메시지 타입을 사용해야 한다.
3. Publisher와 Subscriber는 같은 토픽 이름을 사용해야 한다.
4. setup.py에 실행 파일을 등록해야 ros2 run이 된다.
5. 메시지 수정 후에는 반드시 colcon build와 source를 다시 한다.&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;15305&quot; data-start=&quot;15277&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;15305&quot; data-start=&quot;15277&quot; data-ke-size=&quot;size16&quot;&gt;최종 실행 명령어만 다시 정리하면 다음과 같습니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;jboss-cli&quot;&gt;&lt;code&gt;cd ~/ros2_lab_ws
colcon build --symlink-install
source install/setup.bash&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;15404&quot; data-start=&quot;15394&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;15404&quot; data-start=&quot;15394&quot; data-ke-size=&quot;size16&quot;&gt;Publisher:&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;dockerfile&quot;&gt;&lt;code&gt;ros2 run topic_practice basic_types_pub&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;15470&quot; data-start=&quot;15459&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;15470&quot; data-start=&quot;15459&quot; data-ke-size=&quot;size16&quot;&gt;Subscriber:&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;dockerfile&quot;&gt;&lt;code&gt;ros2 run topic_practice basic_types_sub&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;15531&quot; data-start=&quot;15525&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;15531&quot; data-start=&quot;15525&quot; data-ke-size=&quot;size16&quot;&gt;토픽 확인:&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;jboss-cli&quot;&gt;&lt;code&gt;ros2 topic echo /basic_types&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;15582&quot; data-start=&quot;15575&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;15582&quot; data-start=&quot;15575&quot; data-ke-size=&quot;size16&quot;&gt;메시지 확인:&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;ros2 interface show robot_interfaces/msg/BasicTypes&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>강좌/ROS2</category>
      <category>기본 타입 메시지 발행/구독 실습</category>
      <author>MakingRobotWizard</author>
      <guid isPermaLink="true">https://makingrobot.tistory.com/434</guid>
      <comments>https://makingrobot.tistory.com/434#entry434comment</comments>
      <pubDate>Tue, 26 May 2026 00:04:02 +0900</pubDate>
    </item>
    <item>
      <title>ROS 2 개발자를 위한 C/C++ 기초강의 #1</title>
      <link>https://makingrobot.tistory.com/433</link>
      <description>&lt;p data-end=&quot;401&quot; data-start=&quot;229&quot; data-ke-size=&quot;size16&quot;&gt;ROS 2를 제대로 다루기 위해서는 C++ 문법에 대한 기본기가 필요합니다. ROS 2의 핵심 클라이언트 라이브러리인 rclcpp는 C++ 기반으로 작성되어 있으며, 실제 로봇 제어, 센서 처리, 드론 제어, 실시간 데이터 처리, 메시지 송수신 코드를 작성할 때 C++ 문법을 자연스럽게 사용하게 됩니다.&lt;/p&gt;
&lt;p data-end=&quot;547&quot; data-start=&quot;403&quot; data-ke-size=&quot;size16&quot;&gt;특히 ROS 2에서는 단순히 문법을 외우는 것보다 &lt;b&gt;객체지향 구조, 포인터와 참조, 스마트 포인터, 클래스, 콜백 함수, 람다 함수, 템플릿, 네임스페이스, 빌드 구조&lt;/b&gt;를 이해하는 것이 중요합니다. 이 문법들은 ROS 2 코드에서 거의 매번 등장합니다.&lt;/p&gt;
&lt;p data-end=&quot;547&quot; data-start=&quot;403&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-end=&quot;667&quot; data-start=&quot;639&quot; data-section-id=&quot;1h81g9c&quot; data-ke-size=&quot;size20&quot;&gt;1. C와 C++의 차이를 먼저 이해해야 합니다&lt;/h4&gt;
&lt;p data-end=&quot;705&quot; data-start=&quot;669&quot; data-ke-size=&quot;size16&quot;&gt;C와 C++은 비슷해 보이지만 개발 방식에는 큰 차이가 있습니다.&lt;/p&gt;
&lt;p data-end=&quot;835&quot; data-start=&quot;707&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;835&quot; data-start=&quot;707&quot; data-ke-size=&quot;size16&quot;&gt;C 언어는 절차지향 언어입니다. 프로그램을 함수 중심으로 구성하고, 데이터를 구조체로 묶어 사용합니다. 반면 C++은 C의 기능을 포함하면서도 클래스, 객체, 상속, 다형성, 템플릿, 스마트 포인터 같은 기능을 추가한 언어입니다.&lt;/p&gt;
&lt;p data-end=&quot;835&quot; data-start=&quot;707&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;997&quot; data-start=&quot;837&quot; data-ke-size=&quot;size16&quot;&gt;로봇 개발에서는 아직도 C 언어가 많이 사용됩니다. 특히 MCU 펌웨어, 모터 제어, 센서 드라이버, 임베디드 제어 코드에서는 C 언어가 자주 사용됩니다.&lt;/p&gt;
&lt;p data-end=&quot;997&quot; data-start=&quot;837&quot; data-ke-size=&quot;size16&quot;&gt;반면 ROS 2의 상위 제어 로직, 경로 계획, 상태 관리, 센서 데이터 처리, 노드 구성 등은 C++로 작성하는 경우가 많습니다.&lt;/p&gt;
&lt;p data-end=&quot;1121&quot; data-start=&quot;999&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;1121&quot; data-start=&quot;999&quot; data-ke-size=&quot;size16&quot;&gt;따라서 ROS 2 개발자는 C 문법도 어느 정도 이해해야 하고, C++ 문법도 익숙해야 합니다. 단순히 &amp;ldquo;C++만 알면 된다&amp;rdquo;가 아니라, &lt;b&gt;C의 메모리 구조와 C++의 객체지향 구조를 함께 이해하는 것&lt;/b&gt;이 좋습니다.&lt;/p&gt;
&lt;p data-end=&quot;1121&quot; data-start=&quot;999&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;1121&quot; data-start=&quot;999&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;1121&quot; data-start=&quot;999&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-end=&quot;1121&quot; data-start=&quot;999&quot; data-ke-size=&quot;size20&quot;&gt;2. C/C++ 실행환경 구성&lt;/h4&gt;
&lt;p data-end=&quot;1121&quot; data-start=&quot;999&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;1121&quot; data-start=&quot;999&quot; data-ke-size=&quot;size18&quot;&gt;a.&amp;nbsp;기본 개발 도구 확인하기&lt;/p&gt;
&lt;p data-end=&quot;565&quot; data-start=&quot;528&quot; data-ke-size=&quot;size16&quot;&gt;먼저 C/C++ 컴파일러와 빌드 도구가 설치되어 있는지 확인합니다.&lt;/p&gt;
&lt;p data-end=&quot;565&quot; data-start=&quot;528&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;589&quot; data-start=&quot;567&quot; data-ke-size=&quot;size16&quot;&gt;터미널을 열고 다음 명령어를 입력합니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;brainfuck&quot;&gt;&lt;code&gt;gcc --version
g++ --version
cmake --version
make --version&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;701&quot; data-start=&quot;663&quot; data-ke-size=&quot;size16&quot;&gt;정상적으로 버전 정보가 출력되면 기본 도구가 설치되어 있는 것입니다.&lt;/p&gt;
&lt;p data-end=&quot;732&quot; data-start=&quot;703&quot; data-ke-size=&quot;size16&quot;&gt;만약 설치되어 있지 않다면 다음 명령어로 설치합니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;sudo apt update
sudo apt install -y build-essential cmake gdb&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;828&quot; data-start=&quot;809&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;828&quot; data-start=&quot;809&quot; data-ke-size=&quot;size16&quot;&gt;각 도구의 역할은 다음과 같습니다.&lt;/p&gt;
&lt;p data-end=&quot;850&quot; data-start=&quot;830&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;850&quot; data-start=&quot;830&quot; data-ke-size=&quot;size16&quot;&gt;gcc는 C 언어 컴파일러입니다.&lt;/p&gt;
&lt;p data-end=&quot;871&quot; data-start=&quot;852&quot; data-ke-size=&quot;size16&quot;&gt;g++는 C++ 컴파일러입니다.&lt;/p&gt;
&lt;p data-end=&quot;905&quot; data-start=&quot;873&quot; data-ke-size=&quot;size16&quot;&gt;cmake는 C/C++ 프로젝트 빌드 설정 도구입니다.&lt;/p&gt;
&lt;p data-end=&quot;936&quot; data-start=&quot;907&quot; data-ke-size=&quot;size16&quot;&gt;make는 실제 빌드 명령을 실행하는 도구입니다.&lt;/p&gt;
&lt;p data-end=&quot;961&quot; data-start=&quot;938&quot; data-ke-size=&quot;size16&quot;&gt;gdb는 C/C++ 디버깅 도구입니다.&lt;/p&gt;
&lt;p data-end=&quot;961&quot; data-start=&quot;938&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;961&quot; data-start=&quot;938&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;961&quot; data-start=&quot;938&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;1134&quot; data-start=&quot;1120&quot; data-section-id=&quot;16z0j4j&quot; data-ke-size=&quot;size18&quot;&gt;b. 실습 폴더 만들기&lt;/p&gt;
&lt;p data-end=&quot;1161&quot; data-start=&quot;1136&quot; data-ke-size=&quot;size16&quot;&gt;먼저 C/C++ 문법 실습용 폴더를 만듭니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;jboss-cli&quot;&gt;&lt;code&gt;mkdir -p ~/cpp_practice
cd ~/cpp_practice&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;1252&quot; data-start=&quot;1218&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;1252&quot; data-start=&quot;1218&quot; data-ke-size=&quot;size16&quot;&gt;VSCode에서 해당 폴더를 열려면 다음 명령어를 사용합니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;clean&quot;&gt;&lt;code&gt;code .&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;1301&quot; data-start=&quot;1274&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;1301&quot; data-start=&quot;1274&quot; data-ke-size=&quot;size16&quot;&gt;이제 이 폴더 안에서 실습 파일을 만들면 됩니다.&lt;/p&gt;
&lt;p data-end=&quot;1301&quot; data-start=&quot;1274&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;1301&quot; data-start=&quot;1274&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-end=&quot;1329&quot; data-start=&quot;1308&quot; data-section-id=&quot;llfjo4&quot; data-ke-size=&quot;size20&quot;&gt;c. 가장 간단한 C 프로그램 실습&lt;/h4&gt;
&lt;p data-end=&quot;1354&quot; data-start=&quot;1331&quot; data-ke-size=&quot;size16&quot;&gt;먼저 C 언어 실습 파일을 하나 만듭니다.&lt;/p&gt;
&lt;p data-end=&quot;1378&quot; data-start=&quot;1356&quot; data-ke-size=&quot;size16&quot;&gt;파일 이름은 hello.c로 합니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot;&gt;&lt;code&gt;#include &amp;lt;stdio.h&amp;gt;

int main() {
    printf(&quot;Hello C\n&quot;);
    return 0;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;1477&quot; data-start=&quot;1464&quot; data-ke-size=&quot;size16&quot;&gt;터미널에서 컴파일합니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;css&quot;&gt;&lt;code&gt;gcc hello.c -o hello_c&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;1521&quot; data-start=&quot;1515&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;1521&quot; data-start=&quot;1515&quot; data-ke-size=&quot;size16&quot;&gt;실행합니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;jboss-cli&quot;&gt;&lt;code&gt;./hello_c&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;1559&quot; data-start=&quot;1546&quot; data-ke-size=&quot;size16&quot;&gt;결과는 다음과 같습니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;ebnf&quot;&gt;&lt;code&gt;Hello C&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;1612&quot; data-start=&quot;1582&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;1612&quot; data-start=&quot;1582&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1295&quot; data-origin-height=&quot;956&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/TxMPI/dJMcabj36V6/N6tX1wbhVG7w1GRv1jZqeK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/TxMPI/dJMcabj36V6/N6tX1wbhVG7w1GRv1jZqeK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/TxMPI/dJMcabj36V6/N6tX1wbhVG7w1GRv1jZqeK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FTxMPI%2FdJMcabj36V6%2FN6tX1wbhVG7w1GRv1jZqeK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1295&quot; height=&quot;956&quot; data-origin-width=&quot;1295&quot; data-origin-height=&quot;956&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-end=&quot;1612&quot; data-start=&quot;1582&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;1612&quot; data-start=&quot;1582&quot; data-ke-size=&quot;size16&quot;&gt;여기서 반드시 이해해야 할 부분은 다음입니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;css&quot;&gt;&lt;code&gt;gcc hello.c -o hello_c&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;1706&quot; data-start=&quot;1650&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;1706&quot; data-start=&quot;1650&quot; data-ke-size=&quot;size16&quot;&gt;이 명령어는 hello.c 파일을 컴파일해서 hello_c라는 실행 파일을 만들라는 뜻입니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;jboss-cli&quot;&gt;&lt;code&gt;./hello_c&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;1776&quot; data-start=&quot;1731&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;1776&quot; data-start=&quot;1731&quot; data-ke-size=&quot;size16&quot;&gt;이 명령어는 현재 폴더에 있는 hello_c 실행 파일을 실행하라는 뜻입니다.&lt;/p&gt;
&lt;p data-end=&quot;1776&quot; data-start=&quot;1731&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;1776&quot; data-start=&quot;1731&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;1776&quot; data-start=&quot;1731&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;1806&quot; data-start=&quot;1783&quot; data-section-id=&quot;d3xier&quot; data-ke-size=&quot;size18&quot;&gt;d. 가장 간단한 C++ 프로그램 실습&lt;/p&gt;
&lt;p data-end=&quot;1829&quot; data-start=&quot;1808&quot; data-ke-size=&quot;size16&quot;&gt;이번에는 C++ 파일을 만들어 봅니다.&lt;/p&gt;
&lt;p data-end=&quot;1855&quot; data-start=&quot;1831&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;1855&quot; data-start=&quot;1831&quot; data-ke-size=&quot;size16&quot;&gt;파일 이름은 hello.cpp로 합니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot;&gt;&lt;code&gt;#include &amp;lt;iostream&amp;gt;

int main() {
    std::cout &amp;lt;&amp;lt; &quot;Hello C++&quot; &amp;lt;&amp;lt; std::endl;
    return 0;
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;1969&quot; data-start=&quot;1962&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;1969&quot; data-start=&quot;1962&quot; data-ke-size=&quot;size16&quot;&gt;컴파일합니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;brainfuck&quot;&gt;&lt;code&gt;g++ hello.cpp -o hello_cpp&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;2017&quot; data-start=&quot;2011&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;2017&quot; data-start=&quot;2011&quot; data-ke-size=&quot;size16&quot;&gt;실행합니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;jboss-cli&quot;&gt;&lt;code&gt;./hello_cpp&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;2057&quot; data-start=&quot;2044&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;2057&quot; data-start=&quot;2044&quot; data-ke-size=&quot;size16&quot;&gt;결과는 다음과 같습니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;brainfuck&quot;&gt;&lt;code&gt;Hello C++&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;2124&quot; data-start=&quot;2082&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;2124&quot; data-start=&quot;2082&quot; data-ke-size=&quot;size16&quot;&gt;C 파일은 gcc로 컴파일하고, C++ 파일은 g++로 컴파일합니다.&lt;/p&gt;
&lt;p data-end=&quot;2140&quot; data-start=&quot;2126&quot; data-ke-size=&quot;size16&quot;&gt;정리하면 다음과 같습니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;css&quot;&gt;&lt;code&gt;gcc hello.c -o hello_c
g++ hello.cpp -o hello_cpp&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1295&quot; data-origin-height=&quot;956&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bci4k1/dJMcagTbjlh/6koF5EQsxIghRKM6e2IL3k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bci4k1/dJMcagTbjlh/6koF5EQsxIghRKM6e2IL3k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bci4k1/dJMcagTbjlh/6koF5EQsxIghRKM6e2IL3k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbci4k1%2FdJMcagTbjlh%2F6koF5EQsxIghRKM6e2IL3k%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1295&quot; height=&quot;956&quot; data-origin-width=&quot;1295&quot; data-origin-height=&quot;956&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;1121&quot; data-start=&quot;999&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-end=&quot;1139&quot; data-start=&quot;1128&quot; data-section-id=&quot;1v7g6bf&quot; data-ke-size=&quot;size20&quot;&gt;3. 기본 자료형&lt;/h4&gt;
&lt;p data-end=&quot;1199&quot; data-start=&quot;1141&quot; data-ke-size=&quot;size16&quot;&gt;프로그래밍에서 자료형은 데이터를 저장하는 방식입니다. C/C++에서는 변수마다 자료형을 지정해야 합니다.&lt;/p&gt;
&lt;p data-end=&quot;1223&quot; data-start=&quot;1201&quot; data-ke-size=&quot;size16&quot;&gt;대표적인 기본 자료형은 다음과 같습니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;int age = 20;
float temperature = 36.5f;
double position = 12.345678;
char grade = 'A';
bool is_active = true;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;1417&quot; data-start=&quot;1348&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;1417&quot; data-start=&quot;1348&quot; data-ke-size=&quot;size16&quot;&gt;int는 정수, float와 double은 실수, char는 문자, bool은 참 또는 거짓을 저장합니다.&lt;/p&gt;
&lt;p data-end=&quot;1417&quot; data-start=&quot;1348&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;1505&quot; data-start=&quot;1419&quot; data-ke-size=&quot;size16&quot;&gt;로봇 개발에서는 자료형 선택이 중요합니다. 예를 들어 모터 속도, 센서 값, 좌표, 각도, 시간, 상태값 등을 저장할 때 적절한 자료형을 선택해야 합니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;int motor_rpm = 1500;
double x_position = 1.25;
double yaw_angle = 0.785;
bool emergency_stop = false;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;1735&quot; data-start=&quot;1622&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;1735&quot; data-start=&quot;1622&quot; data-ke-size=&quot;size16&quot;&gt;초보자들이 자주 하는 실수 중 하나는 모든 숫자를 무조건 int로 처리하는 것입니다. 하지만 위치, 속도, 각도, 시간처럼 소수점이 필요한 값은 float 또는 double을 사용해야 합니다.&lt;/p&gt;
&lt;p data-end=&quot;1735&quot; data-start=&quot;1622&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;1843&quot; data-start=&quot;1737&quot; data-ke-size=&quot;size16&quot;&gt;일반적으로 PC나 ROS 2 환경에서는 정밀도가 높은 double을 많이 사용합니다. 반면 MCU 같은 임베디드 환경에서는 성능과 메모리 때문에 float를 사용하는 경우도 많습니다.&lt;/p&gt;
&lt;p data-end=&quot;1843&quot; data-start=&quot;1737&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;1843&quot; data-start=&quot;1737&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;1843&quot; data-start=&quot;1737&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-end=&quot;1861&quot; data-start=&quot;1850&quot; data-section-id=&quot;1d34sbe&quot; data-ke-size=&quot;size20&quot;&gt;4. 변수와 상수&lt;/h4&gt;
&lt;p data-end=&quot;1887&quot; data-start=&quot;1863&quot; data-ke-size=&quot;size16&quot;&gt;변수는 값이 바뀔 수 있는 저장 공간입니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;ebnf&quot;&gt;&lt;code&gt;int speed = 100;
speed = 150;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;1980&quot; data-start=&quot;1931&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;1980&quot; data-start=&quot;1931&quot; data-ke-size=&quot;size16&quot;&gt;상수는 한 번 정하면 바뀌면 안 되는 값입니다. C++에서는 const를 사용합니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;const double PI = 3.141592;
const int MAX_SPEED = 3000;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;2160&quot; data-start=&quot;2050&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;2160&quot; data-start=&quot;2050&quot; data-ke-size=&quot;size16&quot;&gt;로봇 개발에서는 상수를 적극적으로 사용하는 것이 좋습니다. 예를 들어 최대 속도, 바퀴 반지름, 기어비, 제어 주기 같은 값은 코드 중간에 직접 숫자로 쓰는 것보다 상수로 정의하는 것이 안전합니다.&lt;/p&gt;
&lt;p data-end=&quot;2160&quot; data-start=&quot;2050&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;2181&quot; data-start=&quot;2162&quot; data-ke-size=&quot;size16&quot;&gt;좋지 않은 예시는 다음과 같습니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;double distance = rpm * 0.034 * 3.141592;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;2274&quot; data-start=&quot;2237&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;2274&quot; data-start=&quot;2237&quot; data-ke-size=&quot;size16&quot;&gt;이 코드는 0.034가 무엇을 의미하는지 바로 알기 어렵습니다.&lt;/p&gt;
&lt;p data-end=&quot;2294&quot; data-start=&quot;2276&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;2294&quot; data-start=&quot;2276&quot; data-ke-size=&quot;size16&quot;&gt;더 좋은 예시는 다음과 같습니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;const double WHEEL_RADIUS = 0.034;
const double PI = 3.141592;

double distance = rpm * WHEEL_RADIUS * PI;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;2442&quot; data-start=&quot;2415&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;2442&quot; data-start=&quot;2415&quot; data-ke-size=&quot;size16&quot;&gt;이렇게 작성하면 코드의 의미가 훨씬 분명해집니다.&lt;/p&gt;
&lt;p data-end=&quot;2442&quot; data-start=&quot;2415&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;2442&quot; data-start=&quot;2415&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;2442&quot; data-start=&quot;2415&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-end=&quot;2457&quot; data-start=&quot;2449&quot; data-section-id=&quot;m7nkwc&quot; data-ke-size=&quot;size20&quot;&gt;5. 연산자&lt;/h4&gt;
&lt;p data-end=&quot;2483&quot; data-start=&quot;2459&quot; data-ke-size=&quot;size16&quot;&gt;C/C++에서는 다양한 연산자를 사용합니다.&lt;/p&gt;
&lt;p data-end=&quot;2502&quot; data-start=&quot;2485&quot; data-ke-size=&quot;size16&quot;&gt;산술 연산자는 다음과 같습니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;ebnf&quot;&gt;&lt;code&gt;int a = 10;
int b = 3;

int sum = a + b;
int sub = a - b;
int mul = a * b;
int div = a / b;
int mod = a % b;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;2659&quot; data-start=&quot;2625&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;2659&quot; data-start=&quot;2625&quot; data-ke-size=&quot;size16&quot;&gt;여기서 주의할 점은 정수끼리 나누면 결과도 정수라는 점입니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;ebnf&quot;&gt;&lt;code&gt;int a = 10;
int b = 3;

double result = a / b;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;2797&quot; data-start=&quot;2720&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;2797&quot; data-start=&quot;2720&quot; data-ke-size=&quot;size16&quot;&gt;이 경우 result는 3.3333이 아니라 3.0이 됩니다. 왜냐하면 a / b가 먼저 정수 연산으로 처리되기 때문입니다.&lt;/p&gt;
&lt;p data-end=&quot;2828&quot; data-start=&quot;2799&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;2828&quot; data-start=&quot;2799&quot; data-ke-size=&quot;size16&quot;&gt;정확한 실수 결과를 원하면 다음처럼 작성해야 합니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;cpp&quot;&gt;&lt;code&gt;double result = static_cast&amp;lt;double&amp;gt;(a) / b;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;2955&quot; data-start=&quot;2886&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;2955&quot; data-start=&quot;2886&quot; data-ke-size=&quot;size16&quot;&gt;ROS 2나 로봇 제어 코드에서는 속도, 거리, 각도, 시간 계산이 많기 때문에 정수 나눗셈 실수는 반드시 조심해야 합니다.&lt;/p&gt;
&lt;p data-end=&quot;2955&quot; data-start=&quot;2886&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;2955&quot; data-start=&quot;2886&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;2955&quot; data-start=&quot;2886&quot; data-ke-size=&quot;size16&quot;&gt;아래의 예제 소스를 작성하고 컴파일하여 실행결과를 확인하시기 바랍니다.&lt;/p&gt;
&lt;p data-end=&quot;3097&quot; data-start=&quot;3069&quot; data-ke-size=&quot;size16&quot;&gt;파일 이름은 01_variable.cpp입니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot;&gt;&lt;code&gt;#include &amp;lt;iostream&amp;gt;
#include &amp;lt;string&amp;gt;

int main() {
    int motor_rpm = 1500;
    double battery_voltage = 12.5;
    bool is_motor_on = true;
    std::string robot_name = &quot;mobile_robot&quot;;

    std::cout &amp;lt;&amp;lt; &quot;Robot name: &quot; &amp;lt;&amp;lt; robot_name &amp;lt;&amp;lt; std::endl;
    std::cout &amp;lt;&amp;lt; &quot;Motor RPM: &quot; &amp;lt;&amp;lt; motor_rpm &amp;lt;&amp;lt; std::endl;
    std::cout &amp;lt;&amp;lt; &quot;Battery voltage: &quot; &amp;lt;&amp;lt; battery_voltage &amp;lt;&amp;lt; std::endl;
    std::cout &amp;lt;&amp;lt; &quot;Motor on: &quot; &amp;lt;&amp;lt; is_motor_on &amp;lt;&amp;lt; std::endl;

    return 0;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;3570&quot; data-start=&quot;3563&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;3570&quot; data-start=&quot;3563&quot; data-ke-size=&quot;size16&quot;&gt;컴파일합니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;g++ -std=c++17 01_variable.cpp -o 01_variable
./01_variable&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;3685&quot; data-start=&quot;3645&quot; data-ke-size=&quot;size16&quot;&gt;이 실습에서는 변수, 자료형, 문자열, 출력문을 함께 익힐 수 있습니다.&lt;/p&gt;
&lt;p data-end=&quot;2955&quot; data-start=&quot;2886&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1295&quot; data-origin-height=&quot;956&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bcK0g2/dJMcacXwFxE/zVrYPYrTVlXIko5ExDvn41/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bcK0g2/dJMcacXwFxE/zVrYPYrTVlXIko5ExDvn41/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bcK0g2/dJMcacXwFxE/zVrYPYrTVlXIko5ExDvn41/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbcK0g2%2FdJMcacXwFxE%2FzVrYPYrTVlXIko5ExDvn41%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1295&quot; height=&quot;956&quot; data-origin-width=&quot;1295&quot; data-origin-height=&quot;956&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-end=&quot;2955&quot; data-start=&quot;2886&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;2955&quot; data-start=&quot;2886&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;2955&quot; data-start=&quot;2886&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-end=&quot;2970&quot; data-start=&quot;2962&quot; data-section-id=&quot;mrr0sh&quot; data-ke-size=&quot;size20&quot;&gt;6. 조건문&lt;/h4&gt;
&lt;p data-end=&quot;3007&quot; data-start=&quot;2972&quot; data-ke-size=&quot;size16&quot;&gt;조건문은 특정 조건에 따라 코드를 다르게 실행할 때 사용합니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;int battery = 30;

if (battery &amp;lt; 20) {
    // 배터리 부족
} else if (battery &amp;lt; 50) {
    // 배터리 주의
} else {
    // 배터리 정상
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;3166&quot; data-start=&quot;3140&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;3166&quot; data-start=&quot;3140&quot; data-ke-size=&quot;size16&quot;&gt;로봇 개발에서는 조건문이 매우 많이 사용됩니다.&lt;/p&gt;
&lt;p data-end=&quot;3192&quot; data-start=&quot;3168&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;3192&quot; data-start=&quot;3168&quot; data-ke-size=&quot;size16&quot;&gt;예를 들어 다음과 같은 상황에서 사용합니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;nginx&quot;&gt;&lt;code&gt;if (emergency_stop == true) {
    motor_speed = 0;
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;3282&quot; data-start=&quot;3259&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;3282&quot; data-start=&quot;3259&quot; data-ke-size=&quot;size16&quot;&gt;또는 다음처럼 간단히 작성할 수 있습니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;nginx&quot;&gt;&lt;code&gt;if (emergency_stop) {
    motor_speed = 0;
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;3390&quot; data-start=&quot;3341&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;3390&quot; data-start=&quot;3341&quot; data-ke-size=&quot;size16&quot;&gt;bool 변수는 이미 참 또는 거짓을 의미하므로 == true를 생략해도 됩니다.&lt;/p&gt;
&lt;p data-end=&quot;3418&quot; data-start=&quot;3392&quot; data-ke-size=&quot;size16&quot;&gt;조건이 복잡해질 때는 논리 연산자를 사용합니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;1c&quot;&gt;&lt;code&gt;if (battery_low &amp;amp;&amp;amp; gps_ok) {
    // 배터리는 낮지만 GPS는 정상
}

if (obstacle_detected || emergency_stop) {
    // 장애물이 있거나 비상 정지 상태
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;3595&quot; data-start=&quot;3558&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;3595&quot; data-start=&quot;3558&quot; data-ke-size=&quot;size16&quot;&gt;&amp;amp;&amp;amp;는 AND, ||는 OR, !는 NOT을 의미합니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;gauss&quot;&gt;&lt;code&gt;if (!sensor_ready) {
    // 센서가 준비되지 않았을 때
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래의 예제 소스를 작성하고 컴파일하여 실행결과를 확인하시기 바랍니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;3730&quot; data-start=&quot;3708&quot; data-ke-size=&quot;size16&quot;&gt;파일 이름은 02_if.cpp입니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot;&gt;&lt;code&gt;#include &amp;lt;iostream&amp;gt;

int main() {
    double battery_voltage = 10.8;

    if (battery_voltage &amp;lt; 10.5) {
        std::cout &amp;lt;&amp;lt; &quot;Battery is low&quot; &amp;lt;&amp;lt; std::endl;
    } else if (battery_voltage &amp;lt; 11.5) {
        std::cout &amp;lt;&amp;lt; &quot;Battery warning&quot; &amp;lt;&amp;lt; std::endl;
    } else {
        std::cout &amp;lt;&amp;lt; &quot;Battery normal&quot; &amp;lt;&amp;lt; std::endl;
    }

    return 0;
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;4100&quot; data-start=&quot;4082&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;4100&quot; data-start=&quot;4082&quot; data-ke-size=&quot;size16&quot;&gt;컴파일과 실행은 다음과 같습니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;p data-end=&quot;2312&quot; data-start=&quot;2237&quot; data-ke-size=&quot;size16&quot;&gt;ROS 2 Humble의 C++ 코드는 일반적으로 C++14 이상 문법을 사용하며, 실습에서는 C++17 기준으로 공부해도 괜찮습니다.&lt;/p&gt;
&lt;p data-end=&quot;2345&quot; data-start=&quot;2314&quot; data-ke-size=&quot;size16&quot;&gt;C++17 옵션을 붙여 컴파일하려면 다음처럼 작성합니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;brainfuck&quot;&gt;&lt;code&gt;g++ -std=c++17 hello.cpp -o hello_cpp&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;2435&quot; data-start=&quot;2398&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;2435&quot; data-start=&quot;2398&quot; data-ke-size=&quot;size16&quot;&gt;앞으로 C++ 실습에서는 다음 명령어를 기본으로 사용하면 좋습니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;brainfuck&quot;&gt;&lt;code&gt;g++ -std=c++17 파일이름.cpp -o 실행파일이름&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot;&gt;&lt;code&gt;g++ -std=c++17 02_if.cpp -o 02_if
./02_if&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;4203&quot; data-start=&quot;4157&quot; data-ke-size=&quot;size16&quot;&gt;battery_voltage 값을 직접 바꿔 보면서 출력결과를 확인하시기 바랍니다.&lt;/p&gt;
&lt;p data-end=&quot;4225&quot; data-start=&quot;4205&quot; data-ke-size=&quot;size16&quot;&gt;예를 들어 다음 값으로 바꿔 봅니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;double battery_voltage = 9.8;
double battery_voltage = 10.8;
double battery_voltage = 12.2;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;4376&quot; data-start=&quot;4331&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;4376&quot; data-start=&quot;4331&quot; data-ke-size=&quot;size16&quot;&gt;값에 따라 출력 결과가 달라지는 것을 확인하면 조건문을 쉽게 이해할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1295&quot; data-origin-height=&quot;956&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/wS0Lh/dJMcabYEwTB/9eiPSbjzCyAfCthvOq1YSK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/wS0Lh/dJMcabYEwTB/9eiPSbjzCyAfCthvOq1YSK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/wS0Lh/dJMcabYEwTB/9eiPSbjzCyAfCthvOq1YSK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FwS0Lh%2FdJMcabYEwTB%2F9eiPSbjzCyAfCthvOq1YSK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1295&quot; height=&quot;956&quot; data-origin-width=&quot;1295&quot; data-origin-height=&quot;956&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-end=&quot;3667&quot; data-start=&quot;3659&quot; data-section-id=&quot;lbp357&quot; data-ke-size=&quot;size20&quot;&gt;7. 반복문&lt;/h4&gt;
&lt;p data-end=&quot;3698&quot; data-start=&quot;3669&quot; data-ke-size=&quot;size16&quot;&gt;반복문은 같은 작업을 여러 번 수행할 때 사용합니다.&lt;/p&gt;
&lt;p data-end=&quot;3698&quot; data-start=&quot;3669&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;3739&quot; data-start=&quot;3700&quot; data-ke-size=&quot;size16&quot;&gt;대표적으로 for, while, do-while이 있습니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;for (int i = 0; i &amp;lt; 10; i++) {
    // 10번 반복
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;3829&quot; data-start=&quot;3800&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;3829&quot; data-start=&quot;3800&quot; data-ke-size=&quot;size16&quot;&gt;배열이나 벡터의 데이터를 처리할 때 많이 사용합니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;double sensor_values[5] = {1.0, 2.0, 3.0, 4.0, 5.0};

for (int i = 0; i &amp;lt; 5; i++) {
    double value = sensor_values[i];
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;3995&quot; data-start=&quot;3966&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;3995&quot; data-start=&quot;3966&quot; data-ke-size=&quot;size16&quot;&gt;while문은 조건이 참인 동안 계속 반복합니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;ceylon&quot;&gt;&lt;code&gt;while (is_running) {
    // 실행 중일 때 계속 반복
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;4214&quot; data-start=&quot;4053&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;4214&quot; data-start=&quot;4053&quot; data-ke-size=&quot;size16&quot;&gt;로봇 프로그램에서는 무한 반복 구조를 자주 볼 수 있습니다. 하지만 ROS 2에서는 일반적인 while(true) 반복보다는 콜백, 타이머, executor 구조를 많이 사용합니다. 그래도 C/C++ 기본 반복문을 이해해야 ROS 2 내부 동작과 일반 제어 루프를 이해할 수 있습니다.&lt;/p&gt;
&lt;p data-end=&quot;4214&quot; data-start=&quot;4053&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;4214&quot; data-start=&quot;4053&quot; data-ke-size=&quot;size16&quot;&gt;아래의 예제 소스를 작성하고 컴파일하여 실행결과를 확인하시기 바랍니다.&lt;/p&gt;
&lt;p data-end=&quot;4214&quot; data-start=&quot;4053&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;4422&quot; data-start=&quot;4399&quot; data-ke-size=&quot;size16&quot;&gt;파일 이름은 03_for.cpp입니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot;&gt;&lt;code&gt;#include &amp;lt;iostream&amp;gt;

int main() {
    for (int i = 0; i &amp;lt; 5; i++) {
        std::cout &amp;lt;&amp;lt; &quot;Control loop count: &quot; &amp;lt;&amp;lt; i &amp;lt;&amp;lt; std::endl;
    }

    return 0;
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;4597&quot; data-start=&quot;4590&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;4597&quot; data-start=&quot;4590&quot; data-ke-size=&quot;size16&quot;&gt;컴파일합니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;g++ -std=c++17 03_for.cpp -o 03_for
./03_for&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;4693&quot; data-start=&quot;4657&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;4693&quot; data-start=&quot;4657&quot; data-ke-size=&quot;size16&quot;&gt;로봇 제어에서는 반복문을 제어 루프와 연결해서 설명하면 좋습니다.&lt;/p&gt;
&lt;p data-end=&quot;4214&quot; data-start=&quot;4053&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1295&quot; data-origin-height=&quot;956&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ccKMJN/dJMcaf7Ldun/O7bFI0Uo44napldnJklFX0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ccKMJN/dJMcaf7Ldun/O7bFI0Uo44napldnJklFX0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ccKMJN/dJMcaf7Ldun/O7bFI0Uo44napldnJklFX0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FccKMJN%2FdJMcaf7Ldun%2FO7bFI0Uo44napldnJklFX0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1295&quot; height=&quot;956&quot; data-origin-width=&quot;1295&quot; data-origin-height=&quot;956&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-end=&quot;4214&quot; data-start=&quot;4053&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;4214&quot; data-start=&quot;4053&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;4214&quot; data-start=&quot;4053&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-end=&quot;4228&quot; data-start=&quot;4221&quot; data-section-id=&quot;1xjjst7&quot; data-ke-size=&quot;size20&quot;&gt;8. 배열&lt;/h4&gt;
&lt;p data-end=&quot;4263&quot; data-start=&quot;4230&quot; data-ke-size=&quot;size16&quot;&gt;배열은 같은 자료형의 데이터를 여러 개 저장하는 구조입니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;int numbers[5] = {1, 2, 3, 4, 5};&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;4330&quot; data-start=&quot;4311&quot; data-ke-size=&quot;size16&quot;&gt;배열의 인덱스는 0부터 시작합니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;int first = numbers[0];
int second = numbers[1];&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;4428&quot; data-start=&quot;4393&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;4428&quot; data-start=&quot;4393&quot; data-ke-size=&quot;size16&quot;&gt;초보자가 자주 하는 실수는 배열 범위를 넘어 접근하는 것입니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;int numbers[5] = {1, 2, 3, 4, 5};

int wrong = numbers[5];&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;4556&quot; data-start=&quot;4501&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;4556&quot; data-start=&quot;4501&quot; data-ke-size=&quot;size16&quot;&gt;위 코드는 잘못된 코드입니다. 배열 크기가 5이면 접근 가능한 인덱스는 0부터 4까지입니다.&lt;/p&gt;
&lt;p data-end=&quot;4643&quot; data-start=&quot;4558&quot; data-ke-size=&quot;size16&quot;&gt;C 스타일 배열은 빠르고 단순하지만, 크기 관리가 불편합니다. C++에서는 보통 std::array나 std::vector를 더 많이 사용합니다.&lt;/p&gt;
&lt;p data-end=&quot;4643&quot; data-start=&quot;4558&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;4643&quot; data-start=&quot;4558&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;4643&quot; data-start=&quot;4558&quot; data-ke-size=&quot;size16&quot;&gt;아래의 예제 소스를 작성하고 컴파일하여 실행결과를 확인하시기 바랍니다.&lt;/p&gt;
&lt;p data-end=&quot;4643&quot; data-start=&quot;4558&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;4643&quot; data-start=&quot;4558&quot; data-ke-size=&quot;size16&quot;&gt;04_array.cpp 파일에 다음 코드를 작성합니다.&lt;/p&gt;
&lt;p data-end=&quot;4643&quot; data-start=&quot;4558&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;2403&quot; data-start=&quot;2375&quot; data-ke-size=&quot;size16&quot;&gt;배열의 값은 인덱스를 사용해서 변경할 수 있습니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;ini&quot;&gt;&lt;code&gt;motor_rpm[0] = 1500;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;2455&quot; data-start=&quot;2438&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;2455&quot; data-start=&quot;2438&quot; data-ke-size=&quot;size16&quot;&gt;다음 예제를 작성해 보겠습니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot;&gt;&lt;code&gt;#include &amp;lt;iostream&amp;gt;

int main() {
    int motor_rpm[4] = {1200, 1350, 1280, 1420};

    std::cout &amp;lt;&amp;lt; &quot;Before update&quot; &amp;lt;&amp;lt; std::endl;

    for (int i = 0; i &amp;lt; 4; i++) {
        std::cout &amp;lt;&amp;lt; &quot;Motor &quot; &amp;lt;&amp;lt; i + 1 &amp;lt;&amp;lt; &quot; RPM: &quot;
                  &amp;lt;&amp;lt; motor_rpm[i] &amp;lt;&amp;lt; std::endl;
    }

    motor_rpm[0] = 1500;
    motor_rpm[1] = 1500;

    std::cout &amp;lt;&amp;lt; std::endl;
    std::cout &amp;lt;&amp;lt; &quot;After update&quot; &amp;lt;&amp;lt; std::endl;

    for (int i = 0; i &amp;lt; 4; i++) {
        std::cout &amp;lt;&amp;lt; &quot;Motor &quot; &amp;lt;&amp;lt; i + 1 &amp;lt;&amp;lt; &quot; RPM: &quot;
                  &amp;lt;&amp;lt; motor_rpm[i] &amp;lt;&amp;lt; std::endl;
    }

    return 0;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;3035&quot; data-start=&quot;3023&quot; data-ke-size=&quot;size16&quot;&gt;컴파일하고 실행합니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot;&gt;&lt;code&gt;g++ -std=c++17 04_array.cpp -o 04_array
./04_array&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;3118&quot; data-start=&quot;3101&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;3118&quot; data-start=&quot;3101&quot; data-ke-size=&quot;size16&quot;&gt;실행 결과는 다음과 비슷합니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;Before update
Motor 1 RPM: 1200
Motor 2 RPM: 1350
Motor 3 RPM: 1280
Motor 4 RPM: 1420

After update
Motor 1 RPM: 1500
Motor 2 RPM: 1500
Motor 3 RPM: 1280
Motor 4 RPM: 1420&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;3357&quot; data-start=&quot;3305&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;3357&quot; data-start=&quot;3305&quot; data-ke-size=&quot;size16&quot;&gt;이 실습을 통해 배열의 특정 위치에 있는 값을 직접 바꿀 수 있다는 것을 확인할 수 있습니다.&lt;/p&gt;
&lt;p data-end=&quot;3357&quot; data-start=&quot;3305&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1295&quot; data-origin-height=&quot;1022&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/be63k0/dJMcacpIEZF/S4kzbM5S0fFKYLEuR5et9k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/be63k0/dJMcacpIEZF/S4kzbM5S0fFKYLEuR5et9k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/be63k0/dJMcacpIEZF/S4kzbM5S0fFKYLEuR5et9k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbe63k0%2FdJMcacpIEZF%2FS4kzbM5S0fFKYLEuR5et9k%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1295&quot; height=&quot;1022&quot; data-origin-width=&quot;1295&quot; data-origin-height=&quot;1022&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-end=&quot;3357&quot; data-start=&quot;3305&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;3357&quot; data-start=&quot;3305&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;4643&quot; data-start=&quot;4558&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-end=&quot;4666&quot; data-start=&quot;4650&quot; data-section-id=&quot;1kfs46i&quot; data-ke-size=&quot;size20&quot;&gt;9. std::vector&lt;/h4&gt;
&lt;p data-end=&quot;4730&quot; data-start=&quot;4668&quot; data-ke-size=&quot;size16&quot;&gt;std::vector는 C++에서 가장 많이 사용하는 동적 배열입니다. 크기를 자동으로 조절할 수 있습니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;cpp&quot;&gt;&lt;code&gt;#include &amp;lt;vector&amp;gt;

std::vector&amp;lt;int&amp;gt; numbers;

numbers.push_back(10);
numbers.push_back(20);
numbers.push_back(30);&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;4884&quot; data-start=&quot;4859&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;4884&quot; data-start=&quot;4859&quot; data-ke-size=&quot;size16&quot;&gt;값을 읽을 때는 배열처럼 접근할 수 있습니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;int value = numbers[0];&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;4953&quot; data-start=&quot;4922&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;4953&quot; data-start=&quot;4922&quot; data-ke-size=&quot;size16&quot;&gt;전체 데이터를 반복할 때는 다음처럼 작성할 수 있습니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;matlab&quot;&gt;&lt;code&gt;for (int i = 0; i &amp;lt; numbers.size(); i++) {
    int value = numbers[i];
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;5081&quot; data-start=&quot;5040&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;5081&quot; data-start=&quot;5040&quot; data-ke-size=&quot;size16&quot;&gt;더 현대적인 C++ 문법으로는 range-based for문을 사용합니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;cs&quot;&gt;&lt;code&gt;for (int value : numbers) {
    // value 사용
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;5174&quot; data-start=&quot;5141&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;5174&quot; data-start=&quot;5141&quot; data-ke-size=&quot;size16&quot;&gt;값을 복사하지 않고 참조로 받고 싶다면 다음처럼 작성합니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;for (const auto&amp;amp; value : numbers) {
    // value 읽기 전용 사용
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;5339&quot; data-start=&quot;5248&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;5339&quot; data-start=&quot;5248&quot; data-ke-size=&quot;size16&quot;&gt;ROS 2 개발에서는 여러 개의 좌표, 센서값, 경로점, 객체 목록 등을 다룰 때 std::vector를 자주 사용합니다. 초중급자는 반드시 익숙해져야 합니다.&lt;/p&gt;
&lt;p data-end=&quot;5339&quot; data-start=&quot;5248&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;5339&quot; data-start=&quot;5248&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;5339&quot; data-start=&quot;5248&quot; data-ke-size=&quot;size16&quot;&gt;아래의 예제 소스를 작성하고 컴파일하여 실행결과를 확인하시기 바랍니다.&lt;/p&gt;
&lt;p data-end=&quot;5339&quot; data-start=&quot;5248&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;5422&quot; data-start=&quot;5396&quot; data-ke-size=&quot;size16&quot;&gt;파일 이름은 05_vector.cpp입니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot;&gt;&lt;code&gt;#include &amp;lt;iostream&amp;gt;
#include &amp;lt;vector&amp;gt;

int main() {
    std::vector&amp;lt;double&amp;gt; sensor_values;

    sensor_values.push_back(1.2);
    sensor_values.push_back(2.5);
    sensor_values.push_back(3.1);

    for (const auto&amp;amp; value : sensor_values) {
        std::cout &amp;lt;&amp;lt; &quot;Sensor value: &quot; &amp;lt;&amp;lt; value &amp;lt;&amp;lt; std::endl;
    }

    return 0;
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;5768&quot; data-start=&quot;5761&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;5768&quot; data-start=&quot;5761&quot; data-ke-size=&quot;size16&quot;&gt;컴파일합니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot;&gt;&lt;code&gt;g++ -std=c++17 05_vector.cpp -o 05_vector
./05_vector&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;5918&quot; data-start=&quot;5837&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;5918&quot; data-start=&quot;5837&quot; data-ke-size=&quot;size16&quot;&gt;std::vector는 ROS 2 개발에서도 매우 자주 사용됩니다. 센서값 목록, 경로점 목록, 좌표 목록 등을 저장할 때 사용하기 좋습니다.&lt;/p&gt;
&lt;p data-end=&quot;5918&quot; data-start=&quot;5837&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1295&quot; data-origin-height=&quot;1022&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cuFG19/dJMcafGKHXx/zkY4dQAXez7t20REFMi1PK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cuFG19/dJMcafGKHXx/zkY4dQAXez7t20REFMi1PK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cuFG19/dJMcafGKHXx/zkY4dQAXez7t20REFMi1PK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcuFG19%2FdJMcafGKHXx%2FzkY4dQAXez7t20REFMi1PK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1295&quot; height=&quot;1022&quot; data-origin-width=&quot;1295&quot; data-origin-height=&quot;1022&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-end=&quot;5918&quot; data-start=&quot;5837&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;5339&quot; data-start=&quot;5248&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;5339&quot; data-start=&quot;5248&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;5339&quot; data-start=&quot;5248&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-end=&quot;5354&quot; data-start=&quot;5346&quot; data-section-id=&quot;tdxht9&quot; data-ke-size=&quot;size20&quot;&gt;10. 문자열&lt;/h4&gt;
&lt;p data-end=&quot;5385&quot; data-start=&quot;5356&quot; data-ke-size=&quot;size16&quot;&gt;C 언어에서는 문자열을 char 배열로 다룹니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;pgsql&quot;&gt;&lt;code&gt;char name[] = &quot;robot&quot;;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;5453&quot; data-start=&quot;5422&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;5453&quot; data-start=&quot;5422&quot; data-ke-size=&quot;size16&quot;&gt;C++에서는 보통 std::string을 사용합니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;cpp&quot;&gt;&lt;code&gt;#include &amp;lt;string&amp;gt;

std::string robot_name = &quot;mobile_robot&quot;;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;5543&quot; data-start=&quot;5527&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;5543&quot; data-start=&quot;5527&quot; data-ke-size=&quot;size16&quot;&gt;문자열을 합칠 수도 있습니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;cpp&quot;&gt;&lt;code&gt;std::string frame_id = &quot;base_link&quot;;
std::string topic_name = &quot;/robot/&quot; + frame_id;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;5676&quot; data-start=&quot;5640&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;5676&quot; data-start=&quot;5640&quot; data-ke-size=&quot;size16&quot;&gt;단, 문자열 리터럴끼리 바로 더하는 것은 문제가 될 수 있습니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;arduino&quot;&gt;&lt;code&gt;std::string text = std::string(&quot;robot&quot;) + &quot;_1&quot;;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;5844&quot; data-start=&quot;5738&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;5844&quot; data-start=&quot;5738&quot; data-ke-size=&quot;size16&quot;&gt;ROS 2 개발에서는 토픽 이름, 프레임 이름, 파라미터 이름, 로그 메시지 등을 다룰 때 문자열을 많이 사용합니다. 따라서 std::string 사용법은 기본적으로 알고 있어야 합니다.&lt;/p&gt;
&lt;p data-end=&quot;5844&quot; data-start=&quot;5738&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-end=&quot;5339&quot; data-start=&quot;5248&quot; data-ke-size=&quot;size16&quot;&gt;아래의 예제 소스를 작성하고 컴파일하여 실행결과를 확인하시기 바랍니다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-end=&quot;5339&quot; data-start=&quot;5248&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-end=&quot;5422&quot; data-start=&quot;5396&quot; data-ke-size=&quot;size16&quot;&gt;파일 이름은 06_string.cpp입니다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-end=&quot;5422&quot; data-start=&quot;5396&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;1131&quot; data-start=&quot;1089&quot; data-ke-size=&quot;size16&quot;&gt;이번에는 로봇 이름, 센서 이름, 프레임 이름을 문자열로 저장해 보겠습니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot;&gt;&lt;code&gt;#include &amp;lt;iostream&amp;gt;
#include &amp;lt;string&amp;gt;

int main() {
    std::string robot_name = &quot;delivery_robot&quot;;
    std::string sensor_name = &quot;lidar&quot;;
    std::string frame_id = &quot;base_link&quot;;

    std::cout &amp;lt;&amp;lt; &quot;Robot name: &quot; &amp;lt;&amp;lt; robot_name &amp;lt;&amp;lt; std::endl;
    std::cout &amp;lt;&amp;lt; &quot;Sensor name: &quot; &amp;lt;&amp;lt; sensor_name &amp;lt;&amp;lt; std::endl;
    std::cout &amp;lt;&amp;lt; &quot;Frame ID: &quot; &amp;lt;&amp;lt; frame_id &amp;lt;&amp;lt; std::endl;

    return 0;
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;1531&quot; data-start=&quot;1519&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;1531&quot; data-start=&quot;1519&quot; data-ke-size=&quot;size16&quot;&gt;컴파일하고 실행합니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot;&gt;&lt;code&gt;g++ -std=c++17 06_string.cpp -o 06_string
./06_string&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;1617&quot; data-start=&quot;1600&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;1617&quot; data-start=&quot;1600&quot; data-ke-size=&quot;size16&quot;&gt;실행 결과는 다음과 비슷합니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;groovy&quot;&gt;&lt;code&gt;Robot name: delivery_robot
Sensor name: lidar
Frame ID: base_link&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;1742&quot; data-start=&quot;1698&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;1742&quot; data-start=&quot;1698&quot; data-ke-size=&quot;size16&quot;&gt;이 예제에서는 문자열 변수를 여러 개 만들고 출력하는 방법을 익힐 수 있습니다.&lt;/p&gt;
&lt;p data-end=&quot;1742&quot; data-start=&quot;1698&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1295&quot; data-origin-height=&quot;1028&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/wktNU/dJMcabEjQec/6McX7K6KR6hZLKhGkdyiJk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/wktNU/dJMcabEjQec/6McX7K6KR6hZLKhGkdyiJk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/wktNU/dJMcabEjQec/6McX7K6KR6hZLKhGkdyiJk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FwktNU%2FdJMcabEjQec%2F6McX7K6KR6hZLKhGkdyiJk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1295&quot; height=&quot;1028&quot; data-origin-width=&quot;1295&quot; data-origin-height=&quot;1028&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-end=&quot;1742&quot; data-start=&quot;1698&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;5844&quot; data-start=&quot;5738&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;5844&quot; data-start=&quot;5738&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-end=&quot;5859&quot; data-start=&quot;5851&quot; data-section-id=&quot;olihvd&quot; data-ke-size=&quot;size20&quot;&gt;11. 함수&lt;/h4&gt;
&lt;p data-end=&quot;5887&quot; data-start=&quot;5861&quot; data-ke-size=&quot;size16&quot;&gt;함수는 반복되는 코드를 하나로 묶는 방법입니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;cpp&quot;&gt;&lt;code&gt;int add(int a, int b) {
    return a + b;
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;5967&quot; data-start=&quot;5945&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;5967&quot; data-start=&quot;5945&quot; data-ke-size=&quot;size16&quot;&gt;함수를 호출할 때는 다음처럼 사용합니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;int result = add(3, 5);&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;6045&quot; data-start=&quot;6005&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;6045&quot; data-start=&quot;6005&quot; data-ke-size=&quot;size16&quot;&gt;로봇 개발에서는 계산식이나 반복 작업을 함수로 분리하는 것이 중요합니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;double rpmToVelocity(double rpm, double wheel_radius) {
    const double PI = 3.141592;
    return (rpm / 60.0) * 2.0 * PI * wheel_radius;
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;6238&quot; data-start=&quot;6200&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;6238&quot; data-start=&quot;6200&quot; data-ke-size=&quot;size16&quot;&gt;이렇게 작성하면 속도 계산 코드를 여러 곳에서 재사용할 수 있습니다.&lt;/p&gt;
&lt;p data-end=&quot;6288&quot; data-start=&quot;6240&quot; data-ke-size=&quot;size16&quot;&gt;함수를 잘 나누면 코드가 짧아지고, 테스트하기 쉬워지고, 나중에 수정하기도 편해집니다.&lt;/p&gt;
&lt;p data-end=&quot;6288&quot; data-start=&quot;6240&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;5248&quot; data-end=&quot;5339&quot;&gt;아래의 예제 소스를 작성하고 컴파일하여 실행결과를 확인하시기 바랍니다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;5248&quot; data-end=&quot;5339&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-start=&quot;5396&quot; data-end=&quot;5422&quot; data-ke-size=&quot;size16&quot;&gt;파일 이름은 07_fuction.cpp입니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot;&gt;&lt;code&gt;#include &amp;lt;iostream&amp;gt;

double rpmToVelocity(double rpm, double wheel_radius) {
    const double PI = 3.141592;
    return (rpm / 60.0) * 2.0 * PI * wheel_radius;
}

int main() {
    double rpm = 1500.0;
    double wheel_radius = 0.05;

    double velocity = rpmToVelocity(rpm, wheel_radius);

    std::cout &amp;lt;&amp;lt; &quot;Velocity: &quot; &amp;lt;&amp;lt; velocity &amp;lt;&amp;lt; &quot; m/s&quot; &amp;lt;&amp;lt; std::endl;

    return 0;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;5219&quot; data-start=&quot;5212&quot; data-ke-size=&quot;size16&quot;&gt;컴파일합니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot;&gt;&lt;code&gt;g++ -std=c++17 07_function.cpp -o 07_function
./07_function&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;5369&quot; data-start=&quot;5294&quot; data-ke-size=&quot;size16&quot;&gt;이 예제는 단순한 문법 예제보다 좋습니다. 학생들이 로봇 개발에서 자주 만나는 속도 계산과 함수 개념을 같이 배울 수 있기 때문입니다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-start=&quot;5396&quot; data-end=&quot;5422&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1295&quot; data-origin-height=&quot;1028&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bmsfcG/dJMcacpIFpR/USUjtK1RMUC3ZQiR15vJ80/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bmsfcG/dJMcacpIFpR/USUjtK1RMUC3ZQiR15vJ80/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bmsfcG/dJMcacpIFpR/USUjtK1RMUC3ZQiR15vJ80/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbmsfcG%2FdJMcacpIFpR%2FUSUjtK1RMUC3ZQiR15vJ80%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1295&quot; height=&quot;1028&quot; data-origin-width=&quot;1295&quot; data-origin-height=&quot;1028&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-start=&quot;5396&quot; data-end=&quot;5422&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;6288&quot; data-start=&quot;6240&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;6288&quot; data-start=&quot;6240&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;6288&quot; data-start=&quot;6240&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-end=&quot;6312&quot; data-start=&quot;6295&quot; data-section-id=&quot;1q4e2ku&quot; data-ke-size=&quot;size20&quot;&gt;12. 값 전달과 참조 전달&lt;/h4&gt;
&lt;p data-end=&quot;6345&quot; data-start=&quot;6314&quot; data-ke-size=&quot;size16&quot;&gt;C++ 함수에서 인자를 전달하는 방식은 매우 중요합니다.&lt;/p&gt;
&lt;p data-end=&quot;6358&quot; data-start=&quot;6347&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;6358&quot; data-start=&quot;6347&quot; data-ke-size=&quot;size16&quot;&gt;먼저 값 전달입니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;reasonml&quot;&gt;&lt;code&gt;void changeValue(int x) {
    x = 100;
}

int a = 10;
changeValue(a);&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;6499&quot; data-start=&quot;6442&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;6499&quot; data-start=&quot;6442&quot; data-ke-size=&quot;size16&quot;&gt;이 경우 a의 값은 바뀌지 않습니다. 함수 안의 x는 a를 복사한 별도의 값이기 때문입니다.&lt;/p&gt;
&lt;p data-end=&quot;6499&quot; data-start=&quot;6442&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;6520&quot; data-start=&quot;6501&quot; data-ke-size=&quot;size16&quot;&gt;참조 전달은 원본을 직접 다룹니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;reasonml&quot;&gt;&lt;code&gt;void changeValue(int&amp;amp; x) {
    x = 100;
}

int a = 10;
changeValue(a);&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;6626&quot; data-start=&quot;6605&quot; data-ke-size=&quot;size16&quot;&gt;이 경우 a는 100으로 바뀝니다.&lt;/p&gt;
&lt;p data-end=&quot;6626&quot; data-start=&quot;6605&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;6658&quot; data-start=&quot;6628&quot; data-ke-size=&quot;size16&quot;&gt;읽기만 할 때는 const 참조를 많이 사용합니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;cpp&quot;&gt;&lt;code&gt;void printName(const std::string&amp;amp; name) {
    // name을 읽기만 함
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;6796&quot; data-start=&quot;6735&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;6796&quot; data-start=&quot;6735&quot; data-ke-size=&quot;size16&quot;&gt;const std::string&amp;amp;는 문자열을 복사하지 않고 참조하되, 함수 안에서 수정하지 못하게 합니다.&lt;/p&gt;
&lt;p data-end=&quot;6796&quot; data-start=&quot;6735&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;6935&quot; data-start=&quot;6798&quot; data-ke-size=&quot;size16&quot;&gt;ROS 2 C++ 코드에서도 const auto&amp;amp;, const std::shared_ptr&amp;lt;...&amp;gt;&amp;amp;, const 메시지타입::SharedPtr 같은 형태가 자주 등장합니다. 그래서 참조와 const 개념은 반드시 이해해야 합니다.&lt;/p&gt;
&lt;p data-end=&quot;6935&quot; data-start=&quot;6798&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;6935&quot; data-start=&quot;6798&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;6935&quot; data-start=&quot;6798&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;6935&quot; data-start=&quot;6798&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-end=&quot;6951&quot; data-start=&quot;6942&quot; data-section-id=&quot;tbdphr&quot; data-ke-size=&quot;size20&quot;&gt;13. 포인터&lt;/h4&gt;
&lt;p data-end=&quot;6977&quot; data-start=&quot;6953&quot; data-ke-size=&quot;size16&quot;&gt;포인터는 메모리 주소를 저장하는 변수입니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;cs&quot;&gt;&lt;code&gt;int value = 10;
int* ptr = &amp;amp;value;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;7078&quot; data-start=&quot;7026&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;7078&quot; data-start=&quot;7026&quot; data-ke-size=&quot;size16&quot;&gt;&amp;amp;value는 value 변수의 주소를 의미합니다. ptr은 그 주소를 저장합니다.&lt;/p&gt;
&lt;p data-end=&quot;7113&quot; data-start=&quot;7080&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;7113&quot; data-start=&quot;7080&quot; data-ke-size=&quot;size16&quot;&gt;포인터가 가리키는 실제 값에 접근하려면 *를 사용합니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;autoit&quot;&gt;&lt;code&gt;int data = *ptr;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;7214&quot; data-start=&quot;7144&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;7214&quot; data-start=&quot;7144&quot; data-ke-size=&quot;size16&quot;&gt;포인터는 강력하지만 위험합니다. 잘못된 주소를 가리키거나 이미 해제된 메모리를 접근하면 프로그램이 비정상 종료될 수 있습니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;int* ptr = nullptr;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;7328&quot; data-start=&quot;7248&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;7328&quot; data-start=&quot;7248&quot; data-ke-size=&quot;size16&quot;&gt;nullptr은 아무것도 가리키지 않는 포인터를 의미합니다. C++에서는 예전의 NULL보다 nullptr을 사용하는 것이 좋습니다.&lt;/p&gt;
&lt;p data-end=&quot;7369&quot; data-start=&quot;7330&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;7369&quot; data-start=&quot;7330&quot; data-ke-size=&quot;size16&quot;&gt;포인터를 사용할 때는 항상 유효한 주소인지 확인하는 습관이 필요합니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;autoit&quot;&gt;&lt;code&gt;if (ptr != nullptr) {
    int value = *ptr;
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;7513&quot; data-start=&quot;7429&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;7513&quot; data-start=&quot;7429&quot; data-ke-size=&quot;size16&quot;&gt;ROS 2에서는 일반 포인터보다 스마트 포인터를 훨씬 많이 사용합니다. 하지만 스마트 포인터를 이해하려면 먼저 일반 포인터 개념을 알고 있어야 합니다.&lt;/p&gt;
&lt;p data-end=&quot;7513&quot; data-start=&quot;7429&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-end=&quot;5339&quot; data-start=&quot;5248&quot; data-ke-size=&quot;size16&quot;&gt;아래의 예제 소스를 작성하고 컴파일하여 실행결과를 확인하시기 바랍니다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-end=&quot;5339&quot; data-start=&quot;5248&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-end=&quot;5422&quot; data-start=&quot;5396&quot; data-ke-size=&quot;size16&quot;&gt;파일 이름은 08_pointer.cpp입니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot;&gt;&lt;code&gt;#include &amp;lt;iostream&amp;gt;

int main() {
    int motor_rpm = 1500;

    int* ptr = &amp;amp;motor_rpm;

    std::cout &amp;lt;&amp;lt; &quot;motor_rpm value: &quot; &amp;lt;&amp;lt; motor_rpm &amp;lt;&amp;lt; std::endl;
    std::cout &amp;lt;&amp;lt; &quot;motor_rpm address: &quot; &amp;lt;&amp;lt; &amp;amp;motor_rpm &amp;lt;&amp;lt; std::endl;
    std::cout &amp;lt;&amp;lt; &quot;ptr value: &quot; &amp;lt;&amp;lt; ptr &amp;lt;&amp;lt; std::endl;
    std::cout &amp;lt;&amp;lt; &quot;ptr points to value: &quot; &amp;lt;&amp;lt; *ptr &amp;lt;&amp;lt; std::endl;

    return 0;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;995&quot; data-start=&quot;988&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;995&quot; data-start=&quot;988&quot; data-ke-size=&quot;size16&quot;&gt;컴파일합니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot;&gt;&lt;code&gt;g++ -std=c++17 08_pointer.cpp -o 08_pointer&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;1060&quot; data-start=&quot;1054&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;1060&quot; data-start=&quot;1054&quot; data-ke-size=&quot;size16&quot;&gt;실행합니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot;&gt;&lt;code&gt;./08_pointer&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;1109&quot; data-start=&quot;1088&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;1109&quot; data-start=&quot;1088&quot; data-ke-size=&quot;size16&quot;&gt;실행 결과는 다음과 비슷하게 나옵니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;yaml&quot;&gt;&lt;code&gt;motor_rpm value: 1500
motor_rpm address: 0x7ffc1a2b3c4d
ptr value: 0x7ffc1a2b3c4d
ptr points to value: 1500&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;1254&quot; data-start=&quot;1232&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;1254&quot; data-start=&quot;1232&quot; data-ke-size=&quot;size16&quot;&gt;주소값은 실행 환경마다 다르게 나옵니다.&lt;/p&gt;
&lt;p data-end=&quot;1254&quot; data-start=&quot;1232&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1295&quot; data-origin-height=&quot;1028&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ctzzEC/dJMcadPCa8I/vIFAZ2dwRYUa0swyUiAeiK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ctzzEC/dJMcadPCa8I/vIFAZ2dwRYUa0swyUiAeiK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ctzzEC/dJMcadPCa8I/vIFAZ2dwRYUa0swyUiAeiK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FctzzEC%2FdJMcadPCa8I%2FvIFAZ2dwRYUa0swyUiAeiK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1295&quot; height=&quot;1028&quot; data-origin-width=&quot;1295&quot; data-origin-height=&quot;1028&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-end=&quot;5422&quot; data-start=&quot;5396&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-end=&quot;5422&quot; data-start=&quot;5396&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;7513&quot; data-start=&quot;7429&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;7513&quot; data-start=&quot;7429&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-end=&quot;7529&quot; data-start=&quot;7520&quot; data-section-id=&quot;sg0y1u&quot; data-ke-size=&quot;size20&quot;&gt;14. 구조체&lt;/h4&gt;
&lt;p data-end=&quot;7558&quot; data-start=&quot;7531&quot; data-ke-size=&quot;size16&quot;&gt;구조체는 여러 데이터를 하나로 묶는 자료형입니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;thrift&quot;&gt;&lt;code&gt;struct MotorState {
    double rpm;
    double current;
    double temperature;
};&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;7673&quot; data-start=&quot;7655&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;7673&quot; data-start=&quot;7655&quot; data-ke-size=&quot;size16&quot;&gt;사용할 때는 다음처럼 작성합니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;abnf&quot;&gt;&lt;code&gt;MotorState motor;

motor.rpm = 1500.0;
motor.current = 2.5;
motor.temperature = 45.0;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;7799&quot; data-start=&quot;7773&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;7799&quot; data-start=&quot;7773&quot; data-ke-size=&quot;size16&quot;&gt;구조체는 관련 있는 데이터를 묶을 때 좋습니다.&lt;/p&gt;
&lt;p data-end=&quot;7830&quot; data-start=&quot;7801&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;7830&quot; data-start=&quot;7801&quot; data-ke-size=&quot;size16&quot;&gt;예를 들어 로봇 위치를 다음처럼 표현할 수 있습니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;thrift&quot;&gt;&lt;code&gt;struct Position {
    double x;
    double y;
    double theta;
};&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;7934&quot; data-start=&quot;7911&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;7934&quot; data-start=&quot;7911&quot; data-ke-size=&quot;size16&quot;&gt;그리고 함수의 인자로 사용할 수 있습니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;cpp&quot;&gt;&lt;code&gt;void printPosition(const Position&amp;amp; pos) {
    // pos.x, pos.y, pos.theta 사용
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;8140&quot; data-start=&quot;8026&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;8140&quot; data-start=&quot;8026&quot; data-ke-size=&quot;size16&quot;&gt;C에서는 구조체가 단순히 데이터 묶음에 가깝지만, C++에서는 구조체 안에 함수도 넣을 수 있습니다. C++의 struct와 class는 기본 접근 제한자가 다르다는 점을 제외하면 매우 비슷합니다.&lt;/p&gt;
&lt;p data-end=&quot;8140&quot; data-start=&quot;8026&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;5248&quot; data-end=&quot;5339&quot;&gt;아래의 예제 소스를 작성하고 컴파일하여 실행결과를 확인하시기 바랍니다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;5248&quot; data-end=&quot;5339&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-start=&quot;5396&quot; data-end=&quot;5422&quot; data-ke-size=&quot;size16&quot;&gt;파일 이름은 09_struct.cpp입니다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-start=&quot;5396&quot; data-end=&quot;5422&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;5559&quot; data-start=&quot;5526&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot;&gt;&lt;code&gt;#include &amp;lt;iostream&amp;gt;

struct MotorState {
    double rpm;
    double current;
    double temperature;
};

int main() {
    MotorState motor;

    motor.rpm = 1500.0;
    motor.current = 2.5;
    motor.temperature = 42.0;

    std::cout &amp;lt;&amp;lt; &quot;Motor RPM: &quot; &amp;lt;&amp;lt; motor.rpm &amp;lt;&amp;lt; std::endl;
    std::cout &amp;lt;&amp;lt; &quot;Motor current: &quot; &amp;lt;&amp;lt; motor.current &amp;lt;&amp;lt; std::endl;
    std::cout &amp;lt;&amp;lt; &quot;Motor temperature: &quot; &amp;lt;&amp;lt; motor.temperature &amp;lt;&amp;lt; std::endl;

    return 0;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;6016&quot; data-start=&quot;6009&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;6016&quot; data-start=&quot;6009&quot; data-ke-size=&quot;size16&quot;&gt;컴파일합니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot;&gt;&lt;code&gt;g++ -std=c++17 09_struct.cpp -o 09_struct&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;6079&quot; data-start=&quot;6073&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;6079&quot; data-start=&quot;6073&quot; data-ke-size=&quot;size16&quot;&gt;실행합니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot;&gt;&lt;code&gt;./09_struct&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;6122&quot; data-start=&quot;6106&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;6122&quot; data-start=&quot;6106&quot; data-ke-size=&quot;size16&quot;&gt;실행 결과는 다음과 같습니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;yaml&quot;&gt;&lt;code&gt;Motor RPM: 1500
Motor current: 2.5
Motor temperature: 42&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1295&quot; data-origin-height=&quot;1028&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/caXUFN/dJMcadB2LuN/Z8GnrcLgMuMg4Pf05A88z1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/caXUFN/dJMcadB2LuN/Z8GnrcLgMuMg4Pf05A88z1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/caXUFN/dJMcadB2LuN/Z8GnrcLgMuMg4Pf05A88z1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcaXUFN%2FdJMcadB2LuN%2FZ8GnrcLgMuMg4Pf05A88z1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1295&quot; height=&quot;1028&quot; data-origin-width=&quot;1295&quot; data-origin-height=&quot;1028&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;</description>
      <category>강좌/ROS2</category>
      <category>c/c++ 기초 1</category>
      <author>MakingRobotWizard</author>
      <guid isPermaLink="true">https://makingrobot.tistory.com/433</guid>
      <comments>https://makingrobot.tistory.com/433#entry433comment</comments>
      <pubDate>Mon, 25 May 2026 15:56:30 +0900</pubDate>
    </item>
    <item>
      <title>로봇 개발자를 위한 Python 기초 교육 #3</title>
      <link>https://makingrobot.tistory.com/430</link>
      <description>&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size18&quot; data-section-id=&quot;1krzytq&quot; data-start=&quot;11570&quot; data-end=&quot;11584&quot;&gt;&lt;br /&gt;21. JSON 다루기&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;11586&quot; data-end=&quot;11628&quot;&gt;로봇 설정이나 웨이포인트 파일은 JSON 형식으로 저장하는 경우가 많습니다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;11630&quot; data-end=&quot;11662&quot;&gt;예를 들어 다음과 같은 JSON 파일이 있다고 가정합니다.&lt;/p&gt;
&lt;div style=&quot;color: #333333; text-align: start;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;cpp&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot; data-ke-language=&quot;cpp&quot;&gt;&lt;code&gt;{
    &quot;robot_name&quot;: &quot;delivery_robot&quot;,
    &quot;max_speed&quot;: 1.2,
    &quot;waypoints&quot;: [
        [0.0, 0.0],
        [1.0, 0.0],
        [1.0, 1.0]
    ]
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;11823&quot; data-end=&quot;11860&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;11823&quot; data-end=&quot;11860&quot;&gt;Python에서 JSON을 읽으려면 json 모듈을 사용합니다.&lt;/p&gt;
&lt;div style=&quot;color: #333333; text-align: start;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;cpp&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot; data-ke-language=&quot;cpp&quot;&gt;&lt;code&gt;import json

with open(&quot;config.json&quot;, &quot;r&quot;) as file:
    config = json.load(file)

print(config[&quot;robot_name&quot;])
print(config[&quot;max_speed&quot;])
print(config[&quot;waypoints&quot;])&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;12041&quot; data-end=&quot;12075&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;12041&quot; data-end=&quot;12075&quot;&gt;Python 딕셔너리를 JSON 파일로 저장할 수도 있습니다.&lt;/p&gt;
&lt;div style=&quot;color: #333333; text-align: start;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;cpp&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot; data-ke-language=&quot;cpp&quot;&gt;&lt;code&gt;import json

config = {
    &quot;robot_name&quot;: &quot;delivery_robot&quot;,
    &quot;max_speed&quot;: 1.2,
    &quot;waypoints&quot;: [
        [0.0, 0.0],
        [1.0, 0.0],
        [1.0, 1.0]
    ]
}

with open(&quot;config.json&quot;, &quot;w&quot;) as file:
    json.dump(config, file, indent=4)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;12338&quot; data-end=&quot;12375&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;12338&quot; data-end=&quot;12375&quot;&gt;한글이 들어간 JSON을 저장할 때는 다음처럼 쓰는 것이 좋습니다.&lt;/p&gt;
&lt;div style=&quot;color: #333333; text-align: start;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;cpp&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot; data-ke-language=&quot;cpp&quot;&gt;&lt;code&gt;with open(&quot;config.json&quot;, &quot;w&quot;, encoding=&quot;utf-8&quot;) as file:
    json.dump(config, file, indent=4, ensure_ascii=False)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;235&quot; data-start=&quot;185&quot; data-section-id=&quot;32b4zs&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;a. open(&quot;config.json&quot;, &quot;w&quot;, encoding=&quot;utf-8&quot;)&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;stylus&quot;&gt;&lt;code&gt;open(&quot;config.json&quot;, &quot;w&quot;, encoding=&quot;utf-8&quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;317&quot; data-start=&quot;295&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;317&quot; data-start=&quot;295&quot; data-ke-size=&quot;size16&quot;&gt;config.json 파일을 엽니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;405&quot; data-start=&quot;319&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;347&quot; data-start=&quot;319&quot; data-section-id=&quot;a5jhhn&quot;&gt;&quot;config.json&quot;: 저장할 파일 이름&lt;/li&gt;
&lt;li data-end=&quot;362&quot; data-start=&quot;348&quot; data-section-id=&quot;18v5nox&quot;&gt;&quot;w&quot;: 쓰기 모드&lt;/li&gt;
&lt;li data-end=&quot;405&quot; data-start=&quot;363&quot; data-section-id=&quot;1hb5lq2&quot;&gt;encoding=&quot;utf-8&quot;: 한글이 깨지지 않도록 UTF-8 사용&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-end=&quot;450&quot; data-start=&quot;407&quot; data-ke-size=&quot;size16&quot;&gt;주의할 점은 &quot;w&quot; 모드는 기존 파일이 있으면 내용을 지우고 새로 씁니다.&lt;/p&gt;
&lt;p data-end=&quot;450&quot; data-start=&quot;407&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1779977068901&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;config['hangul_test']=&quot;한글입력&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-end=&quot;481&quot; data-start=&quot;457&quot; data-section-id=&quot;xobndt&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;481&quot; data-start=&quot;457&quot; data-section-id=&quot;xobndt&quot; data-ke-size=&quot;size16&quot;&gt;입력하고 아래의 명령어로 파일을 저장합니다.&lt;/p&gt;
&lt;p data-end=&quot;481&quot; data-start=&quot;457&quot; data-section-id=&quot;xobndt&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1779977133356&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;with open(&quot;config_han.json&quot;, &quot;w&quot;, encoding=&quot;utf-8&quot;) as file:
    json.dump(config, file, indent=4)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-end=&quot;481&quot; data-start=&quot;457&quot; data-section-id=&quot;xobndt&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;481&quot; data-start=&quot;457&quot; data-section-id=&quot;xobndt&quot; data-ke-size=&quot;size16&quot;&gt;config_han.json 파일을 노트북에서 열어 보면 한글이 저장됨을 확인할 수 있습니다. jupyter_ws폴더로 이동하여 gedit로 config_han.json을 열어보면 한글 부분에 unicode 문자가 저장되어 있습니다.&lt;/p&gt;
&lt;p data-end=&quot;481&quot; data-start=&quot;457&quot; data-section-id=&quot;xobndt&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;481&quot; data-start=&quot;457&quot; data-section-id=&quot;xobndt&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;481&quot; data-start=&quot;457&quot; data-section-id=&quot;xobndt&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;481&quot; data-start=&quot;457&quot; data-section-id=&quot;xobndt&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;b. with ... as file&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;livecodeserver&quot;&gt;&lt;code&gt;with open(...) as file:&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;548&quot; data-start=&quot;522&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;548&quot; data-start=&quot;522&quot; data-ke-size=&quot;size16&quot;&gt;파일을 열고 작업이 끝나면 자동으로 닫아줍니다.&lt;/p&gt;
&lt;p data-end=&quot;578&quot; data-start=&quot;550&quot; data-ke-size=&quot;size16&quot;&gt;원래는 파일을 열면 마지막에 이렇게 닫아야 합니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;livecodeserver&quot;&gt;&lt;code&gt;file.close()&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;644&quot; data-start=&quot;608&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;644&quot; data-start=&quot;608&quot; data-ke-size=&quot;size16&quot;&gt;하지만 with를 쓰면 자동으로 닫히기 때문에 더 안전합니다.&lt;/p&gt;
&lt;p data-end=&quot;644&quot; data-start=&quot;608&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;644&quot; data-start=&quot;608&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;687&quot; data-start=&quot;651&quot; data-section-id=&quot;1gehoe9&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;687&quot; data-start=&quot;651&quot; data-section-id=&quot;1gehoe9&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;c. json.dump(config, file, ...)&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot;&gt;&lt;code&gt;json.dump(config, file, indent=4, ensure_ascii=False)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;796&quot; data-start=&quot;758&quot; data-ke-size=&quot;size16&quot;&gt;config 데이터를 JSON 형식으로 바꿔서 파일에 저장합니다.&lt;/p&gt;
&lt;p data-end=&quot;804&quot; data-start=&quot;798&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;804&quot; data-start=&quot;798&quot; data-ke-size=&quot;size16&quot;&gt;예를 들어:&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;makefile&quot;&gt;&lt;code&gt;config = {
    &quot;name&quot;: &quot;드론&quot;,
    &quot;speed&quot;: 10
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;900&quot; data-start=&quot;868&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;900&quot; data-start=&quot;868&quot; data-ke-size=&quot;size16&quot;&gt;이라면 config.json 파일에 이렇게 저장됩니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;json&quot;&gt;&lt;code&gt;{
    &quot;name&quot;: &quot;드론&quot;,
    &quot;speed&quot;: 10
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;974&quot; data-start=&quot;958&quot; data-section-id=&quot;1n8pk96&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;974&quot; data-start=&quot;958&quot; data-section-id=&quot;1n8pk96&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;d. indent=4&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;ini&quot;&gt;&lt;code&gt;indent=4&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;1023&quot; data-start=&quot;1000&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;1023&quot; data-start=&quot;1000&quot; data-ke-size=&quot;size16&quot;&gt;JSON 파일을 보기 좋게 들여쓰기합니다.&amp;nbsp;없으면 한 줄로 저장될 수 있습니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;json&quot;&gt;&lt;code&gt;{&quot;name&quot;:&quot;드론&quot;,&quot;speed&quot;:10}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;1112&quot; data-start=&quot;1085&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;1112&quot; data-start=&quot;1085&quot; data-ke-size=&quot;size16&quot;&gt;indent=4를 쓰면 보기 좋게 저장됩니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;json&quot;&gt;&lt;code&gt;{
    &quot;name&quot;: &quot;드론&quot;,
    &quot;speed&quot;: 10
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;1196&quot; data-start=&quot;1170&quot; data-section-id=&quot;1xd9zca&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;e. ensure_ascii=False&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;ini&quot;&gt;&lt;code&gt;ensure_ascii=False&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;1249&quot; data-start=&quot;1232&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;1249&quot; data-start=&quot;1232&quot; data-ke-size=&quot;size16&quot;&gt;한글을 그대로 저장하게 합니다.&lt;/p&gt;
&lt;p data-end=&quot;1283&quot; data-start=&quot;1251&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;1283&quot; data-start=&quot;1251&quot; data-ke-size=&quot;size16&quot;&gt;이 옵션이 없으면 한글이 이런 식으로 저장될 수 있습니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;taggerscript&quot;&gt;&lt;code&gt;&quot;\ub4dc\ub860&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;1348&quot; data-start=&quot;1313&quot; data-ke-size=&quot;size16&quot;&gt;ensure_ascii=False를 쓰면 이렇게 저장됩니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;1c&quot;&gt;&lt;code&gt;&quot;드론&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-section-id=&quot;1vv30jl&quot; data-start=&quot;12512&quot; data-end=&quot;12524&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span&gt;22. None&lt;/span&gt;&lt;/h4&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;12526&quot; data-end=&quot;12546&quot;&gt;None은 값이 없다는 뜻입니다.&lt;/p&gt;
&lt;div style=&quot;color: #333333; text-align: start;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;fortran&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot;&gt;&lt;code&gt;target = None&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;12577&quot; data-end=&quot;12619&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;12577&quot; data-end=&quot;12619&quot;&gt;아직 목표 지점이 없거나, 센서 값이 유효하지 않을 때 사용할 수 있습니다.&lt;/p&gt;
&lt;div style=&quot;color: #333333; text-align: start;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;python&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot;&gt;&lt;code&gt;target_position = None

if target_position is None:
    print(&quot;No target position&quot;)
else:
    print(&quot;Move to target&quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;12754&quot; data-end=&quot;12791&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;12754&quot; data-end=&quot;12791&quot;&gt;None을 비교할 때는 보통 ==보다 is를 사용합니다.&lt;/p&gt;
&lt;div style=&quot;color: #333333; text-align: start;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;python&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot;&gt;&lt;code&gt;if target_position is None:
    print(&quot;target is none&quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;12864&quot; data-end=&quot;12891&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;12864&quot; data-end=&quot;12891&quot;&gt;함수에서 실패를 표시할 때도 사용할 수 있습니다.&lt;/p&gt;
&lt;div style=&quot;color: #333333; text-align: start;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;cpp&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot; data-ke-language=&quot;cpp&quot;&gt;&lt;code&gt;def find_nearest_obstacle(ranges):
    valid_ranges = [r for r in ranges if r &amp;gt; 0]

    if len(valid_ranges) == 0:
        return None

    return min(valid_ranges)

nearest = find_nearest_obstacle([-1, -1, -1])

if nearest is None:
    print(&quot;No valid obstacle data&quot;)
else:
    print(f&quot;nearest obstacle: {nearest}&quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-section-id=&quot;kvcej5&quot; data-start=&quot;13230&quot; data-end=&quot;13249&quot; data-ke-size=&quot;size20&quot;&gt;23. Boolean 판단 규칙&lt;/h4&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;13251&quot; data-end=&quot;13288&quot;&gt;Python에서는 값 자체가 참 또는 거짓처럼 평가될 수 있습니다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;13290&quot; data-end=&quot;13308&quot;&gt;다음 값들은 거짓으로 판단됩니다.&lt;/p&gt;
&lt;div style=&quot;color: #333333; text-align: start;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;hy&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot;&gt;&lt;code&gt;False
None
0
0.0
&quot;&quot;
[]
{}
()&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;13354&quot; data-end=&quot;13383&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;13354&quot; data-end=&quot;13383&quot;&gt;예를 들어 빈 리스트는 False처럼 동작합니다.&lt;/p&gt;
&lt;div style=&quot;color: #333333; text-align: start;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;isbl&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot;&gt;&lt;code&gt;waypoints = []

if not waypoints:
    print(&quot;No waypoints&quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;13460&quot; data-end=&quot;13482&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;13460&quot; data-end=&quot;13482&quot;&gt;값이 있으면 True처럼 동작합니다.&lt;/p&gt;
&lt;div style=&quot;color: #333333; text-align: start;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;lua&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot;&gt;&lt;code&gt;waypoints = [[0.0, 0.0], [1.0, 0.0]]

if waypoints:
    print(&quot;Waypoint list exists&quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;13585&quot; data-end=&quot;13618&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;13585&quot; data-end=&quot;13618&quot;&gt;로봇 경로, 센서 데이터, 설정값 검사에서 자주 사용됩니다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;13585&quot; data-end=&quot;13618&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;13585&quot; data-end=&quot;13618&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;13585&quot; data-end=&quot;13618&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;13585&quot; data-end=&quot;13618&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-section-id=&quot;pnsxjy&quot; data-start=&quot;13625&quot; data-end=&quot;13639&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span&gt;24. in 연산자&lt;/span&gt;&lt;/h4&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;13641&quot; data-end=&quot;13674&quot;&gt;in은 어떤 값이 포함되어 있는지 확인할 때 사용합니다.&lt;/p&gt;
&lt;div style=&quot;color: #333333; text-align: start;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;vim&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot;&gt;&lt;code&gt;modes = [&quot;manual&quot;, &quot;auto&quot;, &quot;emergency&quot;]

if &quot;auto&quot; in modes:
    print(&quot;auto mode supported&quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;13785&quot; data-end=&quot;13814&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;13785&quot; data-end=&quot;13814&quot;&gt;딕셔너리에서는 key가 있는지 확인할 때 사용합니다.&lt;/p&gt;
&lt;div style=&quot;color: #333333; text-align: start;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;arduino&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot;&gt;&lt;code&gt;config = {
    &quot;max_speed&quot;: 1.0,
    &quot;wheel_radius&quot;: 0.05
}

if &quot;max_speed&quot; in config:
    print(config[&quot;max_speed&quot;])&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;13949&quot; data-end=&quot;13967&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;13949&quot; data-end=&quot;13967&quot;&gt;문자열에서도 사용할 수 있습니다.&lt;/p&gt;
&lt;div style=&quot;color: #333333; text-align: start;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;sas&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot;&gt;&lt;code&gt;message = &quot;robot emergency stop&quot;

if &quot;emergency&quot; in message:
    print(&quot;Emergency message detected&quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-section-id=&quot;11cjn8a&quot; data-start=&quot;14090&quot; data-end=&quot;14121&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span&gt;25. min(), max(), sum()&lt;/span&gt;&lt;/h4&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;14123&quot; data-end=&quot;14145&quot;&gt;센서 데이터 처리에 매우 자주 쓰입니다.&lt;/p&gt;
&lt;div style=&quot;color: #333333; text-align: start;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;gauss&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot;&gt;&lt;code&gt;ranges = [1.2, 0.8, 2.0, 0.5]

print(min(ranges))  # 0.5
print(max(ranges))  # 2.0
print(sum(ranges))  # 4.5&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;14271&quot; data-end=&quot;14278&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;14271&quot; data-end=&quot;14278&quot;&gt;평균값 계산:&lt;/p&gt;
&lt;div style=&quot;color: #333333; text-align: start;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;lisp&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot;&gt;&lt;code&gt;average = sum(ranges) / len(ranges)

print(average)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;14347&quot; data-end=&quot;14373&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;14347&quot; data-end=&quot;14373&quot;&gt;라이다 거리 중 가장 가까운 장애물을 찾을 때:&lt;/p&gt;
&lt;div style=&quot;color: #333333; text-align: start;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;lsl&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot;&gt;&lt;code&gt;lidar_ranges = [2.0, 1.5, 0.9, 0.7, 1.2]

nearest_obstacle = min(lidar_ranges)

print(f&quot;nearest obstacle: {nearest_obstacle} m&quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;14519&quot; data-end=&quot;14551&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;14519&quot; data-end=&quot;14551&quot;&gt;단, 빈 리스트에 min()을 사용하면 에러가 납니다.&lt;/p&gt;
&lt;div style=&quot;color: #333333; text-align: start;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;isbl&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot;&gt;&lt;code&gt;ranges = []

if ranges:
    nearest = min(ranges)
    print(nearest)
else:
    print(&quot;No range data&quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-section-id=&quot;nv69me&quot; data-start=&quot;14675&quot; data-end=&quot;14683&quot; data-ke-size=&quot;size20&quot;&gt;26. 정렬&lt;/h4&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;14685&quot; data-end=&quot;14727&quot;&gt;리스트를 정렬할 때는 sort() 또는 sorted()를 사용합니다.&lt;/p&gt;
&lt;div style=&quot;color: #333333; text-align: start;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;haskell&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot;&gt;&lt;code&gt;data = [3, 1, 4, 2]

data.sort()

print(data)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;14790&quot; data-end=&quot;14793&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;14790&quot; data-end=&quot;14793&quot;&gt;출력:&lt;/p&gt;
&lt;div style=&quot;color: #333333; text-align: start;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;json&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot;&gt;&lt;code&gt;[1, 2, 3, 4]&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;14821&quot; data-end=&quot;14848&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;14821&quot; data-end=&quot;14848&quot;&gt;sort()는 원본 리스트를 직접 변경합니다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;14850&quot; data-end=&quot;14882&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;14850&quot; data-end=&quot;14882&quot;&gt;반면 sorted()는 정렬된 새 리스트를 반환합니다.&lt;/p&gt;
&lt;div style=&quot;color: #333333; text-align: start;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;cpp&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot; data-ke-language=&quot;cpp&quot;&gt;&lt;code&gt;data = [3, 1, 4, 2]

sorted_data = sorted(data)

print(data)
print(sorted_data)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;14979&quot; data-end=&quot;15000&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;14979&quot; data-end=&quot;15000&quot;&gt;딕셔너리 리스트도 정렬할 수 있습니다.&lt;/p&gt;
&lt;div style=&quot;color: #333333; text-align: start;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;cpp&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot; data-ke-language=&quot;cpp&quot;&gt;&lt;code&gt;robots = [
    {&quot;name&quot;: &quot;robot_a&quot;, &quot;battery&quot;: 80},
    {&quot;name&quot;: &quot;robot_b&quot;, &quot;battery&quot;: 50},
    {&quot;name&quot;: &quot;robot_c&quot;, &quot;battery&quot;: 95}
]

robots_sorted = sorted(robots, key=lambda robot: robot[&quot;battery&quot;])

print(robots_sorted)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;15239&quot; data-end=&quot;15279&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;389&quot; data-start=&quot;253&quot; data-ke-size=&quot;size16&quot;&gt;sorted() 함수는 robots 리스트를 정렬합니다. 이때 key 옵션에 lambda robot: robot[&quot;battery&quot;]를 넣었기 때문에, 각 로봇 딕셔너리의 &quot;battery&quot; 값을 기준으로 정렬합니다.&lt;/p&gt;
&lt;p data-end=&quot;472&quot; data-start=&quot;391&quot; data-ke-size=&quot;size16&quot;&gt;배터리 값은 robot_b가 50, robot_a가 80, robot_c가 95이므로 작은 값부터 정렬하면 다음과 같은 순서가 됩니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;json&quot;&gt;&lt;code&gt;[
    {&quot;name&quot;: &quot;robot_b&quot;, &quot;battery&quot;: 50},
    {&quot;name&quot;: &quot;robot_a&quot;, &quot;battery&quot;: 80},
    {&quot;name&quot;: &quot;robot_c&quot;, &quot;battery&quot;: 95}
]&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-is-only-node=&quot;&quot; data-is-last-node=&quot;&quot; data-end=&quot;720&quot; data-start=&quot;612&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-is-only-node=&quot;&quot; data-is-last-node=&quot;&quot; data-end=&quot;720&quot; data-start=&quot;612&quot; data-ke-size=&quot;size16&quot;&gt;마지막으로 print(robots_sorted)는 정렬된 결과를 화면에 출력합니다. 원본 robots 리스트는 그대로 두고, 정렬된 새 리스트가 robots_sorted에 저장됩니다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;15239&quot; data-end=&quot;15279&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;15239&quot; data-end=&quot;15279&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;15239&quot; data-end=&quot;15279&quot;&gt;배터리가 높은 순서로 정렬(내림차순)하려면 reverse=True를 사용합니다.&lt;/p&gt;
&lt;div style=&quot;color: #333333; text-align: start;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;routeros&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot;&gt;&lt;code&gt;robots_sorted = sorted(
    robots,
    key=lambda robot: robot[&quot;battery&quot;],
    reverse=True
)

print(robots_sorted)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-section-id=&quot;1pd76tw&quot; data-start=&quot;15418&quot; data-end=&quot;15429&quot; data-ke-size=&quot;size20&quot;&gt;27. 람다 함수&lt;/h4&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;15431&quot; data-end=&quot;15456&quot;&gt;lambda는 이름 없는 짧은 함수입니다.&lt;/p&gt;
&lt;div style=&quot;color: #333333; text-align: start;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;angelscript&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot;&gt;&lt;code&gt;double = lambda x: x * 2

print(double(3))&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;15516&quot; data-end=&quot;15603&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;15516&quot; data-end=&quot;15603&quot;&gt;하지만 로봇 개발 초보 단계에서는 lambda를 남발하지 않는 것이 좋습니다. 주로 sorted()의 key처럼 간단한 기준을 줄 때 사용합니다.&lt;/p&gt;
&lt;div style=&quot;color: #333333; text-align: start;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;cpp&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot; data-ke-language=&quot;cpp&quot;&gt;&lt;code&gt;points = [
    {&quot;x&quot;: 1.0, &quot;y&quot;: 2.0},
    {&quot;x&quot;: 0.5, &quot;y&quot;: 1.5},
    {&quot;x&quot;: 2.0, &quot;y&quot;: 0.5}
]

points_sorted = sorted(points, key=lambda p: p[&quot;x&quot;])

print(points_sorted)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-section-id=&quot;iil79r&quot; data-start=&quot;15791&quot; data-end=&quot;15804&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span&gt;28. zip()&lt;/span&gt;&lt;/h4&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;15806&quot; data-end=&quot;15843&quot;&gt;zip()은 여러 리스트를 동시에 묶어서 반복할 때 사용합니다.&lt;/p&gt;
&lt;div style=&quot;color: #333333; text-align: start;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;angelscript&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot;&gt;&lt;code&gt;left_speeds = [1.0, 1.1, 1.2]
right_speeds = [1.0, 1.0, 1.1]

for left, right in zip(left_speeds, right_speeds):
    print(f&quot;left={left}, right={right}&quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;16014&quot; data-end=&quot;16017&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;16014&quot; data-end=&quot;16017&quot;&gt;출력:&lt;/p&gt;
&lt;div style=&quot;color: #333333; text-align: start;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;routeros&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot;&gt;&lt;code&gt;left=1.0, right=1.0
left=1.1, right=1.0
left=1.2, right=1.1&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;16092&quot; data-end=&quot;16115&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;16092&quot; data-end=&quot;16115&quot;&gt;시간과 센서 데이터를 묶을 수도 있습니다.&lt;/p&gt;
&lt;div style=&quot;color: #333333; text-align: start;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;cpp&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot; data-ke-language=&quot;cpp&quot;&gt;&lt;code&gt;times = [0.0, 0.1, 0.2]
distances = [1.5, 1.4, 1.3]

for t, d in zip(times, distances):
    print(f&quot;time={t}, distance={d}&quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-section-id=&quot;5tftjr&quot; data-start=&quot;16262&quot; data-end=&quot;16281&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span&gt;29. enumerate()&lt;/span&gt;&lt;/h4&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;16283&quot; data-end=&quot;16323&quot;&gt;enumerate()는 반복하면서 인덱스도 같이 얻을 때 사용합니다.&lt;/p&gt;
&lt;div style=&quot;color: #333333; text-align: start;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;cpp&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot; data-ke-language=&quot;cpp&quot;&gt;&lt;code&gt;waypoints = [
    [0.0, 0.0],
    [1.0, 0.0],
    [1.0, 1.0]
]

for index, point in enumerate(waypoints):
    print(f&quot;{index}: {point}&quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;출력:&lt;/div&gt;
&lt;div&gt;
&lt;pre id=&quot;code_1779977959408&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;0: [0.0, 0.0]
1: [1.0, 0.0]
2: [1.0, 1.0]&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;16477&quot; data-end=&quot;16499&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;16477&quot; data-end=&quot;16499&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;16477&quot; data-end=&quot;16499&quot;&gt;시작 인덱스를 1로 바꿀 수도 있습니다.&lt;/p&gt;
&lt;div style=&quot;color: #333333; text-align: start;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;routeros&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot;&gt;&lt;code&gt;for index, point in enumerate(waypoints, start=1):
    print(f&quot;waypoint {index}: {point}&quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;16607&quot; data-end=&quot;16610&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;16607&quot; data-end=&quot;16610&quot;&gt;출력:&lt;/p&gt;
&lt;div style=&quot;color: #333333; text-align: start;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;angelscript&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot;&gt;&lt;code&gt;waypoint 1: [0.0, 0.0]
waypoint 2: [1.0, 0.0]
waypoint 3: [1.0, 1.0]&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-section-id=&quot;dg704q&quot; data-start=&quot;16699&quot; data-end=&quot;16708&quot; data-ke-size=&quot;size20&quot;&gt;30. 언패킹&lt;/h4&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;16710&quot; data-end=&quot;16744&quot;&gt;리스트나 튜플의 값을 여러 변수에 한 번에 넣을 수 있습니다.&lt;/p&gt;
&lt;div style=&quot;color: #333333; text-align: start;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;stylus&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot;&gt;&lt;code&gt;position = [1.0, 2.0, 0.5]

x, y, yaw = position

print(x)
print(y)
print(yaw)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;16840&quot; data-end=&quot;16859&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;16840&quot; data-end=&quot;16859&quot;&gt;웨이포인트를 처리할 때도 좋습니다.&lt;/p&gt;
&lt;div style=&quot;color: #333333; text-align: start;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;python&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot;&gt;&lt;code&gt;waypoint = [3.0, 4.0]

x, y = waypoint

print(f&quot;x={x}, y={y}&quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;16939&quot; data-end=&quot;16958&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;16939&quot; data-end=&quot;16958&quot;&gt;함수 반환값에서도 자주 사용합니다.&lt;/p&gt;
&lt;div style=&quot;color: #333333; text-align: start;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;python&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot;&gt;&lt;code&gt;def get_velocity():
    linear_x = 0.5
    angular_z = 0.1
    return linear_x, angular_z

linear_x, angular_z = get_velocity()

print(linear_x)
print(angular_z)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-section-id=&quot;1vu6ua6&quot; data-start=&quot;17142&quot; data-end=&quot;17161&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span&gt;31. 가변 인자 *args&lt;/span&gt;&lt;/h4&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;17163&quot; data-end=&quot;17207&quot;&gt;함수에 여러 개의 값을 유동적으로 전달하고 싶을 때 *args를 사용합니다. 개수는 정해지지 않아도 됩니다.&lt;/p&gt;
&lt;div style=&quot;color: #333333; text-align: start;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;cpp&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot; data-ke-language=&quot;cpp&quot;&gt;&lt;code&gt;def print_values(*args):
    for value in args:
        print(value)

print_values(1, 2, 3)
print_values(&quot;x&quot;, &quot;y&quot;, &quot;z&quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;17344&quot; data-end=&quot;17373&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;17344&quot; data-end=&quot;17373&quot;&gt;센서 값을 여러 개 받아 평균을 구할 수도 있습니다.&lt;/p&gt;
&lt;div style=&quot;color: #333333; text-align: start;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;cpp&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot; data-ke-language=&quot;cpp&quot;&gt;&lt;code&gt;def average(*values):
    if not values:
        return 0.0

    return sum(values) / len(values)

print(average(1.0, 2.0, 3.0))&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-section-id=&quot;hu5sh9&quot; data-start=&quot;17524&quot; data-end=&quot;17550&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span&gt;32. 키워드 가변 인자 **kwargs&lt;/span&gt;&lt;/h4&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;17552&quot; data-end=&quot;17592&quot;&gt;**kwargs는 이름이 있는 여러 인자를 딕셔너리 형태로 받습니다.&lt;/p&gt;
&lt;div style=&quot;color: #333333; text-align: start;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;routeros&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot;&gt;&lt;code&gt;def print_config(**kwargs):
    for key, value in kwargs.items():
        print(f&quot;{key}: {value}&quot;)

print_config(max_speed=1.0, wheel_radius=0.05, use_lidar=True)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;17772&quot; data-end=&quot;17775&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;17772&quot; data-end=&quot;17775&quot;&gt;출력:&lt;/p&gt;
&lt;div style=&quot;color: #333333; text-align: start;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;yaml&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot;&gt;&lt;code&gt;max_speed: 1.0
wheel_radius: 0.05
use_lidar: True&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;17840&quot; data-end=&quot;17869&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;17840&quot; data-end=&quot;17869&quot;&gt;설정값을 유연하게 받는 함수에서 사용할 수 있습니다.&lt;/p&gt;
&lt;div style=&quot;color: #333333; text-align: start;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;cpp&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot; data-ke-language=&quot;cpp&quot;&gt;&lt;code&gt;def create_robot_config(**kwargs):
    config = {
        &quot;max_speed&quot;: 1.0,
        &quot;wheel_radius&quot;: 0.05,
        &quot;use_lidar&quot;: False
    }

    config.update(kwargs)
    return config

config = create_robot_config(max_speed=1.5, use_lidar=True)

print(config)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-section-id=&quot;1d67b5i&quot; data-start=&quot;18151&quot; data-end=&quot;18169&quot; data-ke-size=&quot;size20&quot;&gt;33. 얕은 복사와 깊은 복사&lt;/h4&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;18171&quot; data-end=&quot;18196&quot;&gt;리스트나 딕셔너리를 다룰 때 매우 중요합니다.&lt;/p&gt;
&lt;div style=&quot;color: #333333; text-align: start;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;stylus&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot;&gt;&lt;code&gt;a = [1, 2, 3]
b = a

b[0] = 100

print(a)
print(b)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;18264&quot; data-end=&quot;18267&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;18264&quot; data-end=&quot;18267&quot;&gt;출력:&lt;/p&gt;
&lt;div style=&quot;color: #333333; text-align: start;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;json&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot;&gt;&lt;code&gt;[100, 2, 3]
[100, 2, 3]&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;18306&quot; data-end=&quot;18341&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;18306&quot; data-end=&quot;18341&quot;&gt;b = a는 복사가 아니라 같은 리스트를 가리키는 것입니다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;18343&quot; data-end=&quot;18361&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;18343&quot; data-end=&quot;18361&quot;&gt;진짜 복사하려면 다음처럼 합니다.&lt;/p&gt;
&lt;div style=&quot;color: #333333; text-align: start;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;stylus&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot;&gt;&lt;code&gt;a = [1, 2, 3]
b = a.copy()

b[0] = 100

print(a)
print(b)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;18436&quot; data-end=&quot;18439&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;18436&quot; data-end=&quot;18439&quot;&gt;출력:&lt;/p&gt;
&lt;div style=&quot;color: #333333; text-align: start;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;json&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot;&gt;&lt;code&gt;[1, 2, 3]
[100, 2, 3]&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;18476&quot; data-end=&quot;18504&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;18476&quot; data-end=&quot;18504&quot;&gt;하지만 중첩 리스트에서는 문제가 생길 수 있습니다.&lt;/p&gt;
&lt;div style=&quot;color: #333333; text-align: start;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;markdown&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot;&gt;&lt;code&gt;path_a = [[0, 0], [1, 1]]
path_b = path_a.copy()

path_b[0][0] = 100

print(path_a)
print(path_b)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;18619&quot; data-end=&quot;18662&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;18619&quot; data-end=&quot;18662&quot;&gt;중첩 구조까지 완전히 복사하려면 copy.deepcopy()를 사용합니다.&lt;/p&gt;
&lt;div style=&quot;color: #333333; text-align: start;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;markdown&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot;&gt;&lt;code&gt;import copy

path_a = [[0, 0], [1, 1]]
path_b = copy.deepcopy(path_a)

path_b[0][0] = 100

print(path_a)
print(path_b)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;18798&quot; data-end=&quot;18849&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;18798&quot; data-end=&quot;18849&quot;&gt;로봇 경로, 설정 딕셔너리, 센서 데이터 버퍼를 복사할 때 이 차이를 모르면 버그가 납니다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;18798&quot; data-end=&quot;18849&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;18798&quot; data-end=&quot;18849&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;18798&quot; data-end=&quot;18849&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-section-id=&quot;1sphegp&quot; data-start=&quot;18856&quot; data-end=&quot;18867&quot; data-ke-size=&quot;size20&quot;&gt;34. 타입 힌트&lt;/h4&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;18869&quot; data-end=&quot;18903&quot;&gt;타입 힌트는 변수나 함수 인자의 자료형을 표시하는 문법입니다.&lt;/p&gt;
&lt;div style=&quot;color: #333333; text-align: start;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;cpp&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot; data-ke-language=&quot;cpp&quot;&gt;&lt;code&gt;def calculate_speed(distance: float, time: float) -&amp;gt; float:
    return distance / time&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;19007&quot; data-end=&quot;19084&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;19007&quot; data-end=&quot;19084&quot;&gt;이 부분은 함수가 결과로 float 값을 반환한다는 의미입니다. 즉, 계산 결과가 소수점 숫자일 수 있다는 뜻입니다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;19007&quot; data-end=&quot;19084&quot;&gt;Python은 타입 힌트를 강제로 검사하지는 않습니다. 하지만 코드를 읽기 쉬워지고, IDE나 코드 분석 도구가 실수를 더 잘 잡아줍니다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;19086&quot; data-end=&quot;19113&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;19086&quot; data-end=&quot;19113&quot;&gt;로봇 개발에서는 타입 힌트를 쓰는 것이 좋습니다.&lt;/p&gt;
&lt;div style=&quot;color: #333333; text-align: start;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;groovy&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot;&gt;&lt;code&gt;def limit_speed(speed: float, max_speed: float) -&amp;gt; float:
    if speed &amp;gt; max_speed:
        return max_speed

    if speed &amp;lt; -max_speed:
        return -max_speed

    return speed&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;19311&quot; data-end=&quot;19330&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;19311&quot; data-end=&quot;19330&quot;&gt;리스트 타입도 표시할 수 있습니다.&lt;/p&gt;
&lt;div style=&quot;color: #333333; text-align: start;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;sql&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot;&gt;&lt;code&gt;def average(values: list[float]) -&amp;gt; float:
    if not values:
        return 0.0

    return sum(values) / len(values)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;19466&quot; data-end=&quot;19486&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;19466&quot; data-end=&quot;19486&quot;&gt;딕셔너리 타입도 표시할 수 있습니다.&lt;/p&gt;
&lt;div style=&quot;color: #333333; text-align: start;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;python&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot;&gt;&lt;code&gt;def print_robot_config(config: dict[str, float]) -&amp;gt; None:
    for key, value in config.items():
        print(key, value)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;19625&quot; data-end=&quot;19660&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;19625&quot; data-end=&quot;19660&quot;&gt;None을 반환하는 함수는 -&amp;gt; None으로 표시합니다.&lt;/p&gt;
&lt;div style=&quot;color: #333333; text-align: start;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;python&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot;&gt;&lt;code&gt;def stop_robot() -&amp;gt; None:
    print(&quot;stop&quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-section-id=&quot;5krrg1&quot; data-start=&quot;19726&quot; data-end=&quot;19743&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span&gt;35. dataclass&lt;/span&gt;&lt;/h4&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;19745&quot; data-end=&quot;19812&quot;&gt;클래스 문법 자체는 별도 주제지만, Python에서 설정값이나 데이터를 묶을 때 dataclass는 매우 유용합니다.&lt;/p&gt;
&lt;div style=&quot;color: #333333; text-align: start;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;cpp&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot; data-ke-language=&quot;cpp&quot;&gt;&lt;code&gt;from dataclasses import dataclass

@dataclass
class RobotPose:
    x: float
    y: float
    yaw: float&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;19933&quot; data-end=&quot;19949&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;19933&quot; data-end=&quot;19949&quot;&gt;사용 예시는 다음과 같습니다.&lt;/p&gt;
&lt;div style=&quot;color: #333333; text-align: start;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;cpp&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot; data-ke-language=&quot;cpp&quot;&gt;&lt;code&gt;pose = RobotPose(x=1.0, y=2.0, yaw=0.5)

print(pose.x)
print(pose.y)
print(pose.yaw)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;20051&quot; data-end=&quot;20086&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;20051&quot; data-end=&quot;20086&quot;&gt;일반 클래스보다 훨씬 간단하게 데이터 구조를 만들 수 있습니다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;20088&quot; data-end=&quot;20108&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;20088&quot; data-end=&quot;20108&quot;&gt;로봇 설정값에도 사용할 수 있습니다.&lt;/p&gt;
&lt;div style=&quot;color: #333333; text-align: start;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;cpp&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot; data-ke-language=&quot;cpp&quot;&gt;&lt;code&gt;from dataclasses import dataclass

@dataclass
class MotorConfig:
    motor_id: int
    gear_ratio: float
    encoder_resolution: int
    max_rpm: float

config = MotorConfig(
    motor_id=1,
    gear_ratio=30.0,
    encoder_resolution=4096,
    max_rpm=3000.0
)

print(config)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;20402&quot; data-end=&quot;20408&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;20402&quot; data-end=&quot;20408&quot;&gt;출력 예시:&lt;/p&gt;
&lt;div style=&quot;color: #333333; text-align: start;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;routeros&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot;&gt;&lt;code&gt;MotorConfig(motor_id=1, gear_ratio=30.0, encoder_resolution=4096, max_rpm=3000.0)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;20505&quot; data-end=&quot;20536&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;20505&quot; data-end=&quot;20536&quot;&gt;딕셔너리보다 구조가 명확하고, 오타를 줄일 수 있습니다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;20505&quot; data-end=&quot;20536&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;20505&quot; data-end=&quot;20536&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;20505&quot; data-end=&quot;20536&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-section-id=&quot;1d4dn5g&quot; data-start=&quot;20543&quot; data-end=&quot;20557&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span&gt;36. with 문&lt;/span&gt;&lt;/h4&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;20559&quot; data-end=&quot;20590&quot;&gt;with는 자원을 안전하게 열고 닫을 때 사용합니다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;20592&quot; data-end=&quot;20609&quot;&gt;가장 대표적인 예는 파일입니다.&lt;/p&gt;
&lt;div style=&quot;color: #333333; text-align: start;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;livecodeserver&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot;&gt;&lt;code&gt;with open(&quot;log.txt&quot;, &quot;w&quot;) as file:
    file.write(&quot;robot started\n&quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;20695&quot; data-end=&quot;20735&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;20695&quot; data-end=&quot;20735&quot;&gt;with를 사용하면 파일을 직접 close()하지 않아도 됩니다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;20695&quot; data-end=&quot;20735&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;20737&quot; data-end=&quot;20795&quot;&gt;로봇 개발에서는 로그 파일, 설정 파일, 데이터 기록 파일을 자주 다루므로 with 문은 필수입니다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;20797&quot; data-end=&quot;20802&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;20797&quot; data-end=&quot;20802&quot;&gt;나쁜 예:&lt;/p&gt;
&lt;div style=&quot;color: #333333; text-align: start;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;livecodeserver&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot;&gt;&lt;code&gt;file = open(&quot;log.txt&quot;, &quot;w&quot;)
file.write(&quot;data\n&quot;)
file.close()&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;20881&quot; data-end=&quot;20886&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;20881&quot; data-end=&quot;20886&quot;&gt;좋은 예:&lt;/p&gt;
&lt;div style=&quot;color: #333333; text-align: start;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;livecodeserver&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot;&gt;&lt;code&gt;with open(&quot;log.txt&quot;, &quot;w&quot;) as file:
    file.write(&quot;data\n&quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;background-color: #ffffff; color: #555555; text-align: left;&quot; data-section-id=&quot;1jwq7pk&quot; data-start=&quot;8758&quot; data-end=&quot;8783&quot; data-ke-size=&quot;size20&quot;&gt;37. 모듈과 import: 기능 가져오기&lt;/h4&gt;
&lt;p style=&quot;background-color: #ffffff; color: #555555; text-align: left;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;8785&quot; data-end=&quot;8810&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #555555; text-align: left;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;8785&quot; data-end=&quot;8810&quot;&gt;Python은 필요한 기능을 가져와서 씁니다.&lt;/p&gt;
&lt;div style=&quot;background-color: #ffffff; color: #555555; text-align: left;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;moonscript&quot;&gt;&lt;code&gt;import math

angle = math.radians(90)
print(angle)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p style=&quot;background-color: #ffffff; color: #555555; text-align: left;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;8878&quot; data-end=&quot;8881&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #555555; text-align: left;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;8878&quot; data-end=&quot;8881&quot;&gt;출력:&lt;/p&gt;
&lt;div style=&quot;background-color: #ffffff; color: #555555; text-align: left;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;1.5707963267948966&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p style=&quot;background-color: #ffffff; color: #555555; text-align: left;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;8915&quot; data-end=&quot;8927&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #555555; text-align: left;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;8915&quot; data-end=&quot;8927&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #555555; text-align: left;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;8915&quot; data-end=&quot;8927&quot;&gt;자주 쓰는 기본 모듈:&lt;/p&gt;
&lt;div style=&quot;background-color: #ffffff; color: #555555; text-align: left;&quot;&gt;
&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 모듈&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;용도
&lt;table style=&quot;border-collapse: collapse; width: 65.2326%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-start=&quot;8929&quot; data-end=&quot;9081&quot;&gt;
&lt;tbody data-start=&quot;8951&quot; data-end=&quot;9081&quot;&gt;
&lt;tr data-start=&quot;8951&quot; data-end=&quot;8969&quot;&gt;
&lt;td style=&quot;width: 31.9767%;&quot; data-start=&quot;8951&quot; data-end=&quot;8960&quot; data-col-size=&quot;sm&quot;&gt;math&lt;/td&gt;
&lt;td style=&quot;width: 33.1395%;&quot; data-start=&quot;8960&quot; data-end=&quot;8969&quot; data-col-size=&quot;sm&quot;&gt;수학 계산&lt;/td&gt;
&lt;/tr&gt;
&lt;tr data-start=&quot;8970&quot; data-end=&quot;8995&quot;&gt;
&lt;td style=&quot;width: 31.9767%;&quot; data-start=&quot;8970&quot; data-end=&quot;8979&quot; data-col-size=&quot;sm&quot;&gt;time&lt;/td&gt;
&lt;td style=&quot;width: 33.1395%;&quot; data-start=&quot;8979&quot; data-end=&quot;8995&quot; data-col-size=&quot;sm&quot;&gt;시간 지연, 시간 측정&lt;/td&gt;
&lt;/tr&gt;
&lt;tr data-start=&quot;8996&quot; data-end=&quot;9014&quot;&gt;
&lt;td style=&quot;width: 31.9767%;&quot; data-start=&quot;8996&quot; data-end=&quot;9007&quot; data-col-size=&quot;sm&quot;&gt;random&lt;/td&gt;
&lt;td style=&quot;width: 33.1395%;&quot; data-start=&quot;9007&quot; data-end=&quot;9014&quot; data-col-size=&quot;sm&quot;&gt;랜덤값&lt;/td&gt;
&lt;/tr&gt;
&lt;tr data-start=&quot;9015&quot; data-end=&quot;9035&quot;&gt;
&lt;td style=&quot;width: 31.9767%;&quot; data-start=&quot;9015&quot; data-end=&quot;9022&quot; data-col-size=&quot;sm&quot;&gt;os&lt;/td&gt;
&lt;td style=&quot;width: 33.1395%;&quot; data-start=&quot;9022&quot; data-end=&quot;9035&quot; data-col-size=&quot;sm&quot;&gt;파일, 폴더 경로&lt;/td&gt;
&lt;/tr&gt;
&lt;tr data-start=&quot;9036&quot; data-end=&quot;9057&quot;&gt;
&lt;td style=&quot;width: 31.9767%;&quot; data-start=&quot;9036&quot; data-end=&quot;9044&quot; data-col-size=&quot;sm&quot;&gt;csv&lt;/td&gt;
&lt;td style=&quot;width: 33.1395%;&quot; data-start=&quot;9044&quot; data-end=&quot;9057&quot; data-col-size=&quot;sm&quot;&gt;CSV 파일 처리&lt;/td&gt;
&lt;/tr&gt;
&lt;tr data-start=&quot;9058&quot; data-end=&quot;9081&quot;&gt;
&lt;td style=&quot;width: 31.9767%;&quot; data-start=&quot;9058&quot; data-end=&quot;9067&quot; data-col-size=&quot;sm&quot;&gt;json&lt;/td&gt;
&lt;td style=&quot;width: 33.1395%;&quot; data-start=&quot;9067&quot; data-end=&quot;9081&quot; data-col-size=&quot;sm&quot;&gt;JSON 파일 처리&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p style=&quot;background-color: #ffffff; color: #555555; text-align: left;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;9083&quot; data-end=&quot;9092&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #555555; text-align: left;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;9083&quot; data-end=&quot;9092&quot;&gt;시간 지연 예제:&lt;/p&gt;
&lt;div style=&quot;background-color: #ffffff; color: #555555; text-align: left;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;stylus&quot;&gt;&lt;code&gt;import time

print(&quot;모터 ON&quot;)
time.sleep(1.0)
print(&quot;1초 후 모터 OFF&quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p style=&quot;background-color: #ffffff; color: #555555; text-align: left;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;9174&quot; data-end=&quot;9186&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #555555; text-align: left;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;9174&quot; data-end=&quot;9186&quot;&gt;로봇 제어 루프 예제:&lt;/p&gt;
&lt;div style=&quot;background-color: #ffffff; color: #555555; text-align: left;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;isbl&quot;&gt;&lt;code&gt;import time

while True:
    print(&quot;센서 읽기&quot;)
    print(&quot;제어 계산&quot;)
    print(&quot;명령 출력&quot;)

    time.sleep(0.1)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p style=&quot;background-color: #ffffff; color: #555555; text-align: left;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;9306&quot; data-end=&quot;9356&quot;&gt;time.sleep(0.1)은 0.1초 대기입니다.&lt;br /&gt;즉, 대략 10Hz 루프입니다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #555555; text-align: left;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;9306&quot; data-end=&quot;9356&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #555555; text-align: left;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;9306&quot; data-end=&quot;9356&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #555555; text-align: left;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;9306&quot; data-end=&quot;9356&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-section-id=&quot;1fnu5n6&quot; data-start=&quot;20968&quot; data-end=&quot;21011&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span&gt;38. 모듈 실행 진입점 if __name__ == &quot;__main__&quot;&lt;/span&gt;&lt;/h4&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;21013&quot; data-end=&quot;21056&quot;&gt;Python 파일을 직접 실행할 때만 특정 코드가 실행되게 만들 수 있습니다.&lt;/p&gt;
&lt;div style=&quot;color: #333333; text-align: start;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;isbl&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot;&gt;&lt;code&gt;def main():
    print(&quot;robot program start&quot;)

if __name__ == &quot;__main__&quot;:
    main()&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;21157&quot; data-end=&quot;21172&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;21157&quot; data-end=&quot;21172&quot;&gt;이 구조는 매우 중요합니다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;21174&quot; data-end=&quot;21211&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;21174&quot; data-end=&quot;21211&quot;&gt;예를 들어 robot_utils.py 파일이 있다고 가정합니다.&lt;/p&gt;
&lt;div style=&quot;color: #333333; text-align: start;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;python&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot;&gt;&lt;code&gt;def calculate_speed(distance, time):
    return distance / time

def main():
    print(&quot;test&quot;)
    print(calculate_speed(10, 2))

if __name__ == &quot;__main__&quot;:
    main()&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;21396&quot; data-end=&quot;21426&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;21396&quot; data-end=&quot;21426&quot;&gt;이 파일을 직접 실행하면 main()이 실행됩니다.&lt;/p&gt;
&lt;div style=&quot;color: #333333; text-align: start;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;vim&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot;&gt;&lt;code&gt;python3 robot_utils.py&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;21464&quot; data-end=&quot;21505&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;21464&quot; data-end=&quot;21505&quot;&gt;하지만 다른 파일에서 import하면 main()은 실행되지 않습니다.&lt;/p&gt;
&lt;div style=&quot;color: #333333; text-align: start;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;angelscript&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot;&gt;&lt;code&gt;from robot_utils import calculate_speed

speed = calculate_speed(5, 2)
print(speed)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;21606&quot; data-end=&quot;21650&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;21606&quot; data-end=&quot;21650&quot;&gt;로봇 프로젝트에서는 테스트 코드와 실제 재사용 함수를 분리할 때 꼭 필요합니다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;21606&quot; data-end=&quot;21650&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;21606&quot; data-end=&quot;21650&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;21606&quot; data-end=&quot;21650&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-section-id=&quot;1g8gkem&quot; data-start=&quot;21657&quot; data-end=&quot;21671&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span&gt;39. assert&lt;/span&gt;&lt;/h4&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;21673&quot; data-end=&quot;21702&quot;&gt;assert는 조건이 맞는지 검사하는 문법입니다.&lt;/p&gt;
&lt;div style=&quot;color: #333333; text-align: start;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;sqf&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot;&gt;&lt;code&gt;speed = 1.0

assert speed &amp;gt;= 0.0&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;21752&quot; data-end=&quot;21771&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;21752&quot; data-end=&quot;21771&quot;&gt;조건이 거짓이면 에러가 발생합니다.&lt;/p&gt;
&lt;div style=&quot;color: #333333; text-align: start;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;cpp&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot; data-ke-language=&quot;cpp&quot;&gt;&lt;code&gt;speed = -1.0

assert speed &amp;gt;= 0.0&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;21822&quot; data-end=&quot;21839&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;21822&quot; data-end=&quot;21839&quot;&gt;메시지를 추가할 수도 있습니다.&lt;/p&gt;
&lt;div style=&quot;color: #333333; text-align: start;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;cpp&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot; data-ke-language=&quot;cpp&quot;&gt;&lt;code&gt;speed = -1.0

assert speed &amp;gt;= 0.0, &quot;speed must be positive&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;21916&quot; data-end=&quot;21942&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;21916&quot; data-end=&quot;21942&quot;&gt;로봇 코드에서는 계산 함수 테스트에 유용합니다.&lt;/p&gt;
&lt;div style=&quot;color: #333333; text-align: start;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;cpp&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot; data-ke-language=&quot;cpp&quot;&gt;&lt;code&gt;def clamp(value, min_value, max_value):
    if value &amp;lt; min_value:
        return min_value

    if value &amp;gt; max_value:
        return max_value

    return value

assert clamp(5, 0, 10) == 5
assert clamp(-1, 0, 10) == 0
assert clamp(15, 0, 10) == 10&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;22208&quot; data-end=&quot;22291&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;22208&quot; data-end=&quot;22291&quot;&gt;단, assert를 안전 로직으로 사용하면 안 됩니다. 실제 로봇 정지, 충돌 방지, 비상 정지 같은 기능은 명시적인 조건문으로 처리해야 합니다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;22208&quot; data-end=&quot;22291&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;22208&quot; data-end=&quot;22291&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-section-id=&quot;1natua6&quot; data-start=&quot;22298&quot; data-end=&quot;22316&quot; data-ke-size=&quot;size20&quot;&gt;40. 유용한 표준 라이브러리&lt;/h4&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;22318&quot; data-end=&quot;22377&quot;&gt;Python에는 기본으로 제공되는 라이브러리가 많습니다. 로봇 개발에서 자주 쓰는 것들은 다음과 같습니다.&lt;/p&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-section-id=&quot;1iuf40l&quot; data-start=&quot;22379&quot; data-end=&quot;22388&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-section-id=&quot;1iuf40l&quot; data-start=&quot;22379&quot; data-end=&quot;22388&quot;&gt;&lt;span&gt;a. math&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;22390&quot; data-end=&quot;22403&quot;&gt;수학 계산에 사용합니다.&lt;/p&gt;
&lt;div style=&quot;color: #333333; text-align: start;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;lua&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot;&gt;&lt;code&gt;import math

angle = math.pi / 2
print(math.sin(angle))
print(math.cos(angle))&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;22499&quot; data-end=&quot;22505&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;22499&quot; data-end=&quot;22505&quot;&gt;거리 계산:&lt;/p&gt;
&lt;div style=&quot;color: #333333; text-align: start;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;angelscript&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot;&gt;&lt;code&gt;import math

def distance_2d(x1, y1, x2, y2):
    dx = x2 - x1
    dy = y2 - y1
    return math.sqrt(dx * dx + dy * dy)

print(distance_2d(0, 0, 3, 4))&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;22674&quot; data-end=&quot;22699&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;22674&quot; data-end=&quot;22699&quot;&gt;또는 hypot()을 사용할 수 있습니다.&lt;/p&gt;
&lt;div style=&quot;color: #333333; text-align: start;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;cpp&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot; data-ke-language=&quot;cpp&quot;&gt;&lt;code&gt;import math

distance = math.hypot(3, 4)

print(distance)  # 5.0&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-section-id=&quot;1izlkhc&quot; data-start=&quot;22781&quot; data-end=&quot;22790&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-section-id=&quot;1izlkhc&quot; data-start=&quot;22781&quot; data-end=&quot;22790&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-section-id=&quot;1izlkhc&quot; data-start=&quot;22781&quot; data-end=&quot;22790&quot;&gt;&lt;span&gt;b. t&lt;/span&gt;&lt;span&gt;ime&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-section-id=&quot;1izlkhc&quot; data-start=&quot;22781&quot; data-end=&quot;22790&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;22792&quot; data-end=&quot;22816&quot;&gt;시간 지연이나 현재 시간 확인에 사용합니다.&lt;/p&gt;
&lt;div style=&quot;color: #333333; text-align: start;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;stylus&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot;&gt;&lt;code&gt;import time

print(&quot;start&quot;)
time.sleep(1.0)
print(&quot;after 1 second&quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;22901&quot; data-end=&quot;22907&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;22901&quot; data-end=&quot;22907&quot;&gt;현재 시간:&lt;/p&gt;
&lt;div style=&quot;color: #333333; text-align: start;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;stylus&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot;&gt;&lt;code&gt;import time

now = time.time()
print(now)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;22966&quot; data-end=&quot;22976&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;22966&quot; data-end=&quot;22976&quot;&gt;간단한 주기 실행:&lt;/p&gt;
&lt;div style=&quot;color: #333333; text-align: start;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;cpp&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot; data-ke-language=&quot;cpp&quot;&gt;&lt;code&gt;import time

period = 0.1

for i in range(10):
    start_time = time.time()

    print(f&quot;loop {i}&quot;)

    elapsed = time.time() - start_time
    sleep_time = period - elapsed

    if sleep_time &amp;gt; 0:
        time.sleep(sleep_time)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-section-id=&quot;1xwnpeh&quot; data-start=&quot;23222&quot; data-end=&quot;23229&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-section-id=&quot;1xwnpeh&quot; data-start=&quot;23222&quot; data-end=&quot;23229&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-section-id=&quot;1xwnpeh&quot; data-start=&quot;23222&quot; data-end=&quot;23229&quot;&gt;&lt;span&gt;c. os&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;23231&quot; data-end=&quot;23260&quot;&gt;파일 경로, 폴더 확인, 환경 변수 등에 사용합니다.&lt;/p&gt;
&lt;div style=&quot;color: #333333; text-align: start;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;moonscript&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot;&gt;&lt;code&gt;import os

print(os.getcwd())&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;23307&quot; data-end=&quot;23316&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;23307&quot; data-end=&quot;23316&quot;&gt;파일 존재 확인:&lt;/p&gt;
&lt;div style=&quot;color: #333333; text-align: start;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;lua&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot;&gt;&lt;code&gt;import os

if os.path.exists(&quot;config.json&quot;):
    print(&quot;config exists&quot;)
else:
    print(&quot;config not found&quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;23441&quot; data-end=&quot;23447&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;23441&quot; data-end=&quot;23447&quot;&gt;폴더 생성:&lt;/p&gt;
&lt;div style=&quot;color: #333333; text-align: start;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;moonscript&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot;&gt;&lt;code&gt;import os

os.makedirs(&quot;logs&quot;, exist_ok=True)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-section-id=&quot;1tsq4q7&quot; data-start=&quot;23510&quot; data-end=&quot;23522&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-section-id=&quot;1tsq4q7&quot; data-start=&quot;23510&quot; data-end=&quot;23522&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-section-id=&quot;1tsq4q7&quot; data-start=&quot;23510&quot; data-end=&quot;23522&quot;&gt;&lt;span&gt;d. pathlib&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;23524&quot; data-end=&quot;23556&quot;&gt;파일 경로를 다룰 때 os.path보다 보기 좋습니다.&lt;/p&gt;
&lt;div style=&quot;color: #333333; text-align: start;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;cpp&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot; data-ke-language=&quot;cpp&quot;&gt;&lt;code&gt;from pathlib import Path

log_dir = Path(&quot;logs&quot;)
log_dir.mkdir(exist_ok=True)

log_file = log_dir / &quot;robot_log.txt&quot;

with open(log_file, &quot;w&quot;) as file:
    file.write(&quot;robot started\n&quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;23758&quot; data-end=&quot;23767&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;23758&quot; data-end=&quot;23767&quot;&gt;파일 존재 확인:&lt;/p&gt;
&lt;div style=&quot;color: #333333; text-align: start;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;cpp&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot; data-ke-language=&quot;cpp&quot;&gt;&lt;code&gt;from pathlib import Path

config_path = Path(&quot;config.json&quot;)

if config_path.exists():
    print(&quot;config file exists&quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-section-id=&quot;xy1fpf&quot; data-start=&quot;23902&quot; data-end=&quot;23910&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-section-id=&quot;xy1fpf&quot; data-start=&quot;23902&quot; data-end=&quot;23910&quot;&gt;&lt;span&gt;e. csv&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;23912&quot; data-end=&quot;23945&quot;&gt;센서 데이터나 로그 데이터를 CSV로 저장할 때 사용합니다.&lt;/p&gt;
&lt;div style=&quot;color: #333333; text-align: start;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;cpp&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot; data-ke-language=&quot;cpp&quot;&gt;&lt;code&gt;import csv

data = [
    [0.0, 1.2],
    [0.1, 1.3],
    [0.2, 1.1]
]

with open(&quot;sensor_log.csv&quot;, &quot;w&quot;, newline=&quot;&quot;) as file:
    writer = csv.writer(file)
    writer.writerow([&quot;time&quot;, &quot;distance&quot;])
    writer.writerows(data)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;24186&quot; data-end=&quot;24193&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;24186&quot; data-end=&quot;24193&quot;&gt;CSV 읽기:&lt;/p&gt;
&lt;div style=&quot;color: #333333; text-align: start;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;cpp&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot; data-ke-language=&quot;cpp&quot;&gt;&lt;code&gt;import csv

with open(&quot;sensor_log.csv&quot;, &quot;r&quot;) as file:
    reader = csv.reader(file)

    for row in reader:
        print(row)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;26288&quot; data-end=&quot;26318&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-section-id=&quot;orgp0d&quot; data-start=&quot;26325&quot; data-end=&quot;26344&quot; data-ke-size=&quot;size20&quot;&gt;41. 초보자가 자주 하는 실수&lt;/h4&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-section-id=&quot;oqqrcm&quot; data-start=&quot;26346&quot; data-end=&quot;26366&quot;&gt;&lt;span&gt;a. =와 ==를 혼동함&lt;/span&gt;&lt;/p&gt;
&lt;div style=&quot;color: #333333; text-align: start;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;ini&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot;&gt;&lt;code&gt;speed = 1.0&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;26395&quot; data-end=&quot;26411&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;26395&quot; data-end=&quot;26411&quot;&gt;=는 값을 넣는 것입니다.&lt;/p&gt;
&lt;div style=&quot;color: #333333; text-align: start;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;isbl&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot;&gt;&lt;code&gt;if speed == 1.0:
    print(&quot;speed is 1.0&quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;26471&quot; data-end=&quot;26491&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;26471&quot; data-end=&quot;26491&quot;&gt;==는 같은지 비교하는 것입니다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;26471&quot; data-end=&quot;26491&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;26471&quot; data-end=&quot;26491&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;26471&quot; data-end=&quot;26491&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-section-id=&quot;1hl0krr&quot; data-start=&quot;26498&quot; data-end=&quot;26515&quot;&gt;b. 리스트 복사를 잘못함&lt;/p&gt;
&lt;div style=&quot;color: #333333; text-align: start;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;ini&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot;&gt;&lt;code&gt;a = [1, 2, 3]
b = a&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;26552&quot; data-end=&quot;26583&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;26552&quot; data-end=&quot;26583&quot;&gt;이건 복사가 아닙니다. 같은 리스트를 가리키는 것입니다.&lt;/p&gt;
&lt;div style=&quot;color: #333333; text-align: start;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;dockerfile&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot;&gt;&lt;code&gt;b = a.copy()&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;26613&quot; data-end=&quot;26624&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;26613&quot; data-end=&quot;26624&quot;&gt;또는 중첩 구조라면:&lt;/p&gt;
&lt;div style=&quot;color: #333333; text-align: start;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;dockerfile&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot;&gt;&lt;code&gt;import copy

b = copy.deepcopy(a)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-section-id=&quot;1p3hg4i&quot; data-start=&quot;26680&quot; data-end=&quot;26704&quot;&gt;&lt;span&gt;c. 빈 리스트에서 min() 사용&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;div style=&quot;color: #333333; text-align: start;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;ini&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot;&gt;&lt;code&gt;ranges = []

nearest = min(ranges)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;26756&quot; data-end=&quot;26770&quot;&gt;이 코드는 에러가 납니다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;26756&quot; data-end=&quot;26770&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;26772&quot; data-end=&quot;26786&quot;&gt;안전하게 작성해야 합니다.&lt;/p&gt;
&lt;div style=&quot;color: #333333; text-align: start;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;fortran&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot;&gt;&lt;code&gt;if ranges:
    nearest = min(ranges)
else:
    nearest = None&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-section-id=&quot;he2m2u&quot; data-start=&quot;26870&quot; data-end=&quot;26885&quot;&gt;d. 파일을 닫지 않음&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;26887&quot; data-end=&quot;26892&quot;&gt;나쁜 예:&lt;/p&gt;
&lt;div style=&quot;color: #333333; text-align: start;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;livecodeserver&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot;&gt;&lt;code&gt;file = open(&quot;log.txt&quot;, &quot;w&quot;)
file.write(&quot;data&quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;26956&quot; data-end=&quot;26961&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;26956&quot; data-end=&quot;26961&quot;&gt;좋은 예:&lt;/p&gt;
&lt;div style=&quot;color: #333333; text-align: start;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;livecodeserver&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot;&gt;&lt;code&gt;with open(&quot;log.txt&quot;, &quot;w&quot;) as file:
    file.write(&quot;data&quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-section-id=&quot;1g8i6nh&quot; data-start=&quot;27041&quot; data-end=&quot;27061&quot;&gt;e. 예외 처리를 너무 넓게 함&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;27063&quot; data-end=&quot;27068&quot;&gt;나쁜 예:&lt;/p&gt;
&lt;div style=&quot;color: #333333; text-align: start;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;isbl&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot;&gt;&lt;code&gt;try:
    value = int(&quot;abc&quot;)
except:
    print(&quot;error&quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;27140&quot; data-end=&quot;27145&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;27140&quot; data-end=&quot;27145&quot;&gt;좋은 예:&lt;/p&gt;
&lt;div style=&quot;color: #333333; text-align: start;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;isbl&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot;&gt;&lt;code&gt;try:
    value = int(&quot;abc&quot;)
except ValueError:
    print(&quot;invalid number&quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;27237&quot; data-end=&quot;27279&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;27237&quot; data-end=&quot;27279&quot;&gt;무조건 except:로 모든 에러를 숨기면 실제 버그를 찾기 어렵습니다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;27237&quot; data-end=&quot;27279&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;27237&quot; data-end=&quot;27279&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;27237&quot; data-end=&quot;27279&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-section-id=&quot;17s62r8&quot; data-start=&quot;27286&quot; data-end=&quot;27304&quot;&gt;f. 변수 이름을 대충 지음&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;27306&quot; data-end=&quot;27311&quot;&gt;나쁜 예:&lt;/p&gt;
&lt;div style=&quot;color: #333333; text-align: start;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;ini&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot;&gt;&lt;code&gt;a = 1.0
b = 2.0
c = a / b&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;27354&quot; data-end=&quot;27359&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;27354&quot; data-end=&quot;27359&quot;&gt;좋은 예:&lt;/p&gt;
&lt;div style=&quot;color: #333333; text-align: start;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;ini&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot;&gt;&lt;code&gt;distance = 1.0
time_sec = 2.0
speed = distance / time_sec&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;27434&quot; data-end=&quot;27503&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;27434&quot; data-end=&quot;27503&quot;&gt;로봇 코드는 센서, 좌표, 속도, 시간, 각도 단위가 섞입니다. 변수 이름을 명확하게 짓지 않으면 나중에 반드시 고생합니다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;27434&quot; data-end=&quot;27503&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;28899&quot; data-end=&quot;28933&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h1 style=&quot;color: #000000; text-align: start;&quot; data-section-id=&quot;mmjlh2&quot; data-start=&quot;28940&quot; data-end=&quot;28948&quot;&gt;&amp;nbsp;&lt;/h1&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;29691&quot; data-end=&quot;29745&quot; data-is-last-node=&quot;&quot; data-is-only-node=&quot;&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>강좌/ROS2</category>
      <category>Python 기초</category>
      <author>MakingRobotWizard</author>
      <guid isPermaLink="true">https://makingrobot.tistory.com/430</guid>
      <comments>https://makingrobot.tistory.com/430#entry430comment</comments>
      <pubDate>Mon, 25 May 2026 11:04:00 +0900</pubDate>
    </item>
  </channel>
</rss>