diff --git a/doc/generate/generate_default_table.py b/doc/generate/generate_default_table.py index 0c718ad4..f770e564 100644 --- a/doc/generate/generate_default_table.py +++ b/doc/generate/generate_default_table.py @@ -57,12 +57,14 @@ _HEADER = '''\ // doc/generate/generate_default_table.py; test/doc/doc_test.py checks // freshness. // -// One row per schema attribute with a declared default, binding the declared -// values to the bound field. SchemaDefaultsTest compares every row against a -// freshly-constructed spec: the schema's defaults must agree with the C -// default-constructors. Rows are {attr, offset, kind, len, ndecl, values}; -// values beyond ndecl are expected to be zero; kind: 0=double 1=float 2=int -// 3=byte 4=mjtNum. +// One row per bound numeric schema attribute -- total coverage, whether or +// not a default is declared. SchemaDefaultsTest compares every row against a +// freshly-constructed spec: declared values must match the C +// default-constructors, values beyond ndecl must be zero, and rows marked +// unset must hold the mjNAN sentinel. A nonzero constructor default with no +// schema declaration is therefore a test failure: the schema cannot silently +// under-declare. Rows are {attr, offset, kind, len, ndecl, unset, values}; +// kind: 0=double 1=float 2=int 3=byte 4=mjtNum. // clang-format off struct mjXDefaultEntry { @@ -71,6 +73,7 @@ struct mjXDefaultEntry { int kind; int len; int ndecl; + int unset; double value[8]; }; @@ -95,8 +98,28 @@ def _values(schema, attr): return len(values), [repr(v) for v in values] +# fields whose constructor default is the mjNAN "unset" sentinel, not a value; +# the schema deliberately declares no default and the test asserts the NaN +UNSET_SENTINELS = { + ('mjsBody', 'ipos'), ('mjsBody', 'fullinertia'), + ('mjsGeom', 'mass'), ('mjsGeom', 'fromto'), + ('mjsSite', 'fromto'), + ('mjStatistic', 'meaninertia'), ('mjStatistic', 'meanmass'), + ('mjStatistic', 'meansize'), ('mjStatistic', 'extent'), + ('mjStatistic', 'center'), +} + + def collect(schema, structs): - """struct key -> list of row tuples, deduplicated across elements.""" + """struct key -> list of row tuples, deduplicated across elements. + + Emits a row for every bound numeric attribute. An attribute with a declared + default contributes its values; an undeclared one contributes an all-zero + expectation (or the unset flag for UNSET_SENTINELS), so the test enforces + that every nonzero constructor default is declared in the schema. A declared + row replaces an undeclared row for the same field; two declared rows must + agree. + """ tables = {} seen = {} for element in schema.elements.values(): @@ -109,35 +132,51 @@ def collect(schema, structs): continue prefix = f'{sub}.' if sub else '' for attr in schema.expanded_attrs(element): - if attr.default is None or attr.type in ('string', 'file', 'chars', - 'ref', 'id', 'flags'): + if attr.type in ('string', 'file', 'chars', 'ref', 'id', 'flags'): continue field = attr.facets.get('field', attr.name) entry = fields.get(field) if entry is None: - if 'reading' in attr.facets: + if 'reading' in attr.facets or attr.default is None: continue # custom lowering with no direct binding raise ValueError(f'{element.name}.{attr.name}: no field ' f'{element.spec}.{field}') ctype, dim = entry if ctype not in KIND_BY_CTYPE and not ctype.startswith('mjt'): + if attr.default is None: + continue # not a numeric field: nothing to compare raise ValueError(f'{element.name}.{attr.name}: default bound to ' f'field {field} ({ctype})') + if ctype.endswith('*'): + continue # vector pointers have no in-place default kind = KIND_BY_CTYPE.get(ctype, 2) # other mjt enums are int-sized length = dim if dim is not None else '1' - ndecl, values = _values(schema, attr) + unset = 1 if (key, field) in UNSET_SENTINELS else 0 + if attr.default is None: + ndecl, values = 0, [] + else: + if unset: + raise ValueError(f'{element.name}.{attr.name}: declared default ' + 'on an unset-sentinel field') + ndecl, values = _values(schema, attr) if ndecl > 8: raise ValueError(f'{element.name}.{attr.name}: {ndecl} default ' 'values exceed the row capacity') row = (attr.name, f'(int)offsetof({element.spec}, {prefix}{field})', - kind, str(length), ndecl, values) + kind, str(length), ndecl, unset, values) prior = seen.get((key, field)) if prior is not None: - if prior != (ndecl, values): + prior_row, prior_declared = prior + declared = attr.default is not None + if declared and prior_declared and prior_row[4:] != row[4:]: raise ValueError(f'{element.name}.{attr.name}: conflicting ' f'defaults for {key}.{field}') + if not declared or prior_declared: + continue # keep the existing (declared or equivalent) row + tables[key][tables[key].index(prior_row)] = row + seen[(key, field)] = (row, True) continue - seen[(key, field)] = (ndecl, values) + seen[(key, field)] = (row, attr.default is not None) tables.setdefault(key, []).append(row) return tables @@ -152,9 +191,9 @@ def generate() -> str: for key in sorted(tables): array = 'kDefaults_' + key.replace('.', '_') out.append(f'static const mjXDefaultEntry {array}[] = {{') - for attr, offset, kind, length, ndecl, values in tables[key]: - vals = ', '.join(values) - out.append(f' {{"{attr}", {offset}, {kind}, {length}, {ndecl}, ' + for attr, offset, kind, length, ndecl, unset, values in tables[key]: + vals = ', '.join(values) if values else '0' + out.append(f' {{"{attr}", {offset}, {kind}, {length}, {ndecl}, {unset}, ' f'{{{vals}}}}},') out.append('};') out.append('') diff --git a/src/xml/generated/mjcf.xsd b/src/xml/generated/mjcf.xsd index 02ff7965..948be07c 100644 --- a/src/xml/generated/mjcf.xsd +++ b/src/xml/generated/mjcf.xsd @@ -625,6 +625,16 @@ + + + + + + + + + + @@ -682,10 +692,10 @@ - + - + @@ -697,7 +707,7 @@ deprecation error - + @@ -709,10 +719,10 @@ - + - - + + @@ -744,8 +754,8 @@ - - + + @@ -774,17 +784,17 @@ suffixed byte count - + range/exclusivity checks - + range check - + range/exclusivity checks @@ -803,56 +813,56 @@ - + - + - + - + - + - + - + - + @@ -1123,16 +1133,16 @@ - - + + - + - - - - - + + + + + @@ -1244,31 +1254,31 @@ - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + @@ -1320,20 +1330,20 @@ compile directive: saved as stiffness/damping - + saved unless free - + saved for slide/hinge - - - - + + + + spring polynomial, 1+mjNPOLY coefficients @@ -1414,7 +1424,7 @@ - + @@ -1511,7 +1521,7 @@ - + @@ -1522,9 +1532,9 @@ - - - + + + @@ -1535,9 +1545,9 @@ - - - + + + @@ -1588,8 +1598,8 @@ - - + + @@ -1612,8 +1622,8 @@ - - + + @@ -1641,8 +1651,8 @@ - - + + @@ -1666,9 +1676,9 @@ - - - + + + @@ -1696,7 +1706,7 @@ - + @@ -1711,8 +1721,8 @@ - - + + alias: the position-setpoint range @@ -1750,7 +1760,7 @@ - + @@ -1774,8 +1784,8 @@ - - + + @@ -1802,8 +1812,8 @@ - - + + @@ -1817,7 +1827,7 @@ slidercrank-only, validated - + @@ -1835,7 +1845,7 @@ - + @@ -1847,7 +1857,7 @@ - + @@ -2175,7 +2185,7 @@ - + @@ -2298,7 +2308,7 @@ - + @@ -2324,8 +2334,8 @@ - - + + @@ -2337,7 +2347,7 @@ - + @@ -2360,10 +2370,10 @@ - - + + - + @@ -2379,9 +2389,9 @@ space-separated body names - + - seeded to {1,1,1} before reading + seeded before reading @@ -2425,14 +2435,14 @@ - + - - - - + + + + @@ -2468,14 +2478,14 @@ - + - - - - + + + + @@ -2594,9 +2604,9 @@ - - - + + + @@ -2662,8 +2672,8 @@ - - + + @@ -2696,8 +2706,8 @@ - - + + @@ -2735,8 +2745,8 @@ - - + + @@ -2770,9 +2780,9 @@ - - - + + + @@ -2810,7 +2820,7 @@ - + @@ -2830,8 +2840,8 @@ - - + + alias: the position-setpoint range @@ -2879,7 +2889,7 @@ - + @@ -2913,8 +2923,8 @@ - - + + @@ -2951,8 +2961,8 @@ - - + + @@ -2972,7 +2982,7 @@ - + @@ -2993,7 +3003,7 @@ - + @@ -3008,7 +3018,7 @@ - + @@ -3059,9 +3069,9 @@ - - - + + + @@ -3845,8 +3855,8 @@ - - + + @@ -3860,7 +3870,7 @@ constraint: at most one of: fullinertia, quat, axisangle, xyaxes, zaxis, euler - + @@ -3890,20 +3900,20 @@ compile directive: saved as stiffness/damping - + saved unless free - + saved for slide/hinge - - - - + + + + spring polynomial, 1+mjNPOLY coefficients @@ -3946,7 +3956,7 @@ - + @@ -3960,7 +3970,7 @@ - + @@ -3974,7 +3984,7 @@ - + @@ -3991,7 +4001,7 @@ - + @@ -4006,24 +4016,24 @@ - + - - - + + + - - - - + + + + - - + + diff --git a/src/xml/generated/mjcf_default_table.inc b/src/xml/generated/mjcf_default_table.inc index e3b97b6e..2b8857d3 100644 --- a/src/xml/generated/mjcf_default_table.inc +++ b/src/xml/generated/mjcf_default_table.inc @@ -16,12 +16,14 @@ // doc/generate/generate_default_table.py; test/doc/doc_test.py checks // freshness. // -// One row per schema attribute with a declared default, binding the declared -// values to the bound field. SchemaDefaultsTest compares every row against a -// freshly-constructed spec: the schema's defaults must agree with the C -// default-constructors. Rows are {attr, offset, kind, len, ndecl, values}; -// values beyond ndecl are expected to be zero; kind: 0=double 1=float 2=int -// 3=byte 4=mjtNum. +// One row per bound numeric schema attribute -- total coverage, whether or +// not a default is declared. SchemaDefaultsTest compares every row against a +// freshly-constructed spec: declared values must match the C +// default-constructors, values beyond ndecl must be zero, and rows marked +// unset must hold the mjNAN sentinel. A nonzero constructor default with no +// schema declaration is therefore a test failure: the schema cannot silently +// under-declare. Rows are {attr, offset, kind, len, ndecl, unset, values}; +// kind: 0=double 1=float 2=int 3=byte 4=mjtNum. // clang-format off struct mjXDefaultEntry { @@ -30,6 +32,7 @@ struct mjXDefaultEntry { int kind; int len; int ndecl; + int unset; double value[8]; }; @@ -40,240 +43,493 @@ struct mjXDefaultTable { }; +static const mjXDefaultEntry kDefaults_mjLROpt[] = { + {"mode", (int)offsetof(mjLROpt, mode), 2, 1, 1, 0, {(double)mjLRMODE_MUSCLE}}, + {"useexisting", (int)offsetof(mjLROpt, useexisting), 2, 1, 1, 0, {1}}, + {"uselimit", (int)offsetof(mjLROpt, uselimit), 2, 1, 0, 0, {0}}, + {"accel", (int)offsetof(mjLROpt, accel), 4, 1, 1, 0, {20.0}}, + {"maxforce", (int)offsetof(mjLROpt, maxforce), 4, 1, 0, 0, {0}}, + {"timeconst", (int)offsetof(mjLROpt, timeconst), 4, 1, 1, 0, {1.0}}, + {"timestep", (int)offsetof(mjLROpt, timestep), 4, 1, 1, 0, {0.01}}, + {"inttotal", (int)offsetof(mjLROpt, inttotal), 4, 1, 1, 0, {10.0}}, + {"interval", (int)offsetof(mjLROpt, interval), 4, 1, 1, 0, {2.0}}, + {"tolrange", (int)offsetof(mjLROpt, tolrange), 4, 1, 1, 0, {0.05}}, +}; + static const mjXDefaultEntry kDefaults_mjOption[] = { - {"timestep", (int)offsetof(mjOption, timestep), 4, 1, 1, {0.002}}, - {"impratio", (int)offsetof(mjOption, impratio), 4, 1, 1, {1.0}}, - {"tolerance", (int)offsetof(mjOption, tolerance), 4, 1, 1, {1e-08}}, - {"ls_tolerance", (int)offsetof(mjOption, ls_tolerance), 4, 1, 1, {0.01}}, - {"noslip_tolerance", (int)offsetof(mjOption, noslip_tolerance), 4, 1, 1, {1e-06}}, - {"ccd_tolerance", (int)offsetof(mjOption, ccd_tolerance), 4, 1, 1, {1e-06}}, - {"sleep_tolerance", (int)offsetof(mjOption, sleep_tolerance), 4, 1, 1, {0.001}}, - {"gravity", (int)offsetof(mjOption, gravity), 4, 3, 3, {0.0, 0.0, -9.81}}, - {"wind", (int)offsetof(mjOption, wind), 4, 3, 3, {0.0, 0.0, 0.0}}, - {"magnetic", (int)offsetof(mjOption, magnetic), 4, 3, 3, {0.0, -0.5, 0.0}}, - {"o_friction", (int)offsetof(mjOption, o_friction), 4, 5, 5, {1.0, 1.0, 0.005, 0.0001, 0.0001}}, - {"integrator", (int)offsetof(mjOption, integrator), 2, 1, 1, {(double)mjINT_EULER}}, - {"cone", (int)offsetof(mjOption, cone), 2, 1, 1, {(double)mjCONE_PYRAMIDAL}}, - {"jacobian", (int)offsetof(mjOption, jacobian), 2, 1, 1, {(double)mjJAC_AUTO}}, - {"solver", (int)offsetof(mjOption, solver), 2, 1, 1, {(double)mjSOL_NEWTON}}, - {"iterations", (int)offsetof(mjOption, iterations), 2, 1, 1, {100.0}}, - {"ls_iterations", (int)offsetof(mjOption, ls_iterations), 2, 1, 1, {50.0}}, - {"ccd_iterations", (int)offsetof(mjOption, ccd_iterations), 2, 1, 1, {35.0}}, - {"sdf_iterations", (int)offsetof(mjOption, sdf_iterations), 2, 1, 1, {10.0}}, - {"sdf_initpoints", (int)offsetof(mjOption, sdf_initpoints), 2, 1, 1, {40.0}}, + {"timestep", (int)offsetof(mjOption, timestep), 4, 1, 1, 0, {0.002}}, + {"impratio", (int)offsetof(mjOption, impratio), 4, 1, 1, 0, {1.0}}, + {"tolerance", (int)offsetof(mjOption, tolerance), 4, 1, 1, 0, {1e-08}}, + {"ls_tolerance", (int)offsetof(mjOption, ls_tolerance), 4, 1, 1, 0, {0.01}}, + {"noslip_tolerance", (int)offsetof(mjOption, noslip_tolerance), 4, 1, 1, 0, {1e-06}}, + {"ccd_tolerance", (int)offsetof(mjOption, ccd_tolerance), 4, 1, 1, 0, {1e-06}}, + {"sleep_tolerance", (int)offsetof(mjOption, sleep_tolerance), 4, 1, 1, 0, {0.001}}, + {"gravity", (int)offsetof(mjOption, gravity), 4, 3, 3, 0, {0.0, 0.0, -9.81}}, + {"wind", (int)offsetof(mjOption, wind), 4, 3, 3, 0, {0.0, 0.0, 0.0}}, + {"magnetic", (int)offsetof(mjOption, magnetic), 4, 3, 3, 0, {0.0, -0.5, 0.0}}, + {"density", (int)offsetof(mjOption, density), 4, 1, 0, 0, {0}}, + {"viscosity", (int)offsetof(mjOption, viscosity), 4, 1, 0, 0, {0}}, + {"o_margin", (int)offsetof(mjOption, o_margin), 4, 1, 0, 0, {0}}, + {"o_solref", (int)offsetof(mjOption, o_solref), 4, mjNREF, 2, 0, {0.02, 1.0}}, + {"o_solimp", (int)offsetof(mjOption, o_solimp), 4, mjNIMP, 5, 0, {0.9, 0.95, 0.001, 0.5, 2.0}}, + {"o_friction", (int)offsetof(mjOption, o_friction), 4, 5, 5, 0, {1.0, 1.0, 0.005, 0.0001, 0.0001}}, + {"integrator", (int)offsetof(mjOption, integrator), 2, 1, 1, 0, {(double)mjINT_EULER}}, + {"cone", (int)offsetof(mjOption, cone), 2, 1, 1, 0, {(double)mjCONE_PYRAMIDAL}}, + {"jacobian", (int)offsetof(mjOption, jacobian), 2, 1, 1, 0, {(double)mjJAC_AUTO}}, + {"solver", (int)offsetof(mjOption, solver), 2, 1, 1, 0, {(double)mjSOL_NEWTON}}, + {"iterations", (int)offsetof(mjOption, iterations), 2, 1, 1, 0, {100.0}}, + {"ls_iterations", (int)offsetof(mjOption, ls_iterations), 2, 1, 1, 0, {50.0}}, + {"noslip_iterations", (int)offsetof(mjOption, noslip_iterations), 2, 1, 0, 0, {0}}, + {"ccd_iterations", (int)offsetof(mjOption, ccd_iterations), 2, 1, 1, 0, {35.0}}, + {"sdf_iterations", (int)offsetof(mjOption, sdf_iterations), 2, 1, 1, 0, {10.0}}, + {"sdf_initpoints", (int)offsetof(mjOption, sdf_initpoints), 2, 1, 1, 0, {40.0}}, +}; + +static const mjXDefaultEntry kDefaults_mjSpec[] = { + {"njmax", (int)offsetof(mjSpec, njmax), 2, 1, 1, 0, {-1.0}}, + {"nconmax", (int)offsetof(mjSpec, nconmax), 2, 1, 1, 0, {-1.0}}, + {"nstack", (int)offsetof(mjSpec, nstack), 2, 1, 1, 0, {-1.0}}, + {"nuserdata", (int)offsetof(mjSpec, nuserdata), 2, 1, 0, 0, {0}}, + {"nkey", (int)offsetof(mjSpec, nkey), 2, 1, 0, 0, {0}}, + {"nuser_body", (int)offsetof(mjSpec, nuser_body), 2, 1, 1, 0, {-1.0}}, + {"nuser_jnt", (int)offsetof(mjSpec, nuser_jnt), 2, 1, 1, 0, {-1.0}}, + {"nuser_geom", (int)offsetof(mjSpec, nuser_geom), 2, 1, 1, 0, {-1.0}}, + {"nuser_site", (int)offsetof(mjSpec, nuser_site), 2, 1, 1, 0, {-1.0}}, + {"nuser_cam", (int)offsetof(mjSpec, nuser_cam), 2, 1, 1, 0, {-1.0}}, + {"nuser_tendon", (int)offsetof(mjSpec, nuser_tendon), 2, 1, 1, 0, {-1.0}}, + {"nuser_actuator", (int)offsetof(mjSpec, nuser_actuator), 2, 1, 1, 0, {-1.0}}, + {"nuser_sensor", (int)offsetof(mjSpec, nuser_sensor), 2, 1, 1, 0, {-1.0}}, +}; + +static const mjXDefaultEntry kDefaults_mjStatistic[] = { + {"meaninertia", (int)offsetof(mjStatistic, meaninertia), 4, 1, 0, 1, {0}}, + {"meanmass", (int)offsetof(mjStatistic, meanmass), 4, 1, 0, 1, {0}}, + {"meansize", (int)offsetof(mjStatistic, meansize), 4, 1, 0, 1, {0}}, + {"extent", (int)offsetof(mjStatistic, extent), 4, 1, 0, 1, {0}}, + {"center", (int)offsetof(mjStatistic, center), 4, 3, 0, 1, {0}}, }; static const mjXDefaultEntry kDefaults_mjVisual_global[] = { - {"cameraid", (int)offsetof(mjVisual, global.cameraid), 2, 1, 1, {-1.0}}, - {"orthographic", (int)offsetof(mjVisual, global.orthographic), 2, 1, 1, {0}}, - {"fovy", (int)offsetof(mjVisual, global.fovy), 1, 1, 1, {45.0}}, - {"ipd", (int)offsetof(mjVisual, global.ipd), 1, 1, 1, {0.068}}, - {"azimuth", (int)offsetof(mjVisual, global.azimuth), 1, 1, 1, {90.0}}, - {"elevation", (int)offsetof(mjVisual, global.elevation), 1, 1, 1, {-45.0}}, - {"linewidth", (int)offsetof(mjVisual, global.linewidth), 1, 1, 1, {1.0}}, - {"glow", (int)offsetof(mjVisual, global.glow), 1, 1, 1, {0.3}}, - {"offwidth", (int)offsetof(mjVisual, global.offwidth), 2, 1, 1, {640.0}}, - {"offheight", (int)offsetof(mjVisual, global.offheight), 2, 1, 1, {480.0}}, - {"realtime", (int)offsetof(mjVisual, global.realtime), 1, 1, 1, {1.0}}, - {"ellipsoidinertia", (int)offsetof(mjVisual, global.ellipsoidinertia), 2, 1, 1, {0}}, - {"bvactive", (int)offsetof(mjVisual, global.bvactive), 2, 1, 1, {1}}, + {"cameraid", (int)offsetof(mjVisual, global.cameraid), 2, 1, 1, 0, {-1.0}}, + {"orthographic", (int)offsetof(mjVisual, global.orthographic), 2, 1, 1, 0, {0}}, + {"fovy", (int)offsetof(mjVisual, global.fovy), 1, 1, 1, 0, {45.0}}, + {"ipd", (int)offsetof(mjVisual, global.ipd), 1, 1, 1, 0, {0.068}}, + {"azimuth", (int)offsetof(mjVisual, global.azimuth), 1, 1, 1, 0, {90.0}}, + {"elevation", (int)offsetof(mjVisual, global.elevation), 1, 1, 1, 0, {-45.0}}, + {"linewidth", (int)offsetof(mjVisual, global.linewidth), 1, 1, 1, 0, {1.0}}, + {"glow", (int)offsetof(mjVisual, global.glow), 1, 1, 1, 0, {0.3}}, + {"offwidth", (int)offsetof(mjVisual, global.offwidth), 2, 1, 1, 0, {640.0}}, + {"offheight", (int)offsetof(mjVisual, global.offheight), 2, 1, 1, 0, {480.0}}, + {"realtime", (int)offsetof(mjVisual, global.realtime), 1, 1, 1, 0, {1.0}}, + {"ellipsoidinertia", (int)offsetof(mjVisual, global.ellipsoidinertia), 2, 1, 1, 0, {0}}, + {"bvactive", (int)offsetof(mjVisual, global.bvactive), 2, 1, 1, 0, {1}}, }; static const mjXDefaultEntry kDefaults_mjVisual_headlight[] = { - {"ambient", (int)offsetof(mjVisual, headlight.ambient), 1, 3, 3, {0.1, 0.1, 0.1}}, - {"diffuse", (int)offsetof(mjVisual, headlight.diffuse), 1, 3, 3, {0.4, 0.4, 0.4}}, - {"specular", (int)offsetof(mjVisual, headlight.specular), 1, 3, 3, {0.5, 0.5, 0.5}}, - {"active", (int)offsetof(mjVisual, headlight.active), 2, 1, 1, {1.0}}, + {"ambient", (int)offsetof(mjVisual, headlight.ambient), 1, 3, 3, 0, {0.1, 0.1, 0.1}}, + {"diffuse", (int)offsetof(mjVisual, headlight.diffuse), 1, 3, 3, 0, {0.4, 0.4, 0.4}}, + {"specular", (int)offsetof(mjVisual, headlight.specular), 1, 3, 3, 0, {0.5, 0.5, 0.5}}, + {"active", (int)offsetof(mjVisual, headlight.active), 2, 1, 1, 0, {1.0}}, }; static const mjXDefaultEntry kDefaults_mjVisual_map[] = { - {"stiffness", (int)offsetof(mjVisual, map.stiffness), 1, 1, 1, {100.0}}, - {"stiffnessrot", (int)offsetof(mjVisual, map.stiffnessrot), 1, 1, 1, {500.0}}, - {"force", (int)offsetof(mjVisual, map.force), 1, 1, 1, {0.005}}, - {"torque", (int)offsetof(mjVisual, map.torque), 1, 1, 1, {0.1}}, - {"alpha", (int)offsetof(mjVisual, map.alpha), 1, 1, 1, {0.3}}, - {"fogstart", (int)offsetof(mjVisual, map.fogstart), 1, 1, 1, {3.0}}, - {"fogend", (int)offsetof(mjVisual, map.fogend), 1, 1, 1, {10.0}}, - {"znear", (int)offsetof(mjVisual, map.znear), 1, 1, 1, {0.01}}, - {"zfar", (int)offsetof(mjVisual, map.zfar), 1, 1, 1, {50.0}}, - {"haze", (int)offsetof(mjVisual, map.haze), 1, 1, 1, {0.3}}, - {"shadowclip", (int)offsetof(mjVisual, map.shadowclip), 1, 1, 1, {1.0}}, - {"shadowscale", (int)offsetof(mjVisual, map.shadowscale), 1, 1, 1, {0.6}}, - {"actuatortendon", (int)offsetof(mjVisual, map.actuatortendon), 1, 1, 1, {2.0}}, + {"stiffness", (int)offsetof(mjVisual, map.stiffness), 1, 1, 1, 0, {100.0}}, + {"stiffnessrot", (int)offsetof(mjVisual, map.stiffnessrot), 1, 1, 1, 0, {500.0}}, + {"force", (int)offsetof(mjVisual, map.force), 1, 1, 1, 0, {0.005}}, + {"torque", (int)offsetof(mjVisual, map.torque), 1, 1, 1, 0, {0.1}}, + {"alpha", (int)offsetof(mjVisual, map.alpha), 1, 1, 1, 0, {0.3}}, + {"fogstart", (int)offsetof(mjVisual, map.fogstart), 1, 1, 1, 0, {3.0}}, + {"fogend", (int)offsetof(mjVisual, map.fogend), 1, 1, 1, 0, {10.0}}, + {"znear", (int)offsetof(mjVisual, map.znear), 1, 1, 1, 0, {0.01}}, + {"zfar", (int)offsetof(mjVisual, map.zfar), 1, 1, 1, 0, {50.0}}, + {"haze", (int)offsetof(mjVisual, map.haze), 1, 1, 1, 0, {0.3}}, + {"shadowclip", (int)offsetof(mjVisual, map.shadowclip), 1, 1, 1, 0, {1.0}}, + {"shadowscale", (int)offsetof(mjVisual, map.shadowscale), 1, 1, 1, 0, {0.6}}, + {"actuatortendon", (int)offsetof(mjVisual, map.actuatortendon), 1, 1, 1, 0, {2.0}}, }; static const mjXDefaultEntry kDefaults_mjVisual_quality[] = { - {"shadowsize", (int)offsetof(mjVisual, quality.shadowsize), 2, 1, 1, {4096.0}}, - {"offsamples", (int)offsetof(mjVisual, quality.offsamples), 2, 1, 1, {4.0}}, - {"numslices", (int)offsetof(mjVisual, quality.numslices), 2, 1, 1, {28.0}}, - {"numstacks", (int)offsetof(mjVisual, quality.numstacks), 2, 1, 1, {16.0}}, - {"numquads", (int)offsetof(mjVisual, quality.numquads), 2, 1, 1, {4.0}}, + {"shadowsize", (int)offsetof(mjVisual, quality.shadowsize), 2, 1, 1, 0, {4096.0}}, + {"offsamples", (int)offsetof(mjVisual, quality.offsamples), 2, 1, 1, 0, {4.0}}, + {"numslices", (int)offsetof(mjVisual, quality.numslices), 2, 1, 1, 0, {28.0}}, + {"numstacks", (int)offsetof(mjVisual, quality.numstacks), 2, 1, 1, 0, {16.0}}, + {"numquads", (int)offsetof(mjVisual, quality.numquads), 2, 1, 1, 0, {4.0}}, +}; + +static const mjXDefaultEntry kDefaults_mjVisual_rgba[] = { + {"fog", (int)offsetof(mjVisual, rgba.fog), 1, 4, 4, 0, {0.0, 0.0, 0.0, 1.0}}, + {"haze", (int)offsetof(mjVisual, rgba.haze), 1, 4, 4, 0, {1.0, 1.0, 1.0, 1.0}}, + {"force", (int)offsetof(mjVisual, rgba.force), 1, 4, 4, 0, {1.0, 0.5, 0.5, 1.0}}, + {"inertia", (int)offsetof(mjVisual, rgba.inertia), 1, 4, 4, 0, {0.8, 0.2, 0.2, 0.6}}, + {"joint", (int)offsetof(mjVisual, rgba.joint), 1, 4, 4, 0, {0.2, 0.6, 0.8, 1.0}}, + {"actuator", (int)offsetof(mjVisual, rgba.actuator), 1, 4, 4, 0, {0.2, 0.25, 0.2, 1.0}}, + {"actuatornegative", (int)offsetof(mjVisual, rgba.actuatornegative), 1, 4, 4, 0, {0.2, 0.6, 0.9, 1.0}}, + {"actuatorpositive", (int)offsetof(mjVisual, rgba.actuatorpositive), 1, 4, 4, 0, {0.9, 0.4, 0.2, 1.0}}, + {"com", (int)offsetof(mjVisual, rgba.com), 1, 4, 4, 0, {0.9, 0.9, 0.9, 1.0}}, + {"camera", (int)offsetof(mjVisual, rgba.camera), 1, 4, 4, 0, {0.6, 0.9, 0.6, 1.0}}, + {"light", (int)offsetof(mjVisual, rgba.light), 1, 4, 4, 0, {0.6, 0.6, 0.9, 1.0}}, + {"selectpoint", (int)offsetof(mjVisual, rgba.selectpoint), 1, 4, 4, 0, {0.9, 0.9, 0.1, 1.0}}, + {"connect", (int)offsetof(mjVisual, rgba.connect), 1, 4, 4, 0, {0.2, 0.2, 0.8, 1.0}}, + {"contactpoint", (int)offsetof(mjVisual, rgba.contactpoint), 1, 4, 4, 0, {0.9, 0.6, 0.2, 1.0}}, + {"contactforce", (int)offsetof(mjVisual, rgba.contactforce), 1, 4, 4, 0, {0.7, 0.9, 0.9, 1.0}}, + {"contactfriction", (int)offsetof(mjVisual, rgba.contactfriction), 1, 4, 4, 0, {0.9, 0.8, 0.4, 1.0}}, + {"contacttorque", (int)offsetof(mjVisual, rgba.contacttorque), 1, 4, 4, 0, {0.9, 0.7, 0.9, 1.0}}, + {"contactgap", (int)offsetof(mjVisual, rgba.contactgap), 1, 4, 4, 0, {0.5, 0.8, 0.9, 1.0}}, + {"rangefinder", (int)offsetof(mjVisual, rgba.rangefinder), 1, 4, 4, 0, {1.0, 1.0, 0.1, 1.0}}, + {"constraint", (int)offsetof(mjVisual, rgba.constraint), 1, 4, 4, 0, {0.9, 0.0, 0.0, 1.0}}, + {"slidercrank", (int)offsetof(mjVisual, rgba.slidercrank), 1, 4, 4, 0, {0.5, 0.3, 0.8, 1.0}}, + {"crankbroken", (int)offsetof(mjVisual, rgba.crankbroken), 1, 4, 4, 0, {0.9, 0.0, 0.0, 1.0}}, + {"frustum", (int)offsetof(mjVisual, rgba.frustum), 1, 4, 4, 0, {1.0, 1.0, 0.0, 0.2}}, + {"bv", (int)offsetof(mjVisual, rgba.bv), 1, 4, 4, 0, {0.0, 1.0, 0.0, 0.5}}, + {"bvactive", (int)offsetof(mjVisual, rgba.bvactive), 1, 4, 4, 0, {1.0, 0.0, 0.0, 0.5}}, }; static const mjXDefaultEntry kDefaults_mjVisual_scale[] = { - {"forcewidth", (int)offsetof(mjVisual, scale.forcewidth), 1, 1, 1, {0.1}}, - {"contactwidth", (int)offsetof(mjVisual, scale.contactwidth), 1, 1, 1, {0.3}}, - {"contactheight", (int)offsetof(mjVisual, scale.contactheight), 1, 1, 1, {0.1}}, - {"connect", (int)offsetof(mjVisual, scale.connect), 1, 1, 1, {0.2}}, - {"com", (int)offsetof(mjVisual, scale.com), 1, 1, 1, {0.4}}, - {"camera", (int)offsetof(mjVisual, scale.camera), 1, 1, 1, {0.3}}, - {"light", (int)offsetof(mjVisual, scale.light), 1, 1, 1, {0.3}}, - {"selectpoint", (int)offsetof(mjVisual, scale.selectpoint), 1, 1, 1, {0.2}}, - {"jointlength", (int)offsetof(mjVisual, scale.jointlength), 1, 1, 1, {1.0}}, - {"jointwidth", (int)offsetof(mjVisual, scale.jointwidth), 1, 1, 1, {0.1}}, - {"actuatorlength", (int)offsetof(mjVisual, scale.actuatorlength), 1, 1, 1, {0.7}}, - {"actuatorwidth", (int)offsetof(mjVisual, scale.actuatorwidth), 1, 1, 1, {0.2}}, - {"framelength", (int)offsetof(mjVisual, scale.framelength), 1, 1, 1, {1.0}}, - {"framewidth", (int)offsetof(mjVisual, scale.framewidth), 1, 1, 1, {0.1}}, - {"constraint", (int)offsetof(mjVisual, scale.constraint), 1, 1, 1, {0.1}}, - {"slidercrank", (int)offsetof(mjVisual, scale.slidercrank), 1, 1, 1, {0.2}}, - {"frustum", (int)offsetof(mjVisual, scale.frustum), 1, 1, 1, {10.0}}, + {"forcewidth", (int)offsetof(mjVisual, scale.forcewidth), 1, 1, 1, 0, {0.1}}, + {"contactwidth", (int)offsetof(mjVisual, scale.contactwidth), 1, 1, 1, 0, {0.3}}, + {"contactheight", (int)offsetof(mjVisual, scale.contactheight), 1, 1, 1, 0, {0.1}}, + {"connect", (int)offsetof(mjVisual, scale.connect), 1, 1, 1, 0, {0.2}}, + {"com", (int)offsetof(mjVisual, scale.com), 1, 1, 1, 0, {0.4}}, + {"camera", (int)offsetof(mjVisual, scale.camera), 1, 1, 1, 0, {0.3}}, + {"light", (int)offsetof(mjVisual, scale.light), 1, 1, 1, 0, {0.3}}, + {"selectpoint", (int)offsetof(mjVisual, scale.selectpoint), 1, 1, 1, 0, {0.2}}, + {"jointlength", (int)offsetof(mjVisual, scale.jointlength), 1, 1, 1, 0, {1.0}}, + {"jointwidth", (int)offsetof(mjVisual, scale.jointwidth), 1, 1, 1, 0, {0.1}}, + {"actuatorlength", (int)offsetof(mjVisual, scale.actuatorlength), 1, 1, 1, 0, {0.7}}, + {"actuatorwidth", (int)offsetof(mjVisual, scale.actuatorwidth), 1, 1, 1, 0, {0.2}}, + {"framelength", (int)offsetof(mjVisual, scale.framelength), 1, 1, 1, 0, {1.0}}, + {"framewidth", (int)offsetof(mjVisual, scale.framewidth), 1, 1, 1, 0, {0.1}}, + {"constraint", (int)offsetof(mjVisual, scale.constraint), 1, 1, 1, 0, {0.1}}, + {"slidercrank", (int)offsetof(mjVisual, scale.slidercrank), 1, 1, 1, 0, {0.2}}, + {"frustum", (int)offsetof(mjVisual, scale.frustum), 1, 1, 1, 0, {10.0}}, }; static const mjXDefaultEntry kDefaults_mjsActuator[] = { - {"gear", (int)offsetof(mjsActuator, gear), 0, 6, 6, {1.0, 0.0, 0.0, 0.0, 0.0, 0.0}}, - {"actdim", (int)offsetof(mjsActuator, actdim), 2, 1, 1, {-1.0}}, - {"dyntype", (int)offsetof(mjsActuator, dyntype), 2, 1, 1, {(double)mjDYN_NONE}}, - {"gaintype", (int)offsetof(mjsActuator, gaintype), 2, 1, 1, {(double)mjGAIN_FIXED}}, - {"biastype", (int)offsetof(mjsActuator, biastype), 2, 1, 1, {(double)mjBIAS_NONE}}, - {"dynprm", (int)offsetof(mjsActuator, dynprm), 0, mjNDYN, 1, {1.0}}, - {"gainprm", (int)offsetof(mjsActuator, gainprm), 0, mjNGAIN, 1, {1.0}}, + {"group", (int)offsetof(mjsActuator, group), 2, 1, 0, 0, {0}}, + {"nsample", (int)offsetof(mjsActuator, nsample), 2, 1, 0, 0, {0}}, + {"interp", (int)offsetof(mjsActuator, interp), 2, 1, 0, 0, {0}}, + {"delay", (int)offsetof(mjsActuator, delay), 0, 1, 0, 0, {0}}, + {"ctrlrange", (int)offsetof(mjsActuator, ctrlrange), 0, 2, 0, 0, {0}}, + {"ctrllimited", (int)offsetof(mjsActuator, ctrllimited), 2, 1, 1, 0, {(double)2}}, + {"forcelimited", (int)offsetof(mjsActuator, forcelimited), 2, 1, 1, 0, {(double)2}}, + {"actlimited", (int)offsetof(mjsActuator, actlimited), 2, 1, 1, 0, {(double)2}}, + {"forcerange", (int)offsetof(mjsActuator, forcerange), 0, 2, 0, 0, {0}}, + {"actrange", (int)offsetof(mjsActuator, actrange), 0, 2, 0, 0, {0}}, + {"lengthrange", (int)offsetof(mjsActuator, lengthrange), 0, 2, 0, 0, {0}}, + {"gear", (int)offsetof(mjsActuator, gear), 0, 6, 6, 0, {1.0, 0.0, 0.0, 0.0, 0.0, 0.0}}, + {"damping", (int)offsetof(mjsActuator, damping), 0, mjNPOLY+1, 0, 0, {0}}, + {"armature", (int)offsetof(mjsActuator, armature), 0, 1, 0, 0, {0}}, + {"cranklength", (int)offsetof(mjsActuator, cranklength), 0, 1, 0, 0, {0}}, + {"actdim", (int)offsetof(mjsActuator, actdim), 2, 1, 1, 0, {-1.0}}, + {"velrange", (int)offsetof(mjsActuator, velrange), 0, 2, 0, 0, {0}}, + {"ffrange", (int)offsetof(mjsActuator, ffrange), 0, 2, 0, 0, {0}}, + {"dyntype", (int)offsetof(mjsActuator, dyntype), 2, 1, 1, 0, {(double)mjDYN_NONE}}, + {"gaintype", (int)offsetof(mjsActuator, gaintype), 2, 1, 1, 0, {(double)mjGAIN_FIXED}}, + {"biastype", (int)offsetof(mjsActuator, biastype), 2, 1, 1, 0, {(double)mjBIAS_NONE}}, + {"dynprm", (int)offsetof(mjsActuator, dynprm), 0, mjNDYN, 1, 0, {1.0}}, + {"gainprm", (int)offsetof(mjsActuator, gainprm), 0, mjNGAIN, 1, 0, {1.0}}, + {"biasprm", (int)offsetof(mjsActuator, biasprm), 0, mjNBIAS, 0, 0, {0}}, + {"actearly", (int)offsetof(mjsActuator, actearly), 3, 1, 0, 0, {0}}, + {"inheritrange", (int)offsetof(mjsActuator, inheritrange), 0, 1, 0, 0, {0}}, }; static const mjXDefaultEntry kDefaults_mjsBody[] = { - {"pos", (int)offsetof(mjsBody, pos), 0, 3, 3, {0.0, 0.0, 0.0}}, - {"quat", (int)offsetof(mjsBody, quat), 0, 4, 4, {1.0, 0.0, 0.0, 0.0}}, - {"simple", (int)offsetof(mjsBody, simple), 3, 1, 1, {(double)1}}, + {"pos", (int)offsetof(mjsBody, pos), 0, 3, 3, 0, {0.0, 0.0, 0.0}}, + {"quat", (int)offsetof(mjsBody, quat), 0, 4, 4, 0, {1.0, 0.0, 0.0, 0.0}}, + {"mocap", (int)offsetof(mjsBody, mocap), 3, 1, 0, 0, {0}}, + {"gravcomp", (int)offsetof(mjsBody, gravcomp), 0, 1, 0, 0, {0}}, + {"sleep", (int)offsetof(mjsBody, sleep), 2, 1, 0, 0, {0}}, + {"simple", (int)offsetof(mjsBody, simple), 3, 1, 1, 0, {(double)1}}, + {"pos", (int)offsetof(mjsBody, ipos), 0, 3, 0, 1, {0}}, + {"quat", (int)offsetof(mjsBody, iquat), 0, 4, 4, 0, {1.0, 0.0, 0.0, 0.0}}, + {"mass", (int)offsetof(mjsBody, mass), 0, 1, 0, 0, {0}}, + {"diaginertia", (int)offsetof(mjsBody, inertia), 0, 3, 0, 0, {0}}, + {"fullinertia", (int)offsetof(mjsBody, fullinertia), 0, 6, 0, 1, {0}}, }; static const mjXDefaultEntry kDefaults_mjsCamera[] = { - {"fovy", (int)offsetof(mjsCamera, fovy), 0, 1, 1, {45.0}}, - {"ipd", (int)offsetof(mjsCamera, ipd), 0, 1, 1, {0.068}}, - {"resolution", (int)offsetof(mjsCamera, resolution), 2, 2, 2, {1.0, 1.0}}, - {"pos", (int)offsetof(mjsCamera, pos), 0, 3, 3, {0.0, 0.0, 0.0}}, - {"quat", (int)offsetof(mjsCamera, quat), 0, 4, 4, {1.0, 0.0, 0.0, 0.0}}, - {"mode", (int)offsetof(mjsCamera, mode), 2, 1, 1, {(double)mjCAMLIGHT_FIXED}}, + {"projection", (int)offsetof(mjsCamera, proj), 2, 1, 0, 0, {0}}, + {"fovy", (int)offsetof(mjsCamera, fovy), 0, 1, 1, 0, {45.0}}, + {"ipd", (int)offsetof(mjsCamera, ipd), 0, 1, 1, 0, {0.068}}, + {"resolution", (int)offsetof(mjsCamera, resolution), 2, 2, 2, 0, {1.0, 1.0}}, + {"pos", (int)offsetof(mjsCamera, pos), 0, 3, 3, 0, {0.0, 0.0, 0.0}}, + {"quat", (int)offsetof(mjsCamera, quat), 0, 4, 4, 0, {1.0, 0.0, 0.0, 0.0}}, + {"mode", (int)offsetof(mjsCamera, mode), 2, 1, 1, 0, {(double)mjCAMLIGHT_FIXED}}, + {"focal", (int)offsetof(mjsCamera, focal_length), 1, 2, 0, 0, {0}}, + {"focalpixel", (int)offsetof(mjsCamera, focal_pixel), 1, 2, 0, 0, {0}}, + {"principal", (int)offsetof(mjsCamera, principal_length), 1, 2, 0, 0, {0}}, + {"principalpixel", (int)offsetof(mjsCamera, principal_pixel), 1, 2, 0, 0, {0}}, + {"sensorsize", (int)offsetof(mjsCamera, sensor_size), 1, 2, 0, 0, {0}}, +}; + +static const mjXDefaultEntry kDefaults_mjsCompiler[] = { + {"autolimits", (int)offsetof(mjsCompiler, autolimits), 3, 1, 1, 0, {1}}, + {"boundmass", (int)offsetof(mjsCompiler, boundmass), 0, 1, 0, 0, {0}}, + {"boundinertia", (int)offsetof(mjsCompiler, boundinertia), 0, 1, 0, 0, {0}}, + {"settotalmass", (int)offsetof(mjsCompiler, settotalmass), 0, 1, 1, 0, {-1.0}}, + {"balanceinertia", (int)offsetof(mjsCompiler, balanceinertia), 3, 1, 0, 0, {0}}, + {"angle", (int)offsetof(mjsCompiler, degree), 3, 1, 1, 0, {(double)1}}, + {"fitaabb", (int)offsetof(mjsCompiler, fitaabb), 3, 1, 0, 0, {0}}, + {"discardvisual", (int)offsetof(mjsCompiler, discardvisual), 3, 1, 0, 0, {0}}, + {"usethread", (int)offsetof(mjsCompiler, usethread), 3, 1, 1, 0, {1}}, + {"fusestatic", (int)offsetof(mjsCompiler, fusestatic), 3, 1, 0, 0, {0}}, + {"inertiafromgeom", (int)offsetof(mjsCompiler, inertiafromgeom), 2, 1, 1, 0, {(double)2}}, + {"inertiagrouprange", (int)offsetof(mjsCompiler, inertiagrouprange), 2, 2, 2, 0, {0.0, 5.0}}, + {"saveinertial", (int)offsetof(mjsCompiler, saveinertial), 3, 1, 0, 0, {0}}, + {"alignfree", (int)offsetof(mjsCompiler, alignfree), 3, 1, 0, 0, {0}}, + {"conflict", (int)offsetof(mjsCompiler, conflict), 2, 1, 0, 0, {0}}, }; static const mjXDefaultEntry kDefaults_mjsEquality[] = { - {"active", (int)offsetof(mjsEquality, active), 3, 1, 1, {1}}, - {"solref", (int)offsetof(mjsEquality, solref), 4, mjNREF, 2, {0.02, 1.0}}, - {"solimp", (int)offsetof(mjsEquality, solimp), 4, mjNIMP, 5, {0.9, 0.95, 0.001, 0.5, 2.0}}, + {"active", (int)offsetof(mjsEquality, active), 3, 1, 1, 0, {1}}, + {"solref", (int)offsetof(mjsEquality, solref), 4, mjNREF, 2, 0, {0.02, 1.0}}, + {"solimp", (int)offsetof(mjsEquality, solimp), 4, mjNIMP, 5, 0, {0.9, 0.95, 0.001, 0.5, 2.0}}, +}; + +static const mjXDefaultEntry kDefaults_mjsFlex[] = { + {"young", (int)offsetof(mjsFlex, young), 0, 1, 0, 0, {0}}, + {"poisson", (int)offsetof(mjsFlex, poisson), 0, 1, 0, 0, {0}}, + {"damping", (int)offsetof(mjsFlex, damping), 0, 1, 0, 0, {0}}, + {"thickness", (int)offsetof(mjsFlex, thickness), 0, 1, 1, 0, {-1.0}}, + {"elastic2d", (int)offsetof(mjsFlex, elastic2d), 2, 1, 0, 0, {0}}, + {"contype", (int)offsetof(mjsFlex, contype), 2, 1, 1, 0, {1.0}}, + {"conaffinity", (int)offsetof(mjsFlex, conaffinity), 2, 1, 1, 0, {1.0}}, + {"condim", (int)offsetof(mjsFlex, condim), 2, 1, 1, 0, {3.0}}, + {"priority", (int)offsetof(mjsFlex, priority), 2, 1, 0, 0, {0}}, + {"friction", (int)offsetof(mjsFlex, friction), 0, 3, 3, 0, {1.0, 0.005, 0.0001}}, + {"solmix", (int)offsetof(mjsFlex, solmix), 0, 1, 1, 0, {1.0}}, + {"solref", (int)offsetof(mjsFlex, solref), 4, mjNREF, 2, 0, {0.02, 1.0}}, + {"solimp", (int)offsetof(mjsFlex, solimp), 4, mjNIMP, 5, 0, {0.9, 0.95, 0.001, 0.5, 2.0}}, + {"margin", (int)offsetof(mjsFlex, margin), 0, 1, 0, 0, {0}}, + {"gap", (int)offsetof(mjsFlex, gap), 0, 1, 0, 0, {0}}, + {"internal", (int)offsetof(mjsFlex, internal), 3, 1, 0, 0, {0}}, + {"selfcollide", (int)offsetof(mjsFlex, selfcollide), 2, 1, 1, 0, {(double)mjFLEXSELF_AUTO}}, + {"activelayers", (int)offsetof(mjsFlex, activelayers), 2, 1, 1, 0, {1.0}}, + {"passive", (int)offsetof(mjsFlex, passive), 2, 1, 0, 0, {0}}, + {"group", (int)offsetof(mjsFlex, group), 2, 1, 0, 0, {0}}, + {"dim", (int)offsetof(mjsFlex, dim), 2, 1, 1, 0, {2.0}}, + {"radius", (int)offsetof(mjsFlex, radius), 0, 1, 1, 0, {0.005}}, + {"rgba", (int)offsetof(mjsFlex, rgba), 1, 4, 4, 0, {0.5, 0.5, 0.5, 1.0}}, + {"flatskin", (int)offsetof(mjsFlex, flatskin), 3, 1, 0, 0, {0}}, + {"cellcount", (int)offsetof(mjsFlex, cellcount), 2, 3, 3, 0, {1.0, 1.0, 1.0}}, + {"stiffness", (int)offsetof(mjsFlex, edgestiffness), 0, 1, 0, 0, {0}}, + {"damping", (int)offsetof(mjsFlex, edgedamping), 0, 1, 0, 0, {0}}, }; static const mjXDefaultEntry kDefaults_mjsFrame[] = { - {"quat", (int)offsetof(mjsFrame, quat), 0, 4, 4, {1.0, 0.0, 0.0, 0.0}}, + {"pos", (int)offsetof(mjsFrame, pos), 0, 3, 0, 0, {0}}, + {"quat", (int)offsetof(mjsFrame, quat), 0, 4, 4, 0, {1.0, 0.0, 0.0, 0.0}}, }; static const mjXDefaultEntry kDefaults_mjsGeom[] = { - {"type", (int)offsetof(mjsGeom, type), 2, 1, 1, {(double)mjGEOM_SPHERE}}, - {"contype", (int)offsetof(mjsGeom, contype), 2, 1, 1, {1.0}}, - {"conaffinity", (int)offsetof(mjsGeom, conaffinity), 2, 1, 1, {1.0}}, - {"condim", (int)offsetof(mjsGeom, condim), 2, 1, 1, {3.0}}, - {"friction", (int)offsetof(mjsGeom, friction), 0, 3, 3, {1.0, 0.005, 0.0001}}, - {"density", (int)offsetof(mjsGeom, density), 0, 1, 1, {1000.0}}, - {"solmix", (int)offsetof(mjsGeom, solmix), 0, 1, 1, {1.0}}, - {"solref", (int)offsetof(mjsGeom, solref), 4, mjNREF, 2, {0.02, 1.0}}, - {"solimp", (int)offsetof(mjsGeom, solimp), 4, mjNIMP, 5, {0.9, 0.95, 0.001, 0.5, 2.0}}, - {"pos", (int)offsetof(mjsGeom, pos), 0, 3, 3, {0.0, 0.0, 0.0}}, - {"quat", (int)offsetof(mjsGeom, quat), 0, 4, 4, {1.0, 0.0, 0.0, 0.0}}, - {"fitscale", (int)offsetof(mjsGeom, fitscale), 0, 1, 1, {1.0}}, - {"rgba", (int)offsetof(mjsGeom, rgba), 1, 4, 4, {0.5, 0.5, 0.5, 1.0}}, + {"type", (int)offsetof(mjsGeom, type), 2, 1, 1, 0, {(double)mjGEOM_SPHERE}}, + {"contype", (int)offsetof(mjsGeom, contype), 2, 1, 1, 0, {1.0}}, + {"conaffinity", (int)offsetof(mjsGeom, conaffinity), 2, 1, 1, 0, {1.0}}, + {"condim", (int)offsetof(mjsGeom, condim), 2, 1, 1, 0, {3.0}}, + {"group", (int)offsetof(mjsGeom, group), 2, 1, 0, 0, {0}}, + {"priority", (int)offsetof(mjsGeom, priority), 2, 1, 0, 0, {0}}, + {"size", (int)offsetof(mjsGeom, size), 0, 3, 0, 0, {0}}, + {"friction", (int)offsetof(mjsGeom, friction), 0, 3, 3, 0, {1.0, 0.005, 0.0001}}, + {"mass", (int)offsetof(mjsGeom, mass), 0, 1, 0, 1, {0}}, + {"density", (int)offsetof(mjsGeom, density), 0, 1, 1, 0, {1000.0}}, + {"shellinertia", (int)offsetof(mjsGeom, typeinertia), 2, 1, 0, 0, {0}}, + {"solmix", (int)offsetof(mjsGeom, solmix), 0, 1, 1, 0, {1.0}}, + {"solref", (int)offsetof(mjsGeom, solref), 4, mjNREF, 2, 0, {0.02, 1.0}}, + {"solimp", (int)offsetof(mjsGeom, solimp), 4, mjNIMP, 5, 0, {0.9, 0.95, 0.001, 0.5, 2.0}}, + {"margin", (int)offsetof(mjsGeom, margin), 0, 1, 0, 0, {0}}, + {"gap", (int)offsetof(mjsGeom, gap), 0, 1, 0, 0, {0}}, + {"surfacevel", (int)offsetof(mjsGeom, surfacevel), 0, 6, 0, 0, {0}}, + {"adhesion", (int)offsetof(mjsGeom, adhesion), 0, 1, 0, 0, {0}}, + {"fromto", (int)offsetof(mjsGeom, fromto), 0, 6, 0, 1, {0}}, + {"pos", (int)offsetof(mjsGeom, pos), 0, 3, 3, 0, {0.0, 0.0, 0.0}}, + {"quat", (int)offsetof(mjsGeom, quat), 0, 4, 4, 0, {1.0, 0.0, 0.0, 0.0}}, + {"fitscale", (int)offsetof(mjsGeom, fitscale), 0, 1, 1, 0, {1.0}}, + {"rgba", (int)offsetof(mjsGeom, rgba), 1, 4, 4, 0, {0.5, 0.5, 0.5, 1.0}}, + {"fluidshape", (int)offsetof(mjsGeom, fluid_ellipsoid), 4, 1, 0, 0, {0}}, + {"fluidcoef", (int)offsetof(mjsGeom, fluid_coefs), 4, 5, 5, 0, {0.5, 0.25, 1.5, 1.0, 1.0}}, +}; + +static const mjXDefaultEntry kDefaults_mjsHField[] = { + {"nrow", (int)offsetof(mjsHField, nrow), 2, 1, 0, 0, {0}}, + {"ncol", (int)offsetof(mjsHField, ncol), 2, 1, 0, 0, {0}}, + {"size", (int)offsetof(mjsHField, size), 0, 4, 0, 0, {0}}, }; static const mjXDefaultEntry kDefaults_mjsJoint[] = { - {"type", (int)offsetof(mjsJoint, type), 2, 1, 1, {(double)mjJNT_HINGE}}, - {"axis", (int)offsetof(mjsJoint, axis), 0, 3, 3, {0.0, 0.0, 1.0}}, + {"type", (int)offsetof(mjsJoint, type), 2, 1, 1, 0, {(double)mjJNT_HINGE}}, + {"group", (int)offsetof(mjsJoint, group), 2, 1, 0, 0, {0}}, + {"pos", (int)offsetof(mjsJoint, pos), 0, 3, 0, 0, {0}}, + {"axis", (int)offsetof(mjsJoint, axis), 0, 3, 3, 0, {0.0, 0.0, 1.0}}, + {"springdamper", (int)offsetof(mjsJoint, springdamper), 0, 2, 0, 0, {0}}, + {"limited", (int)offsetof(mjsJoint, limited), 2, 1, 1, 0, {(double)2}}, + {"actuatorfrclimited", (int)offsetof(mjsJoint, actfrclimited), 2, 1, 1, 0, {(double)2}}, + {"solreflimit", (int)offsetof(mjsJoint, solref_limit), 4, mjNREF, 2, 0, {0.02, 1.0}}, + {"solimplimit", (int)offsetof(mjsJoint, solimp_limit), 4, mjNIMP, 5, 0, {0.9, 0.95, 0.001, 0.5, 2.0}}, + {"solreffriction", (int)offsetof(mjsJoint, solref_friction), 4, mjNREF, 2, 0, {0.02, 1.0}}, + {"solimpfriction", (int)offsetof(mjsJoint, solimp_friction), 4, mjNIMP, 5, 0, {0.9, 0.95, 0.001, 0.5, 2.0}}, + {"stiffness", (int)offsetof(mjsJoint, stiffness), 0, mjNPOLY+1, 0, 0, {0}}, + {"range", (int)offsetof(mjsJoint, range), 0, 2, 0, 0, {0}}, + {"actuatorfrcrange", (int)offsetof(mjsJoint, actfrcrange), 0, 2, 0, 0, {0}}, + {"actuatorgravcomp", (int)offsetof(mjsJoint, actgravcomp), 3, 1, 0, 0, {0}}, + {"margin", (int)offsetof(mjsJoint, margin), 0, 1, 0, 0, {0}}, + {"ref", (int)offsetof(mjsJoint, ref), 0, 1, 0, 0, {0}}, + {"springref", (int)offsetof(mjsJoint, springref), 0, 1, 0, 0, {0}}, + {"armature", (int)offsetof(mjsJoint, armature), 0, 1, 0, 0, {0}}, + {"damping", (int)offsetof(mjsJoint, damping), 0, mjNPOLY+1, 0, 0, {0}}, + {"frictionloss", (int)offsetof(mjsJoint, frictionloss), 0, 1, 0, 0, {0}}, +}; + +static const mjXDefaultEntry kDefaults_mjsKey[] = { + {"time", (int)offsetof(mjsKey, time), 0, 1, 0, 0, {0}}, }; static const mjXDefaultEntry kDefaults_mjsLight[] = { - {"castshadow", (int)offsetof(mjsLight, castshadow), 3, 1, 1, {1}}, - {"active", (int)offsetof(mjsLight, active), 3, 1, 1, {1}}, - {"pos", (int)offsetof(mjsLight, pos), 0, 3, 3, {0.0, 0.0, 0.0}}, - {"dir", (int)offsetof(mjsLight, dir), 0, 3, 3, {0.0, 0.0, -1.0}}, - {"bulbradius", (int)offsetof(mjsLight, bulbradius), 1, 1, 1, {0.02}}, - {"range", (int)offsetof(mjsLight, range), 1, 1, 1, {10.0}}, - {"attenuation", (int)offsetof(mjsLight, attenuation), 1, 3, 3, {1.0, 0.0, 0.0}}, - {"cutoff", (int)offsetof(mjsLight, cutoff), 1, 1, 1, {45.0}}, - {"exponent", (int)offsetof(mjsLight, exponent), 1, 1, 1, {10.0}}, - {"diffuse", (int)offsetof(mjsLight, diffuse), 1, 3, 3, {0.7, 0.7, 0.7}}, - {"specular", (int)offsetof(mjsLight, specular), 1, 3, 3, {0.3, 0.3, 0.3}}, - {"mode", (int)offsetof(mjsLight, mode), 2, 1, 1, {(double)mjCAMLIGHT_FIXED}}, + {"type", (int)offsetof(mjsLight, type), 2, 1, 0, 0, {0}}, + {"castshadow", (int)offsetof(mjsLight, castshadow), 3, 1, 1, 0, {1}}, + {"active", (int)offsetof(mjsLight, active), 3, 1, 1, 0, {1}}, + {"pos", (int)offsetof(mjsLight, pos), 0, 3, 3, 0, {0.0, 0.0, 0.0}}, + {"dir", (int)offsetof(mjsLight, dir), 0, 3, 3, 0, {0.0, 0.0, -1.0}}, + {"bulbradius", (int)offsetof(mjsLight, bulbradius), 1, 1, 1, 0, {0.02}}, + {"intensity", (int)offsetof(mjsLight, intensity), 1, 1, 0, 0, {0}}, + {"range", (int)offsetof(mjsLight, range), 1, 1, 1, 0, {10.0}}, + {"attenuation", (int)offsetof(mjsLight, attenuation), 1, 3, 3, 0, {1.0, 0.0, 0.0}}, + {"cutoff", (int)offsetof(mjsLight, cutoff), 1, 1, 1, 0, {45.0}}, + {"exponent", (int)offsetof(mjsLight, exponent), 1, 1, 1, 0, {10.0}}, + {"ambient", (int)offsetof(mjsLight, ambient), 1, 3, 0, 0, {0}}, + {"diffuse", (int)offsetof(mjsLight, diffuse), 1, 3, 3, 0, {0.7, 0.7, 0.7}}, + {"specular", (int)offsetof(mjsLight, specular), 1, 3, 3, 0, {0.3, 0.3, 0.3}}, + {"mode", (int)offsetof(mjsLight, mode), 2, 1, 1, 0, {(double)mjCAMLIGHT_FIXED}}, }; static const mjXDefaultEntry kDefaults_mjsMaterial[] = { - {"texrepeat", (int)offsetof(mjsMaterial, texrepeat), 1, 2, 2, {1.0, 1.0}}, - {"specular", (int)offsetof(mjsMaterial, specular), 1, 1, 1, {0.5}}, - {"shininess", (int)offsetof(mjsMaterial, shininess), 1, 1, 1, {0.5}}, - {"metallic", (int)offsetof(mjsMaterial, metallic), 1, 1, 1, {-1.0}}, - {"roughness", (int)offsetof(mjsMaterial, roughness), 1, 1, 1, {-1.0}}, - {"rgba", (int)offsetof(mjsMaterial, rgba), 1, 4, 4, {1.0, 1.0, 1.0, 1.0}}, + {"texrepeat", (int)offsetof(mjsMaterial, texrepeat), 1, 2, 2, 0, {1.0, 1.0}}, + {"texuniform", (int)offsetof(mjsMaterial, texuniform), 3, 1, 0, 0, {0}}, + {"emission", (int)offsetof(mjsMaterial, emission), 1, 1, 0, 0, {0}}, + {"specular", (int)offsetof(mjsMaterial, specular), 1, 1, 1, 0, {0.5}}, + {"shininess", (int)offsetof(mjsMaterial, shininess), 1, 1, 1, 0, {0.5}}, + {"reflectance", (int)offsetof(mjsMaterial, reflectance), 1, 1, 0, 0, {0}}, + {"metallic", (int)offsetof(mjsMaterial, metallic), 1, 1, 1, 0, {-1.0}}, + {"roughness", (int)offsetof(mjsMaterial, roughness), 1, 1, 1, 0, {-1.0}}, + {"rgba", (int)offsetof(mjsMaterial, rgba), 1, 4, 4, 0, {1.0, 1.0, 1.0, 1.0}}, }; static const mjXDefaultEntry kDefaults_mjsMesh[] = { - {"refquat", (int)offsetof(mjsMesh, refquat), 0, 4, 4, {1.0, 0.0, 0.0, 0.0}}, - {"scale", (int)offsetof(mjsMesh, scale), 0, 3, 3, {1.0, 1.0, 1.0}}, - {"maxhullvert", (int)offsetof(mjsMesh, maxhullvert), 2, 1, 1, {-1.0}}, - {"inertia", (int)offsetof(mjsMesh, inertia), 2, 1, 1, {(double)mjMESH_INERTIA_LEGACY}}, + {"refpos", (int)offsetof(mjsMesh, refpos), 0, 3, 0, 0, {0}}, + {"refquat", (int)offsetof(mjsMesh, refquat), 0, 4, 4, 0, {1.0, 0.0, 0.0, 0.0}}, + {"scale", (int)offsetof(mjsMesh, scale), 0, 3, 3, 0, {1.0, 1.0, 1.0}}, + {"smoothnormal", (int)offsetof(mjsMesh, smoothnormal), 3, 1, 0, 0, {0}}, + {"maxhullvert", (int)offsetof(mjsMesh, maxhullvert), 2, 1, 1, 0, {-1.0}}, + {"inertia", (int)offsetof(mjsMesh, inertia), 2, 1, 1, 0, {(double)mjMESH_INERTIA_LEGACY}}, +}; + +static const mjXDefaultEntry kDefaults_mjsNumeric[] = { + {"size", (int)offsetof(mjsNumeric, size), 2, 1, 0, 0, {0}}, }; static const mjXDefaultEntry kDefaults_mjsPair[] = { - {"condim", (int)offsetof(mjsPair, condim), 2, 1, 1, {3.0}}, - {"friction", (int)offsetof(mjsPair, friction), 0, 5, 5, {1.0, 1.0, 0.005, 0.0001, 0.0001}}, - {"solref", (int)offsetof(mjsPair, solref), 4, mjNREF, 2, {0.02, 1.0}}, - {"solimp", (int)offsetof(mjsPair, solimp), 4, mjNIMP, 5, {0.9, 0.95, 0.001, 0.5, 2.0}}, + {"condim", (int)offsetof(mjsPair, condim), 2, 1, 1, 0, {3.0}}, + {"friction", (int)offsetof(mjsPair, friction), 0, 5, 5, 0, {1.0, 1.0, 0.005, 0.0001, 0.0001}}, + {"solref", (int)offsetof(mjsPair, solref), 4, mjNREF, 2, 0, {0.02, 1.0}}, + {"solreffriction", (int)offsetof(mjsPair, solreffriction), 4, mjNREF, 0, 0, {0}}, + {"solimp", (int)offsetof(mjsPair, solimp), 4, mjNIMP, 5, 0, {0.9, 0.95, 0.001, 0.5, 2.0}}, + {"gap", (int)offsetof(mjsPair, gap), 0, 1, 0, 0, {0}}, + {"margin", (int)offsetof(mjsPair, margin), 0, 1, 0, 0, {0}}, + {"adhesion", (int)offsetof(mjsPair, adhesion), 0, 1, 0, 0, {0}}, }; static const mjXDefaultEntry kDefaults_mjsSensor[] = { - {"datatype", (int)offsetof(mjsSensor, datatype), 2, 1, 1, {(double)mjDATATYPE_REAL}}, - {"needstage", (int)offsetof(mjsSensor, needstage), 2, 1, 1, {(double)mjSTAGE_ACC}}, + {"nsample", (int)offsetof(mjsSensor, nsample), 2, 1, 0, 0, {0}}, + {"interp", (int)offsetof(mjsSensor, interp), 2, 1, 0, 0, {0}}, + {"delay", (int)offsetof(mjsSensor, delay), 0, 1, 0, 0, {0}}, + {"interval", (int)offsetof(mjsSensor, interval), 0, 2, 0, 0, {0}}, + {"cutoff", (int)offsetof(mjsSensor, cutoff), 0, 1, 0, 0, {0}}, + {"noise", (int)offsetof(mjsSensor, noise), 0, 1, 0, 0, {0}}, + {"objtype", (int)offsetof(mjsSensor, objtype), 2, 1, 0, 0, {0}}, + {"reftype", (int)offsetof(mjsSensor, reftype), 2, 1, 0, 0, {0}}, + {"datatype", (int)offsetof(mjsSensor, datatype), 2, 1, 1, 0, {(double)mjDATATYPE_REAL}}, + {"needstage", (int)offsetof(mjsSensor, needstage), 2, 1, 1, 0, {(double)mjSTAGE_ACC}}, + {"dim", (int)offsetof(mjsSensor, dim), 2, 1, 0, 0, {0}}, }; static const mjXDefaultEntry kDefaults_mjsSite[] = { - {"type", (int)offsetof(mjsSite, type), 2, 1, 1, {(double)mjGEOM_SPHERE}}, - {"pos", (int)offsetof(mjsSite, pos), 0, 3, 3, {0.0, 0.0, 0.0}}, - {"quat", (int)offsetof(mjsSite, quat), 0, 4, 4, {1.0, 0.0, 0.0, 0.0}}, - {"size", (int)offsetof(mjsSite, size), 0, 3, 3, {0.005, 0.005, 0.005}}, - {"rgba", (int)offsetof(mjsSite, rgba), 1, 4, 4, {0.5, 0.5, 0.5, 1.0}}, + {"type", (int)offsetof(mjsSite, type), 2, 1, 1, 0, {(double)mjGEOM_SPHERE}}, + {"group", (int)offsetof(mjsSite, group), 2, 1, 0, 0, {0}}, + {"pos", (int)offsetof(mjsSite, pos), 0, 3, 3, 0, {0.0, 0.0, 0.0}}, + {"quat", (int)offsetof(mjsSite, quat), 0, 4, 4, 0, {1.0, 0.0, 0.0, 0.0}}, + {"size", (int)offsetof(mjsSite, size), 0, 3, 3, 0, {0.005, 0.005, 0.005}}, + {"fromto", (int)offsetof(mjsSite, fromto), 0, 6, 0, 1, {0}}, + {"rgba", (int)offsetof(mjsSite, rgba), 1, 4, 4, 0, {0.5, 0.5, 0.5, 1.0}}, }; static const mjXDefaultEntry kDefaults_mjsSkin[] = { - {"rgba", (int)offsetof(mjsSkin, rgba), 1, 4, 4, {0.5, 0.5, 0.5, 1.0}}, + {"rgba", (int)offsetof(mjsSkin, rgba), 1, 4, 4, 0, {0.5, 0.5, 0.5, 1.0}}, + {"inflate", (int)offsetof(mjsSkin, inflate), 1, 1, 0, 0, {0}}, + {"group", (int)offsetof(mjsSkin, group), 2, 1, 0, 0, {0}}, }; static const mjXDefaultEntry kDefaults_mjsTendon[] = { - {"springlength", (int)offsetof(mjsTendon, springlength), 0, 2, 2, {-1.0, -1.0}}, - {"width", (int)offsetof(mjsTendon, width), 0, 1, 1, {0.003}}, - {"rgba", (int)offsetof(mjsTendon, rgba), 1, 4, 4, {0.5, 0.5, 0.5, 1.0}}, + {"group", (int)offsetof(mjsTendon, group), 2, 1, 0, 0, {0}}, + {"limited", (int)offsetof(mjsTendon, limited), 2, 1, 1, 0, {(double)2}}, + {"actuatorfrclimited", (int)offsetof(mjsTendon, actfrclimited), 2, 1, 0, 0, {0}}, + {"range", (int)offsetof(mjsTendon, range), 0, 2, 0, 0, {0}}, + {"actuatorfrcrange", (int)offsetof(mjsTendon, actfrcrange), 0, 2, 0, 0, {0}}, + {"solreflimit", (int)offsetof(mjsTendon, solref_limit), 4, mjNREF, 2, 0, {0.02, 1.0}}, + {"solimplimit", (int)offsetof(mjsTendon, solimp_limit), 4, mjNIMP, 5, 0, {0.9, 0.95, 0.001, 0.5, 2.0}}, + {"solreffriction", (int)offsetof(mjsTendon, solref_friction), 4, mjNREF, 2, 0, {0.02, 1.0}}, + {"solimpfriction", (int)offsetof(mjsTendon, solimp_friction), 4, mjNIMP, 5, 0, {0.9, 0.95, 0.001, 0.5, 2.0}}, + {"frictionloss", (int)offsetof(mjsTendon, frictionloss), 0, 1, 0, 0, {0}}, + {"springlength", (int)offsetof(mjsTendon, springlength), 0, 2, 2, 0, {-1.0, -1.0}}, + {"width", (int)offsetof(mjsTendon, width), 0, 1, 1, 0, {0.003}}, + {"margin", (int)offsetof(mjsTendon, margin), 0, 1, 0, 0, {0}}, + {"stiffness", (int)offsetof(mjsTendon, stiffness), 0, mjNPOLY+1, 0, 0, {0}}, + {"damping", (int)offsetof(mjsTendon, damping), 0, mjNPOLY+1, 0, 0, {0}}, + {"armature", (int)offsetof(mjsTendon, armature), 0, 1, 0, 0, {0}}, + {"rgba", (int)offsetof(mjsTendon, rgba), 1, 4, 4, 0, {0.5, 0.5, 0.5, 1.0}}, }; static const mjXDefaultEntry kDefaults_mjsTexture[] = { - {"type", (int)offsetof(mjsTexture, type), 2, 1, 1, {(double)mjTEXTURE_CUBE}}, - {"colorspace", (int)offsetof(mjsTexture, colorspace), 2, 1, 1, {(double)mjCOLORSPACE_AUTO}}, - {"gridsize", (int)offsetof(mjsTexture, gridsize), 2, 2, 2, {1.0, 1.0}}, - {"rgb1", (int)offsetof(mjsTexture, rgb1), 0, 3, 3, {0.8, 0.8, 0.8}}, - {"rgb2", (int)offsetof(mjsTexture, rgb2), 0, 3, 3, {0.5, 0.5, 0.5}}, - {"random", (int)offsetof(mjsTexture, random), 0, 1, 1, {0.01}}, - {"nchannel", (int)offsetof(mjsTexture, nchannel), 2, 1, 1, {3.0}}, + {"type", (int)offsetof(mjsTexture, type), 2, 1, 1, 0, {(double)mjTEXTURE_CUBE}}, + {"colorspace", (int)offsetof(mjsTexture, colorspace), 2, 1, 1, 0, {(double)mjCOLORSPACE_AUTO}}, + {"gridsize", (int)offsetof(mjsTexture, gridsize), 2, 2, 2, 0, {1.0, 1.0}}, + {"builtin", (int)offsetof(mjsTexture, builtin), 2, 1, 0, 0, {0}}, + {"rgb1", (int)offsetof(mjsTexture, rgb1), 0, 3, 3, 0, {0.8, 0.8, 0.8}}, + {"rgb2", (int)offsetof(mjsTexture, rgb2), 0, 3, 3, 0, {0.5, 0.5, 0.5}}, + {"mark", (int)offsetof(mjsTexture, mark), 2, 1, 0, 0, {0}}, + {"markrgb", (int)offsetof(mjsTexture, markrgb), 0, 3, 0, 0, {0}}, + {"random", (int)offsetof(mjsTexture, random), 0, 1, 1, 0, {0.01}}, + {"width", (int)offsetof(mjsTexture, width), 2, 1, 0, 0, {0}}, + {"height", (int)offsetof(mjsTexture, height), 2, 1, 0, 0, {0}}, + {"hflip", (int)offsetof(mjsTexture, hflip), 3, 1, 0, 0, {0}}, + {"vflip", (int)offsetof(mjsTexture, vflip), 3, 1, 0, 0, {0}}, + {"nchannel", (int)offsetof(mjsTexture, nchannel), 2, 1, 1, 0, {3.0}}, }; static const mjXDefaultTable kDefaultTables[] = { + {"mjLROpt", kDefaults_mjLROpt, (int)(sizeof(kDefaults_mjLROpt) / sizeof(kDefaults_mjLROpt[0]))}, {"mjOption", kDefaults_mjOption, (int)(sizeof(kDefaults_mjOption) / sizeof(kDefaults_mjOption[0]))}, + {"mjSpec", kDefaults_mjSpec, (int)(sizeof(kDefaults_mjSpec) / sizeof(kDefaults_mjSpec[0]))}, + {"mjStatistic", kDefaults_mjStatistic, (int)(sizeof(kDefaults_mjStatistic) / sizeof(kDefaults_mjStatistic[0]))}, {"mjVisual", kDefaults_mjVisual_global, (int)(sizeof(kDefaults_mjVisual_global) / sizeof(kDefaults_mjVisual_global[0]))}, {"mjVisual", kDefaults_mjVisual_headlight, (int)(sizeof(kDefaults_mjVisual_headlight) / sizeof(kDefaults_mjVisual_headlight[0]))}, {"mjVisual", kDefaults_mjVisual_map, (int)(sizeof(kDefaults_mjVisual_map) / sizeof(kDefaults_mjVisual_map[0]))}, {"mjVisual", kDefaults_mjVisual_quality, (int)(sizeof(kDefaults_mjVisual_quality) / sizeof(kDefaults_mjVisual_quality[0]))}, + {"mjVisual", kDefaults_mjVisual_rgba, (int)(sizeof(kDefaults_mjVisual_rgba) / sizeof(kDefaults_mjVisual_rgba[0]))}, {"mjVisual", kDefaults_mjVisual_scale, (int)(sizeof(kDefaults_mjVisual_scale) / sizeof(kDefaults_mjVisual_scale[0]))}, {"mjsActuator", kDefaults_mjsActuator, (int)(sizeof(kDefaults_mjsActuator) / sizeof(kDefaults_mjsActuator[0]))}, {"mjsBody", kDefaults_mjsBody, (int)(sizeof(kDefaults_mjsBody) / sizeof(kDefaults_mjsBody[0]))}, {"mjsCamera", kDefaults_mjsCamera, (int)(sizeof(kDefaults_mjsCamera) / sizeof(kDefaults_mjsCamera[0]))}, + {"mjsCompiler", kDefaults_mjsCompiler, (int)(sizeof(kDefaults_mjsCompiler) / sizeof(kDefaults_mjsCompiler[0]))}, {"mjsEquality", kDefaults_mjsEquality, (int)(sizeof(kDefaults_mjsEquality) / sizeof(kDefaults_mjsEquality[0]))}, + {"mjsFlex", kDefaults_mjsFlex, (int)(sizeof(kDefaults_mjsFlex) / sizeof(kDefaults_mjsFlex[0]))}, {"mjsFrame", kDefaults_mjsFrame, (int)(sizeof(kDefaults_mjsFrame) / sizeof(kDefaults_mjsFrame[0]))}, {"mjsGeom", kDefaults_mjsGeom, (int)(sizeof(kDefaults_mjsGeom) / sizeof(kDefaults_mjsGeom[0]))}, + {"mjsHField", kDefaults_mjsHField, (int)(sizeof(kDefaults_mjsHField) / sizeof(kDefaults_mjsHField[0]))}, {"mjsJoint", kDefaults_mjsJoint, (int)(sizeof(kDefaults_mjsJoint) / sizeof(kDefaults_mjsJoint[0]))}, + {"mjsKey", kDefaults_mjsKey, (int)(sizeof(kDefaults_mjsKey) / sizeof(kDefaults_mjsKey[0]))}, {"mjsLight", kDefaults_mjsLight, (int)(sizeof(kDefaults_mjsLight) / sizeof(kDefaults_mjsLight[0]))}, {"mjsMaterial", kDefaults_mjsMaterial, (int)(sizeof(kDefaults_mjsMaterial) / sizeof(kDefaults_mjsMaterial[0]))}, {"mjsMesh", kDefaults_mjsMesh, (int)(sizeof(kDefaults_mjsMesh) / sizeof(kDefaults_mjsMesh[0]))}, + {"mjsNumeric", kDefaults_mjsNumeric, (int)(sizeof(kDefaults_mjsNumeric) / sizeof(kDefaults_mjsNumeric[0]))}, {"mjsPair", kDefaults_mjsPair, (int)(sizeof(kDefaults_mjsPair) / sizeof(kDefaults_mjsPair[0]))}, {"mjsSensor", kDefaults_mjsSensor, (int)(sizeof(kDefaults_mjsSensor) / sizeof(kDefaults_mjsSensor[0]))}, {"mjsSite", kDefaults_mjsSite, (int)(sizeof(kDefaults_mjsSite) / sizeof(kDefaults_mjsSite[0]))}, diff --git a/src/xml/mjcf.schema b/src/xml/mjcf.schema index 4e0000d7..2c6a8bf7 100644 --- a/src/xml/mjcf.schema +++ b/src/xml/mjcf.schema @@ -527,23 +527,23 @@ element mujoco { #---------------------- compiler ------------------------------------------------------------------- element compiler : mjsCompiler { - autolimits : bool + autolimits : bool = true boundmass : double boundinertia : double - settotalmass : double + settotalmass : double = -1 balanceinertia : bool strippath : bool (reading=custom) # stored on the spec coordinate : enum (reading=custom) # deprecation error - angle : enum (field=degree) + angle : enum = degree (field=degree) fitaabb : bool eulerseq : chars[3] (pattern="[xyzXYZ]{3}") meshdir : string texturedir : string discardvisual : bool - usethread : bool + usethread : bool = true fusestatic : bool - inertiafromgeom : enum - inertiagrouprange : int[2] + inertiafromgeom : enum = auto + inertiagrouprange : int[2] = {0, 5} saveinertial : bool assetdir : string (reading=custom) # fans out to mesh/texturedir alignfree : bool @@ -552,16 +552,16 @@ element compiler : mjsCompiler { } element lengthrange : mjLROpt { - mode : enum - useexisting : bool + mode : enum = muscle + useexisting : bool = true uselimit : bool - accel : double + accel : double = 20 maxforce : double - timeconst : double - timestep : double - inttotal : double - interval : double - tolrange : double + timeconst : double = 1 + timestep : double = 0.01 + inttotal : double = 10 + interval : double = 2 + tolrange : double = 0.05 } @@ -581,8 +581,8 @@ element option : mjOption { density : double viscosity : double o_margin : double - o_solref : double[1..mjNREF] - o_solimp : double[1..mjNIMP] + o_solref : double[1..mjNREF] = {0.02, 1} + o_solimp : double[1..mjNIMP] = {0.9, 0.95, 0.001, 0.5, 2} o_friction : double[1..5] = {1, 1, 0.005, 0.0001, 0.0001} integrator : enum = Euler cone : enum = pyramidal @@ -634,19 +634,19 @@ element flag { element size : mjSpec { memory : string (reading=custom) # suffixed byte count - njmax : int (reading=custom) # range/exclusivity checks - nconmax : int (reading=custom) # range check - nstack : int (reading=custom) # range/exclusivity checks + njmax : int = -1 (reading=custom) # range/exclusivity checks + nconmax : int = -1 (reading=custom) # range check + nstack : int = -1 (reading=custom) # range/exclusivity checks nuserdata : int (min=-1) nkey : int (min=-1) - nuser_body : int (min=-1) - nuser_jnt : int (min=-1) - nuser_geom : int (min=-1) - nuser_site : int (min=-1) - nuser_cam : int (min=-1) - nuser_tendon : int (min=-1) - nuser_actuator : int (min=-1) - nuser_sensor : int (min=-1) + nuser_body : int = -1 (min=-1) + nuser_jnt : int = -1 (min=-1) + nuser_geom : int = -1 (min=-1) + nuser_site : int = -1 (min=-1) + nuser_cam : int = -1 (min=-1) + nuser_tendon : int = -1 (min=-1) + nuser_actuator : int = -1 (min=-1) + nuser_sensor : int = -1 (min=-1) exclusive memory nstack exclusive memory njmax } @@ -742,31 +742,31 @@ element scale : mjVisual (field=scale) { } element rgba : mjVisual (field=rgba) { - fog : float[4] - haze : float[4] - force : float[4] - inertia : float[4] - joint : float[4] - actuator : float[4] - actuatornegative : float[4] - actuatorpositive : float[4] - com : float[4] - camera : float[4] - light : float[4] - selectpoint : float[4] - connect : float[4] - contactpoint : float[4] - contactforce : float[4] - contactfriction : float[4] - contacttorque : float[4] - contactgap : float[4] - rangefinder : float[4] - constraint : float[4] - slidercrank : float[4] - crankbroken : float[4] - frustum : float[4] - bv : float[4] - bvactive : float[4] + fog : float[4] = {0, 0, 0, 1} + haze : float[4] = {1, 1, 1, 1} + force : float[4] = {1, 0.5, 0.5, 1} + inertia : float[4] = {0.8, 0.2, 0.2, 0.6} + joint : float[4] = {0.2, 0.6, 0.8, 1} + actuator : float[4] = {0.2, 0.25, 0.2, 1} + actuatornegative : float[4] = {0.2, 0.6, 0.9, 1} + actuatorpositive : float[4] = {0.9, 0.4, 0.2, 1} + com : float[4] = {0.9, 0.9, 0.9, 1} + camera : float[4] = {0.6, 0.9, 0.6, 1} + light : float[4] = {0.6, 0.6, 0.9, 1} + selectpoint : float[4] = {0.9, 0.9, 0.1, 1} + connect : float[4] = {0.2, 0.2, 0.8, 1} + contactpoint : float[4] = {0.9, 0.6, 0.2, 1} + contactforce : float[4] = {0.7, 0.9, 0.9, 1} + contactfriction : float[4] = {0.9, 0.8, 0.4, 1} + contacttorque : float[4] = {0.9, 0.7, 0.9, 1} + contactgap : float[4] = {0.5, 0.8, 0.9, 1} + rangefinder : float[4] = {1, 1, 0.1, 1} + constraint : float[4] = {0.9, 0, 0, 1} + slidercrank : float[4] = {0.5, 0.3, 0.8, 1} + crankbroken : float[4] = {0.9, 0, 0, 1} + frustum : float[4] = {1, 1, 0, 0.2} + bv : float[4] = {0, 1, 0, 0.5} + bvactive : float[4] = {1, 0, 0, 0.5} } @@ -896,8 +896,8 @@ element bone { body : ref (required) bindpos : double[3] bindquat : double[4] - vertid : double[] - vertweight : double[] + vertid : int[] + vertweight : float[] } element texture : mjsTexture { @@ -981,7 +981,7 @@ element body : mjsBody { element inertial : mjsBody { # projects into the parent body's i-frame pos : double[3] (required, field=ipos) - quat : double[4] (reading=custom, field=iquat) + quat : double[4] = {1, 0, 0, 0} (reading=custom, field=iquat) mass : double (required) diaginertia : double[3] (field=inertia) axisangle : double[4] (reading=custom) @@ -1000,12 +1000,12 @@ element joint : mjsJoint { pos : double[3] (writing=custom) # saved unless free axis : double[3] = {0, 0, 1} (writing=custom) # saved for slide/hinge springdamper : double[2] (writing=custom) # compile directive: saved as stiffness/damping - limited : enum (writing=custom) # saved unless free - actuatorfrclimited : enum (field=actfrclimited, writing=custom) # saved for slide/hinge - solreflimit : double[1..mjNREF] (field=solref_limit) - solimplimit : double[1..mjNIMP] (field=solimp_limit) - solreffriction : double[1..mjNREF] (field=solref_friction) - solimpfriction : double[1..mjNIMP] (field=solimp_friction) + limited : enum = auto (writing=custom) # saved unless free + actuatorfrclimited : enum = auto (field=actfrclimited, writing=custom) # saved for slide/hinge + solreflimit : double[1..mjNREF] = {0.02, 1} (field=solref_limit) + solimplimit : double[1..mjNIMP] = {0.9, 0.95, 0.001, 0.5, 2} (field=solimp_limit) + solreffriction : double[1..mjNREF] = {0.02, 1} (field=solref_friction) + solimpfriction : double[1..mjNIMP] = {0.9, 0.95, 0.001, 0.5, 2} (field=solimp_friction) stiffness : double[1..3] # spring polynomial, 1+mjNPOLY coefficients range : double[2] actuatorfrcrange : double[2] (field=actfrcrange) @@ -1055,7 +1055,7 @@ element geom : mjsGeom { fitscale : double = 1 (writing=custom) # compile directive: not saved rgba : float[4] = {0.5, 0.5, 0.5, 1} fluidshape : enum (field=fluid_ellipsoid, reading=custom) - fluidcoef : double[1..5] (field=fluid_coefs) + fluidcoef : double[1..5] = {0.5, 0.25, 1.5, 1, 1} (field=fluid_coefs) user : double[] (field=userdata) child plugin * } @@ -1130,7 +1130,7 @@ element light : mjsLight { element composite { prefix : string type : enum (required) - count : double[1..3] + count : int[1..3] offset : double[3] vertex : double[] initial : string @@ -1154,7 +1154,7 @@ element composite_joint (xml=joint) { solimpfix : double[1..mjNIMP] type : enum axis : double[3] - limited : enum + limited : enum = auto range : double[2] margin : double solreflimit : double[1..mjNREF] @@ -1168,7 +1168,7 @@ element composite_skin (xml=skin) { texcoord : bool material : ref group : int - rgba : double[4] + rgba : float[4] inflate : double subgrid : int } @@ -1182,7 +1182,7 @@ element composite_geom (xml=geom) { priority : int size : double[1..3] material : ref - rgba : double[4] + rgba : float[4] friction : double[1..3] mass : double density : double @@ -1199,7 +1199,7 @@ element composite_site (xml=site) { group : int size : double[1..3] material : ref - rgba : double[4] + rgba : float[4] } element flexcomp { @@ -1208,8 +1208,8 @@ element flexcomp { group : int dim : int dof : enum - count : double[3] - cellcount : double[3] + count : int[3] + cellcount : int[3] spacing : double[3] radius : double rigid : bool @@ -1221,7 +1221,7 @@ element flexcomp { element : double[] texcoord : double[] material : ref - rgba : double[4] + rgba : float[4] flatskin : bool pos : double[3] quat : double[4] @@ -1249,24 +1249,24 @@ element elasticity : mjsFlex { young : double poisson : double damping : double - thickness : double + thickness : double = -1 elastic2d : enum } element flexcomp_contact : mjsFlex (xml=contact) { - contype : int - conaffinity : int - condim : int + contype : int = 1 + conaffinity : int = 1 + condim : int = 3 priority : int - friction : double[1..3] - solmix : double - solref : double[1..mjNREF] - solimp : double[1..mjNIMP] + friction : double[1..3] = {1, 0.005, 0.0001} + solmix : double = 1 + solref : double[1..mjNREF] = {0.02, 1} + solimp : double[1..mjNIMP] = {0.9, 0.95, 0.001, 0.5, 2} margin : double gap : double internal : bool - selfcollide : enum - activelayers : int + selfcollide : enum = auto + activelayers : int = 1 passive : bool } @@ -1288,10 +1288,10 @@ element deformable { element flex : mjsFlex { name : id group : int - dim : int - radius : double + dim : int = 2 + radius : double = 0.005 material : ref - rgba : float[4] + rgba : float[4] = {0.5, 0.5, 0.5, 1} flatskin : bool body : string (required, field=vertbody) # space-separated body names vertex : double[] (field=vert) @@ -1299,7 +1299,7 @@ element flex : mjsFlex { texcoord : float[] elemtexcoord : int[] node : string (field=nodebody) # space-separated body names - cellcount : int[3] (reading=custom) # seeded to {1,1,1} before reading + cellcount : int[3] = {1, 1, 1} (reading=custom) # seeded before reading dof : enum (reading=custom) # lowers to interpolation order child flexcomp_contact ? child flex_edge ? @@ -1352,14 +1352,14 @@ element spatial : mjsTendon { name : id class : ref group : int - limited : enum + limited : enum = auto actuatorfrclimited : enum (field=actfrclimited) range : double[2] actuatorfrcrange : double[2] (field=actfrcrange) - solreflimit : double[1..mjNREF] (field=solref_limit) - solimplimit : double[1..mjNIMP] (field=solimp_limit) - solreffriction : double[1..mjNREF] (field=solref_friction) - solimpfriction : double[1..mjNIMP] (field=solimp_friction) + solreflimit : double[1..mjNREF] = {0.02, 1} (field=solref_limit) + solimplimit : double[1..mjNIMP] = {0.9, 0.95, 0.001, 0.5, 2} (field=solimp_limit) + solreffriction : double[1..mjNREF] = {0.02, 1} (field=solref_friction) + solimpfriction : double[1..mjNIMP] = {0.9, 0.95, 0.001, 0.5, 2} (field=solimp_friction) frictionloss : double springlength : double[1..2] = {-1, -1} (reading=custom) # one value: copied to both width : double = 0.003 @@ -1395,14 +1395,14 @@ element fixed : mjsTendon { name : id class : ref group : int - limited : enum + limited : enum = auto actuatorfrclimited : enum (field=actfrclimited) range : double[2] actuatorfrcrange : double[2] (field=actfrcrange) - solreflimit : double[1..mjNREF] (field=solref_limit) - solimplimit : double[1..mjNIMP] (field=solimp_limit) - solreffriction : double[1..mjNREF] (field=solref_friction) - solimpfriction : double[1..mjNIMP] (field=solimp_friction) + solreflimit : double[1..mjNREF] = {0.02, 1} (field=solref_limit) + solimplimit : double[1..mjNIMP] = {0.9, 0.95, 0.001, 0.5, 2} (field=solimp_limit) + solreffriction : double[1..mjNREF] = {0.02, 1} (field=solref_friction) + solimpfriction : double[1..mjNIMP] = {0.9, 0.95, 0.001, 0.5, 2} (field=solimp_friction) frictionloss : double springlength : double[1..2] = {-1, -1} (reading=custom) # one value: copied to both margin : double @@ -1509,9 +1509,9 @@ element actuator : mjsActuator { element general : mjsActuator { use actuator_base - ctrllimited : enum - forcelimited : enum - actlimited : enum + ctrllimited : enum = auto + forcelimited : enum = auto + actlimited : enum = auto forcerange : double[2] actrange : double[2] use actuator_dynamics @@ -1532,8 +1532,8 @@ element general : mjsActuator { element motor : mjsActuator { use actuator_base - ctrllimited : enum - forcelimited : enum + ctrllimited : enum = auto + forcelimited : enum = auto forcerange : double[2] use actuator_dynamics use transmission @@ -1541,8 +1541,8 @@ element motor : mjsActuator { element position : mjsActuator { use actuator_base - ctrllimited : enum - forcelimited : enum + ctrllimited : enum = auto + forcelimited : enum = auto inheritrange : double forcerange : double[2] use actuator_dynamics @@ -1555,8 +1555,8 @@ element position : mjsActuator { element velocity : mjsActuator { use actuator_base - ctrllimited : enum - forcelimited : enum + ctrllimited : enum = auto + forcelimited : enum = auto forcerange : double[2] use actuator_dynamics use transmission @@ -1565,9 +1565,9 @@ element velocity : mjsActuator { element intvelocity : mjsActuator { use actuator_base - ctrllimited : enum - forcelimited : enum - actlimited : enum + ctrllimited : enum = auto + forcelimited : enum = auto + actlimited : enum = auto forcerange : double[2] actrange : double[2] inheritrange : double @@ -1580,7 +1580,7 @@ element intvelocity : mjsActuator { element orientation : mjsActuator { use actuator_base - forcelimited : enum + forcelimited : enum = auto forcerange : double[2] joint : ref (nodefault) site : ref (nodefault) @@ -1593,8 +1593,8 @@ element orientation : mjsActuator { element pid : mjsActuator { use actuator_base - ctrllimited : enum - forcelimited : enum + ctrllimited : enum = auto + forcelimited : enum = auto posrange : double[2] (field=ctrlrange) # alias: the position-setpoint range velrange : double[2] ffrange : double[2] @@ -1613,7 +1613,7 @@ element pid : mjsActuator { element damper : mjsActuator { use actuator_base - forcelimited : enum + forcelimited : enum = auto forcerange : double[2] use actuator_dynamics use transmission @@ -1622,8 +1622,8 @@ element damper : mjsActuator { element cylinder : mjsActuator { use actuator_base - ctrllimited : enum - forcelimited : enum + ctrllimited : enum = auto + forcelimited : enum = auto forcerange : double[2] use actuator_dynamics use transmission @@ -1635,8 +1635,8 @@ element cylinder : mjsActuator { element muscle : mjsActuator { use actuator_base - ctrllimited : enum - forcelimited : enum + ctrllimited : enum = auto + forcelimited : enum = auto forcerange : double[2] use actuator_dynamics joint : ref (nodefault) @@ -1644,7 +1644,7 @@ element muscle : mjsActuator { tendon : ref (nodefault) slidersite : ref (nodefault) cranksite : ref (nodefault) - timeconst : double + timeconst : double[2] tausmooth : double (nodefault) range : double[2] force : double @@ -1658,7 +1658,7 @@ element muscle : mjsActuator { element adhesion : mjsActuator { use actuator_base - forcelimited : enum + forcelimited : enum = auto forcerange : double[2] body : ref (nodefault) gain : double @@ -1666,7 +1666,7 @@ element adhesion : mjsActuator { element dcmotor : mjsActuator { use actuator_base - ctrllimited : enum + ctrllimited : enum = auto use actuator_dynamics use transmission motorconst : double[1..2] @@ -1685,9 +1685,9 @@ element actuator_plugin : mjsActuator (xml=plugin) { use actuator_base plugin : string instance : ref - ctrllimited : enum - forcelimited : enum - actlimited : enum + ctrllimited : enum = auto + forcelimited : enum = auto + actlimited : enum = auto forcerange : double[2] actrange : double[2] use actuator_dynamics @@ -2268,7 +2268,7 @@ element default_equality (xml=equality) { element default_tendon (xml=tendon) { group : int - limited : enum + limited : enum = auto range : double[2] solreflimit : double[1..mjNREF] solimplimit : double[1..mjNIMP] @@ -2279,8 +2279,8 @@ element default_tendon (xml=tendon) { width : double material : ref margin : double - stiffness : double - damping : double - rgba : double[4] + stiffness : double[1..3] + damping : double[1..3] + rgba : float[4] user : double[] } diff --git a/src/xml/xml_native_writer.cc b/src/xml/xml_native_writer.cc index 64b27fa6..96c395fa 100644 --- a/src/xml/xml_native_writer.cc +++ b/src/xml/xml_native_writer.cc @@ -359,17 +359,17 @@ void mjXWriter::OneJoint(XMLElement* elem, const mjCJoint* joint, mjCDef* def, if (classname != joint->classname && joint->classname != "main") { WriteAttrTxt(elem, "class", joint->classname); } - if (joint->type != mjJNT_FREE) { - WriteAttr(elem, "pos", 3, joint->pos); - } - if (joint->type != mjJNT_FREE && joint->type != mjJNT_BALL) { - WriteAttr(elem, "axis", 3, joint->axis); - } } // defaults and regular WriteAttrTable(elem, static_cast(joint), &def->Joint().spec, kJointAttrs, kJointAttrsN); + if (joint->type != mjJNT_FREE) { + WriteAttr(elem, "pos", 3, joint->pos, def->Joint().spec.pos); + } + if (joint->type != mjJNT_FREE && joint->type != mjJNT_BALL) { + WriteAttr(elem, "axis", 3, joint->axis, def->Joint().spec.axis); + } if (joint->type != mjJNT_FREE) { WriteAttrKey(elem, "limited", FalseTrueAuto_map, 3, joint->limited, def->Joint().limited); } @@ -676,25 +676,33 @@ void mjXWriter::OneEquality(XMLElement* elem, const mjCEquality* equality, mjCDe if (equality->objtype == mjOBJ_BODY) { WriteAttrTxt(elem, "body1", mjs_getString(equality->name1)); WriteAttrTxt(elem, "body2", mjs_getString(equality->name2)); - WriteAttr(elem, "anchor", 3, equality->data); - WriteAttr(elem, "relpose", 7, equality->data+3); + // unlike connect, weld's body semantic does not require anchor, + // and the reader zeroes it when absent: zeros is the default, + // not the constructor's union payload + double zero3[3] = {0, 0, 0}; + WriteAttr(elem, "anchor", 3, equality->data, zero3); + WriteAttr(elem, "relpose", 7, equality->data+3, + def->Equality().spec.data+3); } else { WriteAttrTxt(elem, "site1", mjs_getString(equality->name1)); WriteAttrTxt(elem, "site2", mjs_getString(equality->name2)); } - WriteAttr(elem, "torquescale", 1, equality->data+10); + WriteAttr(elem, "torquescale", 1, equality->data+10, + def->Equality().spec.data+10); break; case mjEQ_JOINT: WriteAttrTxt(elem, "joint1", mjs_getString(equality->name1)); WriteAttrTxt(elem, "joint2", mjs_getString(equality->name2)); - WriteAttr(elem, "polycoef", 5, equality->data); + WriteAttr(elem, "polycoef", 5, equality->data, + def->Equality().spec.data); break; case mjEQ_TENDON: WriteAttrTxt(elem, "tendon1", mjs_getString(equality->name1)); WriteAttrTxt(elem, "tendon2", mjs_getString(equality->name2)); - WriteAttr(elem, "polycoef", 5, equality->data); + WriteAttr(elem, "polycoef", 5, equality->data, + def->Equality().spec.data); break; case mjEQ_FLEX: @@ -704,7 +712,7 @@ void mjXWriter::OneEquality(XMLElement* elem, const mjCEquality* equality, mjCDe case mjEQ_FLEXSTRAIN: WriteAttrTxt(elem, "flex", mjs_getString(equality->name1)); - WriteAttr(elem, "cell", 3, equality->data); + WriteAttr(elem, "cell", 3, equality->data, def->Equality().spec.data); break; default: diff --git a/test/xml/schema_defaults_test.cc b/test/xml/schema_defaults_test.cc index a77a25a5..356a8a32 100644 --- a/test/xml/schema_defaults_test.cc +++ b/test/xml/schema_defaults_test.cc @@ -13,9 +13,13 @@ // limitations under the License. // Checks that the attribute defaults declared in mjcf.schema agree with the -// C default-constructors: every generated row is compared against a -// freshly-constructed spec element. +// C default-constructors: every bound numeric attribute is compared against a +// freshly-constructed spec element. Coverage is total, so a nonzero +// constructor default that the schema does not declare is a failure: the +// schema cannot silently under-declare. Fields whose constructor value is +// the mjNAN "unset" sentinel are marked in the table and asserted NaN. +#include #include #include @@ -40,6 +44,14 @@ TEST_F(SchemaDefaultsTest, DeclaredDefaultsMatchConstructors) { std::map objects = { {"mjOption", &spec->option}, {"mjVisual", &spec->visual}, + {"mjStatistic", &spec->stat}, + {"mjSpec", spec}, + {"mjLROpt", &spec->compiler.LRopt}, + {"mjsCompiler", &spec->compiler}, + {"mjsFlex", mjs_addFlex(spec)}, + {"mjsHField", mjs_addHField(spec)}, + {"mjsKey", mjs_addKey(spec)}, + {"mjsNumeric", mjs_addNumeric(spec)}, {"mjsBody", body}, {"mjsFrame", mjs_addFrame(body, nullptr)}, {"mjsJoint", mjs_addJoint(body, nullptr)}, @@ -69,6 +81,16 @@ TEST_F(SchemaDefaultsTest, DeclaredDefaultsMatchConstructors) { for (int j = 0; j < entry.len; j++) { double expected = j < entry.ndecl ? entry.value[j] : 0; double actual = 0; + if (entry.unset && j == 0) { + // the constructor holds the mjNAN "unset" sentinel in the first + // slot (the rest are zeros), deliberately undeclared in the schema + double v = entry.kind == 4 + ? (double)reinterpret_cast(field)[j] + : reinterpret_cast(field)[j]; + EXPECT_TRUE(std::isnan(v)) + << table.structname << "." << entry.attr << "[" << j << "]"; + continue; + } switch (entry.kind) { case 0: // double actual = reinterpret_cast(field)[j]; diff --git a/test/xml/xml_api_test.cc b/test/xml/xml_api_test.cc index b4da2f7e..f02c05fc 100644 --- a/test/xml/xml_api_test.cc +++ b/test/xml/xml_api_test.cc @@ -135,8 +135,8 @@ TEST_F(MujocoTest, SaveXmlShortString) { std::array out; EXPECT_THAT(mj_saveXMLString(spec, out.data(), out.size(), error.data(), error.size()), - 273); - EXPECT_STREQ(error.data(), "Output string too short, should be at least 274"); + 223); + EXPECT_STREQ(error.data(), "Output string too short, should be at least 224"); mj_deleteSpec(spec); mj_deleteModel(model); diff --git a/test/xml/xml_native_writer_test.cc b/test/xml/xml_native_writer_test.cc index 11fee00f..f7e2c57e 100644 --- a/test/xml/xml_native_writer_test.cc +++ b/test/xml/xml_native_writer_test.cc @@ -1638,5 +1638,86 @@ TEST_F(XMLWriterTest, EmptyFlagsAttribute) { EXPECT_THAT(saved_xml, Not(HasSubstr("output="))); } +TEST_F(XMLWriterTest, OmitsDefaultJointPosAxis) { + static constexpr char xml[] = R"( + + + + + + + + + )"; + MjModelPtr model = LoadModelFromString(xml); + ASSERT_THAT(model.get(), NotNull()); + std::string saved_xml = SaveAndReadXml(model.get()); + EXPECT_THAT(saved_xml, Not(HasSubstr("pos=\"0 0 0\""))); + EXPECT_THAT(saved_xml, Not(HasSubstr("axis="))); +} + +TEST_F(XMLWriterTest, KeepsAuthoredJointPosAxis) { + static constexpr char xml[] = R"( + + + + + + + + + )"; + MjModelPtr model = LoadModelFromString(xml); + ASSERT_THAT(model.get(), NotNull()); + std::string saved_xml = SaveAndReadXml(model.get()); + EXPECT_THAT(saved_xml, HasSubstr("pos=\"0 0 0.5\"")); + EXPECT_THAT(saved_xml, HasSubstr("axis=\"1 0 0\"")); +} + +TEST_F(XMLWriterTest, OmitsDefaultEqualityData) { + static constexpr char xml[] = R"( + + + + + + + + + + + )"; + MjModelPtr model = LoadModelFromString(xml); + ASSERT_THAT(model.get(), NotNull()); + std::string saved_xml = SaveAndReadXml(model.get()); + EXPECT_THAT(saved_xml, Not(HasSubstr("anchor="))); + EXPECT_THAT(saved_xml, Not(HasSubstr("torquescale="))); + EXPECT_THAT(saved_xml, Not(HasSubstr("polycoef="))); + // relpose is legitimately saved: the compiler resolves the zero-quat + // "compute current pose" sentinel into the actual relative pose + EXPECT_THAT(saved_xml, HasSubstr("relpose=\"0 0 0 1 0 0 0\"")); +} + +TEST_F(XMLWriterTest, WritesDefaultClassJointPosAxis) { + // pos and axis set in a default class used to be lost when saving + static constexpr char xml[] = R"( + + + + + + + + + + + + )"; + MjModelPtr model = LoadModelFromString(xml); + ASSERT_THAT(model.get(), NotNull()); + std::string saved_xml = SaveAndReadXml(model.get()); + EXPECT_THAT(saved_xml, HasSubstr("")); +} + } // namespace } // namespace mujoco