Table-driven attribute writing: rebase the writer on the shared rows.
The writer consumes the same generated rows as the reader. mjXWriter::WriteAttrTable drives the mechanical attributes of an element from its mjXAttr rows: each bound field is compared against the class default at the same offset -- the default object is the same struct type, so the rows carry no comparison values -- and attributes equal to their default are skipped. A null default object means the element has no defaults, and every defined value is written. Ranged-arity rows write with trailing-default trimming, which the reader makes round-trip exact by refilling from the same default. Call sites upcast to the private mjs base (the friend declarations permit it; mjCMesh gains the friendship its siblings had); the comparison object is def->X().spec, a freshly-defaulted struct for the sections, or zero-initialized for size, whose spec defaults (-1, auto) are resolved by compilation. Converted: pair, geom, site, joint, camera, light, material, the equality family, both tendon types (the fixed rows are the spatial rows without appearance attributes -- exactly the tag difference), the actuator, flex with its three sub-elements, mesh, skin, option, the six visual sub-sections, statistic and size. The remnants keep names, files, resolved reference strings (the mjC classes null their private base's string pointers; resolved names live behind accessors), and the writing=custom policies the schema declares: compile directives never saved (fromto, springdamper, fitscale), type-dependent lengths and attributes (sizes, joint pos/axis/limited, shellinertia), and alternatives (mass/density, fovy-versus-intrinsics, the plugin-gated gain/bias family). Compiler keeps its write-if-nonzero policy; keyframe keeps its model-sized vectors. Saved files are canonical: attributes follow schema declaration order with remnants trailing, and sections follow the schema's dependency order (statistic before visual, deformable before the contact and equality sections that name flexes, tendon before the equality constraints that name tendons, custom demoted to the data tail). Uniform behavior fixes fall out: default-equal positionals are dropped, dynprm is trimmed like every other ranged vector, and mesh material -- read into the spec but never written -- now survives save/load round trips. Changelog entries ride along. Verified: full suite, doc_test, and the two-tier A/B harness -- saved XML reorders attributes, and every corpus model reloads to a byte-identical binary. PiperOrigin-RevId: 958255003 Change-Id: I5fe7346014450db88b2f3f8680a8f616f7d31266
This commit is contained in:
committed by
Copybara-Service
parent
760477f406
commit
5e99ca6cb8
@@ -20,7 +20,6 @@ import math
|
||||
import os
|
||||
import textwrap
|
||||
import typing
|
||||
import warnings
|
||||
import zipfile # pylint: disable=unused-import
|
||||
|
||||
from absl import flags
|
||||
@@ -61,7 +60,7 @@ class SpecsTest(absltest.TestCase):
|
||||
</mujoco>
|
||||
"""
|
||||
spec = mujoco.MjSpec.from_string(xml)
|
||||
model = spec.compile()
|
||||
spec.compile()
|
||||
self.assertGreater(spec.timer[mujoco.mjtCTimer.mjCTIMER_TOTAL], 0)
|
||||
self.assertGreater(spec.timer[mujoco.mjtCTimer.mjCTIMER_ASSETS], 0)
|
||||
self.assertGreater(spec.timer[mujoco.mjtCTimer.mjCTIMER_TEXTURE], 0)
|
||||
@@ -152,7 +151,7 @@ class SpecsTest(absltest.TestCase):
|
||||
|
||||
<worldbody>
|
||||
<body name="baz" pos="1 2 3" quat="0 1 0 0">
|
||||
<site name="sitename" pos="0 0 0" type="box" user="1 2 3 4 5 6"/>
|
||||
<site name="sitename" type="box" user="1 2 3 4 5 6"/>
|
||||
</body>
|
||||
</worldbody>
|
||||
</mujoco>
|
||||
|
||||
Reference in New Issue
Block a user