mujoco-react 10.8.0 → 10.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mujoco-react",
3
- "version": "10.8.0",
3
+ "version": "10.9.0",
4
4
  "description": "Composable React Three Fiber building blocks for MuJoCo WASM simulations",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -13,6 +13,8 @@ export interface GenericIKOptions {
13
13
  epsilon: number;
14
14
  posWeight: number;
15
15
  rotWeight: number;
16
+ /** Per-iteration |Δq| cap in radians; bounds near-singular DLS steps. */
17
+ maxStepRad: number;
16
18
  jointLimits?: ReadonlyArray<readonly [number, number] | null | undefined>;
17
19
  }
18
20
 
@@ -26,6 +28,7 @@ const DEFAULTS: Required<Omit<GenericIKOptions, 'jointLimits'>> = {
26
28
  epsilon: 1e-6,
27
29
  posWeight: 1.0,
28
30
  rotWeight: 0.3,
31
+ maxStepRad: 0.5,
29
32
  };
30
33
 
31
34
  function resolveOptions(opts?: Partial<GenericIKOptions>): ResolvedGenericIKOptions {
@@ -36,6 +39,7 @@ function resolveOptions(opts?: Partial<GenericIKOptions>): ResolvedGenericIKOpti
36
39
  epsilon: opts?.epsilon ?? DEFAULTS.epsilon,
37
40
  posWeight: opts?.posWeight ?? DEFAULTS.posWeight,
38
41
  rotWeight: opts?.rotWeight ?? DEFAULTS.rotWeight,
42
+ maxStepRad: opts?.maxStepRad ?? DEFAULTS.maxStepRad,
39
43
  jointLimits: opts?.jointLimits,
40
44
  };
41
45
  }
@@ -214,8 +218,26 @@ export class GenericIK {
214
218
  dq[j] = sum;
215
219
  }
216
220
 
217
- // Update joints
218
- for (let i = 0; i < n; i++) q[i] += dq[i];
221
+ // Update joints: bound each step, then clamp to joint limits.
222
+ // Clamping inside the loop pins a saturated joint at its limit so
223
+ // subsequent iterations redistribute the remaining error to the
224
+ // unclamped joints (gradient projection), instead of returning an
225
+ // out-of-range solution for the caller to distort with a post-hoc
226
+ // per-joint clamp.
227
+ for (let i = 0; i < n; i++) {
228
+ let step = dq[i];
229
+ if (step > o.maxStepRad) step = o.maxStepRad;
230
+ else if (step < -o.maxStepRad) step = -o.maxStepRad;
231
+ let next = q[i] + step;
232
+ const limits = o.jointLimits?.[i];
233
+ if (limits) {
234
+ const low = Math.min(limits[0], limits[1]);
235
+ const high = Math.max(limits[0], limits[1]);
236
+ if (next < low) next = low;
237
+ else if (next > high) next = high;
238
+ }
239
+ q[i] = next;
240
+ }
219
241
  }
220
242
 
221
243
  // Restore original qpos