はじめに
今までは、ディファレンシャルドライブのオドメトリとImuセンサを用いてセンサ融合を行っていました。
今回は、imuなしでMapを作成するための構成を掲載しておきます。
前提条件
前提条件は、以下の通りです。
- worldファイルの作成が完了している
- Rviz2 上で /map を表示する方法が分かる (わからない方はこちらを参考)
URDF
first_robot.urdf
<?xml version="1.0" ?>
<robot name="rover">
<!-- main center object -->
<link name="base_link">
<visual>
<geometry>
<box size="0.4 0.35 0.075"/>
</geometry>
<material name="gray">
<color rgba="0.2 0.2 0.2 1"/>
</material>
</visual>
<inertial>
<mass value="2"/>
<inertia ixx="0.04" ixy="0.0" ixz="0.0" iyy="0.17" iyz="0.0" izz="0.25" />
</inertial>
<collision>
<geometry>
<box size="0.4 0.35 0.1"/>
</geometry>
</collision>
</link>
<!-- Robot Footprint -->
<link name="base_footprint"/>
<joint name="base_joint" type="fixed">
<parent link="base_link"/>
<child link="base_footprint"/>
<origin xyz="0.0 0.0 -0.075" rpy="0 0 0"/>
</joint>
<!-- front right wheel object -->
<link name="wheel_front_right">
<inertial>
<mass value="2"/>
<inertia ixx="1e-3" ixy="0.0" ixz="0" iyy="1e-3" iyz="0" izz="1e-3"/>
</inertial>
<visual>
<geometry>
<cylinder radius="0.075" length="0.05"/>
</geometry>
<material name="whtie">
<color rgba="1 1 1 1"/>
</material>
</visual>
<collision>
<geometry>
<cylinder radius="0.075" length="0.05"/>
</geometry>
<contact_coefficients mu="1" kp="1e+13" kd="1.0"/>
</collision>
</link>
<!-- front right wheel joint -->
<joint name="wheel_front_right_joint" type="continuous">
<origin xyz="0.125 0.2 0.0" rpy="1.57 0.0 0.0"/>
<parent link="base_link"/>
<child link="wheel_front_right"/>
<axis xyz="0.0 0.0 1.0"/>
</joint>
<!-- front left wheel object -->
<link name="wheel_front_left">
<inertial>
<mass value="2"/>
<inertia ixx="1e-3" ixy="0.0" ixz="0" iyy="1e-3" iyz="0" izz="1e-3"/>
</inertial>
<visual>
<geometry>
<cylinder radius="0.075" length="0.05"/>
</geometry>
<material name="whtie">
<color rgba="1 1 1 1"/>
</material>
</visual>
<collision>
<geometry>
<cylinder radius="0.075" length="0.05"/>
</geometry>
<contact_coefficients mu="1" kp="1e+13" kd="1.0"/>
</collision>
</link>
<!-- front left wheel joint -->
<joint name="wheel_front_left_joint" type="continuous">
<origin xyz="0.125 -0.2 0.0" rpy="1.57 0.0 0.0"/>
<parent link="base_link"/>
<child link="wheel_front_left"/>
<axis xyz="0.0 0.0 1.0"/>
</joint>
<!-- Caster Wheel -->
<link name="front_caster" type="fix">
<visual>
<geometry>
<sphere radius="0.075"/>
</geometry>
<material name="Cyan">
<color rgba="0 1.0 1.0 1.0"/>
</material>
</visual>
<collision>
<geometry>
<sphere radius="0.075"/>
</geometry>
</collision>
</link>
<joint name="caster_joint" type="fixed">
<parent link="base_link"/>
<child link="front_caster"/>
<origin xyz="-0.15 0.0 0" rpy="0 0 0"/>
</joint>
<!-- add camera object -->
<link name="camera_link">
<inertial>
<mass value="0.5"/>
<inertia ixx="0.01" ixy="0.0" ixz="0" iyy="0.01" iyz="0" izz="0.01"/>
</inertial>
<visual>
<geometry>
<box size="0.05 0.25 0.1"/>
</geometry>
<material name="blue">
<color rgba="0 0 1 1"/>
</material>
</visual>
</link>
<!-- add camera joint -->
<joint name="camera_joint" type="fixed">
<origin xyz="-0.175 0 0.1" rpy="0 0.0 3.14"/>
<parent link="base_link"/>
<child link="camera_link"/>
<axis xyz="0.0 0.0 1.0"/>
</joint>
<!-- add lidar object -->
<link name="lidar_link">
<inertial>
<mass value="0.5"/>
<inertia ixx="0.01" ixy="0.0" ixz="0" iyy="0.01" iyz="0" izz="0.01"/>
</inertial>
<visual>
<geometry>
<cylinder radius="0.05" length="0.05"/>
</geometry>
<material name="red">
<color rgba="1 0 0 0.7"/>
</material>
</visual>
</link>
<!-- add lidar joint -->
<joint name="lidar_joint" type="fixed">
<origin xyz="-0.215 0 0.0" rpy="0 0.0 1.57"/>
<parent link="base_link"/>
<child link="lidar_link"/>
<axis xyz="0.0 0.0 1.0"/>
</joint>
<!-- add imu object -->
<link name="imu_link">
<visual>
<inertial>
<mass value="0.3"/>
<inertia ixx="0.01" ixy="0.0" ixz="0" iyy="0.01" iyz="0" izz="0.01"/>
</inertial>
<geometry>
<box size="0.05 0.05 0.05"/>
</geometry>
<material name="green">
<color rgba="0 1 0 0.7"/>
</material>
</visual>
<collision>
<geometry>
<box size="0.05 0.05 0.05"/>
</geometry>
</collision>
</link>
<!-- add imu joint -->
<joint name="imu_joint" type="fixed">
<origin xyz="0 0 0.075" rpy="0 0 0"/>
<parent link="base_link"/>
<child link="imu_link"/>
<axis xyz="0 0 1.0"/>
</joint>
<!-- front diff drive status -->
<gazebo>
<plugin name="diff_drive" filename="libgazebo_ros_diff_drive.so">
<ros>
<remapping>cmd_vel:=cmd_vel</remapping>
<namespace>/first_robot</namespace>
<remapping>odom:=odom</remapping>
</ros>
<left_joint>wheel_front_left_joint</left_joint>
<right_joint>wheel_front_right_joint</right_joint>
<wheel_separation>0.4</wheel_separation>
<wheel_diameter>0.15</wheel_diameter>
<max_wheel_torque>20</max_wheel_torque>
<max_wheel_acceleration>1.0</max_wheel_acceleration>
<publish_odom>true</publish_odom>
<publish_odom_tf>false</publish_odom_tf>
<publish_wheel_tf>true</publish_wheel_tf>
<update_rate>30</update_rate>
<odometry_topic>odom</odometry_topic>
<odometry_frame>odom</odometry_frame>
<base_frame_id>base_footprint</base_frame_id>
<robot_base_frame>base_link</robot_base_frame>
<command_topic>cmd_vel</command_topic>
</plugin>
</gazebo>
<!-- camera plugin -->
<gazebo reference="camera_link">
<sensor type="camera" name="camera1">
<alwaysOn>true</alwaysOn>
<visualize>true</visualize>
<update_rate>5.0</update_rate>
<camera name="head">
<horizontal_fov>1.3962634</horizontal_fov>
<image>
<width>800</width>
<height>800</height>
<format>R8G8B8</format>
</image>
<clip>
<near>0.02</near>
<far>300</far>
</clip>
<noise>
<type>gaussian</type>
<mean>0.0</mean>
<stddev>0.007</stddev>
</noise>
</camera>
<plugin name="camera_controller" filename="libgazebo_ros_camera.so">
<cameraName>/camera</cameraName>
<imageTopicName>image_raw</imageTopicName>
<cameraInfoTopicName>camera_info</cameraInfoTopicName>
<frameName>camera_link</frameName>
<hackBaseline>0.07</hackBaseline>
</plugin>
</sensor>
<material>Gazebo/Blue</material>
</gazebo>
<!-- imu plugin -->
<gazebo reference="imu_link">
<sensor name="gazebo_imu" type="imu">
<gravity>true</gravity>
<visualize>true</visualize>
<update_rate>30</update_rate>
<always_on>true</always_on>
<plugin filename="libgazebo_ros_imu_sensor.so" name="imu_plugin">
<ros>
<namespace>/first_robot</namespace>
<remapping>~/out:=imu</remapping>
</ros>
<initial_orientation_as_reference>false</initial_orientation_as_reference>
<output_type>sensor_msgs/Imu</output_type>
<frame_name>imu_link</frame_name>
</plugin>
<imu>
<angular_velocity>
<x>
<noise type="gaussian">
<mean>0.0</mean>
<stddev>2e-04</stddev>
<bias_mean>0.0000075</bias_mean>
<bias_stddev>0.0000008</bias_stddev>
</noise>
</x>
<y>
<nosie type="gaussian">
<mean>0.0</mean>
<stddev>2e-04</stddev>
<bias_mean>0.0000075</bias_mean>
<bias_stddev>0.0000008</bias_stddev>
</nosie>
</y>
<z>
<nosie type="gaussian">
<mean>0.0</mean>
<stddev>2e-04</stddev>
<bias_mean>0.0000075</bias_mean>
<bias_stddev>0.0000008</bias_stddev>
</nosie>
</z>
</angular_velocity>
<linear_acceleration>
<x>
<nosie type="gaussian">
<mean>0.0</mean>
<stddev>1.7e-02</stddev>
<bias_mean>0.001</bias_mean>
<bias_stddev>0.001</bias_stddev>
</nosie>
</x>
<y>
<nosie type="gaussian">
<mean>0.0</mean>
<stddev>1.7e-02</stddev>
<bias_mean>0.001</bias_mean>
<bias_stddev>0.001</bias_stddev>
</nosie>
</y>
<z>
<nosie type="gaussian">
<mean>0.0</mean>
<stddev>1.7e-02</stddev>
<bias_mean>0.001</bias_mean>
<bias_stddev>0.001</bias_stddev>
</nosie>
</z>
</linear_acceleration>
</imu>
</sensor>
</gazebo>
<!-- lidar plugin -->
<gazebo reference="lidar_link">
<sensor name="gazebo_lidar" type="ray">
<always_on>true</always_on>
<visualize>true</visualize>
<update_rate>60</update_rate>
<plugin filename="libgazebo_ros_ray_sensor.so" name="gazebo_lidar">
<ros>
<remapping>~/out:=scan</remapping>
</ros>
<output_type>sensor_msgs/LaserScan</output_type>
<frame_name>lidar_link</frame_name>
</plugin>
<ray>
<scan>
<horizontal>
<samples>360</samples>
<resolution>1.000000</resolution>
<min_angle>0.000000</min_angle>
<max_angle>3.140000</max_angle>
</horizontal>
</scan>
<range>
<min>0.150</min>
<max>6.0</max>
<resolution>0.015</resolution>
</range>
<noise>
<type>gaussian</type>
<mean>0.0</mean>
<stddev>0.01</stddev>
</noise>
</ray>
</sensor>
<material>Gazebo/DarkGrey</material>
</gazebo>
</robot>
World
first_world.sdf
<sdf version='1.7'>
<world name='default'>
<light name='sun' type='directional'>
<cast_shadows>1</cast_shadows>
<pose>0 0 10 0 -0 0</pose>
<diffuse>0.8 0.8 0.8 1</diffuse>
<specular>0.2 0.2 0.2 1</specular>
<attenuation>
<range>1000</range>
<constant>0.9</constant>
<linear>0.01</linear>
<quadratic>0.001</quadratic>
</attenuation>
<direction>-0.5 0.1 -0.9</direction>
<spot>
<inner_angle>0</inner_angle>
<outer_angle>0</outer_angle>
<falloff>0</falloff>
</spot>
</light>
<model name='ground_plane'>
<static>1</static>
<link name='link'>
<collision name='collision'>
<geometry>
<plane>
<normal>0 0 1</normal>
<size>100 100</size>
</plane>
</geometry>
<surface>
<friction>
<ode>
<mu>100</mu>
<mu2>50</mu2>
</ode>
<torsional>
<ode/>
</torsional>
</friction>
<contact>
<ode/>
</contact>
<bounce/>
</surface>
<max_contacts>10</max_contacts>
</collision>
<visual name='visual'>
<cast_shadows>0</cast_shadows>
<geometry>
<plane>
<normal>0 0 1</normal>
<size>100 100</size>
</plane>
</geometry>
<material>
<script>
<uri>file://media/materials/scripts/gazebo.material</uri>
<name>Gazebo/Grey</name>
</script>
</material>
</visual>
<self_collide>0</self_collide>
<enable_wind>0</enable_wind>
<kinematic>0</kinematic>
</link>
</model>
<gravity>0 0 -9.8</gravity>
<magnetic_field>6e-06 2.3e-05 -4.2e-05</magnetic_field>
<atmosphere type='adiabatic'/>
<physics type='ode'>
<max_step_size>0.001</max_step_size>
<real_time_factor>1</real_time_factor>
<real_time_update_rate>1000</real_time_update_rate>
</physics>
<scene>
<ambient>0.4 0.4 0.4 1</ambient>
<background>0.7 0.7 0.7 1</background>
<shadows>1</shadows>
</scene>
<audio>
<device>default</device>
</audio>
<wind/>
<spherical_coordinates>
<surface_model>EARTH_WGS84</surface_model>
<latitude_deg>0</latitude_deg>
<longitude_deg>0</longitude_deg>
<elevation>0</elevation>
<heading_deg>0</heading_deg>
</spherical_coordinates>
<model name='first_robot'>
<link name='base_link'>
<inertial>
<pose>-0.065 0 0.016667 0 -0 0</pose>
<mass>3</mass>
<inertia>
<ixx>0.0641667</ixx>
<ixy>0</ixy>
<ixz>0.0055</ixz>
<iyy>0.219917</iyy>
<iyz>0</iyz>
<izz>0.29575</izz>
</inertia>
</inertial>
<collision name='base_link_collision'>
<pose>0 0 0 0 -0 0</pose>
<geometry>
<box>
<size>0.4 0.35 0.1</size>
</box>
</geometry>
<max_contacts>10</max_contacts>
<surface>
<contact>
<ode/>
</contact>
<bounce/>
<friction>
<torsional>
<ode/>
</torsional>
<ode/>
</friction>
</surface>
</collision>
<collision name='base_link_fixed_joint_lump__front_caster_collision_1'>
<pose>-0.15 0 0 0 -0 0</pose>
<geometry>
<sphere>
<radius>0.075</radius>
</sphere>
</geometry>
<max_contacts>10</max_contacts>
<surface>
<contact>
<ode/>
</contact>
<bounce/>
<friction>
<torsional>
<ode/>
</torsional>
<ode/>
</friction>
</surface>
</collision>
<collision name='base_link_fixed_joint_lump__imu_link_collision_2'>
<pose>0 0 0.075 0 -0 0</pose>
<geometry>
<box>
<size>0.05 0.05 0.05</size>
</box>
</geometry>
<surface>
<contact>
<ode/>
</contact>
<friction>
<ode/>
<torsional>
<ode/>
</torsional>
</friction>
<bounce/>
</surface>
<max_contacts>10</max_contacts>
</collision>
<visual name='base_link_visual'>
<pose>0 0 0 0 -0 0</pose>
<geometry>
<box>
<size>0.4 0.35 0.075</size>
</box>
</geometry>
</visual>
<visual name='base_link_fixed_joint_lump__camera_link_visual_1'>
<pose>-0.175 0 0.1 0 -0 3.14</pose>
<geometry>
<box>
<size>0.05 0.25 0.1</size>
</box>
</geometry>
<material>
<script>
<name>Gazebo/Blue</name>
<uri>file://media/materials/scripts/gazebo.material</uri>
</script>
</material>
</visual>
<visual name='base_link_fixed_joint_lump__front_caster_visual_2'>
<pose>-0.15 0 0 0 -0 0</pose>
<geometry>
<sphere>
<radius>0.075</radius>
</sphere>
</geometry>
</visual>
<visual name='base_link_fixed_joint_lump__imu_link_visual_3'>
<pose>0 0 0.075 0 -0 0</pose>
<geometry>
<box>
<size>0.05 0.05 0.05</size>
</box>
</geometry>
</visual>
<visual name='base_link_fixed_joint_lump__lidar_link_visual_4'>
<pose>-0.215 0 0 0 -0 1.57</pose>
<geometry>
<cylinder>
<length>0.05</length>
<radius>0.05</radius>
</cylinder>
</geometry>
<material>
<script>
<name>Gazebo/DarkGrey</name>
<uri>file://media/materials/scripts/gazebo.material</uri>
</script>
</material>
</visual>
<sensor name='camera1' type='camera'>
<visualize>1</visualize>
<update_rate>5</update_rate>
<camera name='head'>
<horizontal_fov>1.39626</horizontal_fov>
<image>
<width>800</width>
<height>800</height>
<format>R8G8B8</format>
</image>
<clip>
<near>0.02</near>
<far>300</far>
</clip>
<noise>
<type>gaussian</type>
<mean>0</mean>
<stddev>0.007</stddev>
</noise>
</camera>
<plugin name='camera_controller' filename='libgazebo_ros_camera.so'>
<cameraName>/camera</cameraName>
<imageTopicName>image_raw</imageTopicName>
<cameraInfoTopicName>camera_info</cameraInfoTopicName>
<frameName>camera_link</frameName>
<hackBaseline>0.07</hackBaseline>
</plugin>
<pose>-0.175 0 0.1 0 -0 3.14</pose>
<alwaysOn>1</alwaysOn>
</sensor>
<sensor name='gazebo_imu' type='imu'>
<visualize>1</visualize>
<update_rate>30</update_rate>
<always_on>1</always_on>
<plugin name='imu_plugin' filename='libgazebo_ros_imu_sensor.so'>
<ros>
<namespace>/first_robot</namespace>
<remapping>~/out:=imu</remapping>
</ros>
<initial_orientation_as_reference>0</initial_orientation_as_reference>
<output_type>sensor_msgs/Imu</output_type>
<frame_name>imu_link</frame_name>
</plugin>
<imu>
<angular_velocity>
<x>
<noise type='gaussian'>
<mean>0</mean>
<stddev>0.0002</stddev>
<bias_mean>7.5e-06</bias_mean>
<bias_stddev>8e-07</bias_stddev>
</noise>
</x>
<y>
<noise type='none'/>
<nosie type='gaussian'>
<mean>0.0</mean>
<stddev>2e-04</stddev>
<bias_mean>0.0000075</bias_mean>
<bias_stddev>0.0000008</bias_stddev>
</nosie>
</y>
<z>
<noise type='none'/>
<nosie type='gaussian'>
<mean>0.0</mean>
<stddev>2e-04</stddev>
<bias_mean>0.0000075</bias_mean>
<bias_stddev>0.0000008</bias_stddev>
</nosie>
</z>
</angular_velocity>
<linear_acceleration>
<x>
<noise type='none'/>
<nosie type='gaussian'>
<mean>0.0</mean>
<stddev>1.7e-02</stddev>
<bias_mean>0.001</bias_mean>
<bias_stddev>0.001</bias_stddev>
</nosie>
</x>
<y>
<noise type='none'/>
<nosie type='gaussian'>
<mean>0.0</mean>
<stddev>1.7e-02</stddev>
<bias_mean>0.001</bias_mean>
<bias_stddev>0.001</bias_stddev>
</nosie>
</y>
<z>
<noise type='none'/>
<nosie type='gaussian'>
<mean>0.0</mean>
<stddev>1.7e-02</stddev>
<bias_mean>0.001</bias_mean>
<bias_stddev>0.001</bias_stddev>
</nosie>
</z>
</linear_acceleration>
</imu>
<pose>0 0 0.075 0 -0 0</pose>
<gravity>1</gravity>
</sensor>
<sensor name='gazebo_lidar' type='ray'>
<always_on>1</always_on>
<visualize>1</visualize>
<update_rate>60</update_rate>
<plugin name='gazebo_lidar' 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>
<ray>
<scan>
<horizontal>
<samples>360</samples>
<resolution>1</resolution>
<min_angle>0</min_angle>
<max_angle>3.14</max_angle>
</horizontal>
<vertical>
<samples>1</samples>
<min_angle>0</min_angle>
<max_angle>0</max_angle>
</vertical>
</scan>
<range>
<min>0.15</min>
<max>6</max>
<resolution>0.015</resolution>
</range>
<noise>
<type>gaussian</type>
<mean>0</mean>
<stddev>0.01</stddev>
</noise>
</ray>
<pose>-0.215 0 0 0 -0 1.57</pose>
</sensor>
<self_collide>0</self_collide>
<enable_wind>0</enable_wind>
<kinematic>0</kinematic>
</link>
<joint name='wheel_front_left_joint' type='revolute'>
<pose relative_to='base_link'>0.125 -0.2 0 1.57 -0 0</pose>
<parent>base_link</parent>
<child>wheel_front_left</child>
<axis>
<xyz>0 0 1</xyz>
<limit>
<lower>-1e+16</lower>
<upper>1e+16</upper>
</limit>
<dynamics>
<spring_reference>0</spring_reference>
<spring_stiffness>0</spring_stiffness>
</dynamics>
</axis>
</joint>
<link name='wheel_front_left'>
<pose relative_to='wheel_front_left_joint'>0 0 0 0 -0 0</pose>
<inertial>
<pose>0 0 0 0 -0 0</pose>
<mass>2</mass>
<inertia>
<ixx>0.001</ixx>
<ixy>0</ixy>
<ixz>0</ixz>
<iyy>0.001</iyy>
<iyz>0</iyz>
<izz>0.001</izz>
</inertia>
</inertial>
<collision name='wheel_front_left_collision'>
<pose>0 0 0 0 -0 0</pose>
<geometry>
<cylinder>
<length>0.05</length>
<radius>0.075</radius>
</cylinder>
</geometry>
<max_contacts>10</max_contacts>
<surface>
<contact>
<ode/>
</contact>
<bounce/>
<friction>
<torsional>
<ode/>
</torsional>
<ode/>
</friction>
</surface>
</collision>
<visual name='wheel_front_left_visual'>
<pose>0 0 0 0 -0 0</pose>
<geometry>
<cylinder>
<length>0.05</length>
<radius>0.075</radius>
</cylinder>
</geometry>
</visual>
<self_collide>0</self_collide>
<enable_wind>0</enable_wind>
<kinematic>0</kinematic>
</link>
<joint name='wheel_front_right_joint' type='revolute'>
<pose relative_to='base_link'>0.125 0.2 0 1.57 -0 0</pose>
<parent>base_link</parent>
<child>wheel_front_right</child>
<axis>
<xyz>0 0 1</xyz>
<limit>
<lower>-1e+16</lower>
<upper>1e+16</upper>
</limit>
<dynamics>
<spring_reference>0</spring_reference>
<spring_stiffness>0</spring_stiffness>
</dynamics>
</axis>
</joint>
<link name='wheel_front_right'>
<pose relative_to='wheel_front_right_joint'>0 0 0 0 -0 0</pose>
<inertial>
<pose>0 0 0 0 -0 0</pose>
<mass>2</mass>
<inertia>
<ixx>0.001</ixx>
<ixy>0</ixy>
<ixz>0</ixz>
<iyy>0.001</iyy>
<iyz>0</iyz>
<izz>0.001</izz>
</inertia>
</inertial>
<collision name='wheel_front_right_collision'>
<pose>0 0 0 0 -0 0</pose>
<geometry>
<cylinder>
<length>0.05</length>
<radius>0.075</radius>
</cylinder>
</geometry>
<max_contacts>10</max_contacts>
<surface>
<contact>
<ode/>
</contact>
<bounce/>
<friction>
<torsional>
<ode/>
</torsional>
<ode/>
</friction>
</surface>
</collision>
<visual name='wheel_front_right_visual'>
<pose>0 0 0 0 -0 0</pose>
<geometry>
<cylinder>
<length>0.05</length>
<radius>0.075</radius>
</cylinder>
</geometry>
</visual>
<self_collide>0</self_collide>
<enable_wind>0</enable_wind>
<kinematic>0</kinematic>
</link>
<static>0</static>
<plugin name='diff_drive' filename='libgazebo_ros_diff_drive.so'>
<ros>
<remapping>cmd_vel:=cmd_vel</remapping>
<namespace>/first_robot</namespace>
<remapping>odom:=odom</remapping>
</ros>
<left_joint>wheel_front_left_joint</left_joint>
<right_joint>wheel_front_right_joint</right_joint>
<wheel_separation>0.4</wheel_separation>
<wheel_diameter>0.15</wheel_diameter>
<max_wheel_torque>20</max_wheel_torque>
<max_wheel_acceleration>1.0</max_wheel_acceleration>
<publish_odom>1</publish_odom>
<publish_odom_tf>0</publish_odom_tf>
<publish_wheel_tf>1</publish_wheel_tf>
<update_rate>30</update_rate>
<odometry_topic>odom</odometry_topic>
<odometry_frame>odom</odometry_frame>
<base_frame_id>base_footprint</base_frame_id>
<robot_base_frame>base_link</robot_base_frame>
<command_topic>cmd_vel</command_topic>
</plugin>
<pose>0 0 0 0 -0 0</pose>
</model>
<state world_name='default'>
<sim_time>85 425000000</sim_time>
<real_time>86 534032298</real_time>
<wall_time>1705369601 344027836</wall_time>
<iterations>85425</iterations>
<model name='cafe'>
<pose>3.26542 -6.22712 0 0 -0 0</pose>
<scale>1 1 1</scale>
<link name='link'>
<pose>3.26542 -6.22712 0 0 -0 0</pose>
<velocity>0 0 0 0 -0 0</velocity>
<acceleration>0 0 0 0 -0 0</acceleration>
<wrench>0 0 0 0 -0 0</wrench>
</link>
</model>
<model name='first_robot'>
<pose>3.57979 -6.67003 0.264809 0 -6e-05 -1.01821</pose>
<scale>1 1 1</scale>
<link name='base_link'>
<pose>3.57979 -6.67003 0.264809 0 -6e-05 -1.01821</pose>
<velocity>0.000423 -0.00075 -0.001719 0.009915 0.005781 -8.2e-05</velocity>
<acceleration>1.02157 -1.1232 -1.94689 -2.91743 0.52183 0.271105</acceleration>
<wrench>3.06472 -3.36959 -5.84068 0 -0 0</wrench>
</link>
<link name='wheel_front_left'>
<pose>3.47516 -6.88141 0.264816 1.5697 -0.777665 -1.01743</pose>
<velocity>0.000406 -0.00078 -0.003219 0.008333 0.008348 -0.001588</velocity>
<acceleration>0.68783 -0.831266 -6.43748 -2.82733 -0.143385 2.74644</acceleration>
<wrench>1.37566 -1.66253 -12.875 0 -0 0</wrench>
</link>
<link name='wheel_front_right'>
<pose>3.81563 -6.67145 0.264817 1.56992 0.466972 -1.0186</pose>
<velocity>0.000419 -0.000798 -0.003094 0.008328 0.008356 -0.001205</velocity>
<acceleration>0.790008 -0.992654 -6.18865 -1.05285 0.973515 -2.77191</acceleration>
<wrench>1.58002 -1.98531 -12.3773 0 -0 0</wrench>
</link>
</model>
<model name='ground_plane'>
<pose>0 0 0 0 -0 0</pose>
<scale>1 1 1</scale>
<link name='link'>
<pose>0 0 0 0 -0 0</pose>
<velocity>0 0 0 0 -0 0</velocity>
<acceleration>0 0 0 0 -0 0</acceleration>
<wrench>0 0 0 0 -0 0</wrench>
</link>
</model>
<light name='sun'>
<pose>0 0 10 0 -0 0</pose>
</light>
</state>
<model name='cafe'>
<static>1</static>
<link name='link'>
<collision name='main_floor'>
<pose>-0.4 -0.75 0.0948 0 -0 0</pose>
<geometry>
<box>
<size>9.38 22.63 0.19</size>
</box>
</geometry>
<max_contacts>10</max_contacts>
<surface>
<contact>
<ode/>
</contact>
<bounce/>
<friction>
<torsional>
<ode/>
</torsional>
<ode/>
</friction>
</surface>
</collision>
<collision name='wall_1'>
<pose>-5.03 0.53 1.415 0 -0 0</pose>
<geometry>
<box>
<size>0.12 23.16 2.83</size>
</box>
</geometry>
<max_contacts>10</max_contacts>
<surface>
<contact>
<ode/>
</contact>
<bounce/>
<friction>
<torsional>
<ode/>
</torsional>
<ode/>
</friction>
</surface>
</collision>
<collision name='wall_2'>
<pose>4.24 -0.31 1.415 0 -0 0</pose>
<geometry>
<box>
<size>0.12 21.48 2.83</size>
</box>
</geometry>
<max_contacts>10</max_contacts>
<surface>
<contact>
<ode/>
</contact>
<bounce/>
<friction>
<torsional>
<ode/>
</torsional>
<ode/>
</friction>
</surface>
</collision>
<collision name='wall_3'>
<pose>-1.48 7.43 1.415 0 -0 0</pose>
<geometry>
<box>
<size>7.2 0.12 2.83</size>
</box>
</geometry>
<max_contacts>10</max_contacts>
<surface>
<contact>
<ode/>
</contact>
<bounce/>
<friction>
<torsional>
<ode/>
</torsional>
<ode/>
</friction>
</surface>
</collision>
<collision name='wall_4'>
<pose>2.09 8.9 1.435 0 -0 0</pose>
<geometry>
<box>
<size>0.12 3.05 2.87</size>
</box>
</geometry>
<max_contacts>10</max_contacts>
<surface>
<contact>
<ode/>
</contact>
<bounce/>
<friction>
<torsional>
<ode/>
</torsional>
<ode/>
</friction>
</surface>
</collision>
<collision name='wall_5'>
<pose>3.155 10.4 1.435 0 -0 0</pose>
<geometry>
<box>
<size>2.13 0.12 2.87</size>
</box>
</geometry>
<max_contacts>10</max_contacts>
<surface>
<contact>
<ode/>
</contact>
<bounce/>
<friction>
<torsional>
<ode/>
</torsional>
<ode/>
</friction>
</surface>
</collision>
<collision name='wall_6'>
<pose>0.615 -10.98 1.415 0 -0 0</pose>
<geometry>
<box>
<size>7.36 0.15 2.83</size>
</box>
</geometry>
<max_contacts>10</max_contacts>
<surface>
<contact>
<ode/>
</contact>
<bounce/>
<friction>
<torsional>
<ode/>
</torsional>
<ode/>
</friction>
</surface>
</collision>
<collision name='wall_7'>
<pose>-4.62 -10.98 1.415 0 -0 0</pose>
<geometry>
<box>
<size>0.93 0.15 2.83</size>
</box>
</geometry>
<max_contacts>10</max_contacts>
<surface>
<contact>
<ode/>
</contact>
<bounce/>
<friction>
<torsional>
<ode/>
</torsional>
<ode/>
</friction>
</surface>
</collision>
<collision name='wall_8'>
<pose>-3.61 -10.98 2.69 0 -0 0</pose>
<geometry>
<box>
<size>1.09 0.15 0.28</size>
</box>
</geometry>
<max_contacts>10</max_contacts>
<surface>
<contact>
<ode/>
</contact>
<bounce/>
<friction>
<torsional>
<ode/>
</torsional>
<ode/>
</friction>
</surface>
</collision>
<collision name='coke'>
<pose>-4.385 0.26 0.95 0 -0 0</pose>
<geometry>
<box>
<size>1.03 1.03 1.52</size>
</box>
</geometry>
<max_contacts>10</max_contacts>
<surface>
<contact>
<ode/>
</contact>
<bounce/>
<friction>
<torsional>
<ode/>
</torsional>
<ode/>
</friction>
</surface>
</collision>
<visual name='visual'>
<geometry>
<mesh>
<uri>model://cafe/meshes/cafe.dae</uri>
</mesh>
</geometry>
</visual>
<self_collide>0</self_collide>
<enable_wind>0</enable_wind>
<kinematic>0</kinematic>
</link>
<pose>-0.223247 0.216961 0 0 -0 0</pose>
</model>
<gui fullscreen='0'>
<camera name='user_camera'>
<pose>2.6866 -8.93942 3.93553 0 0.895643 0.960195</pose>
<view_controller>orbit</view_controller>
<projection_type>perspective</projection_type>
</camera>
</gui>
</world>
</sdf>
launch
first_localization.launch.py
import os
from ament_index_python.packages import get_package_share_directory
import launch
from launch import LaunchDescription
from launch_ros.actions import Node
from launch.substitutions import LaunchConfiguration
def generate_launch_description():
package_dir = get_package_share_directory("ros2_first_test")
urdf = os.path.join(package_dir, "urdf" , "first_robot.urdf")
rviz = os.path.join(package_dir, "rviz" , "first_robot.rviz")
ekf_path = os.path.join(package_dir, "config", 'first_ekf.yaml')
# use_sim_time = LaunchConfiguration('use_sim_time', default='true')
use_sim_time = LaunchConfiguration('use_sim_time', default='false')
world_path = os.path.join(package_dir, 'world', 'first_world.sdf')
return LaunchDescription([
launch.actions.DeclareLaunchArgument(name='gui', default_value='True',
description='Flag to enable joint_state_publisher_gui'),
Node(
package='robot_state_publisher',
executable='robot_state_publisher',
name='robot_state_publisher',
output='screen',
arguments=[urdf],
),
Node(
package='joint_state_publisher',
executable='joint_state_publisher',
name='joint_state_publisher',
output="screen"
# arguments=[urdf],
),
Node(
package='robot_localization',
executable='ekf_node',
name='ekf_filter_node',
output='screen',
parameters=[ekf_path, {'use_sim_time': use_sim_time}]),
# gazebo settings
#launch.actions.ExecuteProcess(
# cmd=["gazebo", "--verbose", "-s", "libgazebo_ros_factory.so"],),
launch.actions.ExecuteProcess(
cmd=['gazebo', '--verbose', '-s', 'libgazebo_ros_factory.so', world_path], output='screen'),
Node(
package="gazebo_ros",
executable="spawn_entity.py",
name="urdf_spawner",
output="screen",
parameters=[{'use_sim_time': use_sim_time}],
arguments=["-topic", "/robot_description", "-entity", "first_robot"],
),
Node(
package="rviz2",
executable="rviz2",
name="rviz2",
arguments=["-d", rviz],
parameters=[{'use_sim_time': use_sim_time}],
output="screen",
),
])
first_slam.launch.py
import os
from ament_index_python.packages import get_package_share_directory
from launch_ros.actions import Node
from launch import LaunchDescription
from launch.substitutions import LaunchConfiguration
def generate_launch_description():
package_dir = get_package_share_directory("ros2_first_test")
use_sim_time = LaunchConfiguration('use_sim_time', default='true')
slam_params = os.path.join(package_dir, "config", 'first_slam_settings.yaml')
return LaunchDescription([
Node(
parameters=[
{"slam_params_file": slam_params},
{'use_sim_time': use_sim_time}
],
package='slam_toolbox',
executable='async_slam_toolbox_node',
name='slam_toolbox',
output='screen'),
])
configs
first_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: 10.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: false
# 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 of odom_frame if unspecified
odom0: first_robot/odom
odom0_config: [true, true, false, # position of xyz
false, false, true, # angle of rpy
true, true, false, # velocity of xyz
false, false, true, # angular velocity of rpy
true, true, false,] # acceleraion of xyz
# imu0: first_robot/imu
# imu0_config: [true, true, false, # position of xyz
# false, false, true, # angle of rpy
# true, true, false, # velocity of xyz
# false, false, true, # angular velocity of rpy
# true, true, false] # acceleraion of xyz
first_localization.yaml
slam_toolbox:
ros__parameters:
# Plugin params
solver_plugin: solver_plugins::CeresSolver
ceres_linear_solver: SPARSE_NORMAL_CHOLESKY
ceres_preconditioner: SCHUR_JACOBI
ceres_trust_strategy: LEVENBERG_MARQUARDT
ceres_dogleg_type: TRADITIONAL_DOGLEG
ceres_loss_function: None
# ROS Parameters
odom_frame: odom
map_frame: map
base_frame: base_footprint
scan_topic: /scan
use_map_saver: true
mode: mapping #localization
# if you'd like to immediately start continuing a map at a given pose
# or at the dock, but they are mutually exclusive, if pose is given
# will use pose
#map_file_name: test_steve
# map_start_pose: [0.0, 0.0, 0.0]
#map_start_at_dock: true
debug_logging: false
throttle_scans: 1
transform_publish_period: 0.02 #if 0 never publishes odometry
map_update_interval: 5.0
resolution: 0.05
max_laser_range: 20.0 #for rastering images
minimum_time_interval: 0.5
transform_timeout: 0.2
tf_buffer_duration: 30.0
stack_size_to_use: 40000000 #// program needs a larger stack size to serialize large maps
enable_interactive_mode: true
# General Parameters
use_scan_matching: true
use_scan_barycenter: true
minimum_travel_distance: 0.5
minimum_travel_heading: 0.5
scan_buffer_size: 200
scan_buffer_maximum_scan_distance: 10.0
link_match_minimum_response_fine: 0.1
link_scan_maximum_distance: 1.5
loop_search_maximum_distance: 3.0
do_loop_closing: true
loop_match_minimum_chain_size: 10
loop_match_maximum_variance_coarse: 3.0
loop_match_minimum_response_coarse: 0.35
loop_match_minimum_response_fine: 0.45
# Correlation Parameters - Correlation Parameters
correlation_search_space_dimension: 0.5
correlation_search_space_resolution: 0.01
correlation_search_space_smear_deviation: 0.1
# Correlation Parameters - Loop Closure Parameters
loop_search_space_dimension: 8.0
loop_search_space_resolution: 0.05
loop_search_space_smear_deviation: 0.03
# Scan Matcher Parameters
distance_variance_penalty: 0.5
angle_variance_penalty: 1.0
fine_search_angle_offset: 0.00349
coarse_search_angle_offset: 0.349
coarse_angle_resolution: 0.0349
minimum_angle_penalty: 0.9
minimum_distance_penalty: 0.5
use_response_expansion: true
実行方法
cd ~/ros2_ws
colcon build
source install/setup.bash
ros2 launch ros2_first_test first_slam.launch.py
別のターミナルを開きます。
source install/setup.bash
ros2 launch ros2_first_test first_localization.launch.py
これで実行完了です。
少し待つと、Rviz2 上にマップが生成されていきます。
エラー対応
[async_slam_toolbox_node-1] [INFO] [1705533866.974027065] [slam_toolbox]: Message Filter dropping message: frame ‘lidar_link’ at time 97.682 for reason ‘discarding message because the queue is full’
と表示される場合は
first_localization.yaml の 44 行目
scan_buffer_size: 200
の数値を増やしてください。
おわりに
今回は imu なしで map を生成するための備忘録です。
この後は Map 作成完結編へと続きます。
コメント