Skip to content

Manipulabilty barrier for singularity avoidance - #239

Open
sjahr wants to merge 4 commits into
open-planning:mainfrom
sjahr:manipulabilty-barrier
Open

Manipulabilty barrier for singularity avoidance#239
sjahr wants to merge 4 commits into
open-planning:mainfrom
sjahr:manipulabilty-barrier

Conversation

@sjahr

@sjahr sjahr commented Jun 9, 2026

Copy link
Copy Markdown
Collaborator

Add manipulability barrier to prevent the robot from getting to close to a singularity. Part of this PR is a new example to test oink in singularities:

python3 roboplan_examples/python/example_singularity.py --help                                                                                 (roboplan) ^(*manipulabilty-barrier+163) 22:59:53
usage: example_singularity.py [-h] [OPTIONS]

Move a UR5 through a kinematic singularity with OInK and display real-time joint-space tracking error and Jacobian metrics in the Viser sidebar. The trajectory ping-pongs continuously between waypoints.

The trajectory is defined in joint space: at each control step the target is recomputed via FK from a linearly-interpolated joint configuration.  This guarantees OInK must track through the exact singular joint
pose.

╭─ options ──────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ -h, --help              show this help message and exit                                                        │
│ --singularity {wrist,elbow,shoulder}                                                                           │
│                         Which singularity to traverse.                                                         │
│                         "wrist"    – wrist_2 (j5) through 0°, wrist_1/wrist_3 axes align.                      │
│                         "elbow"    – elbow (j3) extends from 90° → 0° and retracts, arm passes fully extended. │
│                         "shoulder" – shoulder_lift+elbow≈-90°, wrist center on j1 axis. (default: wrist)       │
│ --lm-damping FLOAT      Levenberg-Marquardt damping λ on the frame-task Hessian                                │
│                         (H = Jᵀ J + λ I). Default 0: the robot drives all the way to the                       │
│                         singularity (joints may chatter at σ_min ≈ 0), giving the clearest                     │
│                         contrast when the barrier is enabled. Increase to see smooth stalling                  │
│                         before the singularity even without the barrier — useful to understand                 │
│                         how damping and the barrier interact differently. (default: 0.0)                       │
│ --waypoint-duration FLOAT                                                                                      │
│                         Seconds to travel between adjacent waypoints. (default: 5.0)                           │
│ --manipulability-barrier, --no-manipulability-barrier                                                          │
│                         Enable CBF-based singularity avoidance. The robot                                      │
│                         will stall before reaching the singular configuration rather than                      │
│                         passing through it. (default: False)                                                   │
│ --sigma-safe FLOAT      Minimum σ_min the barrier enforces. The UR5 elbow trajectory                           │
│                         starts at σ_min ≈ 0.15, so values above ~0.1 will activate the barrier                 │
│                         almost immediately. Default 0.05 gives a clear stopping point well into                │
│                         the extension without activating at the start. (default: 0.05)                         │
│ --barrier-gain FLOAT    Class-K gain γ controlling how aggressively the barrier                                │
│                         pushes back. Higher values give a stiffer wall. (default: 10.0)  

Manipulability and lm-damping have different impact on the singularity behavior and you can play around with both of them. Not sure if we should keep the example or remove.

@sjahr
sjahr marked this pull request as ready for review June 14, 2026 21:02
@sjahr sjahr changed the title [WIP] Manipulabilty barrier for singularity avoidance Manipulabilty barrier for singularity avoidance Jun 14, 2026
@sjahr
sjahr requested review from eholum and sea-bass June 14, 2026 21:02

@sea-bass sea-bass left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tested this and the plotly stuff is really cool!

  • The wrist and shoulder cases made sense/barrier worked as intended, though tracking was of course quite bad when the barrier was on.
  • Elbow had some issues. Without the barrier, I never saw the print for singularities even though sigma did go below the minimum. With the barrier, it seemed like the trajectory wasn't being tracked properly at all even though sigma was way above the safe distance. Is something pushing it back prematurely?

Generally, it might be good to plot where the reference position of the robot is. Whether you plot a full trajectory line, or a "carrot on a stick" showing the instantaneous reference of the end effector, either would be helpful.

I also suspect that picking a manipulator with redundancy, like the Kinova/Franka, will yield better results because you could possibly use some of the redundancy to keep manipulability above the minimum value, while still tracking? But not sure...

VelocityLimit,
)

# Joint-space waypoints for each singularity type (UR5, 6 arm joints).

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it might be more legible to couple the waypoints and labels into a data structure that captures them both together

target_lock = threading.Lock()
running = True

# Build the C++ barrier list once — passed into every solveIk call.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not C++

Comment on lines +384 to +386
current_q_arm_target = [
waypoints_q[0].copy()
] # joint-space reference for error plot

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: put the comment above so the linter doesn't do this

Comment thread pixi.toml
nodeenv = ">=1.10.0, <2"
tyro = ">=0.9.26,<0.10"
viser = ">=1.0.29,<2.0" # See https://github.com/viser-project/viser/issues/719
plotly = ">=5.0,<6"

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is cool, but make sure you also add it to the ubuntu / ros dockers and check that it works there

Comment on lines +47 to +49
for (int i = 0; i < static_cast<int>(v_indices.size()); ++i) {
j_arm_.col(i) = full_jacobian_.col(v_indices[i]);
}

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i feel like there must be a single Eigen operation that can replace doing it in a loop...

Comment on lines +79 to +83
Eigen::MatrixXd J_arm(6, v_indices.size());
for (int i = 0; i < static_cast<int>(v_indices.size()); ++i) {
J_arm.col(i) = J.col(v_indices[i]);
}
const double sigma_min = Eigen::BDCSVD<Eigen::MatrixXd>(J_arm).singularValues().minCoeff();

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should we be calling computeSigmaMin() here too?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants