Siemens NX Grasp Function: Resolving the Junction Parameter Error in Mechanism Simulation
The grasp() function is a core primitive in the Siemens NX mechanism and human modeling simulation runtime. Engineers and ergonomics analysts building assembly sequences, robotic reach studies, and human-task simulations routinely call it from NX Knowledge Fusion (KF), the embedded command language used inside NX assemblies and motion scenarios. A recurring failure mode during simulation playback is the function silently doing nothing, throwing a runtime exception, or causing the kinematic solver to fail to attach a hand/link to the target body. The root cause in nearly every reported case is that the first argument passed to grasp() references a junction instead of the parent object that owns that junction. This article documents the exact correction, the underlying object-model reason it works, and the verification procedure that confirms the fix in NX 1980 through NX 2406 releases.
1. Problem Details
Symptom observed in NX motion scenarios when the grasp() call is malformed:
- The simulation event executes on the timeline but the hand/manipulator never locks onto the target body.
- No Grasp indicator appears in the Mechanism Navigator, and the moving link continues past the intended pick position.
- The Information window logs a warning such as "Unable to resolve object from junction reference" or, in KF output, a null handle is passed to the underlying
UF_MOTION_graspwrapper. - Subsequent
release(),place(), orapply_force()calls chained off the grasp fail with cascading null-reference errors because the grasp itself was never committed.
The reproducer in the original report was minimal: a hand on a HEAD_SL link reaching toward a B_SR body that contains a junction defined at the contact point HEAD_SL_JCT. The faulty call looked like:
grasp ( "HEAD_SL_JCT", getJunction ( "HEAD_SL", "HEAD_SL_JCT" ) );
Execution either returned silently or halted the event-driven solver at the line of the call.
2. Root Cause
NX's grasp() KF primitive is a thin wrapper over the C++ UF_MOTION_grasp API. Its signature requires two arguments with distinct semantic roles:
| Parameter Position | Semantic Role | Expected Type | What It Identifies |
|---|---|---|---|
1 — object
|
Body to be captured | String / tag of the solid or link | The full NX object that the hand will hold and move with the manipulator |
2 — junction
|
Contact anchor | String / tag of a junction | The local point/frame on the object where the hand's palm makes contact |
A junction in NX is a local feature — a coordinate-system datum or contact point that lives on an object. It is not the object itself. Passing the junction tag in the first parameter causes the solver to attempt a rigid attachment of the hand to a datum entity. Because junctions have no mass, no inertia, and no kinematic body, the solver cannot construct a valid constraint and the operation either fails internally or binds the hand to a zero-mass reference, producing unstable results.
The correct interpretation is: "tell NX which body to grab, and where on that body the contact should be anchored." The junction is metadata describing where on the object, not what to grab.
3. Solution
Pass the full body name (or its NX object tag) in the first argument, then pass the junction in the second. Using the reproducer, the corrected call is:
grasp ( "B_SR", getJunction ( "HEAD_SL", "HEAD_SL_JCT" ) );
Step-by-step replacement procedure:
- Open the motion scenario (.sim) in NX containing the failing event.
- Open the Knowledge Fusion editor for the event node where
grasp()is invoked. - Locate the
grasp()statement. Identify the first quoted string — this is the object argument. - Replace the junction name with the name of the solid body or link component that owns the junction. In a typical assembly the body is the part at the top of the Part Navigator for that sub-assembly; in a mechanism, it is the link name as it appears in the Mechanism Navigator.
- Leave the second argument (
getJunction(...)) unchanged. The junction must still be a junction defined on the same body passed in argument one. - Recompile the KF expression with Tools → Knowledge Fusion → Check or press Ctrl+Shift+C. The editor should report zero errors.
- Save the scenario and re-run the simulation segment from the grasp event forward.
listJunctions("B_SR") that the junction is owned by the target body.4. Verification
Confirm the fix is correct and persistent:
- Event indicator: In the Mechanism Navigator, expand the Events node. A successful grasp appears as a child event with a hand/anchor icon. Failure leaves no child node.
- Playback: Step through the timeline from the grasp event. The hand should remain attached to the body and travel with it as the body moves under the next motion command.
- Information window: No null-reference or "object not found" warnings should be logged at the grasp time step.
-
Release pair: The downstream
release()call at the planned drop event should fire cleanly. Ifrelease()also fails, the grasp was never committed and you are still referencing a junction in argument one. -
Command-line probe: From the NX Command dialog (Ctrl+Shift+B), query the object directly:
info object "B_SR"The response should return a valid solid body tag, not a junction tag. If the response is empty, the name is misspelled or the body is suppressed in the scenario.
5. NX Simulation Architecture Context
NX delivers motion and human-modeling simulation through a stack of layered subsystems. Understanding the layering clarifies why the parameter error has the failure profile it does:
| Layer | Component | Role | Failure Surface |
|---|---|---|---|
| User-facing | Mechanism Navigator, Human Modeling | Timeline, posture editor, IK pose | UI flags missing bodies |
| Scripting | Knowledge Fusion (KF) | Event scripting, grasp/release, drivers | First-arg type mismatch |
| API | NX Open / UF_MOTION | C++ and .NET bindings to solver | Null tag handles |
| Solver | RecurDyn-based kinematic/dynamic engine | Constraint assembly, integration | Constraint construction failure on zero-mass anchor |
KF compiles to NX Open calls, which in turn invoke the underlying solver primitives. A junction passed where a body is expected resolves to a zero-mass datum tag. The solver cannot create a rigid joint from a hand to a datum; it must have an inertial body. The result is the silent-fail or constraint-divergence behavior observed.
6. Junction vs. Object Reference — The Rule
Adopt this rule for every grasp(), release(), place(), and apply_force() call in KF:
- Argument one is always the body you want to manipulate.
- Argument two (when present) is a feature on that body: junction, face, edge, or coordinate system.
- The body and the feature must be in a parent-child ownership relationship. A junction on body X cannot anchor a grasp of body Y.
Common valid reference patterns:
// Grab the link named B_SR at its contact junction
grasp ( "B_SR", getJunction ( "B_SR", "GRIP_JCT" ) );
// Grab by NX object tag (numeric, in C++/NX Open)
UF_MOTION_grasp ( bodyTag, junctionTag );
// Multi-finger grasp using two junctions on the same body
grasp ( "B_SR",
getJunction ( "B_SR", "LEFT_FINGER_JCT" ),
getJunction ( "B_SR", "RIGHT_FINGER_JCT" ) );
7. Related KF Primitives and Their Argument Conventions
Use the same body-first rule for the rest of the manipulation API. Mistakes here exhibit the same silent-fail pattern.
| Function | Arg 1 (Body) | Arg 2 (Feature) | Arg 3+ | Common Mistake |
|---|---|---|---|---|
grasp() |
Body to hold | Grasp junction(s) | — | Passing junction as body |
release() |
Body to release | — | — | Passing junction name |
place() |
Body to place | Target location/face | — | Confusing source and target body |
apply_force() |
Body receiving force | Force vector / magnitude | Application point | Using junction where body is required |
move() |
Link to drive | Target position/transform | — | Driving a junction instead of a link |
8. Best Practices for Robust Grasp Simulation
-
Name bodies and junctions distinctly. Avoid the trap of naming a junction with the same suffix as its parent body. A junction
B_SR_JCTon bodyB_SRreads naturally and reduces the temptation to swap them. - Define grasp junctions on the part you intend to grasp. Co-locating the junction on the target body makes the KF call self-documenting and survives part renames better.
-
Use
listJunctions()during development to verify what is on a body before you callgrasp():listJunctions ( "B_SR" );The output should includeHEAD_SL_JCTif that is what you intend to anchor against. -
Wrap manipulation calls in diagnostic logs:
This gives a clean success/failure boundary in the Information window for post-mortem analysis.echo ( "Calling grasp on B_SR" ); grasp ( "B_SR", getJunction ( "B_SR", "HEAD_SL_JCT" ) ); echo ( "Grasp complete" ); -
Test the release path before committing the scenario. If
release()also fails, the grasp never committed and you are still feeding the solver a junction where a body is required. - Run motion scenarios in steps. Use the Step button in the mechanism player to advance one event at a time when debugging. This isolates the failing call.
9. Common Error Patterns and Quick Diagnosis
| Observed Symptom | Likely Cause | Diagnostic | Fix |
|---|---|---|---|
| Hand passes through target | Junction passed in arg 1 | Inspect KF source | Replace with body name |
| Null handle warning at runtime | Body name not in scenario context | info object "B_SR" |
Check part is loaded, not suppressed |
| Grasp commits but slips on motion | Junction defined on wrong body |
listJunctions() on body |
Define junction on target body |
| Release has no effect | Body name mismatch with grasp | Diff string literals | Use identical body string in both calls |
| Constraint solver divergence | Junction on a suppressed component | Part Navigator state | Unsuppress the owning part |
10. Affected NX Versions and Compatibility
The grasp() KF primitive has been stable in the NX mechanism environment since the NX 10 / NX 11 generation when Knowledge Fusion became the canonical event language. Behavior described in this article is consistent across the following releases verified against Siemens PLM documentation:
- NX 1980 series (mechanism simulation shipped with NX 1980, 1984, 1988)
- NX 2007 series (2007, 2011, 2015, 2019)
- NX 2206 series (2206, 2210, 2212, 2306)
- NX 2406 series (current as of release notes covering Designcenter CFD Designer and CAD simulation bundles)
NX 2406 continues the virtual-prototype simulation workflow and exposes the same KF primitive set through the Knowledge Fusion interpreter. The object-versus-junction argument convention is unchanged from prior releases. Engineers migrating scenarios from older NX versions should re-validate grasp() calls because part rename propagation across linked scenarios occasionally leaves the body name string stale even when the underlying tag is valid.
11. Field-Commissioning Checklist
Before signing off a mechanism or human-modeling scenario that contains grasp events, run this checklist:
- Open the KF source for every
grasp()call and confirm the first argument is a body, not a junction. - Use
listJunctions()on the body to confirm the named junction exists and is owned by the body. - Step through the playback. The grasp event must produce a child node in the Mechanism Navigator.
- Confirm the
release()partner executes on the same body string. - Run the full scenario at real-time playback speed; verify no constraint divergence messages appear in the Information window.
- Export a short .mpg or .avi of the segment for stakeholder review. A grasp that visually works but logs warnings is a release-blocker for ergonomic certification workflows.
- Archive the KF source alongside the .sim file. Scenario reproducibility requires the original command sequence.
12. When to Escalate
Escalate to Siemens GTAC (or your authorized reseller) when:
- The body name resolves to a valid tag, the junction exists on the body, the KF source compiles, yet the grasp still fails to commit. This points to a solver-level issue requiring
UF_MOTIONtrace logging. - The error reproduces in a minimal scenario built from default NX samples. Supply the .sim, the part files, and the KF snippet.
- The grasp succeeds in one NX version and fails in another after a version upgrade. NX Open
UF_MOTION_graspsignatures are stable, but licensing of human-modeling modules can disable the KF wrapper silently.
For licensing and module-availability questions, verify that the active license includes the Human Modeling or Mechanism Simulation option. The KF grasp() primitive is gated behind these bundles in the Siemens PLM license server.
Why does my grasp() call fail silently in NX mechanism simulation?
Almost always because the first argument is a junction tag instead of a body tag. Replace the first string with the name of the part or link that owns the junction, leave the junction in the second argument, and the grasp will commit. Verify with info object "<body_name>" that the body resolves to a solid tag.
What is the difference between a body and a junction in NX Knowledge Fusion?
A body is a solid or link with mass and inertia that the kinematic solver can constrain to. A junction is a local feature (point, frame, or face) on a body that describes where on the body a contact occurs. The grasp() call needs both: the body to grab and the junction describing the contact anchor.
How do I list all junctions on a body in NX KF?
Call listJunctions ( "<body_name>" ); from the KF editor or from a transient event. The output lists every junction defined on the named body, which you can then pass to getJunction() for the second argument of grasp().
Does the grasp() fix apply to NX 2406 and recent releases?
Yes. The argument convention is stable across NX 1980 through NX 2406. Knowledge Fusion and the underlying UF_MOTION_grasp API have not changed the first-argument semantic. Re-validate any scenario migrated from an older release because part renames can leave the body string stale.
Can I call grasp() with multiple junctions for a two-finger grip?
Yes. Pass the body as the first argument and provide two or more getJunction() results as the second and subsequent arguments. Each junction must be defined on the same body passed in argument one. The solver will treat the grasp as a multi-anchor contact.