diff --git a/doc/APIreference/APIglobals.rst b/doc/APIreference/APIglobals.rst index 5f6d824f..e237d907 100644 --- a/doc/APIreference/APIglobals.rst +++ b/doc/APIreference/APIglobals.rst @@ -444,6 +444,10 @@ shown in the table below. Their names are in the format ``mjKEY_XXX``. They corr - 5 - The maximal number of real-valued parameters used to define the impedance of each scalar constraint. Determines the size of all ``mjModel.XXX_solimp`` fields. + * - ``mjNSENS`` + - 2 + - The number of sensor parameters. + Determines the size of ``mjModel.sensor_intprm``. * - ``mjNSOLVER`` - 200 - The number of iterations where solver statistics can be stored in ``mjData.solver``. This array is used diff --git a/doc/includes/references.h b/doc/includes/references.h index 3fc2d13d..894cf25b 100644 --- a/doc/includes/references.h +++ b/doc/includes/references.h @@ -1458,6 +1458,7 @@ struct mjModel_ { int* sensor_objid; // id of sensorized object (nsensor x 1) int* sensor_reftype; // type of reference frame (mjtObj) (nsensor x 1) int* sensor_refid; // id of reference frame; -1: global frame (nsensor x 1) + int* sensor_intprm; // sensor parameters (nsensor x mjNSENS) int* sensor_dim; // number of scalar outputs (nsensor x 1) int* sensor_adr; // address in sensor array (nsensor x 1) mjtNum* sensor_cutoff; // cutoff for real and positive; 0: ignore (nsensor x 1) @@ -2324,6 +2325,7 @@ typedef struct mjsSensor_ { // sensor specification mjString* objname; // name of sensorized object mjtObj reftype; // type of referenced object mjString* refname; // name of referenced object + int intprm[mjNSENS]; // integer parameters // user-defined sensors mjtDataType datatype; // data type for sensor measurement diff --git a/include/mujoco/mjmodel.h b/include/mujoco/mjmodel.h index f7b94b90..c92edd75 100644 --- a/include/mujoco/mjmodel.h +++ b/include/mujoco/mjmodel.h @@ -41,6 +41,7 @@ #define mjNFLUID 12 // number of fluid interaction parameters #define mjNREF 2 // number of solver reference parameters #define mjNIMP 5 // number of solver impedance parameters +#define mjNSENS 2 // number of sensor parameters #define mjNSOLVER 200 // size of one mjData.solver array #define mjNISLAND 20 // number of mjData.solver arrays @@ -1130,6 +1131,7 @@ struct mjModel_ { int* sensor_objid; // id of sensorized object (nsensor x 1) int* sensor_reftype; // type of reference frame (mjtObj) (nsensor x 1) int* sensor_refid; // id of reference frame; -1: global frame (nsensor x 1) + int* sensor_intprm; // sensor parameters (nsensor x mjNSENS) int* sensor_dim; // number of scalar outputs (nsensor x 1) int* sensor_adr; // address in sensor array (nsensor x 1) mjtNum* sensor_cutoff; // cutoff for real and positive; 0: ignore (nsensor x 1) diff --git a/include/mujoco/mjspec.h b/include/mujoco/mjspec.h index 2d98c1bd..138b1937 100644 --- a/include/mujoco/mjspec.h +++ b/include/mujoco/mjspec.h @@ -692,6 +692,7 @@ typedef struct mjsSensor_ { // sensor specification mjString* objname; // name of sensorized object mjtObj reftype; // type of referenced object mjString* refname; // name of referenced object + int intprm[mjNSENS]; // integer parameters // user-defined sensors mjtDataType datatype; // data type for sensor measurement diff --git a/include/mujoco/mjxmacro.h b/include/mujoco/mjxmacro.h index 3da0df54..68032375 100644 --- a/include/mujoco/mjxmacro.h +++ b/include/mujoco/mjxmacro.h @@ -540,6 +540,7 @@ X ( int, sensor_objid, nsensor, 1 ) \ X ( int, sensor_reftype, nsensor, 1 ) \ X ( int, sensor_refid, nsensor, 1 ) \ + X ( int, sensor_intprm, nsensor, mjNSENS ) \ X ( int, sensor_dim, nsensor, 1 ) \ X ( int, sensor_adr, nsensor, 1 ) \ X ( mjtNum, sensor_cutoff, nsensor, 1 ) \ diff --git a/python/mujoco/introspect/structs.py b/python/mujoco/introspect/structs.py index bde6a25d..a969052b 100644 --- a/python/mujoco/introspect/structs.py +++ b/python/mujoco/introspect/structs.py @@ -4149,6 +4149,14 @@ STRUCTS: Mapping[str, StructDecl] = dict([ doc='id of reference frame; -1: global frame', array_extent=('nsensor',), ), + StructFieldDecl( + name='sensor_intprm', + type=PointerType( + inner_type=ValueType(name='int'), + ), + doc='sensor parameters', + array_extent=('nsensor', 'mjNSENS'), + ), StructFieldDecl( name='sensor_dim', type=PointerType( @@ -10388,6 +10396,14 @@ STRUCTS: Mapping[str, StructDecl] = dict([ ), doc='name of referenced object', ), + StructFieldDecl( + name='intprm', + type=ArrayType( + inner_type=ValueType(name='int'), + extents=(2,), + ), + doc='integer parameters', + ), StructFieldDecl( name='datatype', type=ValueType(name='mjtDataType'), diff --git a/src/user/user_model.cc b/src/user/user_model.cc index a1b358ac..5a9ae0ba 100644 --- a/src/user/user_model.cc +++ b/src/user/user_model.cc @@ -3454,6 +3454,7 @@ void mjCModel::CopyObjects(mjModel* m) { m->sensor_objid[i] = psen->obj ? psen->obj->id : -1; m->sensor_reftype[i] = psen->reftype; m->sensor_refid[i] = psen->ref ? psen->ref->id : -1; + mjuu_copyvec(m->sensor_intprm+i*mjNSENS, psen->intprm, mjNSENS); m->sensor_dim[i] = psen->dim; m->sensor_cutoff[i] = (mjtNum)psen->cutoff; m->sensor_noise[i] = (mjtNum)psen->noise; diff --git a/test/engine/engine_sensor_test.cc b/test/engine/engine_sensor_test.cc index b81feb66..b6c8faa1 100644 --- a/test/engine/engine_sensor_test.cc +++ b/test/engine/engine_sensor_test.cc @@ -544,7 +544,37 @@ TEST_F(SensorTest, Clock) { mj_deleteModel(model); } -// test clock sensor +// test that integer parameters pass through +TEST_F(SensorTest, IntPrm) { + constexpr char xml[] = R"( + + + + + + )"; + ASSERT_EQ(mjNSENS, 2); + + char err[1024]; + mjSpec* spec = mj_parseXMLString(xml, 0, err, sizeof(err)); + ASSERT_THAT(spec, NotNull()) << err; + + mjModel* model = mj_compile(spec, nullptr); + EXPECT_EQ(model->sensor_intprm[0], 0); + EXPECT_EQ(model->sensor_intprm[1], 0); + mj_deleteModel(model); + + mjsSensor* s = mjs_asSensor(mjs_findElement(spec, mjOBJ_SENSOR, "dummy")); + s->intprm[0] = 3; + s->intprm[1] = 4; + model = mj_compile(spec, nullptr); + EXPECT_EQ(model->sensor_intprm[0], 3); + EXPECT_EQ(model->sensor_intprm[1], 4); + mj_deleteModel(model); + mj_deleteSpec(spec); +} + +// test sequential collision sensors TEST_F(SensorTest, CollisionSequential) { constexpr char xml[] = R"( diff --git a/unity/Runtime/Bindings/MjBindings.cs b/unity/Runtime/Bindings/MjBindings.cs index ba5f8b23..2c540d15 100644 --- a/unity/Runtime/Bindings/MjBindings.cs +++ b/unity/Runtime/Bindings/MjBindings.cs @@ -49,6 +49,7 @@ public const int mjNBIAS = 10; public const int mjNFLUID = 12; public const int mjNREF = 2; public const int mjNIMP = 5; +public const int mjNSENS = 2; public const int mjNSOLVER = 200; public const int mjNISLAND = 20; public const bool THIRD_PARTY_MUJOCO_INCLUDE_MJPLUGIN_H_ = true; @@ -5683,6 +5684,7 @@ public unsafe struct mjModel_ { public int* sensor_objid; public int* sensor_reftype; public int* sensor_refid; + public int* sensor_intprm; public int* sensor_dim; public int* sensor_adr; public double* sensor_cutoff;