Rod Api and its attachment - #70
Conversation
Added NewtonRodAPI and NewtonRodAttachmentAPI schemas for rod simulation. Signed-off-by: 蕉太狼 <1251212394@qq.com>
Signed-off-by: 蕉太狼 <1251212394@qq.com>
This file contains unit tests for the Newton Rod API and its attachment API, verifying API registration, application, and attribute behavior. Signed-off-by: 蕉太狼 <1251212394@qq.com>
Signed-off-by: 蕉太狼 <1251212394@qq.com>
Signed-off-by: 蕉太狼 <1251212394@qq.com>
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
|
@lyd405121 you can likely address the linter failure with |
remove useless function
Add rod visual api
Static Test
IsaacSim
More work
Code and Assets
|
chschuma-disney
left a comment
There was a problem hiding this comment.
Thanks for putting together this RodAPI proposal! I did a first pass to get the discussion started.
In general, I would favor the schema being a bit more distanced from the actual implementation in Newton, so that it is general enough that it could also represent other types of rods (e.g., ones not represented by connected capsules), and wouldn't need to be updated if the Newton implementation was modified. This mostly concerns the documentation and default values.
Besides that, I think there's a bigger (structural) question that I believe is worth thinking about or discussing. USD already provides some variant of rod geometry through BasisCurves, and in an ideal world, these would provide all the geometry that we need, so the RodAPI could apply to a curve and just add all physics attributes. In practice, there's obviously the issue with junctions that are not representable by BasisCurves. So we're stuck with either defining everything ourselves, or using BasisCurves and then adding a mechanism to attach curves to each other to form a junction. If you have any insights into why one is better, it would be great to share them here.
| doc = """Capsule radii for rod segment bodies, in metres. | ||
|
|
||
| Array length semantics (E = number of edges / segments): | ||
| - Empty: the engine uses a default of 0.005 for all E segments. |
There was a problem hiding this comment.
Small point, but following the convention of the rest of the schemas, I would refer to the engine's default without specifying the numerical value itself.
| ) | ||
|
|
||
|
|
||
| int[] newton:fixedPoints ( |
There was a problem hiding this comment.
I think it might be a bit confusing to have two different mechanisms for constraining points: this fixedPoints attribute and NewtonRodAttachmentAPI. I could imagine that both cases could be covered by NewtonRodAttachmentAPI if we also specify the type of attachment (to a body, to world, ...), which would also allow us to extend this in to future to other types of attachments.
There was a problem hiding this comment.
Nice! Attachment to the world, means fixed!
| A value of -1 (default sentinel) means the attribute is unset; the engine uses | ||
| `newton:stretchStiffness` and `newton:bendStiffness` directly. | ||
|
|
||
| Range: (0, inf) when active; -1 as sentinel for "unset" |
There was a problem hiding this comment.
Small point, but using -inf as the sentinel value would better align with the other schemas.
|
|
||
| A value of -1 (default sentinel) means the attribute is unset. | ||
|
|
||
| Range: (-1, 0.5] when active; -1 as sentinel for "unset" |
There was a problem hiding this comment.
I might be mistaken, but I thought that the theoretical bounds for Poisson's ratio were [-1, 0.5], so including -1. Even if it's not useful for this application, having -1 as the "unset" sentinel might be confusing. I'd recommend using -inf instead.
| - Length E: each entry is associated with the corresponding segment/edge.""" | ||
| ) | ||
|
|
||
| bool newton:closed = false ( |
There was a problem hiding this comment.
I'm wondering if this is necessary when we have the option to build the same rod by just specifying the edges explicitly.
There was a problem hiding this comment.
Reasons
- The reseason is newton's rod api has this attribute, which will make the parser easy to impelment
- And deeper, add_rod api most of the time will use wrap_in_articulation=true to avoid orphan joints
- If not telling it is a closed form, some solver will fail for looped joints articulation
- As I know, only disney's kamino solver support looped joints
My thoughts
- Remove the 'closed' attribute, will be more natual to read
- But we should remove the 'closed' parameter for add_rod api
| Ignored when `newton:edges` is non-empty.""" | ||
| ) | ||
|
|
||
| quatf[] newton:quaternions ( |
There was a problem hiding this comment.
Minor point, but I'd call this orientations or some variant of that. quaternions just describes the representation, but not the function.
There was a problem hiding this comment.
I agree with you.
- And this is also the parameter name for add_rod api, I just copy it
- I think a better way is using orientations instaed of quaternions, but make notions in the schema doc
I have thought about this
Case
case.mp4
|
1. delete closed attribute, always use edges 2. delete fixed points,use attachment api instead 3. rename quaternion to orientation 4. attachment api allows multiple nodes attach to one body/world 5. youngsModulus / poissonRatio default value to -inf
andrewkaufman
left a comment
There was a problem hiding this comment.
Thanks lyd405121! Sorry it has taken so long to get you a review of this. I was waiting to be able to refer to the upcoming AOUSD proposal for deformable curves, but it has not been officially posted yet. I have instead included some details of that proposal in my comments here & linked you a draft copy on our Newton chat space. @frankchenlw can share it if you're not on the chat.
My main comment is that I think we need to re-align with this AOUSD proposal, as it is likely to get adopted & become part of the UsdPhysics standard. If we find issues that make it difficult to do this for Newton Rods, we should provide that feedback to AOUSD directly (once the proposal is posted) to ensure the standard doesn't contradict our needs.
| class NewtonRodAPI "NewtonRodAPI" ( | ||
| doc = """`NewtonRodAPI` applies on top of an `Xform` prim, enabling Newton rod simulation. | ||
|
|
||
| The rod geometry is defined entirely by attributes on this prim: | ||
| `newton:points` (N node positions) and `newton:radius` (uniform capsule radius). | ||
|
|
||
| Topology: | ||
| `newton:edges` is the required topology attribute for all rods. Each entry (u, v) | ||
| defines one segment between two nodes in `newton:points`. Linear rods should author | ||
| explicit edges such as (0,1), (1,2), ..., (N-2, N-1); closed loops and branching | ||
| junctions are expressed by the same edge list. | ||
|
|
||
| E is the number of authored edges / rod segments. All per-segment and per-joint array | ||
| attributes use E as their reference length. | ||
|
|
||
| Visual representation: | ||
| Attach one or more `BasisCurves` child prims, each carrying `NewtonRodVisualCurveAPI`, | ||
| to this Xform for rendering. Each curve represents one connected strand of the rod graph | ||
| (e.g. trunk, branch A, branch B). The `newton:rodPointIndices` attribute on each curve | ||
| maps its vertex positions to rod node indices, allowing an engine or tool to synchronize | ||
| the rendered curve with the simulated rod in real time. | ||
|
|
||
| Example layout for a branching graph: | ||
| /World/cable (Xform + NewtonRodAPI, 10 nodes) | ||
| /visual_trunk (BasisCurves + NewtonRodVisualCurveAPI) indices=[0,1,2,3,4] | ||
| /visual_branchA (BasisCurves + NewtonRodVisualCurveAPI) indices=[2,5,6,7] | ||
| /visual_branchB (BasisCurves + NewtonRodVisualCurveAPI) indices=[2,8,9] | ||
|
|
||
| Contact material: | ||
| Rod segment capsules inherit contact properties from the standard USD material binding | ||
| mechanism. Apply `MaterialBindingAPI` to this prim and bind a `Material` prim carrying | ||
| `NewtonMaterialAPI` (and optionally `PhysicsMaterialAPI`). The engine reads | ||
| `newton:contactStiffness`, `newton:contactDamping`, and `newton:contactFrictionGain` | ||
| from the bound material for all rod-object contacts.""" | ||
| ) |
There was a problem hiding this comment.
I agree with @chschuma-disney, most of the non-physics attributes on NewtonRodAPI appear to be re-formulations of BasisCurve (e.g. points, radius->widths, orientations->normals, closed->wrap). In general, we aim to re-use existing schema whenever possible, unless there is sufficent justification to deviate.
The key point is simulation and rendering data should be seperated. If simulation and rendering using some number of points, you can see there is a small gap between segments
This is very common in USD & is still commonly done with BasisCurves. e.g. for hair in film VFX they would use 2 BasisCurve prims, one is a "guide" purpose & has lower resolution (not just less points per curve, but usually also fewer total number of curves). The other BasisCurves is "default" or "render" purpose, is considerably denser, often uses a non-linear basis, and is "skinned" to the simulated curves to inherit & interpolate the motion.
As some additional context, AOUSD has a proposal for adding Deformables to UsdPhysics, and many of the physics attributes on NewtonRodAPI are being proposed on PhysicsCurvesDeformableSimAPI & PhysicsCurvesDeformableMaterialAPI, both of which apply to BasisCurves. There is as well a proposed PhysicsDeformablePoseAPI to define "geometry embeddings" between graphics prims & deforming physics prims. Given this direction of the specification, I think it makes sense for Newton to follow suite, by using & extending PhysicsCurvesDeformableSimAPI and PhysicsCurvesDeformableMaterialAPI with a NewtonCurvesDeformableSimAPI and/or NewtonCurvesDeformableMaterialAPI if we need additional attributes (e.g. the damping attrs or wrapInArticulation).
There was a problem hiding this comment.
Yes, sorry it is not yet posted officially (just due to some administration issue), you can find a tmp copy here TMP AOUSD UsdPhysics Deformables proposal
| ) | ||
|
|
||
|
|
||
| float newton:youngsModulus = -inf ( |
There was a problem hiding this comment.
I don't think newton rods in the runtime expose youngsModulus of poissonRatio currently. How did you decide to add them here? When do you prefer them over authoring the stiffnesses directly?
There was a problem hiding this comment.
- Youngs' modulus and Poisson ratio are more accurate and easy to get
- And I thought for robotics, measuable is important
- It is ok to remove this, but please keep the 'twist' parameter, though newton is not using it
There was a problem hiding this comment.
Ok thank you, I will provide this feedback on the AOUSD proposal. I believe @jumyungc has a draft PR to support twist in newton as well, and the AOUSD already does have twist
| } | ||
| ) | ||
|
|
||
| float[] newton:stretchStiffness ( |
There was a problem hiding this comment.
In the AOUSD proposal, these stiffnesses are placed on the material prim instead & are inherantly uniform (the single value case). GeomSubsets can then be used to provide different values to different vertices (or segments).
I would like to know how granularly you want to vary stiffness?
If you only need a couple values over the curve, Subsets may be a viable solution. If you need a unique value for each segment, Subsets become a bit burdensome & this float[] could act more like a primvar -- an array to override/drive the material value across the surface. That would simplify the documentation (no need to explain the length 1 case, the array is only used when non-uniform values are necessary).
There was a problem hiding this comment.
I will read aousd and update this
| where the natural capsule inertia is very small and causes ill-conditioning. | ||
|
|
||
| Range: [0, inf) | ||
| Units: kg·m²""" |
There was a problem hiding this comment.
Please follow the units notation of the other schemas using "distance" and "mass". It is more confusing perhaps, but in keeping with USD style, as the stage metrics might not be in kg & meters.
| } | ||
| ) | ||
|
|
||
| float newton:armature = 0.0 ( |
There was a problem hiding this comment.
Does this correspond to armature of the cable joint in newton runtime? Or if not, where does this armature get recorded? When would you decide to set armature rather than mass (on the PhysicsDeformableBodyAPI or masses on PhysicsCurvesDeformableSimAPI)?
There was a problem hiding this comment.
- This is a legacy value of newton for making the solver stable
- I reiewed newton's api, it may be deprecated in the future
- So I will delete this
| enabling efficient constraint solving for stiff rods.""" | ||
| ) | ||
|
|
||
| int newton:collisionFilterNeighborDistance = 1 ( |
There was a problem hiding this comment.
Is this used only in wrapInArticulation mode? If so, & if we decide to go with NewtonArticulationRootAPI, then I wonder if this can be re-formulated along with the collision filtering mode on NewtonArticulationRootAPI
There was a problem hiding this comment.
- Emmm, some solver will break down for orphan joints
- Like mujoco and featherstone,most of the time, it has to be true
|
|
||
| } | ||
|
|
||
| class NewtonRodAttachmentAPI "NewtonRodAttachmentAPI" ( |
There was a problem hiding this comment.
I'd like to understand if this can be modelled with PhysicsAttachment and PhysicsElementCollisionFilter from the AOUSD proposal
| doc = """`NewtonRodVisualCurveAPI` marks a `BasisCurves` prim as a visual representation | ||
| of a Newton rod strand. |
There was a problem hiding this comment.
As mentioned on the first comment, the traditional way to mark a graphics prim vs a simulation prim is using purpose -- sim prims are "guide" purpose, while graphics prims are any of "default", "render", or "proxy" purpose
| int[] newton:rodPointIndices = [0, 1, 2, ..., N-1]""" | ||
| ) | ||
| { | ||
| int[] newton:rodPointIndices ( |
There was a problem hiding this comment.
I'd like to understand if this can be re-formualted using PhysicsDeformablePoseAPI from the AOUSD proposal
| /visual_trunk (BasisCurves + NewtonRodVisualCurveAPI) indices=[0,1,2,3,4] | ||
| /visual_branchA (BasisCurves + NewtonRodVisualCurveAPI) indices=[2,5,6,7] | ||
| /visual_branchB (BasisCurves + NewtonRodVisualCurveAPI) indices=[2,8,9] |
There was a problem hiding this comment.
BasisCurves have a packed representation, we shouldnt need to split these out into 3 prims just for branching. We can split them out if that's desirable from a content authoring perspective, or if it makes the geomety embeddings via PhysicsDeformablePoseAPI easier. Just noting it's not strictly necessary for visualization.
eg I think this is the same rendered result, where each p variable is a Vec3f point position. p2 appears in the points listing 3 times, which is allowed
/visual_trunk (BasisCurves) curveVertexCounts[5, 4, 3], points=[p0,p1,p2,p3,p4,p2,p5,p6,p7,p2,p8,p9]
|
We should also syncronize with newton-physics/newton#3192 & verify that PR is loading rod they way you need it to. Can you please review the rod section of that PR when you have some time @lyd405121 ? |
Reduced schema@andrewkaufman @chschuma-disney
newton:youngsModulus
newton:poissonRatio
newton:stretchDamping
newton:bendDamping
newton:twistDamping DetailHow to make a rod graph
Fixed points
Other changes
Test
Question
subGeom.mp4The review
PhysicsAttachment for rigidbody or kinematic body
Curve-to-curve junction graphs
World / segment attachments
USD import path for add_rod_graph()
Per-segment materials via GeomSubset
Newton damping extensions
NewtonArticulationRootAPI semantics currently used by our assets
|
Can you let me know what version of usdview you are testing in? I just tried in both 24.08 and 25.05 and I did not get those warnings in either. |
Can you or @frankchenlw please makes those comments on that PR so the author knows we need those? I already made the PhysicsAttachment comment but not the others. |
I've asked for feedback from AOUSD, will let you know when I hear back. |
Do you find this is effective? Or do you think we should consider a per-vertex or per-segment kinematic flag? |
These are very helpful, I think we should contribute them under https://github.com/newton-physics/newton-assets perhaps. Or maybe they are so simple they can be test cases in newton directly in that PR implementing deformables support. |
|
|
|
done! |
|
I've reproduced your GeomSubset warniing in USD v25.11 as well. It seems related to Hydra 2.0. You can suppress the warning by disabling Hydra 2 ( I've logged the issue here: Note, you probably do want to add the "physics" binding purppose to those assets, so its clear they are not visual materials. If you're using usd-exchange to author assets, we have |
| float newton:youngsModulus = -inf ( | ||
| doc = """Youngs modulus used by Newton importers to derive curve stiffness when | ||
| AOUSD stiffness values are not authored or an importer chooses an elastic-material | ||
| parameterization. | ||
|
|
||
| If set to -inf, the importer should use the authored AOUSD curve stiffness values | ||
| or its simulator defaults. | ||
|
|
||
| Range: [0, inf) | ||
| Units: pressure""" | ||
| limits = { | ||
| dictionary soft = { | ||
| float minimum = 0 | ||
| } | ||
| } | ||
| ) | ||
|
|
||
| float newton:poissonRatio = -inf ( | ||
| doc = """Poisson ratio used with `newton:youngsModulus` to derive shear or twist | ||
| response for Newton curve solvers. | ||
|
|
||
| If set to -inf, the value is unset. | ||
|
|
||
| Range: [-1, 0.5] | ||
| Units: dimensionless""" | ||
| limits = { | ||
| dictionary soft = { | ||
| float minimum = -1 | ||
| float maximum = 0.5 | ||
| } | ||
| } | ||
| ) |
There was a problem hiding this comment.
My understanding is that youngsModulus and poissonRatio are going to be added to the AOUSD proposal soon, so we can drop them here for now & just add a note that their inclussion in Newton runtime is a requirement for us.
There was a problem hiding this comment.
The note in the class doc satisfies this, and the physics it states is right — G = E / (2 * (1 + nu)) governing both transverse shear and torsion is the standard Timoshenko rod formulation, and cross-sectional area, second/polar moments, shear correction and segment rest length are the correct list of factors.
Recording the Newton-side gaps it implies, so they don't get lost:
- The cable path does not read
physics:youngsModulusorphysics:poissonsRatioat all._cable_stiffnesses_from_material(newton/_src/utils/import_usd_deformable_cable.py:82-98) consumes only the four stiffnesses; there are no references to either modulus in that file. Only the volume/tet path reads them (newton/_src/usd/utils.py:1924-1951). - The authoring helper
create_cable_stiffness_from_elastic_moduli(newton/_src/utils/cable.py:70-190) derivesGbut applies it to twist only — its docstring scopesGto torsion andCableStiffnessdocuments "Noshearfield, by design." Transverse shear currently has no modulus-derived value. - There is no shear correction coefficient anywhere in the cable path.
So all three items in the doc note are genuinely unimplemented rather than partially present, which is worth knowing when this gets filed against the runtime.
| } | ||
| ) | ||
|
|
||
| float newton:stretchDamping = -inf ( |
There was a problem hiding this comment.
AOUSD exposes 4 stiffnesses, but we only expose 3 dampings here. Is that intentional?
There was a problem hiding this comment.
Confirming four is correct, and the author's screenshot matches what the runtime exposes.
ModelBuilder.add_rod takes four independent damping arguments (newton/_src/sim/builder.py:7653/7655/7657/7659), as do add_rod_graph (:7882-7888) and add_joint_cable (:5219-5225). They resolve into four separate JointDofConfig(target_kd=...) entries (:5295-5316) and reach the VBD solver as four distinct per-DOF coefficients — JointType.CABLE is built with linear_axes=[stretch, shear] and angular_axes=[bend, twist], and SolverVBD._init_joint_penalty_k (newton/_src/solvers/vbd/solver_vbd.py:1345-1385) fills four consecutive slots. So four is the right number and none of them collapse.
Two related facts worth recording here:
The defaults are asymmetric. shear_damping inherits stretch_damping only when both shear_stiffness and shear_damping are unset (builder.py:5298-5303); the same condition governs twist inheriting bend (:5306-5312). Otherwise it is 0.0. Authoring newton:stretchDamping alone therefore changes shear behavior as a side effect, and authoring newton:shearStiffness silently switches shear damping from inherited to zero. That is worth a sentence in the class doc.
Nothing consumes these yet. import_usd_deformable_cable.py:708-721 calls add_rod with no damping arguments, so all four are inert until the importer is plumbed. That is newton-physics/newton#3485's scope, not this PR's, but it means these attributes cannot be validated end-to-end yet.
There was a problem hiding this comment.
Just sharing the full context: previously, stretch/shear and bend/twist were handled together and shared the same stiffness. Now that we have four independent controls, users who set only stretch and bend stiffness, as before, get backward-compatible defaults: shear inherits stretch stiffness, and twist inherits bend stiffness. This fallback is Newton-specific and can be reconsidered of course via the deprecation process if independent defaults would be better.
andrewkaufman
left a comment
There was a problem hiding this comment.
Thanks @lyd405121, some last comments to address then I think we can get this merged. Once its released I'll update the newton parsing side & ask you to test that PR
| Newton's curve-deformable runtime requires Young's modulus `E` and Poisson ratio | ||
| `nu` to be provided by the AOUSD curve material schema once those attributes are | ||
| standardized; `E` governs stretch and bend response, while `E` and `nu` determine | ||
| the shear modulus `G = E / (2 * (1 + nu))`, which governs shear and twist response. |
There was a problem hiding this comment.
The four dampings have no Units: line. Every other float attribute in this file carries one, and the direct precedent is newton:damping (L408), which uses a dual form because its dimensions differ per DOF type:
Units: effort * seconds / degrees (angular DOFs) or effort * seconds / distance (linear DOFs).
These four split the same way, so one units string cannot cover all of them.
Author them as the time-derivative siblings of the AOUSD curve stiffnesses, which are stretch/shear = force and bend/twist = force * distance * distance. Damping is stiffness times time:
Units: force * time (stretch, shear) or force * distance * distance * time (bend, twist)
Please add that to all four, following this file's convention of "distance"/"force"/"time" rather than named SI units.
On why that is the right target: the AOUSD proposal currently documents all four curve stiffnesses as force/area, which is dimensionally inconsistent for each of them (see PixarAnimationStudios/OpenUSD-proposals#111). AOUSD has indicated the proposal will be updated so that these are true stiffnesses, with units corrected. Newton's importer presently reads them as moduli and multiplies by A/L, A/L, I/L, J/L (newton/_src/utils/import_usd_deformable_cable.py:83-98); that becomes a plain division by segment rest length L, which is a Newton-side change tracked separately. Authoring these dampings in the same convention keeps this schema consistent with the updated proposal and lets the importer apply the identical L division to all eight attributes.
There was a problem hiding this comment.
Just FYI, I’m currently adding per-joint stiffness assignment in Newton. One relevant detail: the discretization length is the joint’s local dual rest length, L_joint = 0.5 * (L_parent + L_child).
There was a problem hiding this comment.
- Add unit for damping
- Add a per-joint doc
Done
| float newton:stretchDamping = -inf ( | ||
| doc = """Newton stretch damping for curve deformables. | ||
|
|
||
| AOUSD curve materials do not define solver damping. If set to -inf, the importer |
There was a problem hiding this comment.
The sentinel wording deviates from this file's standard phrasing. Every other sentinel attribute here names the attribute and refers to the engine, for example L606:
If `newton:contactGap` is set to `-inf`, the engine's default should be used instead.
Please match that form on all four, naming each attribute and using "engine" rather than "importer":
If `newton:stretchDamping` is set to `-inf`, the engine's default should be used instead.
"the importer should use its simulator default" also misplaces the responsibility: the sentinel is resolved by whoever builds the model, not specifically by the USD importer.
There was a problem hiding this comment.
- Use similar description of damping like other property
Done
|
|
||
| Newton's curve-deformable runtime requires Young's modulus `E` and Poisson ratio | ||
| `nu` to be provided by the AOUSD curve material schema once those attributes are | ||
| standardized; `E` governs stretch and bend response, while `E` and `nu` determine |
There was a problem hiding this comment.
Trailing whitespace on L880, L881 and L883.
There was a problem hiding this comment.
remove blank space at the end of lines.done
| } | ||
| ) | ||
|
|
||
| float newton:stretchDamping = -inf ( |
There was a problem hiding this comment.
Confirming four is correct, and the author's screenshot matches what the runtime exposes.
ModelBuilder.add_rod takes four independent damping arguments (newton/_src/sim/builder.py:7653/7655/7657/7659), as do add_rod_graph (:7882-7888) and add_joint_cable (:5219-5225). They resolve into four separate JointDofConfig(target_kd=...) entries (:5295-5316) and reach the VBD solver as four distinct per-DOF coefficients — JointType.CABLE is built with linear_axes=[stretch, shear] and angular_axes=[bend, twist], and SolverVBD._init_joint_penalty_k (newton/_src/solvers/vbd/solver_vbd.py:1345-1385) fills four consecutive slots. So four is the right number and none of them collapse.
Two related facts worth recording here:
The defaults are asymmetric. shear_damping inherits stretch_damping only when both shear_stiffness and shear_damping are unset (builder.py:5298-5303); the same condition governs twist inheriting bend (:5306-5312). Otherwise it is 0.0. Authoring newton:stretchDamping alone therefore changes shear behavior as a side effect, and authoring newton:shearStiffness silently switches shear damping from inherited to zero. That is worth a sentence in the class doc.
Nothing consumes these yet. import_usd_deformable_cable.py:708-721 calls add_rod with no damping arguments, so all four are inert until the importer is plumbed. That is newton-physics/newton#3485's scope, not this PR's, but it means these attributes cannot be validated end-to-end yet.
| float newton:youngsModulus = -inf ( | ||
| doc = """Youngs modulus used by Newton importers to derive curve stiffness when | ||
| AOUSD stiffness values are not authored or an importer chooses an elastic-material | ||
| parameterization. | ||
|
|
||
| If set to -inf, the importer should use the authored AOUSD curve stiffness values | ||
| or its simulator defaults. | ||
|
|
||
| Range: [0, inf) | ||
| Units: pressure""" | ||
| limits = { | ||
| dictionary soft = { | ||
| float minimum = 0 | ||
| } | ||
| } | ||
| ) | ||
|
|
||
| float newton:poissonRatio = -inf ( | ||
| doc = """Poisson ratio used with `newton:youngsModulus` to derive shear or twist | ||
| response for Newton curve solvers. | ||
|
|
||
| If set to -inf, the value is unset. | ||
|
|
||
| Range: [-1, 0.5] | ||
| Units: dimensionless""" | ||
| limits = { | ||
| dictionary soft = { | ||
| float minimum = -1 | ||
| float maximum = 0.5 | ||
| } | ||
| } | ||
| ) |
There was a problem hiding this comment.
The note in the class doc satisfies this, and the physics it states is right — G = E / (2 * (1 + nu)) governing both transverse shear and torsion is the standard Timoshenko rod formulation, and cross-sectional area, second/polar moments, shear correction and segment rest length are the correct list of factors.
Recording the Newton-side gaps it implies, so they don't get lost:
- The cable path does not read
physics:youngsModulusorphysics:poissonsRatioat all._cable_stiffnesses_from_material(newton/_src/utils/import_usd_deformable_cable.py:82-98) consumes only the four stiffnesses; there are no references to either modulus in that file. Only the volume/tet path reads them (newton/_src/usd/utils.py:1924-1951). - The authoring helper
create_cable_stiffness_from_elastic_moduli(newton/_src/utils/cable.py:70-190) derivesGbut applies it to twist only — its docstring scopesGto torsion andCableStiffnessdocuments "Noshearfield, by design." Transverse shear currently has no modulus-derived value. - There is no shear correction coefficient anywhere in the cable path.
So all three items in the doc note are genuinely unimplemented rather than partially present, which is worth knowing when this gets filed against the runtime.
| } | ||
| for name, value in values.items(): | ||
| attr = self.material.GetAttribute(name) | ||
| self.assertTrue(attr.Set(value), name) |
There was a problem hiding this comment.
Please follow the existing per-attribute test style rather than dict-driven loops.
tests/test_material.py is the closest precedent — same sentinel and same soft-limit shape as these four. It gives each attribute its own test (test_contact_stiffness, test_contact_damping, test_contact_adhesion, ...), and each one covers the absence of the attribute before the API is applied, the sentinel fallback, authored-value state, a Set() round-trip, and the declared limits:
def test_contact_damping(self):
self.assertFalse(self.material.HasAttribute("newton:contactDamping"))
self.material.ApplyAPI("NewtonMaterialAPI")
attr = self.material.GetAttribute("newton:contactDamping")
self.assertIsNotNone(attr)
self.assertFalse(attr.HasAuthoredValue())
self.assertEqual(attr.Get(), -math.inf)
success = attr.Set(200.0)
self.assertTrue(success)
self.assertTrue(attr.HasAuthoredValue())
self.assertAlmostEqual(attr.Get(), 200.0)
if USD_HAS_LIMITS:
soft = attr.GetSoftLimits()
self.assertTrue(soft.IsValid())
self.assertAlmostEqual(soft.GetMinimum(), 0.0)
self.assertIsNone(soft.GetMaximum())Here the same coverage is spread across four separate tests that each loop over the same four attribute names — test_api_application, test_material_parameter_defaults, test_material_parameter_roundtrip and test_limits. Please restructure into test_stretch_damping, test_shear_damping, test_bend_damping and test_twist_damping, each self-contained in the form above, keeping test_api_registered, test_api_application and test_api_limitations as they are.
Two gaps that closing this would also fix: nothing currently asserts HasAuthoredValue() is false before a value is set (which is what distinguishes a real authored -inf from the fallback), and test_material_parameter_roundtrip does not assert the attribute was absent prior to ApplyAPI.
There was a problem hiding this comment.
- Writing test code for every property instead of in a big loop
- Done
chschuma-disney
left a comment
There was a problem hiding this comment.
I'm seconding Andrew's comments. Other than that, the PR looks good to me.
- remove blank space at the end of lines - use similar description of damping - add unit for damping - test code for every property instead of in a loop - add a per-joint doc






Make rods parse easier
ClosedChain.mp4
newton-graph.mp4
GraphAttach.mp4
Things should disscussed