Hello Robot#
Learning Objectives#
This tutorial details how to add and move a mobile robot in NVIDIA Isaac Sim in an extension application. After this tutorial, you will understand how to add a robot to the simulation and apply actions to its wheels using Python.
10-15 Minute Tutorial
Getting Started#
Prerequisites
Review Hello World prior to beginning this tutorial.
Begin with the source code of the Hello World example developed in the previous tutorial: Hello World.
Adding a Robot#
Begin by adding a NVIDIA Jetbot to the scene, which allows you to access the library of NVIDIA Isaac Sim robots, sensors, and environments located on a Omniverse Nucleus Server using Python, as well as navigate through it using the Content window.
Note
The server shown in these steps has been connected to in Workstation Setup. Follow these steps first before proceeding.
Add the assets by simply dragging them to the stage window or the viewport.
Try to do the same thing through Python in the Hello World example.
Create a new stage: File > new > Don’t Save
Open the
hello_world.pyfile by clicking the Open Source Code button in the Hello World window.
1import isaacsim.core.experimental.utils.stage as stage_utils
2from isaacsim.core.experimental.prims import Articulation
3from isaacsim.examples.base.base_sample_experimental import BaseSample
4from isaacsim.storage.native import get_assets_root_path
5import carb
6
7
8class HelloWorld(BaseSample):
9 def __init__(self) -> None:
10 super().__init__()
11
12 def setup_scene(self):
13 # Add ground plane
14 ground_plane = stage_utils.add_reference_to_stage(
15 usd_path=get_assets_root_path() + "/Isaac/Environments/Grid/default_environment.usd",
16 path="/World/ground",
17 )
18
19 # Get the assets root path from the Nucleus server
20 assets_root_path = get_assets_root_path()
21 if assets_root_path is None:
22 carb.log_error("Could not find nucleus server with /Isaac folder")
23 return
24
25 # Add the Jetbot robot to the stage
26 asset_path = assets_root_path + "/Isaac/Robots/NVIDIA/Jetbot/jetbot.usd"
27 stage_utils.add_reference_to_stage(usd_path=asset_path, path="/World/Fancy_Robot")
28
29 async def setup_post_load(self):
30 # Wrap the Jetbot with the Articulation class for control
31 self._jetbot = Articulation("/World/Fancy_Robot")
32
33 # Print info about the Jetbot
34 print("Number of DOFs: " + str(self._jetbot.num_dofs))
35 print("DOF names: " + str(self._jetbot.dof_names))
36 print("Joint Positions: " + str(self._jetbot.get_dof_positions().numpy()))
Click the LOAD button to load the scene and see the Jetbot appear. Although it is being simulated, it is not moving. The next section walks through how to make the robot move.
Move the Robot#
In NVIDIA Isaac Sim, Robots are constructed of physically accurate articulated joints. Applying actions to these articulations make them move.
Next, apply random velocities to the Jetbot’s wheel joints to get it moving.
1import isaacsim.core.experimental.utils.stage as stage_utils
2from isaacsim.core.experimental.prims import Articulation
3from isaacsim.examples.base.base_sample_experimental import BaseSample
4from isaacsim.core.simulation_manager import SimulationManager
5from isaacsim.storage.native import get_assets_root_path
6import numpy as np
7import carb
8
9
10class HelloWorld(BaseSample):
11 def __init__(self) -> None:
12 super().__init__()
13 self._physics_callback_id = None
14
15 def setup_scene(self):
16 # Add ground plane
17 ground_plane = stage_utils.add_reference_to_stage(
18 usd_path=get_assets_root_path() + "/Isaac/Environments/Grid/default_environment.usd",
19 path="/World/ground",
20 )
21
22 # Get the assets root path from the Nucleus server
23 assets_root_path = get_assets_root_path()
24 if assets_root_path is None:
25 carb.log_error("Could not find nucleus server with /Isaac folder")
26 return
27
28 # Add the Jetbot robot to the stage
29 asset_path = assets_root_path + "/Isaac/Robots/NVIDIA/Jetbot/jetbot.usd"
30 stage_utils.add_reference_to_stage(usd_path=asset_path, path="/World/Fancy_Robot")
31
32 async def setup_post_load(self):
33 # Wrap the Jetbot with the Articulation class for control
34 self._jetbot = Articulation("/World/Fancy_Robot")
35
36 # Register a physics callback to send actions every physics step
37 from isaacsim.core.simulation_manager.impl.isaac_events import IsaacEvents
38 self._physics_callback_id = SimulationManager.register_callback(
39 self.send_robot_actions, IsaacEvents.POST_PHYSICS_STEP
40 )
41
42 def send_robot_actions(self, dt, context):
43 # Apply random velocity targets to the wheel joints
44 # Jetbot has 2 DOFs: left_wheel_joint and right_wheel_joint
45 random_velocities = 5 * np.random.rand(1, 2) # Shape: (1, num_dofs)
46 self._jetbot.set_dof_velocity_targets(random_velocities)
47
48 def physics_cleanup(self):
49 # Clean up callback when the extension is unloaded
50 if self._physics_callback_id is not None:
51 SimulationManager.deregister_callback(self._physics_callback_id)
52 self._physics_callback_id = None
Click the LOAD button to load the scene and watch the Jetbot move with random velocities.
Note
Pressing STOP, then PLAY in this workflow might not reset the world properly. Use the RESET button instead.
Extra Practice#
This example applies random velocities to the Jetbot articulation controller. Try the following exercises:
Make the Jetbot move backwards (hint: use negative velocities).
Make the Jetbot turn right (hint: apply different velocities to each wheel).
Make the Jetbot stop after 5 seconds (hint: track elapsed time in the callback).
Controlling Specific Joints#
You can also control specific joints by their names or indices. Here’s how to get the wheel joint indices and apply velocities only to specific joints:
1import isaacsim.core.experimental.utils.stage as stage_utils
2from isaacsim.core.experimental.prims import Articulation
3from isaacsim.examples.base.base_sample_experimental import BaseSample
4from isaacsim.core.simulation_manager import SimulationManager
5from isaacsim.storage.native import get_assets_root_path
6import numpy as np
7import carb
8
9
10class HelloWorld(BaseSample):
11 def __init__(self) -> None:
12 super().__init__()
13 self._physics_callback_id = None
14
15 def setup_scene(self):
16 # Add ground plane
17 ground_plane = stage_utils.add_reference_to_stage(
18 usd_path=get_assets_root_path() + "/Isaac/Environments/Grid/default_environment.usd",
19 path="/World/ground",
20 )
21
22 # Add the Jetbot robot to the stage
23 assets_root_path = get_assets_root_path()
24 asset_path = assets_root_path + "/Isaac/Robots/NVIDIA/Jetbot/jetbot.usd"
25 stage_utils.add_reference_to_stage(usd_path=asset_path, path="/World/Fancy_Robot")
26
27 async def setup_post_load(self):
28 # Wrap the Jetbot with the Articulation class
29 self._jetbot = Articulation("/World/Fancy_Robot")
30
31 # Print available DOF names
32 print("Available DOFs:", self._jetbot.dof_names)
33
34 # Get indices for specific wheel joints
35 self._wheel_indices = self._jetbot.get_dof_indices(
36 ["left_wheel_joint", "right_wheel_joint"]
37 ).numpy()
38 print("Wheel indices:", self._wheel_indices)
39
40 # Register physics callback
41 from isaacsim.core.simulation_manager.impl.isaac_events import IsaacEvents
42 self._physics_callback_id = SimulationManager.register_callback(
43 self.send_robot_actions, IsaacEvents.POST_PHYSICS_STEP
44 )
45
46 def send_robot_actions(self, dt, context):
47 # Apply velocity targets to specific DOF indices
48 wheel_velocities = np.array([[10.0, 10.0]]) # Both wheels same speed = forward
49 self._jetbot.set_dof_velocity_targets(
50 wheel_velocities,
51 dof_indices=self._wheel_indices
52 )
53
54 def physics_cleanup(self):
55 if self._physics_callback_id is not None:
56 SimulationManager.deregister_callback(self._physics_callback_id)
57 self._physics_callback_id = None
Summary#
This tutorial covered the following topics:
Adding NVIDIA Isaac Sim library components from a Nucleus Server
Adding a robot to the stage using
stage_utils.add_reference_to_stage()Wrapping a robot with the
Articulationclass for controlUsing
set_dof_velocity_targets()to apply velocity controlRegistering physics callbacks with
SimulationManagerControlling specific joints by name or index
Next Steps#
Continue on to the next tutorial in the Essential Tutorials series, Adding a Manipulator Robot, to learn how to add a manipulator robot to the simulation.
Further Learning#
Nucleus Server
For an overview of how to best leverage a Nucleus Server, see the Nucleus Overview in NVIDIA Omniverse tutorial.
Robot Specific Extensions
NVIDIA Isaac Sim provides several robot extensions such as
isaacsim.robot.manipulators.examples.franka,isaacsim.robot.manipulators.examples.universal_robots, and many more. To learn more, check out the standalone examples located atstandalone_examples/api/isaacsim.robot.manipulators/frankaandstandalone_examples/api/isaacsim.robot.manipulators/universal_robots/.