URDF로봇 이동 시뮬레이션 하기
이 글은 앞선 글의 레퍼런스의 후속 글을 따라해보며 작성한 글입니다.
https://gbiggs.github.io/rosjp_urdf_tutorial_text/mobile_robot_gazebo.html
ロボットモデリング講習会:URDFの作成方法 by gbiggs
移動型ロボットのシミュレーション Updated on: 2018-02-27 トップに戻る 本セクションでは、移動型ロボットのURDF作成で作成したURDFを拡張して、Gazebo上のシミュレーションに必要な情報を追加し
gbiggs.github.io
앞선 글에서 SLAM로봇의 디자인은 만들었지만, 이는 외형만 만들었을 뿐, 질량에 관한 정보는 없습니다.
시뮬레이터로서는 이게 차체가 100kg에 바퀴가 1kg인지 혹은 그 반대인지 알 수가 없다는 이야기지요.
그래서 <visual>과 <collision>이외에 <inertia>정보도 넣어줘야합니다.
inertia정보에는 원점과 rpy이외에도 질량과 관성행렬이 들어갑니다. 질량에 관한 정보만 들어가면 되니까 기하적 형태는 필요없습니다.
관성행렬의 공식은 아래 링크를 참고해주세요.
https://en.wikipedia.org/wiki/List_of_moments_of_inertia#List_of_3D_inertia_tensors
List of moments of inertia - Wikipedia
Moment of inertia, denoted by I, measures the extent to which an object resists rotational acceleration about a particular axis, and is the rotational analogue to mass (which determines an object's resistance to linear acceleration). Mass moments of inerti
en.wikipedia.org
예를들어 Size(0.13,0.1,0.078)에 질량이 0.25kg인 직육면체라면, 관성행렬의 대각성분은 각각(0.000335083, 0.000478833, 0.000560417)이고 대각외성분은 전부 0이 됩니다.
예전 글의 base_link에 관해서라면 이렇게 되겠네요.
<link name="base_link">
<visual>
<geometry>
<box size="0.13 0.1 0.052"/>
</geometry>
<origin xyz="0 0 0" rpy="0 0 0"/>
<material name="grey"/>
</visual>
<visual name="regulators">
<geometry>
<box size="0.005 0.065 0.02"/>
</geometry>
<origin xyz="0.04 0 0.036" rpy="0 0 0"/>
<material name="black"/>
</visual>
<visual name="connector">
<geometry>
<box size="0.075 0.016 0.026"/>
</geometry>
<origin xyz="0 -0.027 0.039" rpy="0 0 0"/>
<material name="black"/>
</visual>
<collision>
<geometry>
<box size="0.13 0.1 0.078"/>
</geometry>
<origin xyz="0 0 0.013" rpy="0 0 0"/>
</collision>
<inertial>
<mass value="0.25" />
<origin xyz="0 0 0.013" rpy="0 0 0"/>
<inertia ixx="0.000335083333333" ixy="0.0" ixz="0.0"
iyy="0.000478833333333" iyz="0.0"
izz="0.000560416666667" />
</inertial>
</link>
비슷한 맥락으로 나머지도 적어줍니다.
caster_support
<inertial>
<mass value="0.25" />
<origin xyz="-0.01 0 0" rpy="0 0 0"/>
<inertia ixx="1.66666666666667e-5" ixy="0.0" ixz="0.0"
iyy="2.66666666666667e-5" iyz="0.0"
izz="1.66666666666667e-5" />
</inertial>
caster_wheel
<inertial>
<mass value="0.1" />
<origin rpy="-1.5708 0 0"/>
<inertia ixx="1.02083333333333e-5" ixy="0.0" ixz="0.0"
iyy="1.02083333333333e-5" iyz="0.0"
izz="2e-5" />
</inertial>
right_wheel/left_wheel
<inertial>
<mass value="0.1" />
<origin rpy="-1.5708 0 0"/>
<inertia ixx="1.49333333333333e-5" ixy="0.0" ixz="0.0"
iyy="1.49333333333333e-5" iyz="0.0"
izz="2.88e-5" />
</inertial>
그 다음엔 시뮬레이션을 위해서 Gazebo용 Launch file를 작성합니다.
cd ~/catkin_ws/src/rt_mouse_replica/launch
touch mouse_gazebo.launch
<?xml version="1.0" ?>
<launch>
<!-- these are the arguments you can pass this launch file, for example paused:=true -->
<arg name="paused" default="true"/>
<arg name="use_sim_time" default="true"/>
<arg name="gui" default="true"/>
<arg name="headless" default="false"/>
<arg name="debug" default="false"/>
<!-- We resume the logic in empty_world.launch -->
<include file="$(find gazebo_ros)/launch/empty_world.launch">
<arg name="debug" value="$(arg debug)" />
<arg name="gui" value="$(arg gui)" />
<arg name="paused" value="$(arg paused)"/>
<arg name="use_sim_time" value="$(arg use_sim_time)"/>
<arg name="headless" value="$(arg headless)"/>
</include>
<!-- Load the URDF into the ROS Parameter Server -->
<param name="robot_description" command="$(find xacro)/xacro '$(find rt_mouse_replica)/urdf/mouse.xacro'" />
<!-- Run a python script to the send a service call to gazebo_ros to spawn a URDF robot -->
<node name="urdf_spawner" pkg="gazebo_ros" type="spawn_model" respawn="false" output="screen"
args="-urdf -model diff_wheeled_robot -param robot_description"/>
</launch>
이제 이걸 기동시켜주면
roslaunch rt_mouse_replica mouse_gazebo.launch
디자인한 로봇이 이렇게 땅에 파묻혀서 나옵니다. 원점이 0,0,0이니까요.
그런데 이건 아랫쪽에 화살표를 눌러주면
이렇게 솟아오릅니다. 화살표 눌러주는게 귀찮다면 런치파일에서 </arg name="paused" default="true"> 부분에서 true를 false로 바꾸시면 됩니다.
View메뉴에서는 무게중심이나 관성모멘트등의 가시화도 가능합니다.
이제 Gazebo가 ROS로부터 오는 명령을 받을 수 있도록 토픽을 구독하게 해줍시다.
mouse.xacro에서 맨 아랫줄의 </robot>바로 위에 이 구문을 추가해줍니다.
<gazebo>
<plugin name="differential_drive_controller" filename="libgazebo_ros_diff_drive.so">
<leftJoint>left_wheel_joint</leftJoint>
<rightJoint>right_wheel_joint</rightJoint>
<robotBaseFrame>base_link</robotBaseFrame>
<wheelSeparation>0.108</wheelSeparation>
<wheelDiameter>0.048</wheelDiameter>
<publishWheelJointState>true</publishWheelJointState>
<legacyMode>false</legacyMode>
</plugin>
</gazebo>
<plugin> 플러그인을 로드합니다. 인수로는 Gazebo에서 2륜 SLAM을 움직이는 플러그인을 로드하도록 주었습니다.
<wheelSeparation><wheelDiameter>은 이동거리를 각속도로 바꿀 때 필요한 인자입니다. 이름으로 보건데, 각각 두 바퀴간의 거리와 바퀴의 직경이네요!
두 바퀴간의 거리는, 베이스 상자가 0.1이었고, 바퀴의 중심까지의 거리까지 생각해준다면 +0.008이 됩니다.
바퀴의 직경은 반지름의 두배니까 0.048이 됩니다.
다시한번 해당 런치파일을 기동하면
몇가지 인수가 부족하네요? 하는 경고메시지가 뜹니다. 일단은 무시해주고요.
아래에 보면 cmd_vel을 구독하겠다는 말이 나옵니다. 위에 경고메시지에서도 나왔듯이 따로 지정을 할경우 다른 토픽을 구독할 수도 있습니다.
ROS status를 보면 /gazebo가 Twist 타입의 /cmd_vel을 구독하고있는데 퍼블리셔가 없다는 걸 알 수 있습니다.
그럼 이걸 간단하게 수동으로 퍼블리시해주죠.
rostopic pub -1 /cmd_vel geometry_msgs/Twist '{linear: {x: 0.0}, angular: {z: 0.2}}'
이렇게 로봇이 회전하는 걸 볼 수 있습니다.
이걸 수동으로 rostopic커맨드가 아니라 원하는 명령을 퍼블리시 해주는 스크립트도 있습니다.
sudo apt-get install ros-noetic-teleop-twist-keyboard
우선 이걸 인스톨해주세요.
그 다음은
rosrun teleop_twist_keyboard teleop_twist_keyboard.py
로 기동합니다.
만약에 스크립트를 해독할수 없다느니 python 변수를 알 수 없다느니 하는 에러가 나온다면 python-is-python3 을 인스톨해주세요.
이런 화면이 나오고 키보드로 조종할 수 있게됩니다.
이 패키지가 아니라 다른 파이썬 스크립트를 인터넷에서 다운받아서 쓰시거나 수정해서 쓰셔도 됩니다.
만약 로봇이 cmd_vel이 아닌 다른 토픽을 구독하고 있다면 파이썬 스크립트를 수정해서 사용하면 되구요.