Skip to content

Commit 36ea382

Browse files
committed
Add planning to grasp API
1 parent 18e9ebd commit 36ea382

38 files changed

+941
-537
lines changed

CHANGELOG.md

+24-1
Original file line numberDiff line numberDiff line change
@@ -10,17 +10,40 @@ its affiliates is strictly prohibited.
1010
-->
1111
# Changelog
1212

13-
## Latest Commit
13+
## Version 0.7.5
14+
15+
### Changes in Default Behavior
16+
- Remove explicit global seed setting for numpy and random. To enforce deterministic behavior,
17+
use `np.random.seed(2)` and `random.seed(2)` in your program.
18+
- geom.types.VoxelGrid now uses a different algorithm to calculate number of voxels per dimension
19+
and also to compute xyz locations in a grid. This new implementation matches implementation in
20+
nvblox.
1421

1522
### New Features
1623
- Add pose cost metric to MPC to allow for partial pose reaching.
1724
- Update obstacle poses in cpu reference with an optional flag.
25+
- Add planning to grasp API in ``MotionGen.plan_grasp`` that plans a sequence of motions to grasp
26+
an object given grasp poses. This API also provides args to disable collisions during the grasping
27+
phase.
28+
- Constrained planning can now use either goal frame or base frame at runtime.
1829

1930
### BugFixes & Misc.
2031
- Fixed optimize_dt not being correctly set when motion gen is called in reactive mode.
2132
- Add documentation for geom module.
2233
- Add descriptive api for computing kinematics.
2334
- Fix cv2 import order in isaac sim realsense examples.
35+
- Fix attach sphere api mismatch in ``TrajOptSolver``.
36+
- Fix bug in ``get_spline_interpolated_trajectory`` where
37+
numpy array was created instead of torch tensor.
38+
- Fix gradient bug when sphere origin is exactly at face of a cuboid.
39+
- Add support for parsing Yaml 1.2 format with an updated regex for scientific notations.
40+
- Move to yaml `SafeLoader` from `Loader`.
41+
- Graph search checks if a node exists before attempting to find a path.
42+
- Fix `steps_max` becoming 0 when optimized dt has NaN values.
43+
- Clone `MotionGenPlanConfig` instance for every plan api.
44+
- Improve sphere position to voxel location calculation to match nvblox's implementation.
45+
- Add self collision checking support for spheres > 1024 and number of checks > 512 * 1024.
46+
- Fix gradient passthrough in warp batch transform kernels.
2447

2548
## Version 0.7.4
2649

benchmark/curobo_benchmark.py

+3-2
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,7 @@ def load_curobo(
210210
trajopt_dt=0.25,
211211
finetune_dt_scale=finetune_dt_scale,
212212
high_precision=args.high_precision,
213+
use_cuda_graph_trajopt_metrics=cuda_graph,
213214
)
214215
mg = MotionGen(motion_gen_config)
215216
mg.warmup(enable_graph=True, warmup_js_trajopt=False, parallel_finetune=parallel_finetune)
@@ -484,7 +485,7 @@ def benchmark_mb(
484485
start_state,
485486
q_traj,
486487
dt=result.interpolation_dt,
487-
save_path=join_path("benchmark/log/usd/", problem_name) + ".usd",
488+
save_path=join_path("benchmark/log/usd/", problem_name)[1:] + ".usd",
488489
interpolation_steps=1,
489490
write_robot_usd_path="benchmark/log/usd/assets/",
490491
robot_usd_local_reference="assets/",
@@ -499,7 +500,7 @@ def benchmark_mb(
499500
result.optimized_plan,
500501
result.optimized_dt.item(),
501502
title=problem_name,
502-
save_path=join_path("benchmark/log/plot/", problem_name + ".png"),
503+
save_path=join_path("benchmark/log/plot/", problem_name + ".png")[1:],
503504
)
504505

505506
m_list.append(current_metrics)

benchmark/curobo_voxel_benchmark.py

+15-10
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,7 @@ def load_curobo(
149149
"base": {
150150
"dims": [2.4, 2.4, 2.4],
151151
"pose": [0, 0, 0, 1, 0, 0, 0],
152-
"voxel_size": 0.005,
152+
"voxel_size": 0.02,
153153
"feature_dtype": torch.bfloat16,
154154
},
155155
}
@@ -294,15 +294,15 @@ def benchmark_mb(
294294
world = WorldConfig.from_dict(problem["obstacles"])
295295

296296
# mg.world_coll_checker.clear_cache()
297-
world_coll = WorldConfig.from_dict(problem["obstacles"])
297+
world_coll = WorldConfig.from_dict(problem["obstacles"]).get_collision_check_world()
298298
if args.mesh:
299299
world_coll = world_coll.get_mesh_world(merge_meshes=False)
300300
robot_world.clear_world_cache()
301301
robot_world.update_world(world_coll)
302302

303303
esdf = robot_world.world_model.get_esdf_in_bounding_box(
304304
Cuboid(name="base", pose=[0, 0, 0, 1, 0, 0, 0], dims=[2.4, 2.4, 2.4]),
305-
voxel_size=0.005,
305+
voxel_size=0.02,
306306
dtype=torch.float32,
307307
)
308308
# esdf.feature_tensor[esdf.feature_tensor < -1.0] = -1000.0
@@ -336,13 +336,16 @@ def benchmark_mb(
336336
world.randomize_color(r=[0.5, 0.9], g=[0.2, 0.5], b=[0.0, 0.2])
337337

338338
coll_mesh = mg.world_coll_checker.get_mesh_in_bounding_box(
339-
curobo_Cuboid(name="test", pose=[0, 0, 0, 1, 0, 0, 0], dims=[2, 2, 2]),
340-
voxel_size=0.005,
339+
curobo_Cuboid(
340+
name="test", pose=[0, 0, 0, 1, 0, 0, 0], dims=[2.4, 2.4, 2.4]
341+
),
342+
voxel_size=0.02,
341343
)
342344

343345
coll_mesh.color = [0.0, 0.8, 0.8, 0.2]
344346

345347
coll_mesh.name = "voxel_world"
348+
346349
# world = WorldConfig(mesh=[coll_mesh])
347350
world.add_obstacle(coll_mesh)
348351
# get costs:
@@ -360,7 +363,7 @@ def benchmark_mb(
360363
plot_cost_iteration(
361364
traj_cost,
362365
title=problem_name + "_" + str(success) + "_" + str(dt),
363-
save_path=join_path("benchmark/log/plot/", problem_name + "_cost"),
366+
save_path=join_path("benchmark/log/plot/", problem_name + "_cost")[1:],
364367
log_scale=False,
365368
)
366369
if "finetune_trajopt_result" in result.debug_info:
@@ -373,7 +376,7 @@ def benchmark_mb(
373376
title=problem_name + "_" + str(success) + "_" + str(dt),
374377
save_path=join_path(
375378
"benchmark/log/plot/", problem_name + "_ft_cost"
376-
),
379+
)[1:],
377380
log_scale=False,
378381
)
379382
if result.success.item():
@@ -481,7 +484,7 @@ def benchmark_mb(
481484
start_state,
482485
q_traj,
483486
dt=result.interpolation_dt,
484-
save_path=join_path("benchmark/log/usd/", problem_name) + ".usd",
487+
save_path=join_path("benchmark/log/usd/", problem_name)[1:] + ".usd",
485488
interpolation_steps=1,
486489
write_robot_usd_path="benchmark/log/usd/assets/",
487490
robot_usd_local_reference="assets/",
@@ -499,15 +502,17 @@ def benchmark_mb(
499502
# result.get_interpolated_plan(),
500503
# result.interpolation_dt,
501504
title=problem_name,
502-
save_path=join_path("benchmark/log/plot/", problem_name + ".pdf"),
505+
save_path=join_path("benchmark/log/plot/", problem_name + ".pdf")[1:],
503506
)
504507
plot_traj(
505508
# result.optimized_plan,
506509
# result.optimized_dt.item(),
507510
result.get_interpolated_plan(),
508511
result.interpolation_dt,
509512
title=problem_name,
510-
save_path=join_path("benchmark/log/plot/", problem_name + "_int.pdf"),
513+
save_path=join_path("benchmark/log/plot/", problem_name + "_int.pdf")[
514+
1:
515+
],
511516
)
512517

513518
m_list.append(current_metrics)

docker/ros1_x86.dockerfile

-69
This file was deleted.

docker/start_docker_arm64.sh

-22
This file was deleted.

docker/start_docker_x86_robot.sh

-24
This file was deleted.

examples/usd_example.py

+27-11
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
from curobo.types.base import TensorDeviceType
2020
from curobo.types.math import Pose
2121
from curobo.types.robot import JointState, RobotConfig
22-
from curobo.util.logger import setup_curobo_logger
22+
from curobo.util.logger import setup_curobo_logger, log_error
2323
from curobo.util.usd_helper import UsdHelper
2424
from curobo.util_file import (
2525
get_assets_path,
@@ -44,7 +44,7 @@ def save_curobo_world_to_usd():
4444
usd_helper.write_stage_to_file("test.usd")
4545

4646

47-
def get_trajectory(robot_file="franka.yml", dt=1.0 / 60.0):
47+
def get_trajectory(robot_file="franka.yml", dt=1.0 / 60.0, plan_grasp: bool = False):
4848
tensor_args = TensorDeviceType()
4949
world_file = "collision_test.yml"
5050
motion_gen_config = MotionGenConfig.load_from_robot_config(
@@ -60,32 +60,48 @@ def get_trajectory(robot_file="franka.yml", dt=1.0 / 60.0):
6060
interpolation_dt=dt,
6161
)
6262
motion_gen = MotionGen(motion_gen_config)
63-
motion_gen.warmup()
63+
motion_gen.warmup(n_goalset=2)
6464
robot_cfg = load_yaml(join_path(get_robot_configs_path(), robot_file))["robot_cfg"]
6565
robot_cfg = RobotConfig.from_dict(robot_cfg, tensor_args)
6666
retract_cfg = motion_gen.get_retract_config()
6767
state = motion_gen.rollout_fn.compute_kinematics(
6868
JointState.from_position(retract_cfg.view(1, -1))
6969
)
70+
if plan_grasp:
71+
retract_pose = Pose(
72+
state.ee_pos_seq.view(1, -1, 3), quaternion=state.ee_quat_seq.view(1, -1, 4)
73+
)
74+
start_state = JointState.from_position(retract_cfg.view(1, -1).clone())
75+
start_state.position[..., :-2] += 0.5
76+
m_config = MotionGenPlanConfig(False, True)
77+
78+
result = motion_gen.plan_grasp(start_state, retract_pose, m_config.clone())
79+
if not result.success:
80+
log_error("Failed to plan grasp: " + result.status)
81+
traj = result.grasp_interpolated_trajectory
82+
traj2 = result.retract_interpolated_trajectory
83+
traj = traj.stack(traj2).clone()
84+
# result = motion_gen.plan_single(start_state, retract_pose)
85+
# traj = result.get_interpolated_plan() # optimized plan
7086

71-
retract_pose = Pose(state.ee_pos_seq.squeeze(), quaternion=state.ee_quat_seq.squeeze())
72-
start_state = JointState.from_position(retract_cfg.view(1, -1).clone())
73-
start_state.position[..., :-2] += 0.5
74-
result = motion_gen.plan_single(start_state, retract_pose)
75-
traj = result.get_interpolated_plan() # optimized plan
87+
else:
88+
retract_pose = Pose(state.ee_pos_seq.squeeze(), quaternion=state.ee_quat_seq.squeeze())
89+
start_state = JointState.from_position(retract_cfg.view(1, -1).clone())
90+
start_state.position[..., :-2] += 0.5
91+
result = motion_gen.plan_single(start_state, retract_pose)
92+
traj = result.get_interpolated_plan() # optimized plan
7693
return traj
7794

7895

79-
def save_curobo_robot_world_to_usd(robot_file="franka.yml"):
80-
print(robot_file)
96+
def save_curobo_robot_world_to_usd(robot_file="franka.yml", plan_grasp: bool = False):
8197
tensor_args = TensorDeviceType()
8298
world_file = "collision_test.yml"
8399
world_model = WorldConfig.from_dict(
84100
load_yaml(join_path(get_world_configs_path(), world_file))
85101
).get_obb_world()
86102
dt = 1 / 60.0
87103

88-
q_traj = get_trajectory(robot_file, dt)
104+
q_traj = get_trajectory(robot_file, dt, plan_grasp)
89105
if q_traj is not None:
90106
q_start = q_traj[0]
91107
UsdHelper.write_trajectory_animation_with_robot_usd(

src/curobo/cuda_robot_model/cuda_robot_generator.py

+5-1
Original file line numberDiff line numberDiff line change
@@ -852,7 +852,11 @@ def _build_collision_model(
852852

853853
if not valid_data:
854854
use_experimental_kernel = False
855-
log_warn("Self Collision checks are greater than 32 * 512, using slower kernel")
855+
log_warn(
856+
"Self Collision checks are greater than 32 * 512, using slower kernel."
857+
+ " Number of spheres: "
858+
+ str(self_collision_distance.shape[0])
859+
)
856860
if use_experimental_kernel:
857861
self_coll_matrix = torch.zeros((2), device=self.tensor_args.device, dtype=torch.uint8)
858862
else:

0 commit comments

Comments
 (0)