Skip to content

Commit 4934cd0

Browse files
authored
Fix Pink IK DAQP dependency checks (#5556)
# Description Pink IK uses DAQP through `qpsolvers`, but the install-time dependency repair only verified that Pinocchio could be imported. In environments where `pin-pink` or `qpsolvers` is present but DAQP is missing, unregistered, or too old for `qpsolvers` warm-start arguments, `solve_ik(..., solver="daqp")` can fail and fall back to current joint targets. The controller then reports a misleading end-effector position error in `test_pink_ik.py`. This change makes the installer probe the full Pink IK stack: `pinocchio`, DAQP registration in `qpsolvers`, and the `daqp.solve` API shape required by current `qpsolvers` (`primal_start`). It also aligns the IsaacLab dependency pin with the compatible DAQP release, `daqp==0.8.5`. Runtime handling stays narrow: ordinary IK failures keep the existing fallback, while missing DAQP or the specific `primal_start` API mismatch is surfaced with an actionable install message instead of being swallowed as an IK fallback. The docs config also mocks `qpsolvers`, matching the existing docs treatment for optional Pink IK dependencies such as `pink` and `pinocchio`, so API docs can be built without the runtime solver stack installed. ## Type of change - Bug fix (non-breaking change which fixes an issue) ## Test Plan - `./isaaclab.sh -p -m py_compile source/isaaclab/isaaclab/cli/commands/install.py source/isaaclab/isaaclab/controllers/pink_ik/pink_ik.py source/isaaclab/setup.py docs/conf.py` - `./isaaclab.sh -p -c "import inspect, pinocchio, daqp, qpsolvers; assert 'daqp' in qpsolvers.available_solvers; assert 'primal_start' in inspect.signature(daqp.solve).parameters; print('pink ik dependency probe passed')"` - `./isaaclab.sh -p -c "..."` small monkeypatch check that `TypeError("solve() got an unexpected keyword argument 'primal_start'")` raises the new DAQP compatibility `RuntimeError` - `./isaaclab.sh -p -m pytest source/isaaclab/test/controllers/test_pink_ik.py::test_movement_types -k "GR1T2-Abs-v0 and stay_still" -q --tb=short -s -x` - `./isaaclab.sh -p -m pytest source/isaaclab/test/controllers/test_pink_ik.py -q --tb=short -x` (`23 passed, 1 skipped`) - `VIRTUAL_ENV=/home/zhengyuz/Projects/IsaacLab.wt/feature-heterogeneous_dexsuite/env_isaaclab PATH=/home/zhengyuz/Projects/IsaacLab.wt/feature-heterogeneous_dexsuite/env_isaaclab/bin:$PATH make current-docs` from `docs/` - `VIRTUAL_ENV=/home/zhengyuz/Projects/IsaacLab.wt/feature-heterogeneous_dexsuite/env_isaaclab ./isaaclab.sh -f` ## Screenshots N/A. ## Checklist - [x] I have read and understood the [contribution guidelines](https://isaac-sim.github.io/IsaacLab/main/source/refs/contributing.html) - [x] I have run the [`pre-commit` checks](https://pre-commit.com/) with `./isaaclab.sh --format` - [x] I have made corresponding changes to the documentation (N/A - docs config only) - [x] My changes generate no new warnings - [x] I have added tests that prove my fix is effective or that my feature works - [x] I have added a changelog fragment under `source/<pkg>/changelog.d/` for every touched package (do **not** edit `CHANGELOG.rst` or bump `extension.toml` -- CI handles that) - [x] I have added my name to the `CONTRIBUTORS.md` or my name already exists there
1 parent b59b3ae commit 4934cd0

5 files changed

Lines changed: 63 additions & 35 deletions

File tree

docs/conf.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,7 @@
203203
"toml",
204204
"pink",
205205
"pinocchio",
206+
"qpsolvers",
206207
"nvidia.srl",
207208
"flatdict",
208209
"filelock",
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
Fixed
2+
^^^^^
3+
4+
* Fixed Pink IK setup checks to reinstall and report the required ``daqp``
5+
solver when it is missing or incompatible.

source/isaaclab/isaaclab/cli/commands/install.py

Lines changed: 24 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -159,22 +159,22 @@ def _maybe_uninstall_prebundled_torch(
159159
)
160160

161161

162-
# Pinocchio stack required by isaaclab.controllers.pink_ik. Installed via the cmeel
163-
# ``pin`` wheel, which provides the ``pinocchio`` Python module under
162+
# Dependency stack required by isaaclab.controllers.pink_ik. Pinocchio is installed
163+
# via the cmeel ``pin`` wheel, which provides the ``pinocchio`` Python module under
164164
# ``cmeel.prefix/lib/python3.12/site-packages/`` and registers it on sys.path via a
165-
# ``cmeel.pth`` hook.
166-
_PINOCCHIO_STACK = ("pin", "pin-pink==3.1.0", "daqp==0.7.2")
165+
# ``cmeel.pth`` hook. DAQP provides the QP solver selected by the Pink IK controller.
166+
_PINK_IK_STACK = ("pin", "pin-pink==3.1.0", "daqp==0.8.5")
167167

168168

169-
def _ensure_pinocchio_installed(python_exe: str, pip_cmd: list[str], *, probe_env: dict[str, str]) -> None:
170-
"""Ensure ``pinocchio`` is importable, force-installing the cmeel pin stack if not.
169+
def _ensure_pink_ik_dependencies_installed(python_exe: str, pip_cmd: list[str], *, probe_env: dict[str, str]) -> None:
170+
"""Ensure the Pink IK dependency stack is importable, force-installing it if not.
171171
172172
Recent Isaac Sim base images preinstall ``pin-pink`` into the kit's bundled
173173
``site-packages`` without its ``pin`` (cmeel pinocchio) dependency. Pip then
174174
treats the ``pin-pink`` requirement as satisfied and never resolves the
175-
transitive ``pin`` dep, leaving ``import pinocchio`` broken. This probes
176-
for ``pinocchio`` at runtime and force-installs the cmeel stack when needed
177-
so the pink IK controller and its tests work out of the box.
175+
transitive ``pin`` dep, leaving ``import pinocchio`` broken. This checks
176+
the runtime dependencies and force-installs the cmeel stack when needed so
177+
the pink IK controller and its tests work out of the box.
178178
179179
Only runs on Linux x86_64 / aarch64 — the same platforms that have
180180
pinocchio listed in :mod:`isaaclab`'s ``setup.py`` install requirements.
@@ -194,7 +194,13 @@ def _ensure_pinocchio_installed(python_exe: str, pip_cmd: list[str], *, probe_en
194194
return
195195

196196
probe_result = run_command(
197-
[python_exe, "-c", "import pinocchio"],
197+
[
198+
python_exe,
199+
"-c",
200+
"import inspect, pinocchio, daqp, qpsolvers; "
201+
"assert 'daqp' in qpsolvers.available_solvers; "
202+
"assert 'primal_start' in inspect.signature(daqp.solve).parameters",
203+
],
198204
env=probe_env,
199205
check=False,
200206
capture_output=True,
@@ -203,19 +209,16 @@ def _ensure_pinocchio_installed(python_exe: str, pip_cmd: list[str], *, probe_en
203209
if probe_result.returncode == 0:
204210
return
205211

206-
print_info(
207-
"``import pinocchio`` failed — the kit-bundled ``pin-pink`` likely shipped without its"
208-
" ``pin`` dep. Force-installing the cmeel pinocchio stack."
209-
)
212+
print_info("Pink IK dependency probe failed. Force-installing the cmeel pinocchio and DAQP stack.")
210213
install_result = run_command(
211-
pip_cmd + ["install", "--upgrade", "--force-reinstall", *_PINOCCHIO_STACK],
214+
pip_cmd + ["install", "--upgrade", "--force-reinstall", *_PINK_IK_STACK],
212215
check=False,
213216
)
214217
if install_result.returncode != 0:
215218
print_warning(
216-
"Force-installing the cmeel pinocchio stack failed (returncode "
219+
"Force-installing the cmeel pinocchio and DAQP stack failed (returncode "
217220
f"{install_result.returncode}). The pink IK controller and its tests will not be"
218-
" usable until ``pin pin-pink==3.1.0 daqp==0.7.2`` is installed manually."
221+
" usable until ``pin pin-pink==3.1.0 daqp==0.8.5`` is installed manually."
219222
)
220223

221224

@@ -735,10 +738,10 @@ def command_install(install_type: str = "all") -> None:
735738
# Can prevent that from happening.
736739
_ensure_cuda_torch()
737740

738-
# Ensure ``pinocchio`` is actually importable. The kit-bundled ``pin-pink`` in recent
739-
# Isaac Sim images ships without its cmeel ``pin`` dependency, so the transitive
740-
# requirement from ``pip install -e source/isaaclab`` can be silently skipped.
741-
_ensure_pinocchio_installed(python_exe, pip_cmd, probe_env=probe_env)
741+
# Ensure Pink IK's runtime dependencies are actually importable. The kit-bundled
742+
# ``pin-pink`` in recent Isaac Sim images can cause transitive dependencies from
743+
# ``pip install -e source/isaaclab`` to be silently skipped.
744+
_ensure_pink_ik_dependencies_installed(python_exe, pip_cmd, probe_env=probe_env)
742745

743746
# Repoint prebundled packages in Isaac Sim to the environment's copies so
744747
# the active venv/conda versions are always loaded regardless of PYTHONPATH

source/isaaclab/isaaclab/controllers/pink_ik/pink_ik.py

Lines changed: 32 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import torch
2121
from pink import solve_ik
2222
from pink.tasks import Task
23+
from qpsolvers.exceptions import SolverNotFound
2324

2425
from isaaclab.assets import ArticulationCfg
2526
from isaaclab.controllers import utils as controller_utils
@@ -34,6 +35,9 @@
3435
from .pink_ik_cfg import PinkIKControllerCfg
3536

3637

38+
_QP_SOLVER = "daqp"
39+
40+
3741
class PinkIKController:
3842
"""Integration of Pink IK controller with Isaac Lab.
3943
@@ -240,30 +244,45 @@ def compute(
240244
# Update Pink's robot configuration with the current joint positions
241245
self.pink_configuration.update(joint_positions_pink)
242246

247+
def _return_current_joint_positions(error: Exception) -> torch.Tensor:
248+
if self.cfg.show_ik_warnings:
249+
print(
250+
"Warning: IK quadratic solver could not find a solution! Did not update the target joint"
251+
f" positions.\nError: {error}"
252+
)
253+
254+
if self.cfg.xr_enabled:
255+
from isaaclab.ui.xr_widgets import XRVisualization
256+
257+
XRVisualization.push_event("ik_error", {"error": error})
258+
return torch.tensor(curr_controlled_joint_pos, device=self.device, dtype=torch.float32)
259+
243260
# Solve IK using Pink's solver
244261
try:
245262
velocity = solve_ik(
246263
self.pink_configuration,
247264
self._variable_input_tasks + self._fixed_input_tasks,
248265
dt,
249-
solver="daqp",
266+
solver=_QP_SOLVER,
250267
safety_break=self.cfg.fail_on_joint_limit_violation,
251268
)
252269
assert not np.isnan(velocity).any(), "Solution to IK contains NaN."
253270
joint_angle_changes = velocity * dt
271+
except SolverNotFound as e:
272+
raise RuntimeError(
273+
f"Pink IK requires the '{_QP_SOLVER}' QP solver. Install the Pink IK stack with "
274+
"``./isaaclab.sh -i`` or manually install ``pin pin-pink==3.1.0 daqp==0.8.5``."
275+
) from e
276+
except TypeError as e:
277+
if "primal_start" in str(e):
278+
raise RuntimeError(
279+
"Pink IK requires a DAQP version compatible with qpsolvers warm-start arguments. "
280+
"Install the Pink IK stack with ``./isaaclab.sh -i`` or manually install "
281+
"``pin pin-pink==3.1.0 daqp==0.8.5``."
282+
) from e
283+
return _return_current_joint_positions(e)
254284
except (AssertionError, Exception) as e:
255-
# Print warning and return the current joint positions as the target
256-
if self.cfg.show_ik_warnings:
257-
print(
258-
"Warning: IK quadratic solver could not find a solution! Did not update the target joint"
259-
f" positions.\nError: {e}"
260-
)
261-
262-
if self.cfg.xr_enabled:
263-
from isaaclab.ui.xr_widgets import XRVisualization
264-
265-
XRVisualization.push_event("ik_error", {"error": e})
266-
return torch.tensor(curr_controlled_joint_pos, device=self.device, dtype=torch.float32)
285+
return _return_current_joint_positions(e)
267286

268287
# Reorder the joint angle changes back to Isaac Lab conventions
269288
joint_vel_isaac_lab = torch.tensor(

source/isaaclab/setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@
6969
# required by isaaclab.isaaclab.controllers.pink_ik
7070
f"pin ; platform_system == 'Linux' and ({SUPPORTED_ARCHS_ARM})",
7171
f"pin-pink==3.1.0 ; platform_system == 'Linux' and ({SUPPORTED_ARCHS_ARM})",
72-
f"daqp==0.7.2 ; platform_system == 'Linux' and ({SUPPORTED_ARCHS_ARM})",
72+
f"daqp==0.8.5 ; platform_system == 'Linux' and ({SUPPORTED_ARCHS_ARM})",
7373
]
7474
# Adds OpenUSD dependencies based on architecture for Kit less mode.
7575
INSTALL_REQUIRES += [

0 commit comments

Comments
 (0)