ROS2 - Gazebo - Unity - robotics

Wiki

Link: http://wiki.ros.org/urdf/XML/link
Joints: http://wiki.ros.org/urdf/XML/joint
        

Commands

CommandWhere to runDescription
source /opt/ros/humble/setup.zshAnywhereSource your ROS 2 Installation ( "humble" is variable )
ros2 pkg create --build-type ament_cmake [package_name]In workspace src folderCreate a new package with CMake as the build tool / script
source install/setup.zshRoot folderAllows your project directory to be recognized by ros2 command
colcon build --symlink-installRoot folderBuild the project
ros2 launch project_name "launch.py file"Root folderRun a launch file detailing what to do ( see example file below )
ros2 launch project_name "launch.py file" use_sim_time:=trueRoot folderRun robot state publisher with sim_time enabled
rviz2Root folderLaunch RViz
ros2 run joint_state_publisher_gui joint_state_publisher_guiRoot folderAllows the setting of joint states via a GUI. Also
ros2 launch gazebo_ros gazebo.launch.pyRoot folderRun 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_nameRoot folderSpawns the robot into gazebo
ros2 run teleop_twist_keyboard teleop_twist_keyboardRoot folderUse our keyboard to send twist velocities to the robot
ros2 run xacro xacro --inorder -o filename.urdf input_file.xacroAnywhereConvert xacro file to urdf
Topics
ros2 topic listAnywhereList topic endpoints
ros2 topic info /cmd_velAnywhereShow info about a specific topic
ros2 interface listAnywhereList message types
ros2 interface show std_msgs/msg/StringAnywhereWill show information on a certain message type
ros2 topic pub /chatter std_msgs/msg/String "data: 'Hello, world'"AnywherePublish a string message to a topic named /chatter
ros2 pkg executables [package]AnywhereLists 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}
)