ROS2 - Gazebo - Unity - robotics
Wiki
Link: http://wiki.ros.org/urdf/XML/linkJoints: http://wiki.ros.org/urdf/XML/joint
Commands
| Command | Where to run | Description |
| source /opt/ros/humble/setup.zsh | Anywhere | Source your ROS 2 Installation ( "humble" is variable ) |
| ros2 pkg create --build-type ament_cmake [package_name] | In workspace src folder | Create a new package with CMake as the build tool / script |
| source install/setup.zsh | Root folder | Allows your project directory to be recognized by ros2 command |
| colcon build --symlink-install | Root folder | Build the project |
| ros2 launch project_name "launch.py file" | Root folder | Run a launch file detailing what to do ( see example file below ) |
| ros2 launch project_name "launch.py file" use_sim_time:=true | Root folder | Run robot state publisher with sim_time enabled |
| rviz2 | Root folder | Launch RViz |
| ros2 run joint_state_publisher_gui joint_state_publisher_gui | Root folder | Allows the setting of joint states via a GUI. Also |
| ros2 launch gazebo_ros gazebo.launch.py | Root folder | Run Gazebo (My assumption is that ros knows where Gazebo is installed and this is some standard launch file) |
| ros2 run gazebo_ros spawn_entity.py -topic robot_description -entity bot_name | Root folder | Spawns the robot into gazebo |
| ros2 run teleop_twist_keyboard teleop_twist_keyboard | Root folder | Use our keyboard to send twist velocities to the robot |
| ros2 run xacro xacro --inorder -o filename.urdf input_file.xacro | Anywhere | Convert xacro file to urdf |
| Topics | ||
|---|---|---|
| ros2 topic list | Anywhere | List topic endpoints |
| ros2 topic info /cmd_vel | Anywhere | Show info about a specific topic |
| ros2 interface list | Anywhere | List message types |
| ros2 interface show std_msgs/msg/String | Anywhere | Will show information on a certain message type |
| ros2 topic pub /chatter std_msgs/msg/String "data: 'Hello, world'" | Anywhere | Publish a string message to a topic named /chatter |
| ros2 pkg executables [package] | Anywhere | Lists executables related to optionally defined package |
Understanding Terminology
The word link is somewhat confusing to me because when I think of a link
I'm thinking of a link between two points. Whereas in URDF files, it seems
like the word link is used to define a physical point in space that is the center
of an object.
The term "link point" makes more sense to me I guess and that a "joint" defines
how a child "link point" moves relative to a parent "link point".
"Twist" in ros is used to specify linear and angular velocities together
Gotchas
- When you rotate a joint, it is rotating the entire axis. So, visuals where the axis of rotation is defined, it will be defined in terms of the rotated joint
Package Info
Packages have an outer directory ( called the workspace ), and a src directory inside. Then another directory
inside that that has all the source files you write.
From the directory above src, run colcon build --symlink-install
to build the files needed to run it
To prepare env for commands, run (from same directory) source install/setup.zsh
Then launch with ros2 launch package_name rsp.launch.py or whatever your launch file is named
Example Launch File
import os
from ament_index_python.packages import get_package_share_directory
from launch import LaunchDescription
from launch.substitutions import LaunchConfiguration
from launch.actions import DeclareLaunchArgument
from launch_ros.actions import Node
import xacro
def generate_launch_description():
# Check if we're told to use sim time
use_sim_time = LaunchConfiguration('use_sim_time')
# Process the URDF file
pkg_path = os.path.join(get_package_share_directory('robotics-tutorial'))
xacro_file = os.path.join(pkg_path,'description','robot.urdf.xacro')
robot_description_config = xacro.process_file(xacro_file)
# Create a robot_state_publisher node
params = {'robot_description': robot_description_config.toxml(), 'use_sim_time': use_sim_time}
node_robot_state_publisher = Node(
package='robot_state_publisher',
executable='robot_state_publisher',
output='screen',
parameters=[params]
)
# Launch!
return LaunchDescription([
DeclareLaunchArgument(
'use_sim_time',
default_value='false',
description='Use sim time if true'),
node_robot_state_publisher
])
Inertial Macros File
<?xml version="1.0"?>
<robot xmlns:xacro="http://www.ros.org/wiki/xacro" >
<!-- Specify some standard inertial calculations https://en.wikipedia.org/wiki/List_of_moments_of_inertia -->
<!-- These make use of xacro's mathematical functionality -->
<xacro:macro name="inertial_sphere" params="mass radius *origin">
<inertial>
<xacro:insert_block name="origin"/>
<mass value="${mass}" />
<inertia ixx="${(2/5) * mass * (radius*radius)}" ixy="0.0" ixz="0.0"
iyy="${(2/5) * mass * (radius*radius)}" iyz="0.0"
izz="${(2/5) * mass * (radius*radius)}" />
</inertial>
</xacro:macro>
<xacro:macro name="inertial_box" params="mass x y z *origin">
<inertial>
<xacro:insert_block name="origin"/>
<mass value="${mass}" />
<inertia ixx="${(1/12) * mass * (y*y+z*z)}" ixy="0.0" ixz="0.0"
iyy="${(1/12) * mass * (x*x+z*z)}" iyz="0.0"
izz="${(1/12) * mass * (x*x+y*y)}" />
</inertial>
</xacro:macro>
<xacro:macro name="inertial_cylinder" params="mass length radius *origin">
<inertial>
<xacro:insert_block name="origin"/>
<mass value="${mass}" />
<inertia ixx="${(1/12) * mass * (3*radius*radius + length*length)}" ixy="0.0" ixz="0.0"
iyy="${(1/12) * mass * (3*radius*radius + length*length)}" iyz="0.0"
izz="${(1/2) * mass * (radius*radius)}" />
</inertial>
</xacro:macro>
</robot>
ROS Gazebo Launch File
import os
from ament_index_python.packages import get_package_share_directory
from launch import LaunchDescription
from launch.actions import IncludeLaunchDescription
from launch.launch_description_sources import PythonLaunchDescriptionSource
from launch_ros.actions import Node
def generate_launch_description():
# Include the robot_state_publisher launch file, provided by our own package. Force sim time to be enabled
# !!! MAKE SURE YOU SET THE PACKAGE NAME CORRECTLY !!!
package_name='articubot_one' #<--- CHANGE ME
rsp = IncludeLaunchDescription(
PythonLaunchDescriptionSource([os.path.join(
get_package_share_directory(package_name),'launch','rsp.launch.py'
)]), launch_arguments={'use_sim_time': 'true'}.items()
)
# Include the Gazebo launch file, provided by the gazebo_ros package
gazebo = IncludeLaunchDescription(
PythonLaunchDescriptionSource([os.path.join(
get_package_share_directory('gazebo_ros'), 'launch', 'gazebo.launch.py')]),
)
# Run the spawner node from the gazebo_ros package. The entity name doesn't really matter if you only have a single robot.
spawn_entity = Node(package='gazebo_ros', executable='spawn_entity.py',
arguments=['-topic', 'robot_description',
'-entity', 'my_bot'],
output='screen')
# Launch them all!
return LaunchDescription([
rsp,
gazebo,
spawn_entity,
])
Import STL Mesh
// Scale by 0.001 because scale is in millimeters vs meters
<geometry>
<mesh filename="file://$(find consumption_rate_limiters)/meshes/Bauer_20V_Battery_Mount.stl" scale="0.001 0.001 0.001" />
</geometry>
Make sure to add meshes to CMakeLists.txt at this section:
install(
DIRECTORY config description launch worlds meshes
DESTINATION share/${PROJECT_NAME}
)