1
+ import argparse
2
+ from isaaclab .app import AppLauncher
3
+
4
+ parser = argparse .ArgumentParser (description = "Robot Arm with Task Space IK Control" )
5
+ parser .add_argument ("--robot" , type = str , default = "franka_panda" , help = "Name of the robot." )
6
+ AppLauncher .add_app_launcher_args (parser )
7
+ args_cli = parser .parse_args ()
8
+
9
+ app_launcher = AppLauncher (args_cli )
10
+ simulation_app = app_launcher .app
11
+
12
+ import torch
13
+
14
+ import isaaclab .sim as sim_utils
15
+ from isaaclab .assets import AssetBaseCfg
16
+ from isaaclab .controllers import DifferentialIKController , DifferentialIKControllerCfg
17
+ from isaaclab .managers import SceneEntityCfg
18
+ from isaaclab .markers import VisualizationMarkers
19
+ from isaaclab .markers .config import FRAME_MARKER_CFG
20
+ from isaaclab .scene import InteractiveScene , InteractiveSceneCfg
21
+ from isaaclab .utils import configclass
22
+ from isaaclab .utils .assets import ISAAC_NUCLEUS_DIR
23
+ from isaaclab .utils .math import subtract_frame_transforms
24
+
25
+ ##
26
+ # Pre-defined configs
27
+ ##
28
+ from isaaclab_assets import UR10_CFG , FRANKA_PANDA_HIGH_PD_CFG
29
+
30
+
31
+ @configclass
32
+ class TableTopSceneCfg (InteractiveSceneCfg ):
33
+ """Configuration for a cart-pole scene."""
34
+
35
+ # ground plane
36
+ ground = AssetBaseCfg (
37
+ prim_path = "/World/defaultGroundPlane" ,
38
+ spawn = sim_utils .GroundPlaneCfg (),
39
+ init_state = AssetBaseCfg .InitialStateCfg (pos = (0.0 , 0.0 , - 1.05 )),
40
+ )
41
+
42
+ # lights
43
+ dome_light = AssetBaseCfg (
44
+ prim_path = "/World/Light" ,
45
+ spawn = sim_utils .DomeLightCfg (intensity = 3000.0 , color = (0.75 , 0.75 , 0.75 ))
46
+ )
47
+
48
+ # mount
49
+ table = AssetBaseCfg (
50
+ prim_path = "{ENV_REGEX_NS}/Table" ,
51
+ spawn = sim_utils .UsdFileCfg (
52
+ usd_path = f"{ ISAAC_NUCLEUS_DIR } /Props/Mounts/Stand/stand_instanceable.usd" , scale = (2.0 , 2.0 , 2.0 )
53
+ ),
54
+ )
55
+
56
+ # Cube
57
+ cube = AssetBaseCfg (
58
+ prim_path = "/World/cube" ,
59
+ spawn = sim_utils .CuboidCfg (
60
+ size = [0.1 , 0.1 , 0.1 ]
61
+ ),
62
+ init_state = AssetBaseCfg .InitialStateCfg (pos = (0.5 , 0.0 , 0.5 )),
63
+ )
64
+
65
+ # articulation
66
+ if args_cli .robot == "franka_panda" :
67
+ robot = FRANKA_PANDA_HIGH_PD_CFG .replace (prim_path = "{ENV_REGEX_NS}/Robot" )
68
+ elif args_cli .robot == "ur10" :
69
+ robot = UR10_CFG .replace (prim_path = "{ENV_REGEX_NS}/Robot" )
70
+ else :
71
+ raise ValueError (f"Robot { args_cli .robot } is not supported. Valid: franka_panda, ur10" )
72
+ # robot = UR10_CFG.replace(prim_path="{ENV_REGEX_NS}/Robot")
73
+
74
+
75
+ def run_simulator (sim : sim_utils .SimulationContext , scene : InteractiveScene ):
76
+
77
+ robot = scene ["robot" ]
78
+
79
+ # Create controller
80
+ diff_ik_cfg = DifferentialIKControllerCfg (command_type = "pose" , use_relative_mode = False , ik_method = "dls" )
81
+ diff_ik_controller = DifferentialIKController (diff_ik_cfg , num_envs = scene .num_envs , device = sim .device )
82
+
83
+ # Markers
84
+ frame_marker_cfg = FRAME_MARKER_CFG .copy ()
85
+ frame_marker_cfg .markers ["frame" ].scale = (0.1 , 0.1 , 0.1 )
86
+ ee_marker = VisualizationMarkers (frame_marker_cfg .replace (prim_path = "/Visuals/ee_current" ))
87
+ goal_marker = VisualizationMarkers (frame_marker_cfg .replace (prim_path = "/Visuals/ee_goal" ))
88
+
89
+ # Specify robot-specific parameters
90
+ if args_cli .robot == "franka_panda" :
91
+ robot_entity_cfg = SceneEntityCfg ("robot" , joint_names = ["panda_joint.*" ], body_names = ["panda_hand" ])
92
+ elif args_cli .robot == "ur10" :
93
+ robot_entity_cfg = SceneEntityCfg ("robot" , joint_names = [".*" ], body_names = ["ee_link" ])
94
+ else :
95
+ raise ValueError (f"Robot { args_cli .robot } is not supported. Valid: franka_panda, ur10" )
96
+ # robot_entity_cfg = SceneEntityCfg("robot", joint_names=[".*"], body_names=["ee_link"])
97
+
98
+ # Resolving the scene entities
99
+ robot_entity_cfg .resolve (scene )
100
+
101
+ # Obtain the frame index of the end-effector ; For a fixed base robot, the frame index is one less than the body index. This is because ; the root body is not included in the returned Jacobians.
102
+ if robot .is_fixed_base :
103
+ ee_jacobi_idx = robot_entity_cfg .body_ids [0 ] - 1
104
+ else :
105
+ ee_jacobi_idx = robot_entity_cfg .body_ids [0 ]
106
+
107
+ # Define simulation stepping
108
+ sim_dt = sim .get_physics_dt ()
109
+
110
+ # May have to set initial position first
111
+ if args_cli .robot == "franka_panda" :
112
+ joint_position = robot .data .default_joint_pos .clone ()
113
+ joint_vel = robot .data .default_joint_vel .clone ()
114
+ robot .write_joint_state_to_sim (joint_position , joint_vel )
115
+ else :
116
+ joint_position_index = 0
117
+ joint_position_list = [
118
+ [0.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 ],
119
+ ]
120
+ joint_position = torch .tensor (joint_position_list [joint_position_index ], device = sim .device )
121
+ joint_vel = robot .data .default_joint_vel .clone ()
122
+ joint_pos_des = joint_position .unsqueeze (0 )[:, robot_entity_cfg .joint_ids ].clone ()
123
+ robot .write_joint_state_to_sim (joint_pos_des , joint_vel )
124
+
125
+ while simulation_app .is_running ():
126
+ # Get cube/target_point coordinates
127
+ position , quaternion = scene ["cube" ].get_world_poses ()
128
+ ik_commands = torch .cat ([position , quaternion ], dim = 1 ) # Quaternion is in (w, x, y, z)
129
+
130
+ diff_ik_controller .set_command (ik_commands )
131
+
132
+ # obtain quantities from simulation
133
+ jacobian = robot .root_physx_view .get_jacobians ()[:, ee_jacobi_idx , :, robot_entity_cfg .joint_ids ]
134
+ ee_pose_w = robot .data .body_state_w [:, robot_entity_cfg .body_ids [0 ], 0 :7 ]
135
+ root_pose_w = robot .data .root_state_w [:, 0 :7 ]
136
+ joint_pos = robot .data .joint_pos [:, robot_entity_cfg .joint_ids ]
137
+
138
+ # compute frame in root frame
139
+ ee_pos_b , ee_quat_b = subtract_frame_transforms (
140
+ root_pose_w [:, 0 :3 ], root_pose_w [:, 3 :7 ], ee_pose_w [:, 0 :3 ], ee_pose_w [:, 3 :7 ]
141
+ )
142
+
143
+ # compute the joint commands
144
+ joint_pos_des = diff_ik_controller .compute (ee_pos_b , ee_quat_b , jacobian , joint_pos )
145
+
146
+ # apply actions (Smooth movement)
147
+ robot .set_joint_position_target (joint_pos_des , joint_ids = robot_entity_cfg .joint_ids )
148
+ scene .write_data_to_sim ()
149
+
150
+ # perform step
151
+ sim .step ()
152
+
153
+ # update buffers
154
+ scene .update (sim_dt )
155
+
156
+ # obtain quantities from simulation
157
+ ee_pose_w = robot .data .body_state_w [:, robot_entity_cfg .body_ids [0 ], 0 :7 ]
158
+
159
+ # update marker positions
160
+ ee_marker .visualize (ee_pose_w [:, 0 :3 ], ee_pose_w [:, 3 :7 ])
161
+ goal_marker .visualize (ik_commands [:, 0 :3 ] + scene .env_origins , ik_commands [:, 3 :7 ])
162
+
163
+
164
+ def main ():
165
+ # Load kit helper
166
+ sim_cfg = sim_utils .SimulationCfg (dt = 0.01 , device = args_cli .device )
167
+ sim = sim_utils .SimulationContext (sim_cfg )
168
+
169
+ # Set main camera
170
+ sim .set_camera_view ([2.5 , 2.5 , 2.5 ], [0.0 , 0.0 , 0.0 ])
171
+
172
+ # Design scene
173
+ scene_cfg = TableTopSceneCfg (num_envs = 1 , env_spacing = 2.0 )
174
+ scene = InteractiveScene (scene_cfg )
175
+
176
+ # Play the simulator
177
+ sim .reset ()
178
+
179
+ print ("[INFO]: Setup complete..." )
180
+
181
+ # Run the simulator
182
+ run_simulator (sim , scene )
183
+
184
+
185
+ if __name__ == "__main__" :
186
+ main ()
187
+ simulation_app .close ()
0 commit comments