| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | 2 | 3 | ||||
| 4 | 5 | 6 | 7 | 8 | 9 | 10 |
| 11 | 12 | 13 | 14 | 15 | 16 | 17 |
| 18 | 19 | 20 | 21 | 22 | 23 | 24 |
| 25 | 26 | 27 | 28 | 29 | 30 | 31 |
- ROS2
- 인공지능 수학
- 결정트리
- 파이썬
- 생물정보학
- 자바
- 딥러닝
- 시그모이드
- bioinformatics
- AP Computer Science A
- 인공지능
- 서열정렬
- AP
- ncbi
- CNN
- COVID
- 바이오파이썬
- 오류역전파
- Kaggle
- BLaST
- 인공신경망
- SVM
- 생명정보학
- 캐글
- 로제타폴드
- 바이오인포매틱스
- 단백질 구조 예측
- Java
- 이항분포
- 알파폴드
- Today
- Total
데이터 과학
ROS 2와 Gazebo를 이용한 사족보행 로봇 시뮬레이션 환경 구축 본문
Ubuntu 26.04에서 ROS 2와 Gazebo를 이용한 PuppyPi 사족보행 로봇 시뮬레이션 환경 구축
1. 개요
Hiwonder PuppyPi는 4개의 다리와 총 8개의 관절을 사용하는 사족보행 로봇입니다. 실제 PuppyPi를 직접 제어하기 전에 Gazebo 환경에서 로봇의 구조와 관절 움직임을 구현하면 보행 알고리즘, ROS 2 제어, 강화학습 등의 실험을 보다 안전하게 진행할 수 있습니다.
본 실습에서는 Ubuntu 26.04 환경에서 ROS 2와 Gazebo를 이용하여 PuppyPi의 가상 모델을 구성하고, 4개의 다리와 8개의 관절을 제어할 수 있는 기본 시뮬레이션 환경을 구축합니다.
전체 구조는 다음과 같습니다.
Ubuntu 26.04
│
└── ROS 2 Lyrical
│
├── robot_state_publisher
│
├── ros2_control
│
└── ros_gz
│
▼
Gazebo Jetty
│
▼
PuppyPi 가상 모델
│
4 Legs / 8 DOF
│
▼
Joint Control
Ubuntu 26.04에서는 ROS 2 Lyrical과 Gazebo Jetty 조합을 사용하는 것이 적절합니다.
2. 개발 환경
본 실습 환경은 다음과 같습니다.
운영체제 : Ubuntu 26.04
ROS 2 : Lyrical
Gazebo : Jetty
Robot : Hiwonder PuppyPi
DOF : 8
먼저 Ubuntu 버전을 확인합니다.
lsb_release -a
ROS 2 배포판을 확인합니다.
printenv ROS_DISTRO
정상적으로 설정되어 있다면 다음과 같이 출력됩니다.
lyrical
Gazebo 버전을 확인합니다.
gz sim --versions
ROS 2 환경을 활성화합니다.
source /opt/ros/lyrical/setup.bash
3. ROS 2와 Gazebo 연동 패키지 설치
ROS 2와 Gazebo 사이의 통신을 위해 ros_gz 패키지를 설치합니다.
sudo apt update
sudo apt install ros-lyrical-ros-gz
추가로 필요한 패키지를 설치합니다.
sudo apt install \
ros-lyrical-xacro \
ros-lyrical-robot-state-publisher \
ros-lyrical-joint-state-publisher \
ros-lyrical-joint-state-publisher-gui
ros2_control 관련 패키지도 설치합니다.
sudo apt install \
ros-lyrical-ros2-control \
ros-lyrical-ros2-controllers
Gazebo와 ros2_control을 연결하기 위해 gz_ros2_control도 필요합니다.
sudo apt install \
ros-lyrical-gz-ros2-control
만약 해당 패키지가 apt 저장소에서 제공되지 않는 경우에는 소스 빌드 방식으로 설치해야 합니다.
4. PuppyPi Workspace 생성
PuppyPi 전용 ROS 2 workspace를 생성합니다.
mkdir -p ~/puppypi_ws/src
cd ~/puppypi_ws/src
PuppyPi description 패키지를 생성합니다.
ros2 pkg create \
--build-type ament_cmake \
puppypi_description
필요한 폴더를 생성합니다.
cd ~/puppypi_ws/src/puppypi_description
mkdir -p \
urdf \
launch \
worlds \
config \
meshes
최종 디렉터리 구조는 다음과 같습니다.
puppypi_ws
└── src
└── puppypi_description
├── config
│ └── controllers.yaml
├── launch
│ └── gazebo.launch.py
├── meshes
├── urdf
│ └── puppypi.urdf.xacro
├── worlds
│ └── puppy_world.sdf
├── CMakeLists.txt
└── package.xml
5. PuppyPi 관절 구조
PuppyPi는 4개의 다리와 8개의 관절을 갖는 구조로 구성합니다.
각 다리는 hip 관절과 knee 관절로 구성합니다.
FRONT
FL FR
Hip Joint Hip Joint
│ │
Upper Leg Upper Leg
│ │
Knee Joint Knee Joint
│ │
Lower Leg Lower Leg
┌────────────────────────┐
│ │
│ base_link │
│ │
└────────────────────────┘
│ │
Hip Joint Hip Joint
│ │
Upper Leg Upper Leg
│ │
Knee Joint Knee Joint
│ │
Lower Leg Lower Leg
RL RR
REAR
8개의 관절 이름은 다음과 같이 정의합니다.
fl_hip_joint
fl_knee_joint
fr_hip_joint
fr_knee_joint
rl_hip_joint
rl_knee_joint
rr_hip_joint
rr_knee_joint
6. PuppyPi URDF/Xacro 작성
URDF/Xacro 파일을 생성합니다.
nano \
~/puppypi_ws/src/puppypi_description/urdf/puppypi.urdf.xacro
다음 내용을 입력합니다.
<?xml version="1.0"?>
<robot
xmlns:xacro="http://www.ros.org/wiki/xacro"
name="puppypi">
<!-- 기본 크기 설정 -->
<xacro:property
name="body_length"
value="0.28"/>
<xacro:property
name="body_width"
value="0.14"/>
<xacro:property
name="body_height"
value="0.06"/>
<xacro:property
name="upper_leg_length"
value="0.10"/>
<xacro:property
name="lower_leg_length"
value="0.11"/>
<!-- 본체 -->
<link name="base_link">
<visual>
<geometry>
<box size="${body_length} ${body_width} ${body_height}"/>
</geometry>
</visual>
<collision>
<geometry>
<box size="${body_length} ${body_width} ${body_height}"/>
</geometry>
</collision>
<inertial>
<mass value="1.5"/>
<inertia
ixx="0.003"
iyy="0.010"
izz="0.012"
ixy="0"
ixz="0"
iyz="0"/>
</inertial>
</link>
<!-- 다리 생성 Macro -->
<xacro:macro
name="leg"
params="prefix x y">
<link name="${prefix}_upper_leg">
<visual>
<origin
xyz="0 0 -${upper_leg_length/2}"/>
<geometry>
<cylinder
radius="0.015"
length="${upper_leg_length}"/>
</geometry>
</visual>
<collision>
<origin
xyz="0 0 -${upper_leg_length/2}"/>
<geometry>
<cylinder
radius="0.015"
length="${upper_leg_length}"/>
</geometry>
</collision>
<inertial>
<origin
xyz="0 0 -${upper_leg_length/2}"/>
<mass value="0.12"/>
<inertia
ixx="0.00012"
iyy="0.00012"
izz="0.000025"
ixy="0"
ixz="0"
iyz="0"/>
</inertial>
</link>
<joint
name="${prefix}_hip_joint"
type="revolute">
<parent link="base_link"/>
<child link="${prefix}_upper_leg"/>
<origin
xyz="${x} ${y} 0"
rpy="0 0 0"/>
<axis xyz="0 1 0"/>
<limit
lower="-1.2"
upper="1.2"
effort="20"
velocity="5"/>
<dynamics
damping="0.15"
friction="0.05"/>
</joint>
<link name="${prefix}_lower_leg">
<visual>
<origin
xyz="0 0 -${lower_leg_length/2}"/>
<geometry>
<cylinder
radius="0.012"
length="${lower_leg_length}"/>
</geometry>
</visual>
<collision>
<origin
xyz="0 0 -${lower_leg_length/2}"/>
<geometry>
<cylinder
radius="0.012"
length="${lower_leg_length}"/>
</geometry>
</collision>
<inertial>
<origin
xyz="0 0 -${lower_leg_length/2}"/>
<mass value="0.08"/>
<inertia
ixx="0.00008"
iyy="0.00008"
izz="0.000015"
ixy="0"
ixz="0"
iyz="0"/>
</inertial>
</link>
<joint
name="${prefix}_knee_joint"
type="revolute">
<parent
link="${prefix}_upper_leg"/>
<child
link="${prefix}_lower_leg"/>
<origin
xyz="0 0 -${upper_leg_length}"
rpy="0 0 0"/>
<axis xyz="0 1 0"/>
<limit
lower="-2.0"
upper="0.2"
effort="20"
velocity="5"/>
<dynamics
damping="0.15"
friction="0.05"/>
</joint>
</xacro:macro>
<!-- Front Left -->
<xacro:leg
prefix="fl"
x="0.11"
y="0.075"/>
<!-- Front Right -->
<xacro:leg
prefix="fr"
x="0.11"
y="-0.075"/>
<!-- Rear Left -->
<xacro:leg
prefix="rl"
x="-0.11"
y="0.075"/>
<!-- Rear Right -->
<xacro:leg
prefix="rr"
x="-0.11"
y="-0.075"/>
<!-- ros2_control -->
<ros2_control
name="GazeboSimSystem"
type="system">
<hardware>
<plugin>
gz_ros2_control/GazeboSimSystem
</plugin>
</hardware>
<joint name="fl_hip_joint">
<command_interface name="position"/>
<state_interface name="position"/>
<state_interface name="velocity"/>
</joint>
<joint name="fl_knee_joint">
<command_interface name="position"/>
<state_interface name="position"/>
<state_interface name="velocity"/>
</joint>
<joint name="fr_hip_joint">
<command_interface name="position"/>
<state_interface name="position"/>
<state_interface name="velocity"/>
</joint>
<joint name="fr_knee_joint">
<command_interface name="position"/>
<state_interface name="position"/>
<state_interface name="velocity"/>
</joint>
<joint name="rl_hip_joint">
<command_interface name="position"/>
<state_interface name="position"/>
<state_interface name="velocity"/>
</joint>
<joint name="rl_knee_joint">
<command_interface name="position"/>
<state_interface name="position"/>
<state_interface name="velocity"/>
</joint>
<joint name="rr_hip_joint">
<command_interface name="position"/>
<state_interface name="position"/>
<state_interface name="velocity"/>
</joint>
<joint name="rr_knee_joint">
<command_interface name="position"/>
<state_interface name="position"/>
<state_interface name="velocity"/>
</joint>
</ros2_control>
<!-- Gazebo ros2_control Plugin -->
<gazebo>
<plugin
filename="libgz_ros2_control-system.so"
name="gz_ros2_control::GazeboSimROS2ControlPlugin">
<robot_param>
robot_description
</robot_param>
<robot_param_node>
robot_state_publisher
</robot_param_node>
<parameters>
$(find puppypi_description)/config/controllers.yaml
</parameters>
</plugin>
</gazebo>
</robot>
gz_ros2_control/GazeboSimSystem
robot_description
robot_state_publisher
$(find puppypi_description)/config/controllers.yaml
7. URDF/Xacro 문법 확인
작성한 Xacro 파일이 정상적으로 URDF로 변환되는지 확인합니다.
cd ~/puppypi_ws
source /opt/ros/lyrical/setup.bash
xacro \
src/puppypi_description/urdf/puppypi.urdf.xacro \
> /tmp/puppypi.urdf
오류가 없다면 정상적으로 변환된 것입니다.
관절이 모두 포함되어 있는지 확인합니다.
grep joint /tmp/puppypi.urdf
다음 8개의 관절이 확인되어야 합니다.
fl_hip_joint
fl_knee_joint
fr_hip_joint
fr_knee_joint
rl_hip_joint
rl_knee_joint
rr_hip_joint
rr_knee_joint
8. ros2_control Controller 설정
Controller 설정 파일을 생성합니다.
nano \
~/puppypi_ws/src/puppypi_description/config/controllers.yaml
다음 내용을 입력합니다.
controller_manager:
ros__parameters:
update_rate: 100
joint_state_broadcaster:
type:
joint_state_broadcaster/JointStateBroadcaster
puppy_joint_controller:
type:
joint_trajectory_controller/JointTrajectoryController
puppy_joint_controller:
ros__parameters:
joints:
- fl_hip_joint
- fl_knee_joint
- fr_hip_joint
- fr_knee_joint
- rl_hip_joint
- rl_knee_joint
- rr_hip_joint
- rr_knee_joint
command_interfaces:
- position
state_interfaces:
- position
- velocity
joint_state_broadcaster는 각 관절의 상태를 ROS 2 Topic으로 전달합니다.
joint_trajectory_controller는 각 관절의 목표 위치를 전달하는 데 사용합니다.
9. Gazebo World 생성
Gazebo에서 사용할 기본 평면 환경을 생성합니다.
nano \
~/puppypi_ws/src/puppypi_description/worlds/puppy_world.sdf
다음 내용을 입력합니다.
<?xml version="1.0" ?>
<sdf version="1.10">
<world name="puppy_world">
<physics
name="physics"
type="ignored">
<max_step_size>
0.001
</max_step_size>
<real_time_factor>
1.0
</real_time_factor>
</physics>
<plugin
filename="gz-sim-physics-system"
name="gz::sim::systems::Physics"/>
<plugin
filename="gz-sim-user-commands-system"
name="gz::sim::systems::UserCommands"/>
<plugin
filename="gz-sim-scene-broadcaster-system"
name="gz::sim::systems::SceneBroadcaster"/>
<light
type="directional"
name="sun">
<pose>
0 0 10 0 0 0
</pose>
<diffuse>
0.8 0.8 0.8 1
</diffuse>
<direction>
-0.5 0.1 -0.9
</direction>
</light>
<model name="ground_plane">
<static>true</static>
<link name="link">
<collision name="collision">
<geometry>
<plane>
<normal>
0 0 1
</normal>
<size>
20 20
</size>
</plane>
</geometry>
</collision>
<visual name="visual">
<geometry>
<plane>
<normal>
0 0 1
</normal>
<size>
20 20
</size>
</plane>
</geometry>
</visual>
</link>
</model>
</world>
</sdf>
10. Gazebo Launch 파일 생성
Gazebo 실행과 PuppyPi 생성, ros2_control Controller 실행을 하나의 launch 파일로 구성합니다.
nano \
~/puppypi_ws/src/puppypi_description/launch/gazebo.launch.py
다음 내용을 입력합니다.
import os
import xacro
from launch import LaunchDescription
from launch.actions import (
IncludeLaunchDescription,
TimerAction
)
from launch.launch_description_sources import (
PythonLaunchDescriptionSource
)
from launch_ros.actions import Node
from ament_index_python.packages import (
get_package_share_directory
)
def generate_launch_description():
pkg_share = (
get_package_share_directory(
'puppypi_description'
)
)
ros_gz_sim_share = (
get_package_share_directory(
'ros_gz_sim'
)
)
xacro_file = os.path.join(
pkg_share,
'urdf',
'puppypi.urdf.xacro'
)
robot_description = (
xacro.process_file(
xacro_file
).toxml()
)
world_file = os.path.join(
pkg_share,
'worlds',
'puppy_world.sdf'
)
gazebo = IncludeLaunchDescription(
PythonLaunchDescriptionSource(
os.path.join(
ros_gz_sim_share,
'launch',
'gz_sim.launch.py'
)
),
launch_arguments={
'gz_args':
f'-r {world_file}'
}.items()
)
robot_state_publisher = Node(
package=
'robot_state_publisher',
executable=
'robot_state_publisher',
name=
'robot_state_publisher',
output=
'screen',
parameters=[
{
'robot_description':
robot_description,
'use_sim_time':
True
}
]
)
spawn_robot = Node(
package=
'ros_gz_sim',
executable=
'create',
arguments=[
'-name',
'puppypi',
'-topic',
'robot_description',
'-x',
'0.0',
'-y',
'0.0',
'-z',
'0.27'
],
output='screen'
)
joint_state_broadcaster = Node(
package=
'controller_manager',
executable=
'spawner',
arguments=[
'joint_state_broadcaster',
'--controller-manager',
'/controller_manager'
],
output='screen'
)
puppy_joint_controller = Node(
package=
'controller_manager',
executable=
'spawner',
arguments=[
'puppy_joint_controller',
'--controller-manager',
'/controller_manager'
],
output='screen'
)
return LaunchDescription([
gazebo,
robot_state_publisher,
spawn_robot,
TimerAction(
period=3.0,
actions=[
joint_state_broadcaster
]
),
TimerAction(
period=5.0,
actions=[
puppy_joint_controller
]
)
])
11. CMakeLists.txt 수정
다음 내용을 CMakeLists.txt에 추가합니다.
install(
DIRECTORY
launch
urdf
worlds
config
meshes
DESTINATION
share/${PROJECT_NAME}
)
12. package.xml 의존성 설정
package.xml에는 다음과 같은 의존성을 추가합니다.
<exec_depend>xacro</exec_depend>
<exec_depend>robot_state_publisher</exec_depend>
<exec_depend>ros_gz_sim</exec_depend>
<exec_depend>controller_manager</exec_depend>
<exec_depend>joint_state_broadcaster</exec_depend>
<exec_depend>joint_trajectory_controller</exec_depend>
<exec_depend>gz_ros2_control</exec_depend>
13. PuppyPi 패키지 빌드
Workspace 루트로 이동합니다.
cd ~/puppypi_ws
ROS 2 환경을 활성화합니다.
source /opt/ros/lyrical/setup.bash
의존성을 설치합니다.
rosdep install \
--from-paths src \
--ignore-src \
-r -y
빌드합니다.
colcon build \
--symlink-install
빌드가 완료되면 환경을 다시 불러옵니다.
source install/setup.bash
14. Gazebo에서 PuppyPi 실행
다음 명령을 실행합니다.
ros2 launch \
puppypi_description \
gazebo.launch.py
정상적으로 실행되면 Gazebo 안에 PuppyPi 가상 모델이 생성됩니다.
FRONT
FL FR
│ │
│ │
┌──────────────────┐
│ │
│ PuppyPi │
│ │
└──────────────────┘
│ │
│ │
RL RR
REAR
현재 모델은 실제 PuppyPi의 외형을 그대로 재현한 모델이 아니라, 관절 제어와 보행 알고리즘 실습을 위한 단순화된 8-DOF 모델입니다.
15. Controller 동작 확인
새로운 터미널을 실행합니다.
source /opt/ros/lyrical/setup.bash
source ~/puppypi_ws/install/setup.bash
Controller 상태를 확인합니다.
ros2 control list_controllers
정상적으로 실행되고 있다면 다음과 유사하게 나타납니다.
joint_state_broadcaster
joint_state_broadcaster/JointStateBroadcaster
active
puppy_joint_controller
joint_trajectory_controller/JointTrajectoryController
active
관절 상태도 확인할 수 있습니다.
ros2 topic echo /joint_states
8개의 관절 이름과 위치 값이 출력되면 정상입니다.
16. PuppyPi의 다리 움직이기
이제 ros2_control을 이용하여 8개의 관절을 움직여 봅니다.
ros2 topic pub --once \
/puppy_joint_controller/joint_trajectory \
trajectory_msgs/msg/JointTrajectory \
"{
joint_names: [
'fl_hip_joint',
'fl_knee_joint',
'fr_hip_joint',
'fr_knee_joint',
'rl_hip_joint',
'rl_knee_joint',
'rr_hip_joint',
'rr_knee_joint'
],
points: [
{
positions: [
0.2, -0.8,
0.2, -0.8,
0.2, -0.8,
0.2, -0.8
],
time_from_start: {
sec: 1,
nanosec: 0
}
}
]
}"
PuppyPi의 네 다리가 동시에 움직인다면 ros2_control 연결이 정상적으로 완료된 것입니다.
17. 앞다리의 자세 변경하기
다음과 같이 각 관절에 서로 다른 값을 전달할 수 있습니다.
ros2 topic pub --once \
/puppy_joint_controller/joint_trajectory \
trajectory_msgs/msg/JointTrajectory \
"{
joint_names: [
'fl_hip_joint',
'fl_knee_joint',
'fr_hip_joint',
'fr_knee_joint',
'rl_hip_joint',
'rl_knee_joint',
'rr_hip_joint',
'rr_knee_joint'
],
points: [{
positions: [
0.5, -1.0,
-0.2, -0.6,
0.2, -0.8,
0.2, -0.8
],
time_from_start: {
sec: 1,
nanosec: 0
}
}]
}"
앞쪽 두 다리의 움직임이 다르게 나타난다면 각 관절을 독립적으로 제어할 수 있는 상태입니다.
18. 현재까지 완성된 구조
현재까지 구성한 전체 시스템은 다음과 같습니다.
ROS 2 Lyrical
│
robot_state_publisher
│
▼
PuppyPi URDF
│
▼
Gazebo Jetty
│
gz_ros2_control
│
▼
controller_manager
┌─────┴─────┐
│ │
▼ ▼
joint_state joint_trajectory
broadcaster controller
│ │
└─────┬─────┘
│
▼
8 joints
FL FR
hip hip
knee knee
PuppyPi
hip hip
knee knee
RL RR
19. WSL에서 Gazebo 실행하기
WSL2에서 Gazebo를 사용하는 경우 WSLg를 통해 Linux GUI 프로그램을 Windows 화면에 표시할 수 있습니다.
먼저 Gazebo가 정상적으로 실행되는지 확인합니다.
gz sim
Gazebo GUI가 나타나면 기본 설정은 정상입니다.
화면이 검게 나타나거나 렌더링 오류가 발생하는 경우 다음을 확인합니다.
echo $DISPLAY
OpenGL 상태도 확인합니다.
glxinfo | grep OpenGL
glxinfo가 설치되어 있지 않은 경우 다음 명령을 사용합니다.
sudo apt install mesa-utils
WSL 환경에서는 Gazebo 시뮬레이션 자체와 GUI 렌더링 문제가 별도로 발생할 수 있으므로, Gazebo 단독 실행을 먼저 확인한 뒤 ROS 2 launch 파일을 실행하는 것이 좋습니다.
20. 실제 PuppyPi와 Gazebo의 관계
현재 구성은 실제 PuppyPi의 Raspberry Pi에 Gazebo를 직접 설치하는 방식이 아닙니다.
Gazebo는 PC 또는 WSL 환경에서 실행합니다.
Windows PC
│
WSL
│
Ubuntu 26.04
│
ROS 2 Lyrical
│
Gazebo Jetty
│
Virtual PuppyPi
실제 PuppyPi에서는 별도의 ROS 2 제어 시스템이 동작합니다.
PuppyPi
│
Raspberry Pi
│
ROS 2
│
puppy_control
│
Gait Controller
│
Inverse Kinematics
│
8 Servos
따라서 Gazebo에서는 PuppyPi의 가상 모델을 이용하여 보행과 제어 알고리즘을 검증하고, 이후 실제 PuppyPi의 제어 시스템으로 해당 알고리즘을 연결하는 방식으로 확장할 수 있습니다.
21. 다음 단계
현재 단계에서는 다음과 같은 기능까지 구성한 상태입니다.
Ubuntu 26.04
↓
ROS 2 Lyrical
↓
Gazebo Jetty
↓
PuppyPi URDF/Xacro
↓
4 Legs / 8 Joints
↓
gz_ros2_control
↓
JointTrajectoryController
↓
관절 제어
다음 단계에서는 PuppyPi 가상 모델에 센서를 추가할 수 있습니다.
PuppyPi
│
├── IMU
├── Contact Sensor
├── Camera
└── LiDAR
보행 기능은 다음과 같은 순서로 확장할 수 있습니다.
Standing
↓
Walking
↓
Trot
↓
Turning
↓
Slope Walking
최종적으로는 다음과 같은 구조를 구현할 수 있습니다.
Gazebo PuppyPi
↓
Gait Generator
↓
Inverse Kinematics
↓
ROS 2 Control
↓
4족 보행
이후 PPO와 같은 강화학습 알고리즘을 연결하면 PuppyPi의 보행 안정성, 경사면 이동, 장애물 회피 등의 실험으로 확장할 수 있습니다.
정리
이번 실습에서는 Ubuntu 26.04, ROS 2 Lyrical 및 Gazebo Jetty 환경에서 PuppyPi 사족보행 로봇의 기본 시뮬레이션 환경을 구축합니다.
PuppyPi를 4개의 다리와 8개의 회전 관절로 구성하고, Xacro를 이용하여 반복적인 다리 구조를 정의합니다. 또한 gz_ros2_control을 이용하여 Gazebo와 ROS 2의 controller manager를 연결하고, joint_trajectory_controller를 통해 각 관절의 목표 각도를 제어합니다.
이 과정을 통해 PuppyPi의 기본적인 관절 구조와 제어 방법을 이해할 수 있으며, 이후 보행 알고리즘, 역기구학, IMU 기반 자세 제어, LiDAR 기반 이동 및 강화학습 실험으로 확장할 수 있습니다.
다만 현재 사용한 링크 길이, 질량, 관성값과 관절 범위는 시뮬레이션 구성을 위한 근사값입니다. 실제 PuppyPi와 동일한 동작을 구현하려면 이후 실제 기체의 링크 길이, 서보 위치, 질량 분포 및 관절 제한값을 반영하여 URDF 모델을 보정하는 과정이 필요합니다.
chatGTP 정리
'인공지능 > 피지컬 AI' 카테고리의 다른 글
| Ubuntu 24.04와 ROS 2 Jazzy에서 PuppyPi 4족 보행 로봇 (0) | 2026.09.21 |
|---|---|
| ROS 2 Jazzy와 Gazebo Harmonic에서 TurtleBot3 시뮬레이션 (0) | 2026.09.21 |
| Windows 11 WSL2에서 Ubuntu 24.04, ROS 2 Jazzy, Gazebo Harmonic, TurtleBot3 (0) | 2026.09.21 |
| Ubuntu 26.04 + ROS 2 Lyrical + Gazebo Jetty 설치 (0) | 2026.09.12 |
| PiDog에 프로그램을 넣는 방법 (0) | 2026.09.10 |