Skip to content

Commit 47ebfe4

Browse files
thowellcopybara-github
authored andcommitted
Update schema.xml from generated schema to include tactile cutoff attribute.
PiperOrigin-RevId: 973076751 Change-Id: Ief7bb0c1c2515f4c55a79d7d685cfb3a914cc21f
1 parent b1d64f4 commit 47ebfe4

9 files changed

Lines changed: 72 additions & 3 deletions

File tree

doc/XMLreference.rst

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9035,6 +9035,8 @@ visualization of contact points.
90359035

90369036
.. _sensor-tactile-name:
90379037

9038+
.. _sensor-tactile-cutoff:
9039+
90389040
.. _sensor-tactile-nsample:
90399041

90409042
.. _sensor-tactile-interp:
@@ -9045,7 +9047,7 @@ visualization of contact points.
90459047

90469048
.. _sensor-tactile-user:
90479049

9048-
:at:`name`, :at:`nsample`, :at:`interval`, :at:`delay`, :at:`user`:
9050+
:at:`name`, :at:`cutoff`, :at:`nsample`, :at:`interval`, :at:`delay`, :at:`user`:
90499051
See :ref:`CSensor`.
90509052

90519053
.. _sensor-e_potential:

doc/XMLschema.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5099,6 +5099,9 @@
50995099
.. grid-item::
51005100
:ref:`interval<sensor-tactile-interval>`
51015101

5102+
.. grid-item::
5103+
:ref:`cutoff<sensor-tactile-cutoff>`
5104+
51025105
.. grid-item::
51035106
:ref:`user<sensor-tactile-user>`
51045107

doc/changelog.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ Compiler
2323
- Custom text fields (:ref:`custom/text<custom-text>`) in MJCF now accept their values inside a ``<![CDATA[ ... ]]>``
2424
block in addition to the ``data`` attribute. When saving a model via :ref:`mj_saveXML`, custom text containing
2525
newlines or XML characters is exported as CDATA.
26+
- Added :ref:`cutoff<sensor-tactile-cutoff>` attribute to :ref:`sensor/tactile<sensor-tactile>`.
2627

2728
Samples
2829
^^^^^^^

src/xml/generated/dmcontrol_schema.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3159,6 +3159,7 @@
31593159
<attribute name="interp" type="keyword" valid_values="zoh linear cubic"/>
31603160
<attribute name="delay" type="float"/>
31613161
<attribute name="interval" type="array" array_type="float" array_size="2"/>
3162+
<attribute name="cutoff" type="float"/>
31623163
<attribute name="user" type="array" array_type="float"/>
31633164
</attributes>
31643165
</element>

src/xml/generated/mjcf.xsd

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3770,6 +3770,7 @@
37703770
<xs:attribute name="interp" type="kw_interp"/>
37713771
<xs:attribute name="delay" type="xs:double"/>
37723772
<xs:attribute name="interval" type="double1to2"/>
3773+
<xs:attribute name="cutoff" type="xs:double"/>
37733774
<xs:attribute name="user" type="doublelist"/>
37743775
</xs:complexType>
37753776

src/xml/generated/mjcf_table.inc

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -461,7 +461,8 @@ std::vector<const char*> MJCF[] = {
461461
{"e_kinetic", "*", "name", "nsample", "interp", "delay", "interval", "cutoff", "noise",
462462
"user"},
463463
{"clock", "*", "name", "nsample", "interp", "delay", "interval", "cutoff", "noise", "user"},
464-
{"tactile", "*", "name", "geom", "mesh", "nsample", "interp", "delay", "interval", "user"},
464+
{"tactile", "*", "name", "geom", "mesh", "nsample", "interp", "delay", "interval",
465+
"cutoff", "user"},
465466
{"user", "*", "name", "objtype", "objname", "datatype", "needstage", "dim", "cutoff",
466467
"noise", "user"},
467468
{"plugin", "*", "name", "plugin", "instance", "cutoff", "objtype", "objname", "reftype",

src/xml/mjcf.schema

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2115,6 +2115,7 @@ element tactile : mjsSensor {
21152115
interp : enum<interp>
21162116
delay : double
21172117
interval : double[1..2]
2118+
cutoff : double
21182119
user : double[]
21192120
}
21202121

src/xml/xml_native_writer.cc

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2192,7 +2192,9 @@ void mjXWriter::Sensor(XMLElement* root) {
21922192
// write name, noise, userdata
21932193
WriteAttrTxt(elem, "name", sensor->name);
21942194
WriteAttr(elem, "cutoff", 1, &sensor->cutoff, &zero);
2195-
if (sensor->type != mjSENS_PLUGIN) { WriteAttr(elem, "noise", 1, &sensor->noise, &zero); }
2195+
if (sensor->type != mjSENS_PLUGIN && sensor->type != mjSENS_TACTILE) {
2196+
WriteAttr(elem, "noise", 1, &sensor->noise, &zero);
2197+
}
21962198
WriteAttrInt(elem, "nsample", sensor->nsample, 0);
21972199
WriteAttrKey(elem, "interp", interp_map, interp_sz, sensor->interp, 0);
21982200
WriteAttr(elem, "delay", 1, &sensor->delay, &zero);

test/engine/engine_sensor_test.cc

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1801,6 +1801,63 @@ TEST_F(SensorTest, TactileSkipTangents) {
18011801
EXPECT_EQ(nonzero_count, 2) << "Expected 2 taxels in contact";
18021802
}
18031803

1804+
// Test tactile sensor cutoff attribute, engine clamping, and round-trip XML save/load
1805+
TEST_F(SensorTest, TactileCutoff) {
1806+
constexpr char xml[] = R"(
1807+
<mujoco>
1808+
<option>
1809+
<flag multiccd="enable"/>
1810+
</option>
1811+
<asset>
1812+
<mesh name="sensor_mesh" builtin="sphere" params="0"/>
1813+
</asset>
1814+
<worldbody>
1815+
<body pos="0 0 1">
1816+
<freejoint/>
1817+
<geom name="sensor_geom" type="mesh" mesh="sensor_mesh"/>
1818+
</body>
1819+
<body>
1820+
<geom type="box" size=".7 .7 .3"/>
1821+
</body>
1822+
</worldbody>
1823+
<sensor>
1824+
<tactile geom="sensor_geom" mesh="sensor_mesh" cutoff="0.05"/>
1825+
</sensor>
1826+
</mujoco>
1827+
)";
1828+
char error[1024];
1829+
MjModelPtr model = LoadModelFromString(xml, error, sizeof(error));
1830+
ASSERT_THAT(model.get(), NotNull()) << error;
1831+
ASSERT_GT(model->nsensordata, 0) << "No sensor data allocated";
1832+
EXPECT_MJTNUM_EQ(model->sensor_cutoff[0], 0.05);
1833+
1834+
MjDataPtr data = MakeData(model);
1835+
1836+
// Compute collisions and sensors at t=0
1837+
mj_forward(model.get(), data.get());
1838+
1839+
int ntaxel = model->nsensordata / 3;
1840+
int nonzero_count = 0;
1841+
for (int i = 0; i < ntaxel; i++) {
1842+
if (data->sensordata[i] != 0) {
1843+
nonzero_count++;
1844+
// Without cutoff, penetration is ~0.2; with cutoff=0.05, it must be clamped to 0.05
1845+
EXPECT_NEAR(data->sensordata[i], 0.05, MjTol(1e-6, 1e-4))
1846+
<< "Penetration depth at taxel " << i << " should be clamped to cutoff";
1847+
}
1848+
}
1849+
EXPECT_EQ(nonzero_count, 2) << "Expected 2 taxels in contact";
1850+
1851+
// Verify XML round-trip preserves cutoff without schema errors
1852+
std::string saved_xml = SaveAndReadXml(model.get());
1853+
EXPECT_THAT(saved_xml, HasSubstr("cutoff=\"0.05\""));
1854+
EXPECT_THAT(saved_xml, Not(HasSubstr("noise")));
1855+
1856+
MjModelPtr reloaded = LoadModelFromString(saved_xml.c_str(), error, sizeof(error));
1857+
ASSERT_THAT(reloaded.get(), NotNull()) << error;
1858+
EXPECT_MJTNUM_EQ(reloaded->sensor_cutoff[0], 0.05);
1859+
}
1860+
18041861
// insidesite uses subtree_com for massless flex parent bodies
18051862
TEST_F(SensorTest, InsideSiteFlexBody) {
18061863
static constexpr char xml[] = R"(

0 commit comments

Comments
 (0)