7. ROS2 Joint Control: Extension Python Scripting

7.1. Learning Objectives

In this tutorial, we will interact with a manipulator, the Franka Emika Panda Robot. We will

  • Add a ROS2 Joint State publisher and subscriber via UI

  • Add a ROS2 Joint State publisher and subscriber using the omnigraph python API using the script editor.

Prerequisite

  • Completed Isaac Sim Workflows to understand the Extension Workflow.

  • ros2_workspace was sourced.

7.2. Add Joint States in UI

  1. Go to Content tab below the viewport, and open Isaac/Robots/Franka/franka_alt_fingers.usd.

  2. Go to Create -> Visual Scripting -> Action Graph to create an Action graph.

  3. Add the following omnigraph nodes into the Action graph: On Playback Tick, Isaac Read Simulation Time, ROS2 Publish Joint State, ROS2 Subscribe Joint State.

  4. Click on each ROS2 Publish Joint State and ROS2 Subscribe Joint State node and add the /panda robot articulation to the targetPrim.

  5. Connect the Tick output of the On Playback Tick node to the Execution input of the ROS2 Publish Joint State and ROS2 Subscribe JointState nodes.

  6. Connect the Simulation Time output of the Isaac Read Simulation Time node to the Timestamp input of the ROS2 Publish Joint State node. The graph should look similar to the one shown below:

    ROS2 Joint State Action Graph
  7. Press Play to start publishing joint states to the /joint_states topic and subscribing commands on the /joint_command topic.

  8. To test out the ROS2 bridge, use provided ROS2 python node to publish joint commands to the robot. In a ROS2-sourced terminal run the following command:

    ros2 run isaac_tutorials ros2_publisher.py
    
  9. While the robot is moving, open a ROS2-sourced terminal and check the joint state rostopic by running:

    ros2 topic echo /joint_states
    

    You’ll see that the position of the joints are changing following the robot.

7.3. Add Joint States in Extension

The same action done via UI can also be done using python script. More details regarding the different workflow of using Omniverse Isaac Sim can be found Isaac Sim Workflows.

  1. Go to Content tab below the viewport, and open Isaac/Robots/Franka/franka_alt_fingers.usd.

  2. Open Script Editor in Window -> Script Editor and copy paste the following code into it. This is the equivalent to Steps 2-6 of the previous section.

    import omni.graph.core as og
    from omni.isaac.core_nodes.scripts.utils import set_target_prims
    og.Controller.edit(
        {"graph_path": "/panda/ActionGraph", "evaluator_name": "execution"},
        {
            og.Controller.Keys.CREATE_NODES: [
                ("OnPlaybackTick", "omni.graph.action.OnPlaybackTick"),
                ("PublishJointState", "omni.isaac.ros2_bridge.ROS2PublishJointState"),
                ("SubscribeJointState", "omni.isaac.ros2_bridge.ROS2SubscribeJointState"),
                ("ReadSimTime", "omni.isaac.core_nodes.IsaacReadSimulationTime"),
            ],
            og.Controller.Keys.CONNECT: [
                ("OnPlaybackTick.outputs:tick", "PublishJointState.inputs:execIn"),
                ("OnPlaybackTick.outputs:tick", "SubscribeJointState.inputs:execIn"),
                ("ReadSimTime.outputs:simulationTime", "PublishJointState.inputs:timeStamp"),
            ],
        },
    )
    
    # Setting the /Franka target prim to Subscribe JointState node
    set_target_prims(primPath="/panda/ActionGraph/SubscribeJointState", targetPrimPaths=["/panda"])
    
    # Setting the /Franka target prim to Publish JointState node
    set_target_prims(primPath="/panda/ActionGraph/PublishJointState", targetPrimPaths=["/panda"])
    
  3. Press Run in the Script Editor and the Action Graph with all required nodes should be added. You can find the corresponding ActionGraph in the Stage Tree.

  4. Same as the previous section, test out the ROS2 bridge using the provide ROS2 python node to publish joint commands to the robot. In a ROS2-sourced terminal run the following command:

    ros2 run isaac_tutorials ros2_publisher.py
    
  5. Check the joint state with ros2 topic echo while it’s moving:

    ros2 topic echo /joint_states
    

7.4. Position and Velocity Control Modes

The joint state subscriber currently supports position and velocity control. Each joint can only be controlled by a single mode at a time, but different joints on the same articulation tree can be controlled by different modes.

The snippet below demonstrates how to command a robot using both position and velocity controls by grouping joints that use the same mode into one message, and create two different messages for position control joints and velocity controlled joints.

import threading

import rclpy
from sensor_msgs.msg import JointState

rclpy.init()
node = rclpy.create_node('position_velocity_publisher')
pub = node.create_publisher(JointState, 'joint_command', 10)

# Spin in a separate thread
thread = threading.Thread(target=rclpy.spin, args=(node, ), daemon=True)
thread.start()

joint_state_position = JointState()
joint_state_velocity = JointState()

joint_state_position.name = ["joint1", "joint2","joint3"]
joint_state_velocity.name = ["wheel_left_joint", "wheel_right_joint"]
joint_state_position.position = [0.2,0.2,0.2]
joint_state_velocity.velocity = [20.0, -20.0]

rate = node.create_rate(10)
try:
    while rclpy.ok():
        pub.publish(joint_state_position)
        pub.publish(joint_state_velocity)
        rate.sleep()
except KeyboardInterrupt:
    pass
rclpy.shutdown()
thread.join()

7.5. Summary

This tutorial covered adding a ROS2 Joint State publisher and subscriber via both UI and Extension scripting.

7.5.1. Next Steps

Continue on to the next tutorial in our ROS2 Tutorials series, MoveIt 2 to learn how to connect the manipulator up with MoveIt 2.