Generate the MJCF grammar table and enforce its constraints.
The hand-written MJCF[] table in xml_native_reader.cc is replaced by
mjcf_table.inc, emitted from mjcf.schema by generate_mjcf_table.py and
checked for freshness by doc_test. nMJCF is now self-sizing. The two
tables are identical as trees of (tag, cardinality, attribute-set);
within-row attribute order changes where the schema factors shared
groups and projects default-context rows, and top-level rows follow
the schema's dependency order -- neither affects validation, which is
set-based, nor XMLschema.rst, whose generator orders sections itself
(regenerated here, reading the .inc instead of the reader source).
The schema's constraint declarations become enforcement: the emitter
writes a companion MJCF_constraints[] array (row-indexed into MJCF[]),
and mjXSchema::Check evaluates each element's constraints after its
attribute check, with uniform messages derived from the declaration:
"at most one of 'fovy', 'sensorsize' can be specified", "attributes
'reftype', 'refname' must be specified together", and so on.
Multi-attribute bundles render as ('site1', 'site2').
Fifteen hand-written co-occurrence checks across fourteen elements are
deleted -- connect/weld semantics mixing and completeness, the actuator
transmission mutex, camera fovy/sensorsize, light directional/type,
inertial fullinertia-versus-orientation, rangefinder and the distance
family, contact's matching criteria, user-sensor pairing, the frame
family's reftype/refname, size memory exclusivities, mesh builtin
exclusions, and attach body/frame (newly declared). Tests assert the
uniform messages.
Two findings along the way: sensorsize-requires-resolution is a
value-level compiler rule (positive resolution), not a presence rule --
a presence constraint would be wrong and is not declared; and Size()'s
nstack/njmax range checks tested the spec value before assignment, so
they never validated the parsed value -- now they do.
Verified by compiling all 81 models in the model/ corpus.
PiperOrigin-RevId: 958064622
Change-Id: I802cf5c0aee08a62926e36a281320ff9e34c0668
This commit is contained in:
committed by
Copybara-Service
parent
3f8db4c17a
commit
790f8fac30
@@ -0,0 +1,542 @@
|
||||
// Copyright 2026 DeepMind Technologies Limited
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// GENERATED FILE, DO NOT EDIT. Generated from src/xml/mjcf.schema by
|
||||
// doc/generate/generate_mjcf_table.py; test/doc/doc_test.py checks freshness.
|
||||
//
|
||||
// The MJCF grammar table consumed by mjXSchema: rows of {name, cardinality,
|
||||
// attributes...} with {"<"}/{">"} nesting markers. worldbody, frame and
|
||||
// replicate have no rows: mjXSchema::NameMatch validates them against the
|
||||
// body row (see the alias= facets in mjcf.schema).
|
||||
|
||||
// clang-format off
|
||||
std::vector<const char*> MJCF[] = {
|
||||
{"mujoco", "!", "model"},
|
||||
{"<"},
|
||||
{"compiler", "*", "autolimits", "boundmass", "boundinertia", "settotalmass", "balanceinertia",
|
||||
"strippath", "coordinate", "angle", "fitaabb", "eulerseq", "meshdir", "texturedir",
|
||||
"discardvisual", "usethread", "fusestatic", "inertiafromgeom", "inertiagrouprange",
|
||||
"saveinertial", "assetdir", "alignfree", "conflict"},
|
||||
{"<"},
|
||||
{"lengthrange", "?", "mode", "useexisting", "uselimit", "accel", "maxforce", "timeconst",
|
||||
"timestep", "inttotal", "interval", "tolrange"},
|
||||
{">"},
|
||||
|
||||
{"option", "*", "timestep", "impratio", "tolerance", "ls_tolerance", "noslip_tolerance",
|
||||
"ccd_tolerance", "sleep_tolerance", "gravity", "wind", "magnetic", "density", "viscosity",
|
||||
"o_margin", "o_solref", "o_solimp", "o_friction", "integrator", "cone", "jacobian",
|
||||
"solver", "iterations", "ls_iterations", "noslip_iterations", "ccd_iterations",
|
||||
"sdf_iterations", "sdf_initpoints", "actuatorgroupdisable"},
|
||||
{"<"},
|
||||
{"flag", "?", "constraint", "equality", "frictionloss", "limit", "contact", "spring",
|
||||
"damper", "gravity", "clampctrl", "warmstart", "filterparent", "actuation", "refsafe",
|
||||
"sensor", "midphase", "eulerdamp", "autoreset", "nativeccd", "island", "multiccd",
|
||||
"override", "energy", "fwdinv", "invdiscrete", "sleep", "diagexact"},
|
||||
{">"},
|
||||
|
||||
{"size", "*", "memory", "njmax", "nconmax", "nstack", "nuserdata", "nkey", "nuser_body",
|
||||
"nuser_jnt", "nuser_geom", "nuser_site", "nuser_cam", "nuser_tendon", "nuser_actuator",
|
||||
"nuser_sensor"},
|
||||
|
||||
{"statistic", "*", "meaninertia", "meanmass", "meansize", "extent", "center"},
|
||||
|
||||
{"visual", "*"},
|
||||
{"<"},
|
||||
{"global", "?", "cameraid", "orthographic", "fovy", "ipd", "azimuth", "elevation",
|
||||
"linewidth", "glow", "offwidth", "offheight", "realtime", "ellipsoidinertia",
|
||||
"bvactive"},
|
||||
{"quality", "?", "shadowsize", "offsamples", "numslices", "numstacks", "numquads"},
|
||||
{"headlight", "?", "ambient", "diffuse", "specular", "active"},
|
||||
{"map", "?", "stiffness", "stiffnessrot", "force", "torque", "alpha", "fogstart", "fogend",
|
||||
"znear", "zfar", "haze", "shadowclip", "shadowscale", "actuatortendon"},
|
||||
{"scale", "?", "forcewidth", "contactwidth", "contactheight", "connect", "com", "camera",
|
||||
"light", "selectpoint", "jointlength", "jointwidth", "actuatorlength", "actuatorwidth",
|
||||
"framelength", "framewidth", "constraint", "slidercrank", "frustum"},
|
||||
{"rgba", "?", "fog", "haze", "force", "inertia", "joint", "actuator", "actuatornegative",
|
||||
"actuatorpositive", "com", "camera", "light", "selectpoint", "connect", "contactpoint",
|
||||
"contactforce", "contactfriction", "contacttorque", "contactgap", "rangefinder",
|
||||
"constraint", "slidercrank", "crankbroken", "frustum", "bv", "bvactive"},
|
||||
{">"},
|
||||
|
||||
{"default", "R", "class"},
|
||||
{"<"},
|
||||
{"mesh", "?", "scale", "maxhullvert", "inertia"},
|
||||
{"material", "?", "texture", "texrepeat", "texuniform", "emission", "specular",
|
||||
"shininess", "reflectance", "metallic", "roughness", "rgba"},
|
||||
{"<"},
|
||||
{"layer", "*", "texture", "role"},
|
||||
{">"},
|
||||
{"joint", "?", "type", "group", "pos", "axis", "springdamper", "limited",
|
||||
"actuatorfrclimited", "solreflimit", "solimplimit", "solreffriction", "solimpfriction",
|
||||
"stiffness", "range", "actuatorfrcrange", "actuatorgravcomp", "margin", "ref",
|
||||
"springref", "armature", "damping", "frictionloss", "user"},
|
||||
{"geom", "?", "type", "contype", "conaffinity", "condim", "group", "priority", "size",
|
||||
"material", "friction", "mass", "density", "shellinertia", "solmix", "solref",
|
||||
"solimp", "margin", "gap", "surfacevel", "adhesion", "fromto", "pos", "quat",
|
||||
"axisangle", "xyaxes", "zaxis", "euler", "hfield", "mesh", "fitscale", "rgba",
|
||||
"fluidshape", "fluidcoef", "user"},
|
||||
{"site", "?", "type", "group", "pos", "quat", "axisangle", "xyaxes", "zaxis", "euler",
|
||||
"material", "size", "fromto", "rgba", "user"},
|
||||
{"camera", "?", "projection", "fovy", "ipd", "resolution", "output", "pos", "quat",
|
||||
"axisangle", "xyaxes", "zaxis", "euler", "mode", "focal", "focalpixel", "principal",
|
||||
"principalpixel", "sensorsize", "user"},
|
||||
{"light", "?", "directional", "type", "castshadow", "active", "pos", "dir", "bulbradius",
|
||||
"intensity", "range", "attenuation", "cutoff", "exponent", "ambient", "diffuse",
|
||||
"specular", "mode"},
|
||||
{"pair", "?", "condim", "friction", "solref", "solreffriction", "solimp", "gap", "margin",
|
||||
"adhesion"},
|
||||
{"equality", "?", "active", "solref", "solimp"},
|
||||
{"tendon", "?", "group", "limited", "range", "solreflimit", "solimplimit",
|
||||
"solreffriction", "solimpfriction", "frictionloss", "springlength", "width",
|
||||
"material", "margin", "stiffness", "damping", "rgba", "user"},
|
||||
{"general", "?", "group", "nsample", "interp", "delay", "ctrlrange", "user", "ctrllimited",
|
||||
"forcelimited", "actlimited", "forcerange", "actrange", "gear", "damping", "armature",
|
||||
"cranklength", "actdim", "input", "velrange", "ffrange", "dyntype", "gaintype",
|
||||
"biastype", "dynprm", "gainprm", "biasprm", "actearly"},
|
||||
{"motor", "?", "group", "nsample", "interp", "delay", "ctrlrange", "user", "ctrllimited",
|
||||
"forcelimited", "forcerange", "gear", "damping", "armature", "cranklength"},
|
||||
{"position", "?", "group", "nsample", "interp", "delay", "ctrlrange", "user",
|
||||
"ctrllimited", "forcelimited", "inheritrange", "forcerange", "gear", "damping",
|
||||
"armature", "cranklength", "kp", "kv", "dampratio", "timeconst"},
|
||||
{"velocity", "?", "group", "nsample", "interp", "delay", "ctrlrange", "user",
|
||||
"ctrllimited", "forcelimited", "forcerange", "gear", "damping", "armature",
|
||||
"cranklength", "kv"},
|
||||
{"intvelocity", "?", "group", "nsample", "interp", "delay", "ctrlrange", "user",
|
||||
"ctrllimited", "forcelimited", "actlimited", "forcerange", "actrange", "inheritrange",
|
||||
"gear", "damping", "armature", "cranklength", "kp", "kv", "dampratio"},
|
||||
{"orientation", "?", "group", "nsample", "interp", "delay", "ctrlrange", "user",
|
||||
"forcelimited", "forcerange", "kp", "kv", "dampratio", "input"},
|
||||
{"pid", "?", "group", "nsample", "interp", "delay", "ctrlrange", "user", "ctrllimited",
|
||||
"forcelimited", "posrange", "velrange", "ffrange", "forcerange", "inheritrange",
|
||||
"gear", "damping", "armature", "cranklength", "kp", "kv", "dampratio", "ki", "imax",
|
||||
"slewmax", "input"},
|
||||
{"damper", "?", "group", "nsample", "interp", "delay", "ctrlrange", "user", "forcelimited",
|
||||
"forcerange", "gear", "damping", "armature", "cranklength", "kv"},
|
||||
{"cylinder", "?", "group", "nsample", "interp", "delay", "ctrlrange", "user",
|
||||
"ctrllimited", "forcelimited", "forcerange", "gear", "damping", "armature",
|
||||
"cranklength", "timeconst", "area", "diameter", "bias"},
|
||||
{"muscle", "?", "group", "nsample", "interp", "delay", "ctrlrange", "user", "ctrllimited",
|
||||
"forcelimited", "forcerange", "gear", "damping", "armature", "cranklength",
|
||||
"timeconst", "range", "force", "scale", "lmin", "lmax", "vmax", "fpmax", "fvmax"},
|
||||
{"adhesion", "?", "group", "nsample", "interp", "delay", "ctrlrange", "user",
|
||||
"forcelimited", "forcerange", "gain"},
|
||||
{"dcmotor", "?", "group", "nsample", "interp", "delay", "ctrlrange", "user", "ctrllimited",
|
||||
"gear", "damping", "armature", "cranklength", "motorconst", "resistance", "nominal",
|
||||
"saturation", "inductance", "cogging", "controller", "thermal", "lugre", "input"},
|
||||
{">"},
|
||||
|
||||
{"extension", "*"},
|
||||
{"<"},
|
||||
{"plugin", "*", "plugin"},
|
||||
{"<"},
|
||||
{"instance", "*", "name"},
|
||||
{"<"},
|
||||
{"config", "*", "key", "value"},
|
||||
{">"},
|
||||
{">"},
|
||||
{">"},
|
||||
|
||||
{"asset", "*"},
|
||||
{"<"},
|
||||
{"mesh", "*", "name", "class", "content_type", "file", "vertex", "normal", "texcoord",
|
||||
"face", "refpos", "refquat", "scale", "smoothnormal", "maxhullvert", "inertia",
|
||||
"builtin", "params", "material"},
|
||||
{"<"},
|
||||
{"plugin", "*", "plugin", "instance"},
|
||||
{"<"},
|
||||
{"config", "*", "key", "value"},
|
||||
{">"},
|
||||
{">"},
|
||||
{"hfield", "*", "name", "content_type", "file", "nrow", "ncol", "size", "elevation"},
|
||||
{"skin", "*", "name", "file", "material", "rgba", "inflate", "vertex", "texcoord", "face",
|
||||
"group"},
|
||||
{"<"},
|
||||
{"bone", "*", "body", "bindpos", "bindquat", "vertid", "vertweight"},
|
||||
{">"},
|
||||
{"texture", "*", "name", "type", "colorspace", "content_type", "file", "gridsize",
|
||||
"gridlayout", "fileright", "fileleft", "fileup", "filedown", "filefront", "fileback",
|
||||
"builtin", "rgb1", "rgb2", "mark", "markrgb", "random", "width", "height", "hflip",
|
||||
"vflip", "nchannel"},
|
||||
{"material", "*", "name", "class", "texture", "texrepeat", "texuniform", "emission",
|
||||
"specular", "shininess", "reflectance", "metallic", "roughness", "rgba"},
|
||||
{"<"},
|
||||
{"layer", "*", "texture", "role"},
|
||||
{">"},
|
||||
{"model", "*", "name", "file", "content_type"},
|
||||
{">"},
|
||||
|
||||
{"body", "R", "name", "childclass", "pos", "quat", "axisangle", "xyaxes", "zaxis", "euler",
|
||||
"mocap", "gravcomp", "sleep", "simple", "user"},
|
||||
{"<"},
|
||||
{"inertial", "?", "pos", "quat", "mass", "diaginertia", "axisangle", "xyaxes", "zaxis",
|
||||
"euler", "fullinertia"},
|
||||
{"joint", "*", "name", "class", "type", "group", "pos", "axis", "springdamper", "limited",
|
||||
"actuatorfrclimited", "solreflimit", "solimplimit", "solreffriction", "solimpfriction",
|
||||
"stiffness", "range", "actuatorfrcrange", "actuatorgravcomp", "margin", "ref",
|
||||
"springref", "armature", "damping", "frictionloss", "user"},
|
||||
{"freejoint", "*", "name", "group", "align"},
|
||||
{"geom", "*", "name", "class", "type", "contype", "conaffinity", "condim", "group",
|
||||
"priority", "size", "material", "friction", "mass", "density", "shellinertia",
|
||||
"solmix", "solref", "solimp", "margin", "gap", "surfacevel", "adhesion", "fromto",
|
||||
"pos", "quat", "axisangle", "xyaxes", "zaxis", "euler", "hfield", "mesh", "fitscale",
|
||||
"rgba", "fluidshape", "fluidcoef", "user"},
|
||||
{"<"},
|
||||
{"plugin", "*", "plugin", "instance"},
|
||||
{"<"},
|
||||
{"config", "*", "key", "value"},
|
||||
{">"},
|
||||
{">"},
|
||||
{"attach", "*", "model", "body", "frame", "prefix"},
|
||||
{"site", "*", "name", "class", "type", "group", "pos", "quat", "axisangle", "xyaxes",
|
||||
"zaxis", "euler", "material", "size", "fromto", "rgba", "user"},
|
||||
{"camera", "*", "name", "class", "projection", "fovy", "ipd", "resolution", "output",
|
||||
"pos", "quat", "axisangle", "xyaxes", "zaxis", "euler", "mode", "target", "focal",
|
||||
"focalpixel", "principal", "principalpixel", "sensorsize", "user"},
|
||||
{"light", "*", "name", "class", "directional", "type", "castshadow", "active", "pos",
|
||||
"dir", "bulbradius", "intensity", "range", "attenuation", "cutoff", "exponent",
|
||||
"ambient", "diffuse", "specular", "mode", "target", "texture"},
|
||||
{"plugin", "*", "plugin", "instance"},
|
||||
{"<"},
|
||||
{"config", "*", "key", "value"},
|
||||
{">"},
|
||||
{"composite", "*", "prefix", "type", "count", "offset", "vertex", "initial", "curve",
|
||||
"size", "quat"},
|
||||
{"<"},
|
||||
{"joint", "*", "kind", "group", "stiffness", "damping", "armature", "solreffix",
|
||||
"solimpfix", "type", "axis", "limited", "range", "margin", "solreflimit",
|
||||
"solimplimit", "frictionloss", "solreffriction", "solimpfriction"},
|
||||
{"skin", "?", "texcoord", "material", "group", "rgba", "inflate", "subgrid"},
|
||||
{"geom", "?", "type", "contype", "conaffinity", "condim", "group", "priority", "size",
|
||||
"material", "rgba", "friction", "mass", "density", "solmix", "solref", "solimp",
|
||||
"margin", "gap", "surfacevel", "adhesion"},
|
||||
{"site", "?", "group", "size", "material", "rgba"},
|
||||
{"plugin", "*", "plugin", "instance"},
|
||||
{"<"},
|
||||
{"config", "*", "key", "value"},
|
||||
{">"},
|
||||
{">"},
|
||||
{"flexcomp", "*", "name", "type", "group", "dim", "dof", "count", "cellcount", "spacing",
|
||||
"radius", "rigid", "mass", "inertiabox", "scale", "file", "point", "element",
|
||||
"texcoord", "material", "rgba", "flatskin", "pos", "quat", "axisangle", "xyaxes",
|
||||
"zaxis", "euler", "origin"},
|
||||
{"<"},
|
||||
{"edge", "?", "equality", "solref", "solimp", "stiffness", "damping"},
|
||||
{"elasticity", "?", "young", "poisson", "damping", "thickness", "elastic2d"},
|
||||
{"contact", "?", "contype", "conaffinity", "condim", "priority", "friction", "solmix",
|
||||
"solref", "solimp", "margin", "gap", "internal", "selfcollide", "activelayers",
|
||||
"passive"},
|
||||
{"pin", "*", "id", "range", "grid", "gridrange"},
|
||||
{"plugin", "*", "plugin", "instance"},
|
||||
{"<"},
|
||||
{"config", "*", "key", "value"},
|
||||
{">"},
|
||||
{">"},
|
||||
{">"},
|
||||
|
||||
{"deformable", "*"},
|
||||
{"<"},
|
||||
{"flex", "*", "name", "group", "dim", "radius", "material", "rgba", "flatskin", "body",
|
||||
"vertex", "element", "texcoord", "elemtexcoord", "node", "cellcount", "dof"},
|
||||
{"<"},
|
||||
{"contact", "?", "contype", "conaffinity", "condim", "priority", "friction", "solmix",
|
||||
"solref", "solimp", "margin", "gap", "internal", "selfcollide", "activelayers",
|
||||
"passive"},
|
||||
{"edge", "?", "stiffness", "damping"},
|
||||
{"elasticity", "?", "young", "poisson", "damping", "thickness", "elastic2d"},
|
||||
{">"},
|
||||
{"skin", "*", "name", "file", "material", "rgba", "inflate", "vertex", "texcoord", "face",
|
||||
"group"},
|
||||
{"<"},
|
||||
{"bone", "*", "body", "bindpos", "bindquat", "vertid", "vertweight"},
|
||||
{">"},
|
||||
{">"},
|
||||
|
||||
{"contact", "*"},
|
||||
{"<"},
|
||||
{"pair", "*", "name", "class", "geom1", "geom2", "condim", "friction", "solref",
|
||||
"solreffriction", "solimp", "gap", "margin", "adhesion"},
|
||||
{"exclude", "*", "name", "body1", "body2"},
|
||||
{">"},
|
||||
|
||||
{"tendon", "*"},
|
||||
{"<"},
|
||||
{"spatial", "*", "name", "class", "group", "limited", "actuatorfrclimited", "range",
|
||||
"actuatorfrcrange", "solreflimit", "solimplimit", "solreffriction", "solimpfriction",
|
||||
"frictionloss", "springlength", "width", "material", "margin", "stiffness", "damping",
|
||||
"armature", "rgba", "user"},
|
||||
{"<"},
|
||||
{"site", "*", "site"},
|
||||
{"geom", "*", "geom", "sidesite"},
|
||||
{"pulley", "*", "divisor"},
|
||||
{">"},
|
||||
{"fixed", "*", "name", "class", "group", "limited", "actuatorfrclimited", "range",
|
||||
"actuatorfrcrange", "solreflimit", "solimplimit", "solreffriction", "solimpfriction",
|
||||
"frictionloss", "springlength", "margin", "stiffness", "damping", "armature", "user"},
|
||||
{"<"},
|
||||
{"joint", "*", "joint", "coef"},
|
||||
{">"},
|
||||
{">"},
|
||||
|
||||
{"equality", "*"},
|
||||
{"<"},
|
||||
{"connect", "*", "name", "class", "active", "solref", "solimp", "body1", "body2", "anchor",
|
||||
"site1", "site2"},
|
||||
{"weld", "*", "name", "class", "active", "solref", "solimp", "body1", "body2", "relpose",
|
||||
"anchor", "site1", "site2", "torquescale"},
|
||||
{"joint", "*", "name", "class", "active", "solref", "solimp", "joint1", "joint2",
|
||||
"polycoef"},
|
||||
{"tendon", "*", "name", "class", "active", "solref", "solimp", "tendon1", "tendon2",
|
||||
"polycoef"},
|
||||
{"flex", "*", "name", "class", "active", "solref", "solimp", "flex"},
|
||||
{"flexvert", "*", "name", "class", "active", "solref", "solimp", "flex"},
|
||||
{"flexstrain", "*", "name", "class", "active", "solref", "solimp", "flex", "cell"},
|
||||
{">"},
|
||||
|
||||
{"actuator", "*"},
|
||||
{"<"},
|
||||
{"general", "*", "name", "class", "group", "nsample", "interp", "delay", "ctrlrange",
|
||||
"user", "ctrllimited", "forcelimited", "actlimited", "forcerange", "actrange",
|
||||
"lengthrange", "gear", "damping", "armature", "cranklength", "joint", "jointinparent",
|
||||
"tendon", "slidersite", "cranksite", "site", "refsite", "body", "actdim", "input",
|
||||
"velrange", "ffrange", "dyntype", "gaintype", "biastype", "dynprm", "gainprm",
|
||||
"biasprm", "actearly"},
|
||||
{"motor", "*", "name", "class", "group", "nsample", "interp", "delay", "ctrlrange", "user",
|
||||
"ctrllimited", "forcelimited", "forcerange", "lengthrange", "gear", "damping",
|
||||
"armature", "cranklength", "joint", "jointinparent", "tendon", "slidersite",
|
||||
"cranksite", "site", "refsite"},
|
||||
{"position", "*", "name", "class", "group", "nsample", "interp", "delay", "ctrlrange",
|
||||
"user", "ctrllimited", "forcelimited", "inheritrange", "forcerange", "lengthrange",
|
||||
"gear", "damping", "armature", "cranklength", "joint", "jointinparent", "tendon",
|
||||
"slidersite", "cranksite", "site", "refsite", "kp", "kv", "dampratio", "timeconst"},
|
||||
{"velocity", "*", "name", "class", "group", "nsample", "interp", "delay", "ctrlrange",
|
||||
"user", "ctrllimited", "forcelimited", "forcerange", "lengthrange", "gear", "damping",
|
||||
"armature", "cranklength", "joint", "jointinparent", "tendon", "slidersite",
|
||||
"cranksite", "site", "refsite", "kv"},
|
||||
{"intvelocity", "*", "name", "class", "group", "nsample", "interp", "delay", "ctrlrange",
|
||||
"user", "ctrllimited", "forcelimited", "actlimited", "forcerange", "actrange",
|
||||
"inheritrange", "lengthrange", "gear", "damping", "armature", "cranklength", "joint",
|
||||
"jointinparent", "tendon", "slidersite", "cranksite", "site", "refsite", "kp", "kv",
|
||||
"dampratio"},
|
||||
{"orientation", "*", "name", "class", "group", "nsample", "interp", "delay", "ctrlrange",
|
||||
"user", "forcelimited", "forcerange", "joint", "site", "refsite", "kp", "kv",
|
||||
"dampratio", "input"},
|
||||
{"pid", "*", "name", "class", "group", "nsample", "interp", "delay", "ctrlrange", "user",
|
||||
"ctrllimited", "forcelimited", "posrange", "velrange", "ffrange", "forcerange",
|
||||
"inheritrange", "lengthrange", "gear", "damping", "armature", "cranklength", "joint",
|
||||
"jointinparent", "tendon", "slidersite", "cranksite", "site", "refsite", "kp", "kv",
|
||||
"dampratio", "ki", "imax", "slewmax", "input"},
|
||||
{"damper", "*", "name", "class", "group", "nsample", "interp", "delay", "ctrlrange",
|
||||
"user", "forcelimited", "forcerange", "lengthrange", "gear", "damping", "armature",
|
||||
"cranklength", "joint", "jointinparent", "tendon", "slidersite", "cranksite", "site",
|
||||
"refsite", "kv"},
|
||||
{"cylinder", "*", "name", "class", "group", "nsample", "interp", "delay", "ctrlrange",
|
||||
"user", "ctrllimited", "forcelimited", "forcerange", "lengthrange", "gear", "damping",
|
||||
"armature", "cranklength", "joint", "jointinparent", "tendon", "slidersite",
|
||||
"cranksite", "site", "refsite", "timeconst", "area", "diameter", "bias"},
|
||||
{"muscle", "*", "name", "class", "group", "nsample", "interp", "delay", "ctrlrange",
|
||||
"user", "ctrllimited", "forcelimited", "forcerange", "lengthrange", "gear", "damping",
|
||||
"armature", "cranklength", "joint", "jointinparent", "tendon", "slidersite",
|
||||
"cranksite", "timeconst", "tausmooth", "range", "force", "scale", "lmin", "lmax",
|
||||
"vmax", "fpmax", "fvmax"},
|
||||
{"adhesion", "*", "name", "class", "group", "nsample", "interp", "delay", "ctrlrange",
|
||||
"user", "forcelimited", "forcerange", "body", "gain"},
|
||||
{"dcmotor", "*", "name", "class", "group", "nsample", "interp", "delay", "ctrlrange",
|
||||
"user", "ctrllimited", "lengthrange", "gear", "damping", "armature", "cranklength",
|
||||
"joint", "jointinparent", "tendon", "slidersite", "cranksite", "site", "refsite",
|
||||
"motorconst", "resistance", "nominal", "saturation", "inductance", "cogging",
|
||||
"controller", "thermal", "lugre", "input"},
|
||||
{"plugin", "*", "name", "class", "group", "nsample", "interp", "delay", "ctrlrange",
|
||||
"user", "plugin", "instance", "ctrllimited", "forcelimited", "actlimited",
|
||||
"forcerange", "actrange", "lengthrange", "gear", "damping", "armature", "cranklength",
|
||||
"joint", "jointinparent", "site", "actdim", "dyntype", "dynprm", "tendon", "cranksite",
|
||||
"slidersite", "actearly"},
|
||||
{"<"},
|
||||
{"config", "*", "key", "value"},
|
||||
{">"},
|
||||
{">"},
|
||||
|
||||
{"sensor", "*"},
|
||||
{"<"},
|
||||
{"touch", "*", "name", "nsample", "interp", "delay", "interval", "cutoff", "noise", "user",
|
||||
"site"},
|
||||
{"accelerometer", "*", "name", "nsample", "interp", "delay", "interval", "cutoff", "noise",
|
||||
"user", "site"},
|
||||
{"velocimeter", "*", "name", "nsample", "interp", "delay", "interval", "cutoff", "noise",
|
||||
"user", "site"},
|
||||
{"gyro", "*", "name", "nsample", "interp", "delay", "interval", "cutoff", "noise", "user",
|
||||
"site"},
|
||||
{"force", "*", "name", "nsample", "interp", "delay", "interval", "cutoff", "noise", "user",
|
||||
"site"},
|
||||
{"torque", "*", "name", "nsample", "interp", "delay", "interval", "cutoff", "noise",
|
||||
"user", "site"},
|
||||
{"magnetometer", "*", "name", "nsample", "interp", "delay", "interval", "cutoff", "noise",
|
||||
"user", "site"},
|
||||
{"camprojection", "*", "name", "nsample", "interp", "delay", "interval", "cutoff", "noise",
|
||||
"user", "site", "camera"},
|
||||
{"rangefinder", "*", "name", "nsample", "interp", "delay", "interval", "cutoff", "noise",
|
||||
"user", "site", "camera", "data"},
|
||||
{"jointpos", "*", "name", "nsample", "interp", "delay", "interval", "cutoff", "noise",
|
||||
"user", "joint"},
|
||||
{"jointvel", "*", "name", "nsample", "interp", "delay", "interval", "cutoff", "noise",
|
||||
"user", "joint"},
|
||||
{"tendonpos", "*", "name", "nsample", "interp", "delay", "interval", "cutoff", "noise",
|
||||
"user", "tendon"},
|
||||
{"tendonvel", "*", "name", "nsample", "interp", "delay", "interval", "cutoff", "noise",
|
||||
"user", "tendon"},
|
||||
{"actuatorpos", "*", "name", "nsample", "interp", "delay", "interval", "cutoff", "noise",
|
||||
"user", "actuator"},
|
||||
{"actuatorvel", "*", "name", "nsample", "interp", "delay", "interval", "cutoff", "noise",
|
||||
"user", "actuator"},
|
||||
{"actuatorfrc", "*", "name", "nsample", "interp", "delay", "interval", "cutoff", "noise",
|
||||
"user", "actuator"},
|
||||
{"jointactuatorfrc", "*", "name", "nsample", "interp", "delay", "interval", "cutoff",
|
||||
"noise", "user", "joint"},
|
||||
{"tendonactuatorfrc", "*", "name", "nsample", "interp", "delay", "interval", "cutoff",
|
||||
"noise", "user", "tendon"},
|
||||
{"ballquat", "*", "name", "nsample", "interp", "delay", "interval", "cutoff", "noise",
|
||||
"user", "joint"},
|
||||
{"ballangvel", "*", "name", "nsample", "interp", "delay", "interval", "cutoff", "noise",
|
||||
"user", "joint"},
|
||||
{"jointlimitpos", "*", "name", "nsample", "interp", "delay", "interval", "cutoff", "noise",
|
||||
"user", "joint"},
|
||||
{"jointlimitvel", "*", "name", "nsample", "interp", "delay", "interval", "cutoff", "noise",
|
||||
"user", "joint"},
|
||||
{"jointlimitfrc", "*", "name", "nsample", "interp", "delay", "interval", "cutoff", "noise",
|
||||
"user", "joint"},
|
||||
{"tendonlimitpos", "*", "name", "nsample", "interp", "delay", "interval", "cutoff",
|
||||
"noise", "user", "tendon"},
|
||||
{"tendonlimitvel", "*", "name", "nsample", "interp", "delay", "interval", "cutoff",
|
||||
"noise", "user", "tendon"},
|
||||
{"tendonlimitfrc", "*", "name", "nsample", "interp", "delay", "interval", "cutoff",
|
||||
"noise", "user", "tendon"},
|
||||
{"framepos", "*", "name", "nsample", "interp", "delay", "interval", "cutoff", "noise",
|
||||
"user", "objtype", "objname", "reftype", "refname"},
|
||||
{"framequat", "*", "name", "nsample", "interp", "delay", "interval", "cutoff", "noise",
|
||||
"user", "objtype", "objname", "reftype", "refname"},
|
||||
{"framexaxis", "*", "name", "nsample", "interp", "delay", "interval", "cutoff", "noise",
|
||||
"user", "objtype", "objname", "reftype", "refname"},
|
||||
{"frameyaxis", "*", "name", "nsample", "interp", "delay", "interval", "cutoff", "noise",
|
||||
"user", "objtype", "objname", "reftype", "refname"},
|
||||
{"framezaxis", "*", "name", "nsample", "interp", "delay", "interval", "cutoff", "noise",
|
||||
"user", "objtype", "objname", "reftype", "refname"},
|
||||
{"framelinvel", "*", "name", "nsample", "interp", "delay", "interval", "cutoff", "noise",
|
||||
"user", "objtype", "objname", "reftype", "refname"},
|
||||
{"frameangvel", "*", "name", "nsample", "interp", "delay", "interval", "cutoff", "noise",
|
||||
"user", "objtype", "objname", "reftype", "refname"},
|
||||
{"framelinacc", "*", "name", "nsample", "interp", "delay", "interval", "cutoff", "noise",
|
||||
"user", "objtype", "objname"},
|
||||
{"frameangacc", "*", "name", "nsample", "interp", "delay", "interval", "cutoff", "noise",
|
||||
"user", "objtype", "objname"},
|
||||
{"subtreecom", "*", "name", "nsample", "interp", "delay", "interval", "cutoff", "noise",
|
||||
"user", "body"},
|
||||
{"subtreelinvel", "*", "name", "nsample", "interp", "delay", "interval", "cutoff", "noise",
|
||||
"user", "body"},
|
||||
{"subtreeangmom", "*", "name", "nsample", "interp", "delay", "interval", "cutoff", "noise",
|
||||
"user", "body"},
|
||||
{"insidesite", "*", "name", "nsample", "interp", "delay", "interval", "cutoff", "noise",
|
||||
"user", "site", "objtype", "objname"},
|
||||
{"distance", "*", "name", "nsample", "interp", "delay", "interval", "cutoff", "noise",
|
||||
"user", "geom1", "geom2", "body1", "body2"},
|
||||
{"normal", "*", "name", "nsample", "interp", "delay", "interval", "cutoff", "noise",
|
||||
"user", "geom1", "geom2", "body1", "body2"},
|
||||
{"fromto", "*", "name", "nsample", "interp", "delay", "interval", "cutoff", "noise",
|
||||
"user", "geom1", "geom2", "body1", "body2"},
|
||||
{"contact", "*", "name", "nsample", "interp", "delay", "interval", "cutoff", "noise",
|
||||
"user", "geom1", "geom2", "body1", "body2", "subtree1", "subtree2", "site", "num",
|
||||
"data", "reduce"},
|
||||
{"e_potential", "*", "name", "nsample", "interp", "delay", "interval", "cutoff", "noise",
|
||||
"user"},
|
||||
{"e_kinetic", "*", "name", "nsample", "interp", "delay", "interval", "cutoff", "noise",
|
||||
"user"},
|
||||
{"clock", "*", "name", "nsample", "interp", "delay", "interval", "cutoff", "noise", "user"},
|
||||
{"tactile", "*", "name", "geom", "mesh", "nsample", "interp", "delay", "interval", "user"},
|
||||
{"user", "*", "name", "objtype", "objname", "datatype", "needstage", "dim", "cutoff",
|
||||
"noise", "user"},
|
||||
{"plugin", "*", "name", "plugin", "instance", "cutoff", "objtype", "objname", "reftype",
|
||||
"refname", "user"},
|
||||
{"<"},
|
||||
{"config", "*", "key", "value"},
|
||||
{">"},
|
||||
{">"},
|
||||
|
||||
{"custom", "*"},
|
||||
{"<"},
|
||||
{"numeric", "*", "name", "size", "data"},
|
||||
{"text", "*", "name", "data"},
|
||||
{"tuple", "*", "name"},
|
||||
{"<"},
|
||||
{"element", "*", "objtype", "objname", "prm"},
|
||||
{">"},
|
||||
{">"},
|
||||
|
||||
{"keyframe", "*"},
|
||||
{"<"},
|
||||
{"key", "*", "name", "time", "qpos", "qvel", "act", "mpos", "mquat", "ctrl"},
|
||||
{">"},
|
||||
|
||||
{">"},
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
const int nMJCF = sizeof(MJCF) / sizeof(MJCF[0]);
|
||||
|
||||
// presence constraints, indexed into MJCF[]; enforced by
|
||||
// mjXSchema::Check. spec: attribute bundles, space-joined,
|
||||
// '|'-separated; kind: e=exclusive t=together r=requires o=oneof
|
||||
// clang-format off
|
||||
const mjXConstraintDef MJCF_constraints[] = {
|
||||
{10, 'e', "memory|nstack"},
|
||||
{10, 'e', "memory|njmax"},
|
||||
{31, 'e', "fovy|sensorsize"},
|
||||
{32, 'e', "directional|type"},
|
||||
{61, 'e', "builtin|file"},
|
||||
{61, 'e', "builtin|vertex"},
|
||||
{82, 'e', "fullinertia|quat|axisangle|xyaxes|zaxis|euler"},
|
||||
{92, 'e', "body|frame"},
|
||||
{94, 'e', "fovy|sensorsize"},
|
||||
{95, 'e', "directional|type"},
|
||||
{156, 'e', "site1 site2|body1 body2 anchor"},
|
||||
{156, 'o', "site1 site2|body1 anchor"},
|
||||
{156, 't', "site1|site2"},
|
||||
{157, 'e', "site1 site2|body1 body2 anchor relpose"},
|
||||
{157, 'o', "site1 site2|body1"},
|
||||
{157, 't', "site1|site2"},
|
||||
{193, 'e', "site|camera"},
|
||||
{193, 'o', "site|camera"},
|
||||
{211, 't', "reftype|refname"},
|
||||
{212, 't', "reftype|refname"},
|
||||
{213, 't', "reftype|refname"},
|
||||
{214, 't', "reftype|refname"},
|
||||
{215, 't', "reftype|refname"},
|
||||
{216, 't', "reftype|refname"},
|
||||
{217, 't', "reftype|refname"},
|
||||
{224, 'e', "geom1|body1"},
|
||||
{224, 'o', "geom1|body1"},
|
||||
{224, 'e', "geom2|body2"},
|
||||
{224, 'o', "geom2|body2"},
|
||||
{225, 'e', "geom1|body1"},
|
||||
{225, 'o', "geom1|body1"},
|
||||
{225, 'e', "geom2|body2"},
|
||||
{225, 'o', "geom2|body2"},
|
||||
{226, 'e', "geom1|body1"},
|
||||
{226, 'o', "geom1|body1"},
|
||||
{226, 'e', "geom2|body2"},
|
||||
{226, 'o', "geom2|body2"},
|
||||
{227, 'e', "geom1|body1|subtree1|site"},
|
||||
{227, 'e', "geom2|body2|subtree2"},
|
||||
{232, 't', "objtype|objname"},
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
const int nMJCF_constraints = sizeof(MJCF_constraints) / sizeof(MJCF_constraints[0]);
|
||||
+17
-579
@@ -165,457 +165,7 @@ static void UpdateString(string& psuffix, int count, int i) {
|
||||
|
||||
|
||||
//---------------------------------- MJCF schema ---------------------------------------------------
|
||||
|
||||
// clang-format off
|
||||
std::vector<const char*> MJCF[nMJCF] = {
|
||||
{"mujoco", "!", "model"},
|
||||
{"<"},
|
||||
{"compiler", "*", "autolimits", "boundmass", "boundinertia", "settotalmass",
|
||||
"balanceinertia", "strippath", "coordinate", "angle", "fitaabb", "eulerseq",
|
||||
"meshdir", "texturedir", "discardvisual", "usethread", "fusestatic", "inertiafromgeom",
|
||||
"inertiagrouprange", "saveinertial", "assetdir", "alignfree", "conflict"},
|
||||
{"<"},
|
||||
{"lengthrange", "?", "mode", "useexisting", "uselimit",
|
||||
"accel", "maxforce", "timeconst", "timestep",
|
||||
"inttotal", "interval", "tolrange"},
|
||||
{">"},
|
||||
|
||||
{"option", "*",
|
||||
"timestep", "impratio", "tolerance", "ls_tolerance", "noslip_tolerance",
|
||||
"ccd_tolerance", "sleep_tolerance", "gravity", "wind", "magnetic", "density", "viscosity",
|
||||
"o_margin", "o_solref", "o_solimp", "o_friction",
|
||||
"integrator", "cone", "jacobian",
|
||||
"solver", "iterations", "ls_iterations", "noslip_iterations", "ccd_iterations",
|
||||
"sdf_iterations", "sdf_initpoints", "actuatorgroupdisable"},
|
||||
{"<"},
|
||||
{"flag", "?", "constraint", "equality", "frictionloss", "limit", "contact",
|
||||
"spring", "damper", "gravity", "clampctrl", "warmstart", "filterparent", "actuation",
|
||||
"refsafe", "sensor", "midphase", "eulerdamp", "autoreset", "nativeccd", "island",
|
||||
"override", "energy", "fwdinv", "invdiscrete", "multiccd", "sleep",
|
||||
"diagexact"},
|
||||
{">"},
|
||||
|
||||
{"size", "*", "memory", "njmax", "nconmax", "nstack", "nuserdata", "nkey",
|
||||
"nuser_body", "nuser_jnt", "nuser_geom", "nuser_site", "nuser_cam",
|
||||
"nuser_tendon", "nuser_actuator", "nuser_sensor"},
|
||||
|
||||
{"visual", "*"},
|
||||
{"<"},
|
||||
{"global", "?", "cameraid", "orthographic", "fovy", "ipd", "azimuth", "elevation",
|
||||
"linewidth", "glow", "offwidth", "offheight", "realtime", "ellipsoidinertia",
|
||||
"bvactive"},
|
||||
{"quality", "?", "shadowsize", "offsamples", "numslices", "numstacks",
|
||||
"numquads"},
|
||||
{"headlight", "?", "ambient", "diffuse", "specular", "active"},
|
||||
{"map", "?", "stiffness", "stiffnessrot", "force", "torque", "alpha",
|
||||
"fogstart", "fogend", "znear", "zfar", "haze", "shadowclip", "shadowscale",
|
||||
"actuatortendon"},
|
||||
{"scale", "?", "forcewidth", "contactwidth", "contactheight", "connect", "com",
|
||||
"camera", "light", "selectpoint", "jointlength", "jointwidth", "actuatorlength",
|
||||
"actuatorwidth", "framelength", "framewidth", "constraint", "slidercrank", "frustum"},
|
||||
{"rgba", "?", "fog", "haze", "force", "inertia", "joint",
|
||||
"actuator", "actuatornegative", "actuatorpositive", "com",
|
||||
"camera", "light", "selectpoint", "connect", "contactpoint", "contactforce",
|
||||
"contactfriction", "contacttorque", "contactgap", "rangefinder",
|
||||
"constraint", "slidercrank", "crankbroken", "frustum", "bv", "bvactive"},
|
||||
{">"},
|
||||
|
||||
{"statistic", "*", "meaninertia", "meanmass", "meansize", "extent", "center"},
|
||||
|
||||
{"default", "R", "class"},
|
||||
{"<"},
|
||||
{"mesh", "?", "scale", "maxhullvert", "inertia"},
|
||||
{"material", "?", "texture", "emission", "specular", "shininess",
|
||||
"reflectance", "metallic", "roughness", "rgba", "texrepeat", "texuniform"},
|
||||
{"<"},
|
||||
{"layer", "*", "texture", "role"},
|
||||
{">"},
|
||||
{"joint", "?", "type", "group", "pos", "axis", "springdamper",
|
||||
"limited", "actuatorfrclimited", "solreflimit", "solimplimit",
|
||||
"solreffriction", "solimpfriction", "stiffness", "range", "actuatorfrcrange",
|
||||
"actuatorgravcomp", "margin", "ref", "springref", "armature", "damping",
|
||||
"frictionloss", "user"},
|
||||
{"geom", "?", "type", "pos", "quat", "contype", "conaffinity", "condim",
|
||||
"group", "priority", "size", "material", "friction", "mass", "density",
|
||||
"shellinertia", "solmix", "solref", "solimp",
|
||||
"margin", "gap", "surfacevel", "adhesion", "fromto", "axisangle", "xyaxes", "zaxis",
|
||||
"euler",
|
||||
"hfield", "mesh", "fitscale", "rgba", "fluidshape", "fluidcoef", "user"},
|
||||
{"site", "?", "type", "group", "pos", "quat", "material",
|
||||
"size", "fromto", "axisangle", "xyaxes", "zaxis", "euler", "rgba", "user"},
|
||||
{"camera", "?", "projection", "fovy", "ipd", "resolution", "output", "pos", "quat",
|
||||
"axisangle", "xyaxes", "zaxis", "euler", "mode", "focal", "focalpixel",
|
||||
"principal", "principalpixel", "sensorsize", "user"},
|
||||
{"light", "?", "pos", "dir", "bulbradius", "intensity", "range",
|
||||
"directional", "type", "castshadow", "active", "attenuation", "cutoff", "exponent",
|
||||
"ambient", "diffuse", "specular", "mode"},
|
||||
{"pair", "?", "condim", "friction", "solref", "solreffriction", "solimp",
|
||||
"gap", "margin", "adhesion"},
|
||||
{"equality", "?", "active", "solref", "solimp"},
|
||||
{"tendon", "?", "group", "limited", "range",
|
||||
"solreflimit", "solimplimit", "solreffriction", "solimpfriction",
|
||||
"frictionloss", "springlength", "width", "material",
|
||||
"margin", "stiffness", "damping", "rgba", "user"},
|
||||
{"general", "?", "ctrllimited", "forcelimited", "actlimited", "ctrlrange", "forcerange",
|
||||
"actrange", "gear", "damping", "armature", "cranklength", "user", "group", "nsample",
|
||||
"interp", "delay", "actdim", "input", "velrange", "ffrange", "dyntype", "gaintype", "biastype", "dynprm", "gainprm",
|
||||
"biasprm", "actearly"},
|
||||
{"motor", "?", "ctrllimited", "forcelimited", "ctrlrange", "forcerange",
|
||||
"gear", "damping", "armature", "cranklength", "user", "group", "nsample", "interp", "delay"},
|
||||
{"position", "?", "ctrllimited", "forcelimited", "ctrlrange", "inheritrange", "forcerange",
|
||||
"gear", "damping", "armature", "cranklength", "user", "group", "nsample", "interp",
|
||||
"delay", "kp", "kv", "dampratio", "timeconst"},
|
||||
{"velocity", "?", "ctrllimited", "forcelimited", "ctrlrange", "forcerange", "gear",
|
||||
"damping", "armature", "cranklength", "user", "group", "nsample", "interp", "delay", "kv"},
|
||||
{"intvelocity", "?", "ctrllimited", "forcelimited", "actlimited", "ctrlrange", "forcerange",
|
||||
"actrange", "inheritrange", "gear", "damping", "armature", "cranklength", "user", "group",
|
||||
"nsample", "interp", "delay", "kp", "kv", "dampratio"},
|
||||
{"orientation", "?", "forcelimited", "ctrlrange", "forcerange", "user", "group",
|
||||
"nsample", "interp", "delay", "kp", "kv", "dampratio", "input"},
|
||||
{"pid", "?", "ctrllimited", "forcelimited", "ctrlrange", "posrange", "velrange", "ffrange",
|
||||
"forcerange", "inheritrange", "gear", "damping", "armature", "cranklength", "user",
|
||||
"group", "nsample", "interp", "delay", "kp", "kv", "dampratio", "ki", "imax", "slewmax",
|
||||
"input"},
|
||||
{"damper", "?", "forcelimited", "ctrlrange", "forcerange",
|
||||
"gear", "damping", "armature", "cranklength", "user", "group", "nsample", "interp", "delay", "kv"},
|
||||
{"cylinder", "?", "ctrllimited", "forcelimited", "ctrlrange", "forcerange",
|
||||
"gear", "damping", "armature", "cranklength", "user", "group", "nsample", "interp", "delay",
|
||||
"timeconst", "area", "diameter", "bias"},
|
||||
{"muscle", "?", "ctrllimited", "forcelimited", "ctrlrange", "forcerange",
|
||||
"gear", "damping", "armature", "cranklength", "user", "group", "nsample", "interp", "delay",
|
||||
"timeconst", "range", "force", "scale",
|
||||
"lmin", "lmax", "vmax", "fpmax", "fvmax"},
|
||||
{"adhesion", "?", "forcelimited", "ctrlrange", "forcerange",
|
||||
"gain", "user", "group", "nsample", "interp", "delay"},
|
||||
{"dcmotor", "?", "ctrllimited", "ctrlrange",
|
||||
"gear", "damping", "armature", "cranklength", "user", "group", "nsample", "interp", "delay",
|
||||
"motorconst", "resistance", "nominal", "saturation",
|
||||
"inductance", "cogging", "controller", "input", "thermal", "lugre"},
|
||||
{">"},
|
||||
|
||||
{"extension", "*"},
|
||||
{"<"},
|
||||
{"plugin", "*", "plugin"},
|
||||
{"<"},
|
||||
{"instance", "*", "name"},
|
||||
{"<"},
|
||||
{"config", "*", "key", "value"},
|
||||
{">"},
|
||||
{">"},
|
||||
{">"},
|
||||
|
||||
{"custom", "*"},
|
||||
{"<"},
|
||||
{"numeric", "*", "name", "size", "data"},
|
||||
{"text", "*", "name", "data"},
|
||||
{"tuple", "*", "name"},
|
||||
{"<"},
|
||||
{"element", "*", "objtype", "objname", "prm"},
|
||||
{">"},
|
||||
{">"},
|
||||
|
||||
{"asset", "*"},
|
||||
{"<"},
|
||||
{"mesh", "*", "name", "class", "content_type", "file", "vertex", "normal",
|
||||
"texcoord", "face", "refpos", "refquat", "scale", "smoothnormal",
|
||||
"maxhullvert", "inertia", "builtin", "params", "material"},
|
||||
{"<"},
|
||||
{"plugin", "*", "plugin", "instance"},
|
||||
{"<"},
|
||||
{"config", "*", "key", "value"},
|
||||
{">"},
|
||||
{">"},
|
||||
{"hfield", "*", "name", "content_type", "file", "nrow", "ncol", "size", "elevation"},
|
||||
{"skin", "*", "name", "file", "material", "rgba", "inflate",
|
||||
"vertex", "texcoord", "face", "group"},
|
||||
{"<"},
|
||||
{"bone", "*", "body", "bindpos", "bindquat", "vertid", "vertweight"},
|
||||
{">"},
|
||||
{"texture", "*", "name", "type", "colorspace", "content_type", "file", "gridsize",
|
||||
"gridlayout", "fileright", "fileleft", "fileup", "filedown", "filefront", "fileback",
|
||||
"builtin", "rgb1", "rgb2", "mark", "markrgb", "random", "width", "height",
|
||||
"hflip", "vflip", "nchannel"},
|
||||
{"material", "*", "name", "class", "texture", "texrepeat", "texuniform",
|
||||
"emission", "specular", "shininess", "reflectance", "metallic", "roughness", "rgba"},
|
||||
{"<"},
|
||||
{"layer", "*", "texture", "role"},
|
||||
{">"},
|
||||
{"model", "*", "name", "file", "content_type"},
|
||||
{">"},
|
||||
{"body", "R", "name", "childclass", "pos", "quat", "mocap", "axisangle",
|
||||
"xyaxes", "zaxis", "euler", "gravcomp", "sleep", "simple", "user"},
|
||||
{"<"},
|
||||
{"inertial", "?", "pos", "quat", "mass", "diaginertia",
|
||||
"axisangle", "xyaxes", "zaxis", "euler", "fullinertia"},
|
||||
{"joint", "*", "name", "class", "type", "group", "pos", "axis",
|
||||
"springdamper", "limited", "actuatorfrclimited",
|
||||
"solreflimit", "solimplimit", "solreffriction", "solimpfriction",
|
||||
"stiffness", "range", "actuatorfrcrange", "actuatorgravcomp", "margin", "ref",
|
||||
"springref", "armature", "damping", "frictionloss", "user"},
|
||||
{"freejoint", "*", "name", "group", "align"},
|
||||
{"geom", "*", "name", "class", "type", "contype", "conaffinity", "condim",
|
||||
"group", "priority", "size", "material", "friction", "mass", "density",
|
||||
"shellinertia", "solmix", "solref", "solimp",
|
||||
"margin", "gap", "surfacevel", "adhesion", "fromto", "pos", "quat", "axisangle",
|
||||
"xyaxes", "zaxis", "euler", "hfield", "mesh", "fitscale", "rgba", "fluidshape",
|
||||
"fluidcoef", "user"},
|
||||
{"<"},
|
||||
{"plugin", "*", "plugin", "instance"},
|
||||
{"<"},
|
||||
{"config", "*", "key", "value"},
|
||||
{">"},
|
||||
{">"},
|
||||
{"attach", "*", "model", "body", "frame", "prefix"},
|
||||
{"site", "*", "name", "class", "type", "group", "pos", "quat",
|
||||
"material", "size", "fromto", "axisangle", "xyaxes", "zaxis", "euler", "rgba", "user"},
|
||||
{"camera", "*", "name", "class", "projection", "fovy", "ipd", "resolution", "output", "pos",
|
||||
"quat", "axisangle", "xyaxes", "zaxis", "euler", "mode", "target",
|
||||
"focal", "focalpixel", "principal", "principalpixel", "sensorsize", "user"},
|
||||
{"light", "*", "name", "class", "directional", "type", "castshadow", "active",
|
||||
"pos", "dir", "bulbradius", "intensity", "range", "attenuation", "cutoff",
|
||||
"exponent", "ambient", "diffuse", "specular", "mode", "target", "texture"},
|
||||
{"plugin", "*", "plugin", "instance"},
|
||||
{"<"},
|
||||
{"config", "*", "key", "value"},
|
||||
{">"},
|
||||
{"composite", "*", "prefix", "type", "count", "offset",
|
||||
"vertex", "initial", "curve", "size", "quat"},
|
||||
{"<"},
|
||||
{"joint", "*", "kind", "group", "stiffness", "damping", "armature",
|
||||
"solreffix", "solimpfix", "type", "axis",
|
||||
"limited", "range", "margin", "solreflimit", "solimplimit",
|
||||
"frictionloss", "solreffriction", "solimpfriction"},
|
||||
{"skin", "?", "texcoord", "material", "group", "rgba", "inflate", "subgrid"},
|
||||
{"geom", "?", "type", "contype", "conaffinity", "condim",
|
||||
"group", "priority", "size", "material", "rgba", "friction", "mass",
|
||||
"density", "solmix", "solref", "solimp", "margin", "gap", "surfacevel",
|
||||
"adhesion"},
|
||||
{"site", "?", "group", "size", "material", "rgba"},
|
||||
{"plugin", "*", "plugin", "instance"},
|
||||
{"<"},
|
||||
{"config", "*", "key", "value"},
|
||||
{">"},
|
||||
{">"},
|
||||
{"flexcomp", "*", "name", "type", "group", "dim", "dof",
|
||||
"count", "cellcount", "spacing", "radius", "rigid", "mass", "inertiabox",
|
||||
"scale", "file", "point", "element", "texcoord", "material", "rgba",
|
||||
"flatskin", "pos", "quat", "axisangle", "xyaxes", "zaxis", "euler", "origin"},
|
||||
{"<"},
|
||||
{"edge", "?", "equality", "solref", "solimp", "stiffness", "damping"},
|
||||
{"elasticity", "?", "young", "poisson", "damping", "thickness", "elastic2d"},
|
||||
{"contact", "?", "contype", "conaffinity", "condim", "priority",
|
||||
"friction", "solmix", "solref", "solimp", "margin", "gap",
|
||||
"internal", "selfcollide", "activelayers", "passive"},
|
||||
{"pin", "*", "id", "range", "grid", "gridrange"},
|
||||
{"plugin", "*", "plugin", "instance"},
|
||||
{"<"},
|
||||
{"config", "*", "key", "value"},
|
||||
{">"},
|
||||
{">"},
|
||||
{">"},
|
||||
|
||||
{"deformable", "*"},
|
||||
{"<"},
|
||||
{"flex", "*", "name", "group", "dim", "radius", "material", "rgba", "flatskin", "body",
|
||||
"vertex", "element", "texcoord", "elemtexcoord", "node", "cellcount", "dof"},
|
||||
{"<"},
|
||||
{"contact", "?", "contype", "conaffinity", "condim", "priority",
|
||||
"friction", "solmix", "solref", "solimp", "margin", "gap",
|
||||
"internal", "selfcollide", "activelayers", "passive"},
|
||||
{"edge", "?", "stiffness", "damping"},
|
||||
{"elasticity", "?", "young", "poisson", "damping", "thickness", "elastic2d"},
|
||||
{">"},
|
||||
{"skin", "*", "name", "file", "material", "rgba", "inflate",
|
||||
"vertex", "texcoord", "face", "group"},
|
||||
{"<"},
|
||||
{"bone", "*", "body", "bindpos", "bindquat", "vertid", "vertweight"},
|
||||
{">"},
|
||||
{">"},
|
||||
|
||||
{"contact", "*"},
|
||||
{"<"},
|
||||
{"pair", "*", "name", "class", "geom1", "geom2", "condim", "friction",
|
||||
"solref", "solreffriction", "solimp", "gap", "margin", "adhesion"},
|
||||
{"exclude", "*", "name", "body1", "body2"},
|
||||
{">"},
|
||||
|
||||
{"equality", "*"},
|
||||
{"<"},
|
||||
{"connect", "*", "name", "class", "body1", "body2", "anchor",
|
||||
"site1", "site2", "active", "solref", "solimp"},
|
||||
{"weld", "*", "name", "class", "body1", "body2", "relpose", "anchor",
|
||||
"site1", "site2", "active", "solref", "solimp", "torquescale"},
|
||||
{"joint", "*", "name", "class", "joint1", "joint2", "polycoef",
|
||||
"active", "solref", "solimp"},
|
||||
{"tendon", "*", "name", "class", "tendon1", "tendon2", "polycoef",
|
||||
"active", "solref", "solimp"},
|
||||
{"flex", "*", "name", "class", "flex",
|
||||
"active", "solref", "solimp"},
|
||||
{"flexvert", "*", "name", "class", "flex",
|
||||
"active", "solref", "solimp"},
|
||||
{"flexstrain", "*", "name", "class", "flex", "cell",
|
||||
"active", "solref", "solimp"},
|
||||
{">"},
|
||||
|
||||
{"tendon", "*"},
|
||||
{"<"},
|
||||
{"spatial", "*", "name", "class", "group", "limited", "actuatorfrclimited", "range",
|
||||
"actuatorfrcrange", "solreflimit", "solimplimit", "solreffriction", "solimpfriction",
|
||||
"frictionloss", "springlength", "width", "material",
|
||||
"margin", "stiffness", "damping", "armature", "rgba", "user"},
|
||||
{"<"},
|
||||
{"site", "*", "site"},
|
||||
{"geom", "*", "geom", "sidesite"},
|
||||
{"pulley", "*", "divisor"},
|
||||
{">"},
|
||||
{"fixed", "*", "name", "class", "group", "limited", "actuatorfrclimited", "range",
|
||||
"actuatorfrcrange", "solreflimit", "solimplimit", "solreffriction", "solimpfriction",
|
||||
"frictionloss", "springlength", "margin", "stiffness", "damping", "armature", "user"},
|
||||
{"<"},
|
||||
{"joint", "*", "joint", "coef"},
|
||||
{">"},
|
||||
{">"},
|
||||
|
||||
{"actuator", "*"},
|
||||
{"<"},
|
||||
{"general", "*", "name", "class", "group", "nsample", "interp", "delay",
|
||||
"ctrllimited", "forcelimited", "actlimited", "ctrlrange", "forcerange", "actrange",
|
||||
"lengthrange", "gear", "damping", "armature", "cranklength", "user",
|
||||
"joint", "jointinparent", "tendon", "slidersite", "cranksite", "site", "refsite",
|
||||
"body", "actdim", "input", "velrange", "ffrange", "dyntype", "gaintype", "biastype", "dynprm", "gainprm", "biasprm",
|
||||
"actearly"},
|
||||
{"motor", "*", "name", "class", "group", "nsample", "interp", "delay",
|
||||
"ctrllimited", "forcelimited", "ctrlrange", "forcerange",
|
||||
"lengthrange", "gear", "damping", "armature", "cranklength", "user",
|
||||
"joint", "jointinparent", "tendon", "slidersite", "cranksite", "site", "refsite"},
|
||||
{"position", "*", "name", "class", "group", "nsample", "interp", "delay",
|
||||
"ctrllimited", "forcelimited", "ctrlrange", "inheritrange", "forcerange",
|
||||
"lengthrange", "gear", "damping", "armature", "cranklength", "user",
|
||||
"joint", "jointinparent", "tendon", "slidersite", "cranksite", "site", "refsite",
|
||||
"kp", "kv", "dampratio", "timeconst"},
|
||||
{"velocity", "*", "name", "class", "group", "nsample", "interp", "delay",
|
||||
"ctrllimited", "forcelimited", "ctrlrange", "forcerange",
|
||||
"lengthrange", "gear", "damping", "armature", "cranklength", "user",
|
||||
"joint", "jointinparent", "tendon", "slidersite", "cranksite", "site", "refsite",
|
||||
"kv"},
|
||||
{"intvelocity", "*", "name", "class", "group", "nsample", "interp", "delay",
|
||||
"ctrllimited", "forcelimited", "actlimited",
|
||||
"ctrlrange", "forcerange", "actrange", "inheritrange", "lengthrange",
|
||||
"gear", "damping", "armature", "cranklength", "user",
|
||||
"joint", "jointinparent", "tendon", "slidersite", "cranksite", "site", "refsite",
|
||||
"kp", "kv", "dampratio"},
|
||||
{"orientation", "*", "name", "class", "group", "nsample", "interp", "delay",
|
||||
"forcelimited", "ctrlrange", "forcerange", "user",
|
||||
"joint", "site", "refsite",
|
||||
"kp", "kv", "dampratio", "input"},
|
||||
{"pid", "*", "name", "class", "group", "nsample", "interp", "delay",
|
||||
"ctrllimited", "forcelimited", "ctrlrange", "posrange", "velrange", "ffrange",
|
||||
"forcerange", "inheritrange", "lengthrange", "gear", "damping", "armature",
|
||||
"cranklength", "user",
|
||||
"joint", "jointinparent", "tendon", "slidersite", "cranksite", "site", "refsite",
|
||||
"kp", "kv", "dampratio", "ki", "imax", "slewmax", "input"},
|
||||
{"damper", "*", "name", "class", "group", "nsample", "interp", "delay",
|
||||
"forcelimited", "ctrlrange", "forcerange",
|
||||
"lengthrange", "gear", "damping", "armature", "cranklength", "user",
|
||||
"joint", "jointinparent", "tendon", "slidersite", "cranksite", "site", "refsite",
|
||||
"kv"},
|
||||
{"cylinder", "*", "name", "class", "group", "nsample", "interp", "delay",
|
||||
"ctrllimited", "forcelimited", "ctrlrange", "forcerange",
|
||||
"lengthrange", "gear", "damping", "armature", "cranklength", "user",
|
||||
"joint", "jointinparent", "tendon", "slidersite", "cranksite", "site", "refsite",
|
||||
"timeconst", "area", "diameter", "bias"},
|
||||
{"muscle", "*", "name", "class", "group", "nsample", "interp", "delay",
|
||||
"ctrllimited", "forcelimited", "ctrlrange", "forcerange",
|
||||
"lengthrange", "gear", "damping", "armature", "cranklength", "user",
|
||||
"joint", "jointinparent", "tendon", "slidersite", "cranksite",
|
||||
"timeconst", "tausmooth", "range", "force", "scale",
|
||||
"lmin", "lmax", "vmax", "fpmax", "fvmax"},
|
||||
{"adhesion", "*", "name", "class", "group", "nsample", "interp", "delay",
|
||||
"forcelimited", "ctrlrange", "forcerange", "user", "body", "gain"},
|
||||
{"dcmotor", "*", "name", "class", "group", "nsample", "interp", "delay",
|
||||
"ctrllimited", "ctrlrange",
|
||||
"lengthrange", "gear", "damping", "armature", "cranklength", "user",
|
||||
"joint", "jointinparent", "tendon", "slidersite", "cranksite", "site", "refsite",
|
||||
"motorconst", "resistance", "nominal", "saturation",
|
||||
"inductance", "cogging", "controller", "thermal", "lugre", "input"},
|
||||
{"plugin", "*", "name", "class", "plugin", "instance", "group", "nsample", "interp", "delay",
|
||||
"ctrllimited", "forcelimited", "actlimited", "ctrlrange", "forcerange", "actrange",
|
||||
"lengthrange", "gear", "damping", "armature", "cranklength", "joint", "jointinparent",
|
||||
"site", "actdim", "dyntype", "dynprm", "tendon", "cranksite", "slidersite", "user",
|
||||
"actearly"},
|
||||
{"<"},
|
||||
{"config", "*", "key", "value"},
|
||||
{">"},
|
||||
{">"},
|
||||
|
||||
{"sensor", "*"},
|
||||
{"<"},
|
||||
{"touch", "*", "name", "site", "nsample", "interp", "delay", "interval", "cutoff", "noise", "user"},
|
||||
{"accelerometer", "*", "name", "site", "nsample", "interp", "delay", "interval", "cutoff", "noise", "user"},
|
||||
{"velocimeter", "*", "name", "site", "nsample", "interp", "delay", "interval", "cutoff", "noise", "user"},
|
||||
{"gyro", "*", "name", "site", "nsample", "interp", "delay", "interval", "cutoff", "noise", "user"},
|
||||
{"force", "*", "name", "site", "nsample", "interp", "delay", "interval", "cutoff", "noise", "user"},
|
||||
{"torque", "*", "name", "site", "nsample", "interp", "delay", "interval", "cutoff", "noise", "user"},
|
||||
{"magnetometer", "*", "name", "site", "nsample", "interp", "delay", "interval", "cutoff", "noise", "user"},
|
||||
{"camprojection", "*", "name", "site", "camera", "nsample", "interp", "delay", "interval", "cutoff", "noise", "user"},
|
||||
{"rangefinder", "*", "name", "site", "camera", "data", "nsample", "interp", "delay", "interval", "cutoff", "noise", "user"},
|
||||
{"jointpos", "*", "name", "joint", "nsample", "interp", "delay", "interval", "cutoff", "noise", "user"},
|
||||
{"jointvel", "*", "name", "joint", "nsample", "interp", "delay", "interval", "cutoff", "noise", "user"},
|
||||
{"tendonpos", "*", "name", "tendon", "nsample", "interp", "delay", "interval", "cutoff", "noise", "user"},
|
||||
{"tendonvel", "*", "name", "tendon", "nsample", "interp", "delay", "interval", "cutoff", "noise", "user"},
|
||||
{"actuatorpos", "*", "name", "actuator", "nsample", "interp", "delay", "interval", "cutoff", "noise", "user"},
|
||||
{"actuatorvel", "*", "name", "actuator", "nsample", "interp", "delay", "interval", "cutoff", "noise", "user"},
|
||||
{"actuatorfrc", "*", "name", "actuator", "nsample", "interp", "delay", "interval", "cutoff", "noise", "user"},
|
||||
{"jointactuatorfrc", "*", "name", "joint", "nsample", "interp", "delay", "interval", "cutoff", "noise", "user"},
|
||||
{"tendonactuatorfrc", "*", "name", "tendon", "nsample", "interp", "delay", "interval", "cutoff", "noise", "user"},
|
||||
{"ballquat", "*", "name", "joint", "nsample", "interp", "delay", "interval", "cutoff", "noise", "user"},
|
||||
{"ballangvel", "*", "name", "joint", "nsample", "interp", "delay", "interval", "cutoff", "noise", "user"},
|
||||
{"jointlimitpos", "*", "name", "joint", "nsample", "interp", "delay", "interval", "cutoff", "noise", "user"},
|
||||
{"jointlimitvel", "*", "name", "joint", "nsample", "interp", "delay", "interval", "cutoff", "noise", "user"},
|
||||
{"jointlimitfrc", "*", "name", "joint", "nsample", "interp", "delay", "interval", "cutoff", "noise", "user"},
|
||||
{"tendonlimitpos", "*", "name", "tendon", "nsample", "interp", "delay", "interval", "cutoff", "noise", "user"},
|
||||
{"tendonlimitvel", "*", "name", "tendon", "nsample", "interp", "delay", "interval", "cutoff", "noise", "user"},
|
||||
{"tendonlimitfrc", "*", "name", "tendon", "nsample", "interp", "delay", "interval", "cutoff", "noise", "user"},
|
||||
{"framepos", "*", "name", "objtype", "objname", "reftype", "refname", "nsample", "interp", "delay", "interval", "cutoff", "noise", "user"},
|
||||
{"framequat", "*", "name", "objtype", "objname", "reftype", "refname", "nsample", "interp", "delay", "interval", "cutoff", "noise", "user"},
|
||||
{"framexaxis", "*", "name", "objtype", "objname", "reftype", "refname", "nsample", "interp", "delay", "interval", "cutoff", "noise", "user"},
|
||||
{"frameyaxis", "*", "name", "objtype", "objname", "reftype", "refname", "nsample", "interp", "delay", "interval", "cutoff", "noise", "user"},
|
||||
{"framezaxis", "*", "name", "objtype", "objname", "reftype", "refname", "nsample", "interp", "delay", "interval", "cutoff", "noise", "user"},
|
||||
{"framelinvel", "*", "name", "objtype", "objname", "reftype", "refname", "nsample", "interp", "delay", "interval", "cutoff", "noise", "user"},
|
||||
{"frameangvel", "*", "name", "objtype", "objname", "reftype", "refname", "nsample", "interp", "delay", "interval", "cutoff", "noise", "user"},
|
||||
{"framelinacc", "*", "name", "objtype", "objname", "nsample", "interp", "delay", "interval", "cutoff", "noise", "user"},
|
||||
{"frameangacc", "*", "name", "objtype", "objname", "nsample", "interp", "delay", "interval", "cutoff", "noise", "user"},
|
||||
{"subtreecom", "*", "name", "body", "nsample", "interp", "delay", "interval", "cutoff", "noise", "user"},
|
||||
{"subtreelinvel", "*", "name", "body", "nsample", "interp", "delay", "interval", "cutoff", "noise", "user"},
|
||||
{"subtreeangmom", "*", "name", "body", "nsample", "interp", "delay", "interval", "cutoff", "noise", "user"},
|
||||
{"insidesite", "*", "name", "site", "objtype", "objname", "nsample", "interp", "delay", "interval", "cutoff", "noise", "user"},
|
||||
{"distance", "*", "name", "geom1", "geom2", "body1", "body2", "nsample", "interp", "delay", "interval", "cutoff", "noise", "user"},
|
||||
{"normal", "*", "name", "geom1", "geom2", "body1", "body2", "nsample", "interp", "delay", "interval", "cutoff", "noise", "user"},
|
||||
{"fromto", "*", "name", "geom1", "geom2", "body1", "body2", "nsample", "interp", "delay", "interval", "cutoff", "noise", "user"},
|
||||
{"contact", "*", "name", "geom1", "geom2", "body1", "body2", "subtree1", "subtree2", "site",
|
||||
"num", "data", "reduce", "nsample", "interp", "delay", "interval", "cutoff", "noise", "user"},
|
||||
{"e_potential", "*", "name", "nsample", "interp", "delay", "interval", "cutoff", "noise", "user"},
|
||||
{"e_kinetic", "*", "name", "nsample", "interp", "delay", "interval", "cutoff", "noise", "user"},
|
||||
{"clock", "*", "name", "nsample", "interp", "delay", "interval", "cutoff", "noise", "user"},
|
||||
{"tactile", "*", "name", "geom", "mesh", "nsample", "interp", "delay", "interval", "user"},
|
||||
{"user", "*", "name", "objtype", "objname", "datatype", "needstage",
|
||||
"dim", "cutoff", "noise", "user"},
|
||||
{"plugin", "*", "name", "plugin", "instance", "cutoff", "objtype", "objname", "reftype", "refname",
|
||||
"user"},
|
||||
{"<"},
|
||||
{"config", "*", "key", "value"},
|
||||
{">"},
|
||||
{">"},
|
||||
|
||||
{"keyframe", "*"},
|
||||
{"<"},
|
||||
{"key", "*", "name", "time", "qpos", "qvel", "act", "mpos", "mquat", "ctrl"},
|
||||
{">"},
|
||||
{">"}
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
|
||||
#include "mjcf_table.inc"
|
||||
|
||||
//---------------------------------- MJCF keywords used in attributes ------------------------------
|
||||
|
||||
@@ -1121,7 +671,8 @@ const mjMap flexeq_map[4] = {
|
||||
//---------------------------------- class mjXReader implementation --------------------------------
|
||||
|
||||
// constructor
|
||||
mjXReader::mjXReader() : schema(MJCF, nMJCF) {
|
||||
mjXReader::mjXReader()
|
||||
: schema(MJCF, nMJCF, MJCF_constraints, nMJCF_constraints) {
|
||||
readingdefaults = false;
|
||||
}
|
||||
|
||||
@@ -1541,33 +1092,16 @@ void mjXReader::Size(XMLElement* section, mjSpec* s) {
|
||||
ReadAttrInt(section, "nconmax", &s->nconmax);
|
||||
if (s->nconmax < -1) throw mjXError(section, "nconmax must be >= -1");
|
||||
|
||||
// memory/nstack and memory/njmax exclusivity is enforced by the schema
|
||||
{
|
||||
int nstack = -1;
|
||||
const bool has_nstack = ReadAttrInt(section, "nstack", &nstack);
|
||||
if (has_nstack) {
|
||||
if (s->nstack < -1) {
|
||||
throw mjXError(section, "nstack must be >= -1");
|
||||
}
|
||||
if (s->memory != -1 && nstack != -1) {
|
||||
throw mjXError(section,
|
||||
"either 'memory' and 'nstack' attribute can be specified, not both");
|
||||
}
|
||||
if (ReadAttrInt(section, "nstack", &nstack)) {
|
||||
if (nstack < -1) throw mjXError(section, "nstack must be >= -1");
|
||||
s->nstack = nstack;
|
||||
}
|
||||
}
|
||||
{
|
||||
int njmax = -1;
|
||||
const bool has_njmax = ReadAttrInt(section, "njmax", &njmax);
|
||||
if (has_njmax) {
|
||||
if (s->njmax < -1) {
|
||||
throw mjXError(section, "njmax must be >= -1");
|
||||
}
|
||||
if (s->memory != -1 && njmax != -1) {
|
||||
throw mjXError(section,
|
||||
"either 'memory' and 'njmax' attribute can be specified, not both");
|
||||
}
|
||||
s->njmax = njmax;
|
||||
}
|
||||
if (ReadAttrInt(section, "njmax", &s->njmax)) {
|
||||
if (s->njmax < -1) throw mjXError(section, "njmax must be >= -1");
|
||||
}
|
||||
|
||||
ReadAttrInt(section, "nuser_body", &s->nuser_body);
|
||||
@@ -1794,12 +1328,6 @@ void mjXReader::OneMesh(XMLElement* elem, mjsMesh* mesh, const mjVFS* vfs) {
|
||||
if (MapValue(elem, "builtin", &n, meshbuiltin_map, meshbuiltin_sz)) {
|
||||
std::vector<double> params;
|
||||
int nparams = ReadVector(elem, "params", params, text, /*required*/ true);
|
||||
if (file) {
|
||||
throw mjXError(elem, "builtin cannot be used with a mesh file");
|
||||
}
|
||||
if (!mesh->uservert->empty()) {
|
||||
throw mjXError(elem, "builtin mesh cannot be used with user vertex data");
|
||||
}
|
||||
if (mjs_makeMesh(mesh, (mjtMeshBuiltin)n, params.data(), nparams)) {
|
||||
throw mjXError(elem, "%s", mjs_getError(spec));
|
||||
}
|
||||
@@ -2166,11 +1694,8 @@ void mjXReader::OneCamera(XMLElement* elem, mjsCamera* camera) {
|
||||
}
|
||||
}
|
||||
|
||||
bool sensorsize = ReadAttr(elem, "sensorsize", 2, camera->sensor_size, text);
|
||||
bool fovy = ReadAttr(elem, "fovy", 1, &camera->fovy, text);
|
||||
if (fovy && sensorsize) {
|
||||
throw mjXError(elem, "either 'fovy' or 'sensorsize' attribute can be specified, not both");
|
||||
}
|
||||
ReadAttr(elem, "sensorsize", 2, camera->sensor_size, text);
|
||||
ReadAttr(elem, "fovy", 1, &camera->fovy, text);
|
||||
|
||||
// read userdata
|
||||
ReadVector(elem, "user", userdata, text);
|
||||
@@ -2185,7 +1710,6 @@ void mjXReader::OneCamera(XMLElement* elem, mjsCamera* camera) {
|
||||
// light element parser
|
||||
void mjXReader::OneLight(XMLElement* elem, mjsLight* light) {
|
||||
int n;
|
||||
bool has_directional = false;
|
||||
string text, name, texture, targetbody;
|
||||
|
||||
// read attributes
|
||||
@@ -2205,12 +1729,8 @@ void mjXReader::OneLight(XMLElement* elem, mjsLight* light) {
|
||||
}
|
||||
if (MapValue(elem, "directional", &n, bool_map, 2)) {
|
||||
light->type = (n == 1) ? mjLIGHT_DIRECTIONAL : mjLIGHT_SPOT;
|
||||
has_directional = true;
|
||||
}
|
||||
if (MapValue(elem, "type", &n, lighttype_map, lighttype_sz)) {
|
||||
if (has_directional) {
|
||||
throw mjXError(elem, "type and directional cannot both be defined");
|
||||
}
|
||||
light->type = (mjtLightType)n;
|
||||
}
|
||||
if (MapValue(elem, "castshadow", &n, bool_map, 2)) {
|
||||
@@ -2297,19 +1817,7 @@ void mjXReader::OneEquality(XMLElement* elem, mjsEquality* equality) {
|
||||
auto maybe_body2 = ReadAttrStr(elem, "body2");
|
||||
bool has_anchor = ReadAttr(elem, "anchor", 3, equality->data, text);
|
||||
|
||||
bool maybe_site = maybe_site1.has_value() || maybe_site2.has_value();
|
||||
bool maybe_body = maybe_body1.has_value() || maybe_body2.has_value() || has_anchor;
|
||||
|
||||
if (maybe_site && maybe_body) {
|
||||
throw mjXError(elem, "body and site semantics cannot be mixed");
|
||||
}
|
||||
|
||||
bool site_semantic = maybe_site1.has_value() && maybe_site2.has_value();
|
||||
bool body_semantic = maybe_body1.has_value() && has_anchor;
|
||||
if (site_semantic == body_semantic) {
|
||||
throw mjXError(elem, "either both body1 and anchor must be defined,"
|
||||
" or both site1 and site2 must be defined");
|
||||
}
|
||||
|
||||
if (body_semantic) {
|
||||
name1 = maybe_body1.value();
|
||||
@@ -2331,28 +1839,10 @@ void mjXReader::OneEquality(XMLElement* elem, mjsEquality* equality) {
|
||||
auto maybe_body1 = ReadAttrStr(elem, "body1");
|
||||
auto maybe_body2 = ReadAttrStr(elem, "body2");
|
||||
bool has_anchor = ReadAttr(elem, "anchor", 3, equality->data, text);
|
||||
bool has_relpose = ReadAttr(elem, "relpose", 7, equality->data+3, text);
|
||||
ReadAttr(elem, "relpose", 7, equality->data+3, text);
|
||||
|
||||
bool maybe_site = maybe_site1.has_value() || maybe_site2.has_value();
|
||||
bool maybe_body = maybe_body1.has_value() ||
|
||||
maybe_body2.has_value() ||
|
||||
has_anchor ||
|
||||
has_relpose;
|
||||
|
||||
if (maybe_site && maybe_body) {
|
||||
throw mjXError(elem, "body and site semantics cannot be mixed");
|
||||
}
|
||||
|
||||
bool site_semantic = maybe_site1.has_value() && maybe_site2.has_value();
|
||||
bool body_semantic = maybe_body1.has_value();
|
||||
|
||||
if (site_semantic == body_semantic) {
|
||||
throw mjXError(
|
||||
elem,
|
||||
"either body1 must be defined and optionally {body2, anchor, relpose},"
|
||||
" or site1 and site2 must be defined");
|
||||
}
|
||||
|
||||
if (body_semantic) {
|
||||
name1 = maybe_body1.value();
|
||||
if (maybe_body2.has_value()) {
|
||||
@@ -2496,42 +1986,30 @@ void mjXReader::OneActuator(XMLElement* elem, mjsActuator* actuator) {
|
||||
ReadAttr(elem, "armature", 1, &actuator->armature, text, false, false);
|
||||
|
||||
// transmission target and type
|
||||
int cnt = 0;
|
||||
if (ReadAttrTxt(elem, "joint", target)) {
|
||||
mjs_setString(actuator->target, target.c_str());
|
||||
actuator->trntype = mjTRN_JOINT;
|
||||
cnt++;
|
||||
}
|
||||
if (ReadAttrTxt(elem, "jointinparent", target)) {
|
||||
mjs_setString(actuator->target, target.c_str());
|
||||
actuator->trntype = mjTRN_JOINTINPARENT;
|
||||
cnt++;
|
||||
}
|
||||
if (ReadAttrTxt(elem, "tendon", target)) {
|
||||
mjs_setString(actuator->target, target.c_str());
|
||||
actuator->trntype = mjTRN_TENDON;
|
||||
cnt++;
|
||||
}
|
||||
if (ReadAttrTxt(elem, "cranksite", target)) {
|
||||
mjs_setString(actuator->target, target.c_str());
|
||||
actuator->trntype = mjTRN_SLIDERCRANK;
|
||||
cnt++;
|
||||
}
|
||||
if (ReadAttrTxt(elem, "site", target)) {
|
||||
mjs_setString(actuator->target, target.c_str());
|
||||
actuator->trntype = mjTRN_SITE;
|
||||
cnt++;
|
||||
}
|
||||
if (ReadAttrTxt(elem, "body", target)) {
|
||||
mjs_setString(actuator->target, target.c_str());
|
||||
actuator->trntype = mjTRN_BODY;
|
||||
cnt++;
|
||||
}
|
||||
// check for repeated transmission
|
||||
if (cnt > 1) {
|
||||
throw mjXError(elem, "actuator can have at most one of transmission target");
|
||||
}
|
||||
|
||||
// slidercrank-specific parameters
|
||||
int r1 = ReadAttr(elem, "cranklength", 1, &actuator->cranklength, text);
|
||||
int r2 = ReadAttrTxt(elem, "slidersite", slidersite);
|
||||
@@ -3843,11 +3321,8 @@ void mjXReader::Body(XMLElement* section, mjsBody* body, mjsFrame* frame,
|
||||
ReadQuat(elem, "quat", body->iquat, text);
|
||||
ReadAttr(elem, "mass", 1, &body->mass, text, true);
|
||||
ReadAttr(elem, "diaginertia", 3, body->inertia, text);
|
||||
bool alt = ReadAlternative(elem, body->ialt);
|
||||
bool full = ReadAttr(elem, "fullinertia", 6, body->fullinertia, text);
|
||||
if (alt && full) {
|
||||
throw mjXError(elem, "fullinertia and inertial orientation cannot both be specified");
|
||||
}
|
||||
ReadAlternative(elem, body->ialt);
|
||||
ReadAttr(elem, "fullinertia", 6, body->fullinertia, text);
|
||||
}
|
||||
|
||||
// joint sub-element
|
||||
@@ -4100,9 +3575,6 @@ void mjXReader::Body(XMLElement* section, mjsBody* body, mjsFrame* frame,
|
||||
bool has_frame = ReadAttrTxt(elem, "frame", child_name, /*required=*/false);
|
||||
ReadAttrTxt(elem, "prefix", prefix, /*required=*/true);
|
||||
|
||||
if (has_body && has_frame) {
|
||||
throw mjXError(elem, "only one of body or frame can be specified in attach");
|
||||
}
|
||||
mjtObj type = mjOBJ_UNKNOWN;
|
||||
if (has_body) type = mjOBJ_BODY;
|
||||
else if (has_frame) type = mjOBJ_FRAME;
|
||||
@@ -4444,10 +3916,7 @@ void mjXReader::Sensor(XMLElement* section) {
|
||||
} else if (type == "rangefinder") {
|
||||
sensor->type = mjSENS_RANGEFINDER;
|
||||
bool use_site = ReadAttrTxt(elem, "site", objname, false);
|
||||
bool use_camera = ReadAttrTxt(elem, "camera", objname, false);
|
||||
if (use_site == use_camera) {
|
||||
throw mjXError(elem, "rangefinder requires exactly one of 'site' or 'camera'");
|
||||
}
|
||||
ReadAttrTxt(elem, "camera", objname, false);
|
||||
sensor->objtype = use_site ? mjOBJ_SITE : mjOBJ_CAMERA;
|
||||
|
||||
// process data specification (intprm[0])
|
||||
@@ -4559,8 +4028,6 @@ void mjXReader::Sensor(XMLElement* section) {
|
||||
if (ReadAttrTxt(elem, "reftype", text)) {
|
||||
sensor->reftype = (mjtObj)mju_str2Type(text.c_str());
|
||||
ReadAttrTxt(elem, "refname", refname, true);
|
||||
} else if (ReadAttrTxt(elem, "refname", text)) {
|
||||
throw mjXError(elem, "refname '%s' given but reftype is missing", text.c_str());
|
||||
}
|
||||
} else if (type == "framequat") {
|
||||
sensor->type = mjSENS_FRAMEQUAT;
|
||||
@@ -4570,8 +4037,6 @@ void mjXReader::Sensor(XMLElement* section) {
|
||||
if (ReadAttrTxt(elem, "reftype", text)) {
|
||||
sensor->reftype = (mjtObj)mju_str2Type(text.c_str());
|
||||
ReadAttrTxt(elem, "refname", refname, true);
|
||||
} else if (ReadAttrTxt(elem, "refname", text)) {
|
||||
throw mjXError(elem, "refname '%s' given but reftype is missing", text.c_str());
|
||||
}
|
||||
} else if (type == "framexaxis") {
|
||||
sensor->type = mjSENS_FRAMEXAXIS;
|
||||
@@ -4581,8 +4046,6 @@ void mjXReader::Sensor(XMLElement* section) {
|
||||
if (ReadAttrTxt(elem, "reftype", text)) {
|
||||
sensor->reftype = (mjtObj)mju_str2Type(text.c_str());
|
||||
ReadAttrTxt(elem, "refname", refname, true);
|
||||
} else if (ReadAttrTxt(elem, "refname", text)) {
|
||||
throw mjXError(elem, "refname '%s' given but reftype is missing", text.c_str());
|
||||
}
|
||||
} else if (type == "frameyaxis") {
|
||||
sensor->type = mjSENS_FRAMEYAXIS;
|
||||
@@ -4592,8 +4055,6 @@ void mjXReader::Sensor(XMLElement* section) {
|
||||
if (ReadAttrTxt(elem, "reftype", text)) {
|
||||
sensor->reftype = (mjtObj)mju_str2Type(text.c_str());
|
||||
ReadAttrTxt(elem, "refname", refname, true);
|
||||
} else if (ReadAttrTxt(elem, "refname", text)) {
|
||||
throw mjXError(elem, "refname '%s' given but reftype is missing", text.c_str());
|
||||
}
|
||||
} else if (type == "framezaxis") {
|
||||
sensor->type = mjSENS_FRAMEZAXIS;
|
||||
@@ -4603,8 +4064,6 @@ void mjXReader::Sensor(XMLElement* section) {
|
||||
if (ReadAttrTxt(elem, "reftype", text)) {
|
||||
sensor->reftype = (mjtObj)mju_str2Type(text.c_str());
|
||||
ReadAttrTxt(elem, "refname", refname, true);
|
||||
} else if (ReadAttrTxt(elem, "refname", text)) {
|
||||
throw mjXError(elem, "refname '%s' given but reftype is missing", text.c_str());
|
||||
}
|
||||
} else if (type == "framelinvel") {
|
||||
sensor->type = mjSENS_FRAMELINVEL;
|
||||
@@ -4614,8 +4073,6 @@ void mjXReader::Sensor(XMLElement* section) {
|
||||
if (ReadAttrTxt(elem, "reftype", text)) {
|
||||
sensor->reftype = (mjtObj)mju_str2Type(text.c_str());
|
||||
ReadAttrTxt(elem, "refname", refname, true);
|
||||
} else if (ReadAttrTxt(elem, "refname", text)) {
|
||||
throw mjXError(elem, "refname '%s' given but reftype is missing", text.c_str());
|
||||
}
|
||||
} else if (type == "frameangvel") {
|
||||
sensor->type = mjSENS_FRAMEANGVEL;
|
||||
@@ -4625,8 +4082,6 @@ void mjXReader::Sensor(XMLElement* section) {
|
||||
if (ReadAttrTxt(elem, "reftype", text)) {
|
||||
sensor->reftype = (mjtObj)mju_str2Type(text.c_str());
|
||||
ReadAttrTxt(elem, "refname", refname, true);
|
||||
} else if (ReadAttrTxt(elem, "refname", text)) {
|
||||
throw mjXError(elem, "refname '%s' given but reftype is missing", text.c_str());
|
||||
}
|
||||
} else if (type == "framelinacc") {
|
||||
sensor->type = mjSENS_FRAMELINACC;
|
||||
@@ -4665,16 +4120,10 @@ void mjXReader::Sensor(XMLElement* section) {
|
||||
// sensors for geometric distance; attached to geoms or bodies
|
||||
else if (type == "distance" || type == "normal" || type == "fromto") {
|
||||
bool has_body1 = ReadAttrTxt(elem, "body1", objname);
|
||||
bool has_geom1 = ReadAttrTxt(elem, "geom1", objname);
|
||||
if (has_body1 == has_geom1) {
|
||||
throw mjXError(elem, "exactly one of (geom1, body1) must be specified");
|
||||
}
|
||||
ReadAttrTxt(elem, "geom1", objname);
|
||||
sensor->objtype = has_body1 ? mjOBJ_BODY : mjOBJ_GEOM;
|
||||
bool has_body2 = ReadAttrTxt(elem, "body2", refname);
|
||||
bool has_geom2 = ReadAttrTxt(elem, "geom2", refname);
|
||||
if (has_body2 == has_geom2) {
|
||||
throw mjXError(elem, "exactly one of (geom2, body2) must be specified");
|
||||
}
|
||||
ReadAttrTxt(elem, "geom2", refname);
|
||||
sensor->reftype = has_body2 ? mjOBJ_BODY : mjOBJ_GEOM;
|
||||
if (type == "distance") {
|
||||
sensor->type = mjSENS_GEOMDIST;
|
||||
@@ -4692,9 +4141,6 @@ void mjXReader::Sensor(XMLElement* section) {
|
||||
bool has_body1 = ReadAttrTxt(elem, "body1", objname);
|
||||
bool has_subtree1 = ReadAttrTxt(elem, "subtree1", objname);
|
||||
bool has_geom1 = ReadAttrTxt(elem, "geom1", objname);
|
||||
if (has_site + has_body1 + has_subtree1 + has_geom1 > 1) {
|
||||
throw mjXError(elem, "at most one of (geom1, body1, subtree1, site) can be specified");
|
||||
}
|
||||
if (has_site) { sensor->objtype = mjOBJ_SITE; }
|
||||
else if (has_body1) { sensor->objtype = mjOBJ_BODY; }
|
||||
else if (has_subtree1) { sensor->objtype = mjOBJ_XBODY; }
|
||||
@@ -4705,9 +4151,6 @@ void mjXReader::Sensor(XMLElement* section) {
|
||||
bool has_body2 = ReadAttrTxt(elem, "body2", refname);
|
||||
bool has_subtree2 = ReadAttrTxt(elem, "subtree2", refname);
|
||||
bool has_geom2 = ReadAttrTxt(elem, "geom2", refname);
|
||||
if (has_body2 + has_subtree2 + has_geom2 > 1) {
|
||||
throw mjXError(elem, "at most one of (geom2, body2, subtree2) can be specified");
|
||||
}
|
||||
if (has_body2) { sensor->reftype = mjOBJ_BODY; }
|
||||
else if (has_subtree2) { sensor->reftype = mjOBJ_XBODY; }
|
||||
else if (has_geom2) { sensor->reftype = mjOBJ_GEOM; }
|
||||
@@ -4767,14 +4210,9 @@ void mjXReader::Sensor(XMLElement* section) {
|
||||
// user-defined sensor
|
||||
else if (type == "user") {
|
||||
sensor->type = mjSENS_USER;
|
||||
bool objname_given = ReadAttrTxt(elem, "objname", objname);
|
||||
ReadAttrTxt(elem, "objname", objname);
|
||||
if (ReadAttrTxt(elem, "objtype", text)) {
|
||||
if (!objname_given) {
|
||||
throw mjXError(elem, "objtype '%s' given but objname is missing", text.c_str());
|
||||
}
|
||||
sensor->objtype = (mjtObj)mju_str2Type(text.c_str());
|
||||
} else if (objname_given) {
|
||||
throw mjXError(elem, "objname '%s' given but objtype is missing", objname.c_str());
|
||||
}
|
||||
ReadAttrInt(elem, "dim", &sensor->dim, true);
|
||||
|
||||
|
||||
@@ -101,8 +101,10 @@ class mjXReader : public mjXBase {
|
||||
mujoco::user::FilePath texturedir_;
|
||||
};
|
||||
|
||||
// MJCF schema
|
||||
#define nMJCF 252
|
||||
extern std::vector<const char*> MJCF[nMJCF];
|
||||
// MJCF schema table, generated from mjcf.schema into mjcf_table.inc
|
||||
extern const int nMJCF;
|
||||
extern std::vector<const char*> MJCF[];
|
||||
extern const mjXConstraintDef MJCF_constraints[];
|
||||
extern const int nMJCF_constraints;
|
||||
|
||||
#endif // MUJOCO_SRC_XML_XML_NATIVE_READER_H_
|
||||
|
||||
+113
-2
@@ -333,11 +333,20 @@ XMLElement* NextSiblingElement(XMLElement* e, const char* name) {
|
||||
}
|
||||
|
||||
// constructor
|
||||
mjXSchema::mjXSchema(std::vector<const char*> schema[], unsigned nrow) {
|
||||
mjXSchema::mjXSchema(std::vector<const char*> schema[], unsigned nrow,
|
||||
const mjXConstraintDef* constraints, int nconstraint,
|
||||
int first_row) {
|
||||
// set name and type
|
||||
name_ = schema[0][0];
|
||||
type_ = schema[0][1][0];
|
||||
|
||||
// adopt the presence constraints declared for this row
|
||||
for (int i = 0; i < nconstraint; i++) {
|
||||
if (constraints[i].row == first_row) {
|
||||
constraints_.push_back(&constraints[i]);
|
||||
}
|
||||
}
|
||||
|
||||
// set attributes
|
||||
int nattr = schema[0].size() - 2;
|
||||
for (int i = 0; i < nattr; i++) {
|
||||
@@ -370,7 +379,8 @@ mjXSchema::mjXSchema(std::vector<const char*> schema[], unsigned nrow) {
|
||||
}
|
||||
|
||||
// add child element
|
||||
subschema_.emplace_back(schema+start, end-start+1);
|
||||
subschema_.emplace_back(schema+start, end-start+1, constraints,
|
||||
nconstraint, first_row+start);
|
||||
|
||||
// proceed with next subelement
|
||||
start = end+1;
|
||||
@@ -380,6 +390,102 @@ mjXSchema::mjXSchema(std::vector<const char*> schema[], unsigned nrow) {
|
||||
|
||||
|
||||
|
||||
// quoted list of constraint bundles: 'a' or ('a', 'b'), comma-joined
|
||||
static std::string BundleList(const std::vector<std::vector<std::string>>& bundles) {
|
||||
std::string out;
|
||||
for (size_t i = 0; i < bundles.size(); i++) {
|
||||
if (i) {
|
||||
out += ", ";
|
||||
}
|
||||
if (bundles[i].size() == 1) {
|
||||
out += "'" + bundles[i][0] + "'";
|
||||
} else {
|
||||
out += '(';
|
||||
for (size_t j = 0; j < bundles[i].size(); j++) {
|
||||
out += (j ? ", '" : "'") + bundles[i][j] + "'";
|
||||
}
|
||||
out += ')';
|
||||
}
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// enforce the presence constraints declared for this element
|
||||
XMLElement* mjXSchema::CheckConstraints(XMLElement* elem) {
|
||||
for (const mjXConstraintDef* con : constraints_) {
|
||||
// split the spec into bundles of attribute names
|
||||
std::vector<std::vector<std::string>> bundles(1);
|
||||
std::string token;
|
||||
for (const char* c = con->spec;; c++) {
|
||||
if (*c == ' ' || *c == '|' || *c == '\0') {
|
||||
if (!token.empty()) {
|
||||
bundles.back().push_back(token);
|
||||
token.clear();
|
||||
}
|
||||
if (*c == '|') {
|
||||
bundles.emplace_back();
|
||||
}
|
||||
if (*c == '\0') {
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
token += *c;
|
||||
}
|
||||
}
|
||||
|
||||
// per-bundle presence: any member present / all members present
|
||||
int n_any = 0, n_all = 0, n_attr = 0, n_present = 0;
|
||||
for (const auto& bundle : bundles) {
|
||||
bool any = false, all = true;
|
||||
for (const std::string& attr : bundle) {
|
||||
bool present = elem->Attribute(attr.c_str()) != nullptr;
|
||||
any |= present;
|
||||
all &= present;
|
||||
n_attr++;
|
||||
n_present += present;
|
||||
}
|
||||
n_any += any;
|
||||
n_all += all;
|
||||
}
|
||||
|
||||
switch (con->kind) {
|
||||
case 'e': // at most one bundle may be present
|
||||
if (n_any > 1) {
|
||||
error = "at most one of " + BundleList(bundles) +
|
||||
" can be specified";
|
||||
return elem;
|
||||
}
|
||||
break;
|
||||
case 't': // all listed attributes appear together or not at all
|
||||
if (n_present != 0 && n_present != n_attr) {
|
||||
error = "attributes " + BundleList(bundles) +
|
||||
" must be specified together";
|
||||
return elem;
|
||||
}
|
||||
break;
|
||||
case 'r': // first attribute requires the second
|
||||
if (n_any && elem->Attribute(bundles[0][0].c_str()) &&
|
||||
!elem->Attribute(bundles[1][0].c_str())) {
|
||||
error = "attribute '" + bundles[0][0] + "' requires attribute '" +
|
||||
bundles[1][0] + "'";
|
||||
return elem;
|
||||
}
|
||||
break;
|
||||
case 'o': // at least one bundle must be complete
|
||||
if (n_all == 0) {
|
||||
error = "one of " + BundleList(bundles) + " must be specified";
|
||||
return elem;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// get pointer to error message
|
||||
std::string mjXSchema::GetError() {
|
||||
return error;
|
||||
@@ -525,6 +631,11 @@ XMLElement* mjXSchema::Check(XMLElement* elem, int level) {
|
||||
}
|
||||
}
|
||||
|
||||
// check presence constraints
|
||||
if ((bad = CheckConstraints(elem))) {
|
||||
return bad;
|
||||
}
|
||||
|
||||
// handle recursion
|
||||
if (type_ == 'R') {
|
||||
// check child elements with same name
|
||||
|
||||
+19
-1
@@ -49,10 +49,25 @@ class [[nodiscard]] mjXError {
|
||||
};
|
||||
|
||||
|
||||
// presence constraint over an element's attributes, generated from the
|
||||
// schema into the grammar table's companion array. spec holds attribute
|
||||
// bundles, space-joined within a bundle and '|'-separated between them;
|
||||
// kind: e=exclusive (at most one bundle present), t=together (all or
|
||||
// none), r=requires (first needs second), o=oneof (at least one bundle
|
||||
// complete).
|
||||
struct mjXConstraintDef {
|
||||
int row; // index of the element's row in the grammar table
|
||||
char kind;
|
||||
const char* spec;
|
||||
};
|
||||
|
||||
|
||||
// Custom XML file validation
|
||||
class mjXSchema {
|
||||
public:
|
||||
mjXSchema(std::vector<const char*> schema[], unsigned nrow);
|
||||
mjXSchema(std::vector<const char*> schema[], unsigned nrow,
|
||||
const mjXConstraintDef* constraints = nullptr,
|
||||
int nconstraint = 0, int first_row = 0);
|
||||
|
||||
std::string GetError(); // return error
|
||||
void Print(std::stringstream& str, int level) const; // print schema
|
||||
@@ -67,6 +82,9 @@ class mjXSchema {
|
||||
std::set<std::string> attr_; // allowed attributes
|
||||
std::vector<mjXSchema> subschema_; // allowed child elements
|
||||
|
||||
std::vector<const mjXConstraintDef*> constraints_; // constraints here
|
||||
tinyxml2::XMLElement* CheckConstraints(tinyxml2::XMLElement* elem);
|
||||
|
||||
int refcnt_ = 0; // refcount used for validation
|
||||
std::string error; // error from constructor or Check
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user