grid SLAM with a 2D LiDAR
mapping: requires global positioning to record environment
localization: using a map to determine position in global coordinate system
sometimes we only have starting point, detection and odometry and we need to do SLAM
2 categories: feature and grid SLAM. In grid we define a grid of cells and determine if they are occupied/unoccupied
navigation: using maps to determine safe trajectory between locations.
base_link
is the frame attached to our robot
odom
represents world origin as seen by odometry. Note odometry integrates wheel velocities, hence it is smooth but has small drift errors that accumulate over time.
map
represents the true world origin, and allows to visualize drift errors. map
to odom
jumps around but stays generally correct over time
base_footprint
frame is shadow of base_link
on the 2D ground
- add
base _footprint
link torobot_core.xacro
<!-- BASE_FOOTPRINT LINK -->
<joint name="base_footprint_joint type="fixed">
<parent link="base_link"/>
<child link="base_footprint"/>
<origin xyz="0 0 0" rpy="0 0 0"/>
</joint>
<link name="base_footprint">
</link>
- install
slam_toolbox
$ sudo apt install ros-foxy-slam-toolbox
We will run SLAM in online (live) asynchronous (may skip some scans but always process the latest) mode
Copy the parameter file to our project:
$ cp /opt/ros/foxy/share/slam_toolbox/config/mapper_params_online_async.yaml sevillabot/sevillabot/config/
Run with:
(PC T1)$ ros2 launch sevillabot launch_sim.launch.py world:=~/dev_ws/src/sevillabot/worlds/obstacles.world
Gazebo does not start!
First issue: Cannot import name 'GazeboRosPaths' error apparently caused by keeping python scripts in /scripts folder. I moved them to my_scripts.
After long troubleshooting and comparing with articubot_one from Josh Newans I found the differences:
- in file
rsp.launch.py
: add a newsim_mode
parameter in the call made torobot.urdf.xacro
, make it same value asuse_sim_time
- in file
robot.urdf.xacro
declaresim_mode
xacro parameter withfalse
as default. Note this file usesuse_ros2_control
to toggle betweenros2_control.xacro
and agazebo_control.xacro
, which does not exist!! - in
ros2_control.xacro
file usesim_mode
to toggle between DiffDriveArduino (real robot) and GazeboSystem (simulation). Addgaz_ros2_ctl_use_sim.yaml
parameter file in call tolibgazebo_ros2_control.so
- Create
gaz_ros2_ctl_use_sim.yaml
parameter file that setsuse_sim_time
totrue
Launch also rviz:
(PC T2)$ rviz2 -d ~/dev_ws/src/sevillabot/config/bot_with_sensors.rviz
Launch teleop (would be better with gamepad if available):
(PC T3)$ ros2 run teleop_twist_keyboard teleop_twist_keyboard --ros-args -r /cmd_vel:=/diff_cont/cmd_vel_unstamped
Launch SLAM:
(PC T2)$ ros2 launch slam_toolbox online_async_launch.py params_file:=./src/sevillabot/config/mapper_params_online_async.yaml use_sim_time:=true
In RVIZ:
-
add a Map and set the topic to /map
-
change the Fixed Frame from odom to map (this to have the map steady)
-
save RVIZ config to
slam_gazebo.rviz
(PC T1)$ ros2 launch sevillabot launch_sim.launch.py world:=~/dev_ws/src/sevillabot/worlds/obstacles.world
(PC T2)$ ros2 launch slam_toolbox online_async_launch.py params_file:=./src/sevillabot/config/mapper_params_online_async.yaml use_sim_time:=true
(PC T3)$ rviz2 -d ~/dev_ws/src/sevillabot/config/slam_gazebo.rviz
(PC T4)$ ros2 run teleop_twist_keyboard teleop_twist_keyboard --ros-args -r /cmd_vel:=/diff_cont/cmd_vel_unstamped
Note: the above is now obsolete due to use of twist_mux
Close everything an reopen
Make sure config file mapper_params_online_async.yaml
is ok: set mode to mapping, map file and start commented out:
mode: mapping # localization or mapping depending on the activity
...
# map_file_name: /home/mhered/sevillabot/sevillabot/maps/map_obstacles_serial
...
# map_start_at_dock: true
In RVIZ:
- Drive around to build the map
- May help to switch View to TopDownOrthographic
To save the map:
- In RVIZ Add New Panel
- save map for external services eg navigation produces PGM + YAML, serialize to reuse in slam_toolbox produces DATA + POSEGRAPH
- map files saved by default in the workspace
/dev_ws
Close everything and reopen
Modify config file mapper_params_online_async.yaml
: set mode to localization, declare map full path without extension and set start at dock
mode: localization # localization or mapping depending on the activity
...
map_file_name: /home/mhered/sevillabot/sevillabot/maps/map_obstacles_serial
...
map_start_at_dock: true
Install Nav2 (acml is part of nav2)
$ sudo apt install ros-foxy-navigation2 ros-foxy-nav2-bringup
Several steps:
- Run a map server (from save version because it is external):
(PC T1)$ ros2 run nav2_map_server map_server --ros-args -p yaml_filename:=/home/mhered/sevillabot/sevillabot/maps/map_obstacles_save.yaml -p use_sim_time:=true
- Activate it
(PC T2)$ ros2 run nav2_util lifecycle_bringup map_server
- Relaunch gazebo, RVIZ and slam_toolbox
In RVIZ take care Map is set to Reliable and Transient Local
- run acml
$ ros2 run nav2_amcl amcl --ros-args -p use_sim_time:=true
- activate it
$ ros2 run nav2_util lifecycle_bringup amcl
Finding a safe trajectory between an initial and a target pose We will need:
- accurate position estimate ie localization from SLAM
- awareness of obstacles from 1) a static prerrecorded map used for plnning the trajectory + 2) updated live sensor data. Stored in a costmap (avoid high cost, low cost is safe)
- info about size and dynamics of the robot
$ sudo apt install ros-foxy-navigation2 ros-foxy-nav2-bringup
$ sudo apt install ros-foxy-twist-mux
Will need to remap velocities from /cmd_vel
where nav2 publishes to /diff_cont/cmd_vel_unstamped
where our controller expects them, but instead we will use twist_mux
node to multiplex velocities. This allows to prioritize, block topics on certain circumstances etc
We will set up twist_mux
to take joystick velocities from /cmd_vel_joy
and navigation velocities from /cmd_vel
combine them and publish them to /diff_cont/cmd_vel_unstamped
Modify joystick.launch.py
so it remaps velocities to /cmd_vel_joy
instead of directly to/diff_cont/cmd_vel_unstamped
and add new file twist_mux.yaml
:
twist_mux:
ros__parameters:
topics:
navigation:
topic: cmd_vel
timeout: 0.5
priority: 10
joystick:
topic: cmd_vel_joy
timeout: 0.5
priority: 100
- Run with:
$ ros2 run twist_mux twist_mux --ros-args --params-file ~/dev_ws/src/sevillabot/config/twist_mux.yaml -r cmd_vel_out:=diff_cont/cmd_vel_unstamped
[INFO] [1712707933.767525498] [twist_mux]: Topic handler 'topics.joystick' subscribed to topic 'cmd_vel_joy': timeout = 0.500000s , priority = 100.
[INFO] [1712707933.767752264] [twist_mux]: Topic handler 'topics.navigation' subscribed to topic 'cmd_vel': timeout = 0.500000s , priority = 10.
-
Launch gazebo, RVIZ and slam_toolbox
-
Launch nav2
$ ros2 launch nav2_bringup navigation_launch.py use_sim_time:=true
- In RVIZ add a new Map, set topic to
/global_costmap/costmap
, set Color Scheme to costmap, turn off the other map. - Set a 2D goal pose. It works!!
$ sudo apt install ros-foxy-slam-toolbox
$ sudo apt install ros-foxy-navigation2 ros-foxy-nav2-bringup
$ sudo apt install ros-foxy-twist-mux
git pull to update the repo in the bot
- Clone and symlink the repo:
(bot):$ cd ~/git
(bot):$ git clone https://github.com/ldrobotSensorTeam/ldlidar_stl_ros2
(bot):$ ln -s ~/git/ldlidar_stl_ros2/ ~/robot_ws/src/
- Plug the LD06 and find out the device id (
by-id
because the path/dev/ttyUSB*
may change):
(bot):$ ls /dev/serial/by-id
usb-1a86_USB2.0-Ser_-if00-port0
usb-Silicon_Labs_CP2102_USB_to_UART_Bridge_Controller_0001-if00-port0
Where usb-Silicon_Labs_CP2102_USB_to_UART_Bridge_Controller_0001-if00-port0
is the LD06 ( andusb-1a86_USB2.0-Ser_-if00-port0
is the arduino)
- Set device permissions:
(bot):$ sudo chmod 777 /dev/serial/by-id/usb-Silicon_Labs_CP2102_USB_to_UART_Bridge_Controller_0001-if00-port0
- Copy
ldlidar_stl_ros2/launch/ld06.launch.py
over to sevillabot repo, updatepackage_name
andport_name
then build the package and source:
(bot):$ cp ~/robot_ws/src/ldlidar_stl_ros2/launch/ld06.launch.py ~/robot_ws/src/sevillabot/launch/ld06.launch.py
... # edit file
(bot):$ cd ~/robot_ws
(bot):$ colcon build
(bot):$ source install/setup.bash
13/04/24 Updated launch_robot.launch.py
and launch_sim.launch.py
to spawn robot, launch gamepad and twist_mux with a single command
(robot T1):$ ros2 launch sevillabot launch_robot.launch.py #spawns robot, launches gamepad and twist_mux
Launch Lidar:
(robot T2):$ ros2 launch sevillabot ld06.launch.py
View it from PC with:
(PC):$ rviz2 -d ~/dev_ws/src/sevillabot/config/bot_with_sensors.rviz