移動ロボットのモデルを動力学シミュレータGazeboに対応するために設定を行っていきます.
マップが記載されている座標系があったときに,その座標系からみた移動ロボットの相対位置を表す座標系をodomフレームとしてTFで設定します.
マップ座標系は,複数マップも設定することができますが,複数マップを作ったときは,基準となるマップからのオドメトリのフレームodomを設定する必要があります.複数マップの上位にはearth(地球)の座標フレームが有り,GPSの計算でも用いられるECEF (earth-centered earth-fixed)で定められるXYZの直交座標系があります.詳しくは,リンク先のREP 105 を確認してください.
TFのつながりは下記の通り.
earth -> map -> odom -> base_link
オドメトリの定義はnav_msgs/Odometryで定義されており,下記の項目となります.
# Includes the frame id of the pose parent.
std_msgs/Header header
# Frame id the pose is pointing at. The twist is in this coordinate frame.
string child_frame_id
# Estimated pose that is typically relative to a fixed world frame.
geometry_msgs/PoseWithCovariance pose
# Estimated linear and angular velocity relative to child_frame_id.
geometry_msgs/TwistWithCovariance twist
ロボットの速度情報がtwist型で管理されているので,車輪の回転速度から並進速度と回転速度を計算します.
並進速度をlinear,回転速度をangular,左右の車輪の回転により発生している推定速度をright_wheel_est_vel,left_wheel_ext_vel,左右の車輪間の距離をwheel_separationとすると下記のように計算される.
linear = (right_wheel_est_vel + left_wheel_est_vel) / 2
angular = (right_wheel_est_vel - left_wheel_est_vel) / wheel_separation
ROS 2では,ros2_controlのdiff_drive_controllerで差動移動ロボットの管理が行えるようになっているので上記計算を手動で計算する必要はありません.詳しくは公式のros2_control_documentationを見てください.
未だにClassicの接続のほうが簡単なので,まずこちらの接続から確認.
gazebo_ros_pkgをインストールしておく.
sudo apt install ros-humble-gazebo-ros-pkgs
まず,差動駆動のプラグインとIMUのプラグインをURDFに追加してみる.
差動駆動のプラグインは,UDFDファイルに下記を追記.
追記場所はURDFファイルの</robot>の直前.
<gazebo>
<plugin name='diff_drive' filename='libgazebo_ros_diff_drive.so'>
<ros>
<namespace>/demo</namespace>
</ros>
<!-- wheels -->
<left_joint>drivewhl_l_joint</left_joint>
<right_joint>drivewhl_r_joint</right_joint>
<!-- kinematics -->
<wheel_separation>0.4</wheel_separation>
<wheel_diameter>0.2</wheel_diameter>
<!-- limits -->
<max_wheel_torque>20</max_wheel_torque>
<max_wheel_acceleration>1.0</max_wheel_acceleration>
<!-- output -->
<publish_odom>true</publish_odom>
<publish_odom_tf>false</publish_odom_tf>
<publish_wheel_tf>true</publish_wheel_tf>
<odometry_frame>odom</odometry_frame>
<robot_base_frame>base_link</robot_base_frame>
</plugin>
</gazebo>
太字にしているところを確認するとわかるが,<odometory_frame>のタグでodomという名前を指定している.
<robot_base_frame>のタグにはbase_linkの名前がしている.
これらの名前がURDFで設定しているフレームの名前とずれていると動かない.
IMUのプラグインは,シミュレーションで2次元のマップを作るときは使うことはないのですが,3次元マップや,2Dでもジャイロオドメトリを試したいときには取り付けた方が良い.
先ほど追加した,差動駆動のプラグインの直後に下記の記載をURDFに追加.
記載が長いので折りたたんであります.
下のラインをクリックするとIMUの追記内容が表示されます.
追記例では,Gazeboのセンサーノイズモデルでノイズも載せてあります.
<link name="imu_link">
<visual>
<geometry>
<box size="0.1 0.1 0.1"/>
</geometry>
</visual>
<collision>
<geometry>
<box size="0.1 0.1 0.1"/>
</geometry>
</collision>
<xacro:box_inertia m="0.1" w="0.1" d="0.1" h="0.1"/>
</link>
<joint name="imu_joint" type="fixed">
<parent link="base_link"/>
<child link="imu_link"/>
<origin xyz="0 0 0.01"/>
</joint>
<gazebo reference="imu_link">
<sensor name="imu_sensor" type="imu">
<plugin filename="libgazebo_ros_imu_sensor.so" name="imu_plugin">
<ros>
<namespace>/demo</namespace>
<remapping>~/out:=imu</remapping>
</ros>
<initial_orientation_as_reference>false</initial_orientation_as_reference>
</plugin>
<always_on>true</always_on>
<update_rate>100</update_rate>
<visualize>true</visualize>
<imu>
<angular_velocity>
<x>
<noise type="gaussian">
<mean>0.0</mean>
<stddev>2e-4</stddev>
<bias_mean>0.0000075</bias_mean>
<bias_stddev>0.0000008</bias_stddev>
</noise>
</x>
<y>
<noise type="gaussian">
<mean>0.0</mean>
<stddev>2e-4</stddev>
<bias_mean>0.0000075</bias_mean>
<bias_stddev>0.0000008</bias_stddev>
</noise>
</y>
<z>
<noise type="gaussian">
<mean>0.0</mean>
<stddev>2e-4</stddev>
<bias_mean>0.0000075</bias_mean>
<bias_stddev>0.0000008</bias_stddev>
</noise>
</z>
</angular_velocity>
<linear_acceleration>
<x>
<noise type="gaussian">
<mean>0.0</mean>
<stddev>1.7e-2</stddev>
<bias_mean>0.1</bias_mean>
<bias_stddev>0.001</bias_stddev>
</noise>
</x>
<y>
<noise type="gaussian">
<mean>0.0</mean>
<stddev>1.7e-2</stddev>
<bias_mean>0.1</bias_mean>
<bias_stddev>0.001</bias_stddev>
</noise>
</y>
<z>
<noise type="gaussian">
<mean>0.0</mean>
<stddev>1.7e-2</stddev>
<bias_mean>0.1</bias_mean>
<bias_stddev>0.001</bias_stddev>
</noise>
</z>
</linear_acceleration>
</imu>
</sensor>
</gazebo>
前回(移動ロボットのモデル)作ったdisplay.launch.pyファイルを編集する.
display.launch.py内のgenerate_launch_description()内にある動作確認用に記載していたGUIである下記joint state publisher_gui_nodeを削除する.
joint_state_publisher_gui_node = launch_ros.actions.Node(
package='joint_state_publisher_gui',
executable='joint_state_publisher_gui',
name='joint_state_publisher_gui',
condition=launch.conditions.IfCondition(LaunchConfiguration('gui'))
)
また,return launch.LaunchDescription()内の最初に記載していた下記パラメータ設定の部分も削除.
launch.actions.DeclareLaunchArgument(name='gui', default_value='True',
description='Flag to enable joint_state_publisher_gui'),
と下記の行も削除
joint_state_publisher_gui_node,
下記の行を「joint_state_publisher_node,」の前の行に追加.
launch.actions.ExecuteProcess(cmd=['gazebo', '--verbose', '-s', 'libgazebo_ros_init.so', '-s', 'libgazebo_ros_factory.so'], output='screen'),
(ここまでreturn launch.LaunchDescription()内の編集)
return launch.LaunchDescription()の直前に下記をペースト
spawn_entity = launch_ros.actions.Node(
package='gazebo_ros',
executable='spawn_entity.py',
arguments=['-entity', 'sam_bot', '-topic', 'robot_description'],
output='screen'
)
joint_state_publisher_nodeには,下記のように引数を2行削除して,1行追加.
joint_state_publisher_node = launch_ros.actions.Node(
package='joint_state_publisher',
executable='joint_state_publisher',
name='joint_state_publisher',
parameters=[{'robot_description': Command(['xacro ', default_model_path])}], # この行削除
condition=launch.conditions.UnlessCondition(LaunchConfiguration('gui')) # この行削除
arguments=[default_model_path] #この行を追加
)
また,「spawn_entity, 」の記載を「return launch.LaunchDescription()」の中の最後の方にある「rviz」の直前に追加.
下記は修正後のreturn launch.LaunchDescription()
return launch.LaunchDescription([
launch.actions.DeclareLaunchArgument(name='model', default_value=default_model_path,
description='Absolute path to robot urdf file'),
launch.actions.DeclareLaunchArgument(name='rvizconfig', default_value=default_rviz_config_path,
description='Absolute path to rviz config file'),
launch.actions.ExecuteProcess(cmd=['gazebo', '--verbose', '-s', 'libgazebo_ros_init.so', '-s', 'libgazebo_ros_factory.so'], output='screen'),
joint_state_publisher_node,
robot_state_publisher_node,
spawn_entity,
rviz_node
])
修正後のdisplay.launch.pyは下記の通り.
import launch
from launch.substitutions import Command, LaunchConfiguration
import launch_ros
import os
def generate_launch_description():
pkg_share = launch_ros.substitutions.FindPackageShare(package='sam_bot_description').find('sam_bot_description')
default_model_path = os.path.join(pkg_share, 'src/description/sam_bot_description.urdf')
default_rviz_config_path = os.path.join(pkg_share, 'rviz/urdf_config.rviz')
robot_state_publisher_node = launch_ros.actions.Node(
package='robot_state_publisher',
executable='robot_state_publisher',
parameters=[{'robot_description': Command(['xacro ', LaunchConfiguration('model')])}]
)
joint_state_publisher_node = launch_ros.actions.Node(
package='joint_state_publisher',
executable='joint_state_publisher',
name='joint_state_publisher',
arguments=[default_model_path]
)
rviz_node = launch_ros.actions.Node(
package='rviz2',
executable='rviz2',
name='rviz2',
output='screen',
arguments=['-d', LaunchConfiguration('rvizconfig')],
)
spawn_entity = launch_ros.actions.Node(
package='gazebo_ros',
executable='spawn_entity.py',
arguments=['-entity', 'sam_bot', '-topic', 'robot_description'],
output='screen'
)
return launch.LaunchDescription([
launch.actions.DeclareLaunchArgument(name='model', default_value=default_model_path,
description='Absolute path to robot urdf file'),
launch.actions.DeclareLaunchArgument(name='rvizconfig', default_value=default_rviz_config_path,
description='Absolute path to rviz config file'),
launch.actions.ExecuteProcess(cmd=['gazebo', '--verbose', '-s', 'libgazebo_ros_init.so', '-s', 'libgazebo_ros_factory.so'], output='screen'),
joint_state_publisher_node,
robot_state_publisher_node,
spawn_entity,
rviz_node
])
次に,package.xmlファイルを開いて下記の行を削除.
<exec_depend>joint_state_publisher_gui</exec_depend>
以上で修正終了なので,gazeboで表示できるかを確認.
cd ~/ros2_ws
colcon build
. install/setup.bash
ros2 launch sam_bot_description deiplay.launch.py
下記画面のようにgazeboが立ち上がって移動ロボットが表示される.
GazeboとRvizがきちんと立ち上がっていたら,コマンドラインで,下記コマンドでtopicのlistを確認してみてください.
ros2 topic list
/demo/imuと/demo/odomが見つかると思います.
下記を実行するとimuのデータが確認できます.
ros2 topic echo /demo/imu
終了はctl+z
下記でodomの確認
ros2 topic echo /demo/odom
ros2 topic infoで各topicの型を確認.
ros2 topic info /demo/imu
Type: sensor_msgs/msg/Imu
Publisher count: 1
Subscription count: 0
ros2 topic info /demo odom
Type: nav_msgs/msg/Odometry
Publisher count: 1
Subscription count: 0
imuはsensor_msgs/msg/Imu型,odomはnav_msgs/msg/Odometry型とわかる.
robot_localizationパッケージを使ってタイヤの回転角やIMUなどの内界センサを使った位置推定を行う.
まずは下記で,robot_localizationをインストール.
sudo apt install ros-humble-robot-localization
robot_localizationの拡張カルマンフィルタを使うためにconfigディレクトリを作成してその中にekf.yamlを作成する.
cd ~/ros2_ws/src/sam_bot_description
mkdir config
cd config
gedit ekf.yaml
ekf.yamlの中身は下記の内容を記載.
### ekf config file ###
ekf_filter_node:
ros__parameters:
# The frequency, in Hz, at which the filter will output a position estimate. Note that the filter will not begin
# computation until it receives at least one message from one of theinputs. It will then run continuously at the
# frequency specified here, regardless of whether it receives more measurements. Defaults to 30 if unspecified.
frequency: 30.0
# ekf_localization_node and ukf_localization_node both use a 3D omnidirectional motion model. If this parameter is
# set to true, no 3D information will be used in your state estimate. Use this if you are operating in a planar
# environment and want to ignore the effect of small variations in the ground plane that might otherwise be detected
# by, for example, an IMU. Defaults to false if unspecified.
two_d_mode: false
# Whether to publish the acceleration state. Defaults to false if unspecified.
publish_acceleration: true
# Whether to broadcast the transformation over the /tf topic. Defaultsto true if unspecified.
publish_tf: true
# 1. Set the map_frame, odom_frame, and base_link frames to the appropriate frame names for your system.
# 1a. If your system does not have a map_frame, just remove it, and make sure "world_frame" is set to the value of odom_frame.
# 2. If you are fusing continuous position data such as wheel encoder odometry, visual odometry, or IMU data, set "world_frame"
# to your odom_frame value. This is the default behavior for robot_localization's state estimation nodes.
# 3. If you are fusing global absolute position data that is subject to discrete jumps (e.g., GPS or position updates from landmark
# observations) then:
# 3a. Set your "world_frame" to your map_frame value
# 3b. MAKE SURE something else is generating the odom->base_link transform. Note that this can even be another state estimation node
# from robot_localization! However, that instance should *not* fuse the global data.
map_frame: map # Defaults to "map" if unspecified
odom_frame: odom # Defaults to "odom" if unspecified
base_link_frame: base_link # Defaults to "base_link" ifunspecified
world_frame: odom # Defaults to the value ofodom_frame if unspecified
odom0: demo/odom
odom0_config: [true, true, true,
false, false, false,
false, false, false,
false, false, true,
false, false, false]
imu0: demo/imu
imu0_config: [false, false, false,
true, true, true,
false, false, false,
false, false, false,
false, false, false]
設定ファイルは,frequency, two_d_mode, publish_acceleration, publish_tf, map_frame, odom_frame, base_link_frame, world_fram に対して設定をしている.
詳細な設定は, Parameters of state estimation nodes を参考にしてください.
ekf.yamlのサンプルは,ここ.
ちなみに,odom0_configとimu0_configは,x, y, z, roll, pitch, yaw, vx, vy, vz, vroll, vpitch, vyaw, ax, ay, az の15個のフィルター後に出力される値の有効・無効を表している.
odom0の入力にdemo/odomを設定,imu0にはdemo/imuを設定している.
odom0は,trueの場所を見るとx, y, z, vyaw が有効ということになる.
imu0は,trueの場所を見るとroll, pitch, yawとなっている.
display.launch.pyをまた修正する.
launchファイルの最後の方にあるreturn launch.launchDescription()の直前に下記のrobot_localization_nodeを追加する.
robot_localization_node = launch_ros.actions.Node(
package='robot_localization',
executable='ekf_node',
name='ekf_filter_node',
output='screen',
parameters=[os.path.join(pkg_share, 'config/ekf.yaml'), {'use_sim_time': LaunchConfiguration('use_sim_time')}]
)
return launch.launchDescription()の中にuse_sim_timの下記設定を加える.
launch.actions.DeclareLaunchArgument(name='use_sim_time', default_value='True',
description='Flag to enable use_sim_time'),
また,同じくreturn launch.launchDescription()の中の最後の方に,robot_localization_nodeを追加する.具体的な場所は下記.
robot_state_publisher_node,
spawn_entity,
robot_localization_node,
rviz_node
])
CMakeLists.txtにconfigファイルがインストールされるように,install()の部分を修正.
install(
DIRECTORY src launch rviz config
DESTINATION share/${PROJECT_NAME}
)
以上で終了なので,ビルドと実行をしてみる.
cd ~/ros2_ws/
colcon build
. install/setup.bash
ros2 launch sam_bot_description display.launch.py
rviz内の左のメニューのFramesを展開してTFが下の図の通り登録されていることを確認する.
ずっと見ていると,odomフレームがドリフトして勝手に動いていることが確認できる...
とりあえずtopic listでトピックを確認する.
ros2 topic list
odometry/filteredとaccel/filteredと/tfがリストに存在していることが確認できる.
次に,/demo/imuとdemo/odomのinfoを確認してみる.
ros2 topic info /demo/imu
Type: sensor_msgs/msg/Imu
Publisher count: 1
Subscription count: 1
上記のようにsubscriptionが1になっている.
同じく
ros2 topic info /demo/odom
Type: nav_msgs/msg/Odometry
Publisher count: 1
Subscription count: 1
こちらもsubscriptionが1になっている.
ekf_filter_nodeのinfoも確認してみる.
ros2 node info ekf_filter_node
Subscribers:
/clock: rosgraph_msgs/msg/Clock
/demo/imu: sensor_msgs/msg/Imu
/demo/odom: nav_msgs/msg/Odometry
/parameter_events: rcl_interfaces/msg/ParameterEvent
/set_pose: geometry_msgs/msg/PoseWithCovarianceStamped
Publishers:
/accel/filtered: geometry_msgs/msg/AccelWithCovarianceStamped
/diagnostics: diagnostic_msgs/msg/DiagnosticArray
/odometry/filtered: nav_msgs/msg/Odometry
/parameter_events: rcl_interfaces/msg/ParameterEvent
/rosout: rcl_interfaces/msg/Log
/tf: tf2_msgs/msg/TFMessage
Service Servers:
/ekf_filter_node/describe_parameters: rcl_interfaces/srv/DescribeParameters
...
/demo/imuと/demo/odomをサブスクライブしていることが確認できる.
また,/accel/filteredと/odometry/filteredと/tfをパブリッシュしていることが確認できる.
robot_localizationはodomフレームからbase_linkへの変換をtf2でパブリッシュしているので下記コマンドで情報が出ているかを確認する.
ros2 run tf2_ros tf2_echo odom base_link
下記のような出力がされていることが確認できる.勝手にドリフトしているので,設定が間違っている可能性あり??
- Translation: [-0.425, -0.008, -13.215]
- Rotation: in Quaternion [0.000, -0.000, 0.010, 1.000]
- Rotation: in RPY (radian) [0.000, -0.000, 0.020]
- Rotation: in RPY (degree) [0.000, -0.000, 1.149]
- Matrix:
1.000 -0.020 -0.000 -0.425
0.020 1.000 -0.000 -0.008
0.000 0.000 1.000 -13.215
0.000 0.000 0.000 1.000
At time 286.992000000
- Translation: [-0.426, -0.008, -13.271]
- Rotation: in Quaternion [0.000, 0.000, 0.010, 1.000]
- Rotation: in RPY (radian) [0.000, 0.000, 0.020]
- Rotation: in RPY (degree) [0.000, 0.000, 1.152]
- Matrix:
1.000 -0.020 0.000 -0.426
0.020 1.000 -0.000 -0.008
-0.000 0.000 1.000 -13.271
0.000 0.000 0.000 1.000
マップ作成のための外界センサとして2D-Lidarを設定します.
sensor_msgsでは,2D-Lidarはsensor_msgs/LaserScan型で取り扱われます.
3次元のLidarの場合はsensor_msgs/PointCloud2などが使われるはず.3次元Lidarから2次元のマップを作りたいときは,ある高さの平面のデータをLaserScan型に変換するnodeを作る必要がある.
今回は2D-Lidarと深度カメラの設定を説明します.
まずは,URDFにGazeboプラグインを追加の編集をします.
cd ~/ros2_ws/src/sam_bot_description/src/description/
gedit sam_bot_description.urdf
で再編集開始.
urdfファイルの一番最後の行にある</robot>の直前に下記のLidarの記載を追記するだけです.
<link name="lidar_link">
<inertial>
<origin xyz="0 0 0" rpy="0 0 0"/>
<mass value="0.125"/>
<inertia ixx="0.001" ixy="0" ixz="0" iyy="0.001" iyz="0" izz="0.001" />
</inertial>
<collision>
<origin xyz="0 0 0" rpy="0 0 0"/>
<geometry>
<cylinder radius="0.0508" length="0.055"/>
</geometry>
</collision>
<visual>
<origin xyz="0 0 0" rpy="0 0 0"/>
<geometry>
<cylinder radius="0.0508" length="0.055"/>
</geometry>
</visual>
</link>
<joint name="lidar_joint" type="fixed">
<parent link="base_link"/>
<child link="lidar_link"/>
<origin xyz="0 0 0.12" rpy="0 0 0"/>
</joint>
<gazebo reference="lidar_link">
<sensor name="lidar" type="ray">
<always_on>true</always_on>
<visualize>true</visualize>
<update_rate>5</update_rate>
<ray>
<scan>
<horizontal>
<samples>360</samples>
<resolution>1.000000</resolution>
<min_angle>0.000000</min_angle>
<max_angle>6.280000</max_angle>
</horizontal>
</scan>
<range>
<min>0.120000</min>
<max>3.5</max>
<resolution>0.015000</resolution>
</range>
<noise>
<type>gaussian</type>
<mean>0.0</mean>
<stddev>0.01</stddev>
</noise>
</ray>
<plugin name="scan" filename="libgazebo_ros_ray_sensor.so">
<ros>
<remapping>~/out:=scan</remapping>
</ros>
<output_type>sensor_msgs/LaserScan</output_type>
<frame_name>lidar_link</frame_name>
</plugin>
</sensor>
</gazebo>
2D-Lidarをlidar_linkとして記載し,libgazebo_ros_ray_sensor.soプラグインで/scanトピックにデータが送信されるように設定します.
<output_type>でデータ型をsensor_msgs/LaserScan に設定している.
<horizontal>タグで,計測範囲や解像度,最大,最小計測角(単位rad)を決定.
<range>タグで,レーザの計測距離のレンジの最大最小値(単位m)と分散を<stddev>タグで設定している.
深度カメラも同じく</robot>の直前に下記の記載を追記してURDFに実装します.
<link name="camera_link">
<visual>
<origin xyz="0 0 0" rpy="0 0 0"/>
<geometry>
<box size="0.015 0.130 0.022"/>
</geometry>
</visual>
<collision>
<origin xyz="0 0 0" rpy="0 0 0"/>
<geometry>
<box size="0.015 0.130 0.022"/>
</geometry>
</collision>
<inertial>
<origin xyz="0 0 0" rpy="0 0 0"/>
<mass value="0.035"/>
<inertia ixx="0.001" ixy="0" ixz="0" iyy="0.001" iyz="0" izz="0.001" />
</inertial>
</link>
<joint name="camera_joint" type="fixed">
<parent link="base_link"/>
<child link="camera_link"/>
<origin xyz="0.215 0 0.05" rpy="0 0 0"/>
</joint>
<link name="camera_depth_frame"/>
<joint name="camera_depth_joint" type="fixed">
<origin xyz="0 0 0" rpy="${-pi/2} 0 ${-pi/2}"/>
<parent link="camera_link"/>
<child link="camera_depth_frame"/>
</joint>
<gazebo reference="camera_link">
<sensor name="depth_camera" type="depth">
<visualize>true</visualize>
<update_rate>30.0</update_rate>
<camera name="camera">
<horizontal_fov>1.047198</horizontal_fov>
<image>
<width>640</width>
<height>480</height>
<format>R8G8B8</format>
</image>
<clip>
<near>0.05</near>
<far>3</far>
</clip>
</camera>
<plugin name="depth_camera_controller" filename="libgazebo_ros_camera.so">
<baseline>0.2</baseline>
<alwaysOn>true</alwaysOn>
<updateRate>0.0</updateRate>
<frame_name>camera_depth_frame</frame_name>
<pointCloudCutoff>0.5</pointCloudCutoff>
<pointCloudCutoffMax>3.0</pointCloudCutoffMax>
<distortionK1>0</distortionK1>
<distortionK2>0</distortionK2>
<distortionK3>0</distortionK3>
<distortionT1>0</distortionT1>
<distortionT2>0</distortionT2>
<CxPrime>0</CxPrime>
<Cx>0</Cx>
<Cy>0</Cy>
<focalLength>0</focalLength>
<hackBaseline>0</hackBaseline>
</plugin>
</sensor>
</gazebo>
camera_linkの名前でリンクを追加し,libgazebo_ros_camera.soプラグインでカメラの各種設定をします.
詳細は一旦略します...
Gazeboの中にworld設定がないと計測できないので,worldを設定します.
まず,パッケージ内にworldディレクトリを作成して,そのディレクトリの中にmy_world.sdfファイルを生成します.
cd ~/ros2_ws/src/sam_bot_description
mkdir world
cd world
gedit my_world.sdf
my_world.sdfはなにもない簡単なものでもよいのですが,計測できないので,チュートリアルのページの通りのファイルを生成します.
このリンク先のデータをmy_world.sdfにペーストしてください.
次にlaunchファイルの編集をします.
generate_launch_description(): の次の行に下記の記載を追記してください.
world_path=os.path.join(pkg_share, 'world/my_world.sdf'),
launchファイルの最後の方にある return launch.LaunchDescription()の中にlaunch.actions.ExecuteProcess(cmd=['gazebo'の行があるので,その行を下記のように変更します.
launch.actions.ExecuteProcess(cmd=['gazebo', '--verbose', '-s', 'libgazebo_ros_init.so', '-s', 'libgazebo_ros_factory.so', world_path], output='screen'),
最後にCMakeLists.txtを修正.install()の中にworldを追加します.
install(
DIRECTORY src launch rviz config world
DESTINATION share/${PROJECT_NAME}
)
以上で終わり.
ビルドして確認します.
cd ~/ros2_ws/
colcon build
. install/setup.bash
ros2 launch sam_bot_description display.launch.py
実行すると下記のようにGazebo内のロボットから360度水平にLidarを照射している様子が確認できます.
RvizでLidarとcameraが設定されていることを確認する.
imu_linkとlidar_linkが反映されていることが確認できる.
sensor_mesgs/LaserScanが出ていることを確認するために,Rvizから直接確認する.
左メニュー下にある「Add」ボタンを押して出てくる下記ウィンドウの「By topic」タブを押して,出てくる画面に/scanが存在しているはずなので,その中のLaserScanを選択して右下の「OK」を押す.
Rvizを確認すると,下記画像のようにロボットの周辺でLidarが計測している場所に赤い点が表示される
同様に深度カメラの画像とポイントクラウドデータも表示できる.
以上で,移動ロボットのGazebo上の設定の説明は終了.
次は,Nav2での地図生成と自己位置推定の説明をします.