Improve error reporting of sensorized objects.

Also remove duplication of element name and id from most error messages.

PiperOrigin-RevId: 628065116
Change-Id: Idd962fbab7aeba09e3a70c6c9d044b23db94cf23
This commit is contained in:
Yuval Tassa
2024-04-25 07:12:26 -07:00
committed by Copybara-Service
parent cbb048ff00
commit 027c26a153
4 changed files with 187 additions and 217 deletions
+97 -169
View File
@@ -61,7 +61,7 @@ static void checksize(double* size, mjtGeom type, mjCBase* object, const char* n
// plane: handle infinite
if (type==mjGEOM_PLANE) {
if (size[2]<=0) {
throw mjCError(object, "plane size(3) must be positive in object '%s' (id = %d)", name, id);
throw mjCError(object, "plane size(3) must be positive");
}
}
@@ -69,7 +69,7 @@ static void checksize(double* size, mjtGeom type, mjCBase* object, const char* n
else {
for (int i=0; i<mjGEOMINFO[type]; i++) {
if (size[i]<=0) {
throw mjCError(object, "sizes must be positive in object '%s' (id = %d)", name, id);
throw mjCError(object, "size %d must be positive in geom", "", i);
}
}
}
@@ -159,14 +159,14 @@ mjCError::mjCError(const mjCBase* obj, const char* msg, const char* str, int pos
mju::strcat_arr(message, temp);
}
// append info from mjCBase object
// append info from mjCBase element
if (obj) {
// with or without xml position
if (!obj->info.empty()) {
mju::sprintf_arr(temp, "Object name = %s, id = %d, %s",
mju::sprintf_arr(temp, "Element name '%s', id %d, %s",
obj->name.c_str(), obj->id, obj->info.c_str());
} else {
mju::sprintf_arr(temp, "Object name = %s, id = %d", obj->name.c_str(), obj->id);
mju::sprintf_arr(temp, "Element name '%s', id %d", obj->name.c_str(), obj->id);
}
// append to message
@@ -1244,8 +1244,7 @@ void mjCBody::Compile(void) {
// resize userdata
if (userdata_.size() > model->nuser_body) {
throw mjCError(this, "user has more values than nuser_body in body '%s' (id = %d)",
name.c_str(), id);
throw mjCError(this, "user has more values than nuser_body in body");
}
userdata_.resize(model->nuser_body);
@@ -1627,17 +1626,14 @@ int mjCJoint::Compile(void) {
// resize userdata
if (userdata_.size() > model->nuser_jnt) {
throw mjCError(this, "user has more values than nuser_jnt in joint '%s' (id = %d)",
name.c_str(), id);
throw mjCError(this, "user has more values than nuser_jnt in joint");
}
userdata_.resize(model->nuser_jnt);
// check springdamper
if (springdamper[0] || springdamper[1]) {
if (springdamper[0]<=0 || springdamper[1]<=0) {
throw mjCError(this,
"when defined, springdamper values must be positive in joint '%s' (id = %d)",
name.c_str(), id);
throw mjCError(this, "when defined, springdamper values must be positive in joint");
}
}
@@ -1655,12 +1651,10 @@ int mjCJoint::Compile(void) {
if (is_limited()) {
// check data
if (range[0]>=range[1] && type!=mjJNT_BALL) {
throw mjCError(this,
"range[0] should be smaller than range[1] in joint '%s' (id = %d)",
name.c_str(), id);
throw mjCError(this, "range[0] should be smaller than range[1] in joint");
}
if (range[0] && type==mjJNT_BALL) {
throw mjCError(this, "range[0] should be 0 in ball joint '%s' (id = %d)", name.c_str(), id);
throw mjCError(this, "range[0] should be 0 in ball joint");
}
// convert limits to radians
@@ -1688,9 +1682,7 @@ int mjCJoint::Compile(void) {
if (is_actfrclimited()) {
// check data
if (actfrcrange[0]>=actfrcrange[1]) {
throw mjCError(this,
"actfrcrange[0] should be smaller than actfrcrange[1] in joint '%s' (id = %d)",
name.c_str(), id);
throw mjCError(this, "actfrcrange[0] should be smaller than actfrcrange[1] in joint");
}
}
@@ -1714,13 +1706,12 @@ int mjCJoint::Compile(void) {
// normalize axis, check norm
if (mjuu_normvec(axis, 3)<mjEPS) {
throw mjCError(this, "axis too small in joint '%s' (id = %d)", name.c_str(), id);
throw mjCError(this, "axis too small in joint");
}
// check data
if (type==mjJNT_FREE && limited == mjLIMITED_TRUE) {
throw mjCError(this,
"limits should not be defined in free joint '%s' (id = %d)", name.c_str(), id);
throw mjCError(this, "limits should not be defined in free joint");
}
// compute local position
@@ -1851,7 +1842,7 @@ double mjCGeom::GetVolume(void) {
// get from mesh
if (type==mjGEOM_MESH || type==mjGEOM_SDF) {
if (mesh->id<0 || !((std::size_t) mesh->id <= model->meshes.size())) {
throw mjCError(this, "invalid mesh id in mesh geom '%s' (id = %d)", name.c_str(), id);
throw mjCError(this, "invalid mesh id in mesh geom");
}
return mesh->GetVolumeRef(typeinertia);
@@ -1904,7 +1895,7 @@ void mjCGeom::SetInertia(void) {
// get from mesh
if (type==mjGEOM_MESH || type==mjGEOM_SDF) {
if (mesh->id<0 || !((std::size_t) mesh->id <= model->meshes.size())) {
throw mjCError(this, "invalid mesh id in mesh geom '%s' (id = %d)", name.c_str(), id);
throw mjCError(this, "invalid mesh id in mesh geom");
}
double* boxsz = mesh->GetInertiaBoxPtr(typeinertia);
@@ -2190,12 +2181,12 @@ void mjCGeom::Compile(void) {
// check type
if (type<0 || type>=mjNGEOMTYPES) {
throw mjCError(this, "invalid type in geom '%s' (id = %d)", name.c_str(), id);
throw mjCError(this, "invalid type in geom");
}
// check condim
if (condim!=1 && condim!=3 && condim!=4 && condim!=6) {
throw mjCError(this, "invalid condim in geom '%s' (id = %d)", name.c_str(), id);
throw mjCError(this, "invalid condim in geom");
}
// check mesh
@@ -2210,8 +2201,7 @@ void mjCGeom::Compile(void) {
// plane only allowed in static bodies
if (type==mjGEOM_PLANE && body->weldid!=0) {
throw mjCError(this, "plane only allowed in static bodies: geom '%s' (id = %d)",
name.c_str(), id);
throw mjCError(this, "plane only allowed in static bodies");
}
// check if can collide
@@ -2227,16 +2217,12 @@ void mjCGeom::Compile(void) {
type!=mjGEOM_CYLINDER &&
type!=mjGEOM_ELLIPSOID &&
type!=mjGEOM_BOX) {
throw mjCError(this,
"fromto requires capsule, cylinder, box or ellipsoid in geom '%s' (id = %d)",
name.c_str(), id);
throw mjCError(this, "fromto requires capsule, cylinder, box or ellipsoid in geom");
}
// make sure pos is not defined; cannot use mjuu_defined because default is (0,0,0)
if (pos[0] || pos[1] || pos[2]) {
throw mjCError(this,
"both pos and fromto defined in geom '%s' (id = %d)",
name.c_str(), id);
throw mjCError(this, "both pos and fromto defined in geom");
}
// size[1] = length (for capsule and cylinder)
@@ -2247,7 +2233,7 @@ void mjCGeom::Compile(void) {
};
size[1] = mjuu_normvec(vec, 3)/2;
if (size[1]<mjEPS) {
throw mjCError(this, "fromto points too close in geom '%s' (id = %d)", name.c_str(), id);
throw mjCError(this, "fromto points too close in geom");
}
// adjust size for ellipsoid and box
@@ -2277,7 +2263,7 @@ void mjCGeom::Compile(void) {
if (mesh) {
// check for inapplicable fromto
if (mjuu_defined(fromto[0])) {
throw mjCError(this, "fromto cannot be used with mesh geom '%s' (id = %d)", name.c_str(), id);
throw mjCError(this, "fromto cannot be used with mesh geom");
}
// save reference in case this is not an mjGEOM_MESH
@@ -2319,7 +2305,7 @@ void mjCGeom::Compile(void) {
for (double s : size) {
if (std::isnan(s)) {
throw mjCError(this, "nan size in geom '%s' (id = %d)", name.c_str(), id);
throw mjCError(this, "nan size in geom");
}
}
// compute aabb
@@ -2343,8 +2329,7 @@ void mjCGeom::Compile(void) {
// check for negative values
if (mass_<0 || inertia[0]<0 || inertia[1]<0 || inertia[2]<0 || density<0)
throw mjCError(this, "mass, inertia or density are negative in geom '%s' (id = %d)",
name.c_str(), id);
throw mjCError(this, "mass, inertia or density are negative in geom");
}
// fluid-interaction coefficients, requires computed inertia and mass
@@ -2356,8 +2341,7 @@ void mjCGeom::Compile(void) {
if (plugin.active) {
if (plugin_name.empty() && plugin_instance_name.empty()) {
throw mjCError(
this, "neither 'plugin' nor 'instance' is specified for geom '%s', (id = %d)",
name.c_str(), id);
this, "neither 'plugin' nor 'instance' is specified for geom");
}
mjCPlugin* plugin_instance = static_cast<mjCPlugin*>(plugin.instance);
@@ -2453,20 +2437,18 @@ void mjCSite::Compile(void) {
// resize userdata
if (userdata_.size() > model->nuser_site) {
throw mjCError(this, "user has more values than nuser_site in site '%s' (id = %d)",
name.c_str(), id);
throw mjCError(this, "user has more values than nuser_site in site");
}
userdata_.resize(model->nuser_site);
// check type
if (type<0 || type>=mjNGEOMTYPES) {
throw mjCError(this, "invalid type in site '%s' (id = %d)", name.c_str(), id);
throw mjCError(this, "invalid type in site");
}
// do not allow meshes, hfields and planes
if (type==mjGEOM_MESH || type==mjGEOM_HFIELD || type==mjGEOM_PLANE) {
throw mjCError(this, "meshes, hfields and planes not allowed in site '%s' (id = %d)",
name.c_str(), id);
throw mjCError(this, "meshes, hfields and planes not allowed in site");
}
// 'fromto': compute pos, quat, size
@@ -2476,14 +2458,12 @@ void mjCSite::Compile(void) {
type!=mjGEOM_CYLINDER &&
type!=mjGEOM_ELLIPSOID &&
type!=mjGEOM_BOX) {
throw mjCError(this,
"fromto requires capsule, cylinder, box or ellipsoid in geom '%s' (id = %d)",
name.c_str(), id);
throw mjCError(this, "fromto requires capsule, cylinder, box or ellipsoid in geom");
}
// make sure pos is not defined; cannot use mjuu_defined because default is (0,0,0)
if (pos[0] || pos[1] || pos[2]) {
throw mjCError(this, "both pos and fromto defined in geom '%s' (id = %d)", name.c_str(), id);
throw mjCError(this, "both pos and fromto defined in geom");
}
// size[1] = length (for capsule and cylinder)
@@ -2494,7 +2474,7 @@ void mjCSite::Compile(void) {
};
size[1] = mjuu_normvec(vec, 3)/2;
if (size[1]<mjEPS) {
throw mjCError(this, "fromto points too close in geom '%s' (id = %d)", name.c_str(), id);
throw mjCError(this, "fromto points too close in geom");
}
// adjust size for ellipsoid and box
@@ -2618,8 +2598,7 @@ void mjCCamera::Compile(void) {
// resize userdata
if (userdata_.size() > model->nuser_cam) {
throw mjCError(this, "user has more values than nuser_cam in camera '%s' (id = %d)",
name.c_str(), id);
throw mjCError(this, "user has more values than nuser_cam in camera");
}
userdata_.resize(model->nuser_cam);
@@ -2643,7 +2622,7 @@ void mjCCamera::Compile(void) {
if (tb) {
targetbodyid = tb->id;
} else {
throw mjCError(this, "unknown target body in camera '%s' (id = %d)", name.c_str(), id);
throw mjCError(this, "unknown target body in camera");
}
}
@@ -2656,14 +2635,12 @@ void mjCCamera::Compile(void) {
// check that specs are not duplicated
if ((principal_length[0] && principal_pixel[0]) ||
(principal_length[1] && principal_pixel[1])) {
throw mjCError(this, "principal length duplicated in camera '%s' (id = %d)",
name.c_str(), id);
throw mjCError(this, "principal length duplicated in camera");
}
if ((focal_length[0] && focal_pixel[0]) ||
(focal_length[1] && focal_pixel[1])) {
throw mjCError(this, "focal length duplicated in camera '%s' (id = %d)",
name.c_str(), id);
throw mjCError(this, "focal length duplicated in camera");
}
// compute number of pixels per unit length
@@ -2774,7 +2751,7 @@ void mjCLight::Compile(void) {
// normalize direction, make sure it is not zero
if (mjuu_normvec(dir, 3)<mjMINVAL) {
throw mjCError(this, "zero direction in light '%s' (id = %d)", name.c_str(), id);
throw mjCError(this, "zero direction in light");
}
// get targetbodyid
@@ -2783,7 +2760,7 @@ void mjCLight::Compile(void) {
if (tb) {
targetbodyid = tb->id;
} else {
throw mjCError(this, "unknown target body in light '%s' (id = %d)", name.c_str(), id);
throw mjCError(this, "unknown target body in light");
}
}
}
@@ -2976,8 +2953,7 @@ void mjCHField::Compile(const mjVFS* vfs) {
// check size parameters
for (int i=0; i<4; i++)
if (size[i]<=0)
throw mjCError(this,
"size parameter is not positive in hfield '%s' (id = %d)", name.c_str(), id);
throw mjCError(this, "size parameter is not positive in hfield");
// remove path from file if necessary
if (model->strippath) {
@@ -2988,8 +2964,7 @@ void mjCHField::Compile(const mjVFS* vfs) {
if (!file_.empty()) {
// make sure hfield was not already specified manually
if (nrow || ncol || !data.empty()) {
throw mjCError(this,
"hfield '%s' (id = %d) specified from file and manually", name.c_str(), id);
throw mjCError(this, "hfield specified from file and manually");
}
std::string asset_type = GetAssetContentType(file_, content_type_);
@@ -3021,7 +2996,7 @@ void mjCHField::Compile(const mjVFS* vfs) {
// make sure hfield was specified (from file or manually)
if (nrow<1 || ncol<1 || data.empty()) {
throw mjCError(this, "hfield '%s' (id = %d) not specified", name.c_str(), id);
throw mjCError(this, "hfield not specified");
}
// set elevation data to [0-1] range
@@ -3530,9 +3505,7 @@ void mjCTexture::Load2D(string filename, const mjVFS* vfs) {
void mjCTexture::LoadCubeSingle(string filename, const mjVFS* vfs) {
// check gridsize
if (gridsize[0]<1 || gridsize[1]<1 || gridsize[0]*gridsize[1]>12) {
throw mjCError(this,
"gridsize must be non-zero and no more than 12 squares in texture '%s' (id %d)",
(const char*)name.c_str(), id);
throw mjCError(this, "gridsize must be non-zero and no more than 12 squares in texture");
}
// load PNG or custom
@@ -3590,8 +3563,7 @@ void mjCTexture::LoadCubeSingle(string filename, const mjVFS* vfs) {
} else if (gridlayout[k]=='B') {
i = 5;
} else if (gridlayout[k]!='.')
throw mjCError(this, "gridlayout symbol is not among '.RLUDFB' in texture '%s' (id %d)",
(const char*)file_.c_str(), id);
throw mjCError(this, "gridlayout symbol is not among '.RLUDFB' in texture");
// load if specified
if (i>=0) {
@@ -3660,9 +3632,7 @@ void mjCTexture::LoadCubeSeparate(const mjVFS* vfs) {
height = 6*width;
rgb.assign(3*width*height, 0);
if (rgb.empty()) {
throw mjCError(this,
"Could not allocate memory for texture '%s' (id %d)",
(const char*)name.c_str(), id);
throw mjCError(this, "Could not allocate memory for texture");
}
}
@@ -3706,9 +3676,7 @@ void mjCTexture::Compile(const mjVFS* vfs) {
if (builtin!=mjBUILTIN_NONE) {
// check size
if (width<1 || height<1) {
throw mjCError(this,
"Invalid width or height of builtin texture '%s' (id %d)",
(const char*)name.c_str(), id);
throw mjCError(this, "Invalid width or height of builtin texture");
}
// adjust height of cube texture
@@ -3719,9 +3687,7 @@ void mjCTexture::Compile(const mjVFS* vfs) {
// allocate data
rgb.assign(3*width*height, 0);
if (rgb.empty()) {
throw mjCError(this,
"Could not allocate memory for texture '%s' (id %d)",
(const char*)name.c_str(), id);
throw mjCError(this, "Could not allocate memory for texture");
}
// dispatch
@@ -3755,8 +3721,7 @@ void mjCTexture::Compile(const mjVFS* vfs) {
// 2D not allowed
if (type==mjTEXTURE_2D) {
throw mjCError(this,
"Cannot load 2D texture from separate files, texture '%s' (id %d)",
(const char*)name.c_str(), id);
"Cannot load 2D texture from separate files, texture");
}
// at least one cubefile must be defined
@@ -3769,8 +3734,7 @@ void mjCTexture::Compile(const mjVFS* vfs) {
}
if (!defined) {
throw mjCError(this,
"No cubefiles_ defined in cube or skybox texture '%s' (id %d)",
(const char*)name.c_str(), id);
"No cubefiles_ defined in cube or skybox texture");
}
// only cube and skybox
@@ -3779,8 +3743,7 @@ void mjCTexture::Compile(const mjVFS* vfs) {
// make sure someone allocated data; SHOULD NOT OCCUR
if (rgb.empty()) {
throw mjCError(this,
"texture '%s' (id %d) was not specified", (const char*)name.c_str(), id);
throw mjCError(this, "texture '%s' (id %d) was not specified", name.c_str(), id);
}
}
@@ -3979,7 +3942,7 @@ void mjCPair::Compile(void) {
// check condim
if (condim!=1 && condim!=3 && condim!=4 && condim!=6) {
throw mjCError(this, "invalid condim in collision %d", "", id);
throw mjCError(this, "invalid condim in contact pair");
}
// find geoms
@@ -4289,7 +4252,7 @@ void mjCEquality::ResolveReferences(const mjCModel* m) {
} else if (type==mjEQ_FLEX) {
objtype = mjOBJ_FLEX;
} else {
throw mjCError(this, "invalid type in equality constraint '%s' (id = %d)'", name.c_str(), id);
throw mjCError(this, "invalid type in equality constraint");
}
// find object 1, get id
@@ -4311,8 +4274,7 @@ void mjCEquality::ResolveReferences(const mjCModel* m) {
// object 2 unspecified: set to -1
else {
if (objtype==mjOBJ_GEOM) {
throw mjCError(this, "both geom are required in equality constraint '%s' (id = %d)",
name.c_str(), id);
throw mjCError(this, "both geom are required in equality constraint");
} else {
obj2id = -1;
px2 = 0;
@@ -4335,8 +4297,7 @@ void mjCEquality::ResolveReferences(const mjCModel* m) {
jt2 = (px2 ? ((mjCJoint*)px2)->type : mjJNT_HINGE);
if ((jt1!=mjJNT_HINGE && jt1!=mjJNT_SLIDE) ||
(jt2!=mjJNT_HINGE && jt2!=mjJNT_SLIDE)) {
throw mjCError(this, "only HINGE and SLIDE joint allowed in constraint '%s' (id = %d)",
name.c_str(), id);
throw mjCError(this, "only HINGE and SLIDE joint allowed in constraint");
}
}
}
@@ -4568,8 +4529,7 @@ void mjCTendon::Compile(void) {
// resize userdata
if (userdata_.size() > model->nuser_tendon) {
throw mjCError(this, "user has more values than nuser_tendon in tendon '%s' (id = %d)",
name.c_str(), id);
throw mjCError(this, "user has more values than nuser_tendon in tendon");
}
userdata_.resize(model->nuser_tendon);
@@ -4677,12 +4637,12 @@ void mjCTendon::Compile(void) {
// check limits
if (range[0]>=range[1] && is_limited()) {
throw mjCError(this, "invalid limits in tendon '%s (id = %d)'", name.c_str(), id);
throw mjCError(this, "invalid limits in tendon");
}
// check springlength
if (springlength[0] > springlength[1]) {
throw mjCError(this, "invalid springlength in tendon '%s (id = %d)'", name.c_str(), id);
throw mjCError(this, "invalid springlength in tendon");
}
}
@@ -4987,7 +4947,7 @@ void mjCActuator::ResolveReferences(const mjCModel* m) {
break;
default:
throw mjCError(this, "invalid transmission type in actuator '%s' (id = %d)", name.c_str(), id);
throw mjCError(this, "invalid transmission type in actuator");
}
// assign and check
@@ -5014,7 +4974,7 @@ void mjCActuator::Compile(void) {
// check for missing target name
if (target_.empty()) {
throw mjCError(this,
"missing transmission target for actuator '%s' (id = %d)", name.c_str(), id);
"missing transmission target for actuator");
}
// find transmission target in object arrays
@@ -5033,7 +4993,7 @@ void mjCActuator::Compile(void) {
range = actrange;
} else {
throw mjCError(this, "inheritrange only available for position "
"and intvelocity actuators '%s' (id = %d)", name.c_str(), id);
"and intvelocity actuators");
}
const double* target_range;
@@ -5041,7 +5001,7 @@ void mjCActuator::Compile(void) {
mjCJoint* pjnt = (mjCJoint*) ptarget;
if (pjnt->spec.type != mjJNT_HINGE && pjnt->spec.type != mjJNT_SLIDE) {
throw mjCError(this, "inheritrange can only be used with hinge and slide joints, "
"actuator '%s' (id = %d)", name.c_str(), id);
"actuator");
}
target_range = pjnt->get_range();
} else if (trntype == mjTRN_TENDON) {
@@ -5049,7 +5009,7 @@ void mjCActuator::Compile(void) {
target_range = pten->get_range();
} else {
throw mjCError(this, "inheritrange can only be used with joint and tendon transmission, "
"actuator '%s' (id = %d)", name.c_str(), id);
"actuator");
}
if (target_range[0] == target_range[1]) {
@@ -5080,29 +5040,27 @@ void mjCActuator::Compile(void) {
// check limits
if (forcerange[0]>=forcerange[1] && is_forcelimited()) {
throw mjCError(this, "invalid force range for actuator '%s' (id = %d)", name.c_str(), id);
throw mjCError(this, "invalid force range for actuator");
}
if (ctrlrange[0]>=ctrlrange[1] && is_ctrllimited()) {
throw mjCError(this, "invalid control range for actuator '%s' (id = %d)", name.c_str(), id);
throw mjCError(this, "invalid control range for actuator");
}
if (actrange[0]>=actrange[1] && is_actlimited()) {
throw mjCError(this, "invalid actrange for actuator '%s' (id = %d)", name.c_str(), id);
throw mjCError(this, "invalid actrange for actuator");
}
if (is_actlimited() && dyntype == mjDYN_NONE) {
throw mjCError(this, "actrange specified but dyntype is 'none' in actuator '%s' (id = %d)",
name.c_str(), id);
throw mjCError(this, "actrange specified but dyntype is 'none' in actuator");
}
// check and set actdim
if (actdim > 1 && dyntype != mjDYN_USER) {
throw mjCError(this, "actdim > 1 is only allowed for dyntype 'user' in actuator '%s' (id = %d)",
name.c_str(), id);
throw mjCError(this, "actdim > 1 is only allowed for dyntype 'user' in actuator");
}
if (actdim == 1 && dyntype == mjDYN_NONE) {
throw mjCError(this, "invalid actdim 1 in stateless actuator '%s' (id = %d)", name.c_str(), id);
throw mjCError(this, "invalid actdim 1 in stateless actuator");
}
if (actdim == 0 && dyntype != mjDYN_NONE) {
throw mjCError(this, "invalid actdim 0 in stateful actuator '%s' (id = %d)", name.c_str(), id);
throw mjCError(this, "invalid actdim 0 in stateful actuator");
}
// set actdim
@@ -5127,12 +5085,12 @@ void mjCActuator::Compile(void) {
// range
if (prm[0]>=prm[1]) {
throw mjCError(this, "range[0]<range[1] required in muscle '%s' (id = %d)", name.c_str(), id);
throw mjCError(this, "range[0]<range[1] required in muscle");
}
// lmin<1<lmax
if (prm[4]>=1 || prm[5]<=1) {
throw mjCError(this, "lmin<1<lmax required in muscle '%s' (id = %d)", name.c_str(), id);
throw mjCError(this, "lmin<1<lmax required in muscle");
}
// scale, vmax, fpmax, fvmax>0
@@ -5255,17 +5213,13 @@ void mjCSensor::ResolveReferences(const mjCModel* m) {
if (objtype!=mjOBJ_UNKNOWN) {
// check for missing object name
if (objname_.empty()) {
throw mjCError(this,
"missing name of sensorized object in sensor '%s' (id = %d)",
name.c_str(), id);
throw mjCError(this, "missing name of sensorized object in sensor");
}
// find name
obj = m->FindObject(objtype, objname_);
if (!obj) {
throw mjCError(this,
"unrecognized name of sensorized object in sensor '%s' (id = %d)",
name.c_str(), id);
throw mjCError(this, "unrecognized name '%s' of sensorized object", objname_.c_str());
}
// if geom mark it as non visual
@@ -5275,32 +5229,27 @@ void mjCSensor::ResolveReferences(const mjCModel* m) {
// get sensorized object id
} else if (type != mjSENS_CLOCK && type != mjSENS_PLUGIN && type != mjSENS_USER) {
throw mjCError(this, "invalid type in sensor '%s' (id = %d)", name.c_str(), id);
throw mjCError(this, "invalid type in sensor");
}
// get refid from reftype and refname
if (reftype!=mjOBJ_UNKNOWN) {
// check for missing object name
if (refname_.empty()) {
throw mjCError(this,
"missing name of reference frame object in sensor '%s' (id = %d)",
name.c_str(), id);
throw mjCError(this, "missing name of reference frame object in sensor");
}
// find name
ref = m->FindObject(reftype, refname_);
if (!ref) {
throw mjCError(this,
"unrecognized name of reference frame object in sensor '%s' (id = %d)",
name.c_str(), id);
throw mjCError(this, "unrecognized name '%s' of reference frame object", refname_.c_str());
}
// must be attached to object with spatial frame
if (reftype!=mjOBJ_BODY && reftype!=mjOBJ_XBODY &&
reftype!=mjOBJ_GEOM && reftype!=mjOBJ_SITE && reftype!=mjOBJ_CAMERA) {
throw mjCError(this,
"reference frame object must be (x)body, geom, site or camera:"
" sensor '%s' (id = %d)", name.c_str(), id);
"reference frame object must be (x)body, geom, site or camera in sensor");
}
// get sensorized object id
@@ -5316,19 +5265,18 @@ void mjCSensor::Compile(void) {
// resize userdata
if (userdata_.size() > model->nuser_sensor) {
throw mjCError(this, "user has more values than nuser_sensor in sensor '%s' (id = %d)",
name.c_str(), id);
throw mjCError(this, "user has more values than nuser_sensor in sensor");
}
userdata_.resize(model->nuser_sensor);
// require non-negative noise
if (noise<0) {
throw mjCError(this, "negative noise in sensor '%s' (id = %d)", name.c_str(), id);
throw mjCError(this, "negative noise in sensor");
}
// require non-negative cutoff
if (cutoff<0) {
throw mjCError(this, "negative cutoff in sensor '%s' (id = %d)", name.c_str(), id);
throw mjCError(this, "negative cutoff in sensor");
}
// Find referenced object
@@ -5347,8 +5295,7 @@ void mjCSensor::Compile(void) {
case mjSENS_CAMPROJECTION:
// must be attached to site
if (objtype!=mjOBJ_SITE) {
throw mjCError(this,
"sensor must be attached to site: sensor '%s' (id = %d)", name.c_str(), id);
throw mjCError(this, "sensor must be attached to site: sensor");
}
// set dim and datatype
@@ -5376,9 +5323,7 @@ void mjCSensor::Compile(void) {
if (type==mjSENS_CAMPROJECTION) {
mjCCamera* camref = (mjCCamera*)ref;
if (!camref->resolution[0] || !camref->resolution[1]) {
throw mjCError(this,
"camera projection sensor requires camera resolution '%s' (id = %d)",
name.c_str(), id);
throw mjCError(this, "camera projection sensor requires camera resolution");
}
}
break;
@@ -5388,14 +5333,12 @@ void mjCSensor::Compile(void) {
case mjSENS_JOINTACTFRC:
// must be attached to joint
if (objtype!=mjOBJ_JOINT) {
throw mjCError(this,
"sensor must be attached to joint: sensor '%s' (id = %d)", name.c_str(), id);
throw mjCError(this, "sensor must be attached to joint: sensor");
}
// make sure joint is slide or hinge
if (((mjCJoint*)obj)->type!=mjJNT_SLIDE && ((mjCJoint*)obj)->type!=mjJNT_HINGE) {
throw mjCError(this,
"joint must be slide or hinge in sensor '%s' (id = %d)", name.c_str(), id);
throw mjCError(this, "joint must be slide or hinge in sensor");
}
// set
@@ -5414,8 +5357,7 @@ void mjCSensor::Compile(void) {
case mjSENS_TENDONVEL:
// must be attached to tendon
if (objtype!=mjOBJ_TENDON) {
throw mjCError(this,
"sensor must be attached to tendon: sensor '%s' (id = %d)", name.c_str(), id);
throw mjCError(this, "sensor must be attached to tendon: sensor");
}
// set
@@ -5433,8 +5375,7 @@ void mjCSensor::Compile(void) {
case mjSENS_ACTUATORFRC:
// must be attached to actuator
if (objtype!=mjOBJ_ACTUATOR) {
throw mjCError(this,
"sensor must be attached to actuator: sensor '%s' (id = %d)", name.c_str(), id);
throw mjCError(this, "sensor must be attached to actuator: sensor");
}
// set
@@ -5453,14 +5394,12 @@ void mjCSensor::Compile(void) {
case mjSENS_BALLANGVEL:
// must be attached to joint
if (objtype!=mjOBJ_JOINT) {
throw mjCError(this,
"sensor must be attached to joint: sensor '%s' (id = %d)", name.c_str(), id);
throw mjCError(this, "sensor must be attached to joint: sensor");
}
// make sure joint is ball
if (((mjCJoint*)obj)->type!=mjJNT_BALL) {
throw mjCError(this,
"joint must be ball in sensor '%s' (id = %d)", name.c_str(), id);
throw mjCError(this, "joint must be ball in sensor");
}
// set
@@ -5480,13 +5419,12 @@ void mjCSensor::Compile(void) {
case mjSENS_JOINTLIMITFRC:
// must be attached to joint
if (objtype!=mjOBJ_JOINT) {
throw mjCError(this,
"sensor must be attached to joint: sensor '%s' (id = %d)", name.c_str(), id);
throw mjCError(this, "sensor must be attached to joint: sensor");
}
// make sure joint has limit
if (!((mjCJoint*)obj)->is_limited()) {
throw mjCError(this, "joint must be limited in sensor '%s' (id = %d)", name.c_str(), id);
throw mjCError(this, "joint must be limited in sensor");
}
// set
@@ -5506,13 +5444,12 @@ void mjCSensor::Compile(void) {
case mjSENS_TENDONLIMITFRC:
// must be attached to tendon
if (objtype!=mjOBJ_TENDON) {
throw mjCError(this,
"sensor must be attached to tendon: sensor '%s' (id = %d)", name.c_str(), id);
throw mjCError(this, "sensor must be attached to tendon: sensor");
}
// make sure tendon has limit
if (!((mjCTendon*)obj)->is_limited()) {
throw mjCError(this, "tendon must be limited in sensor '%s' (id = %d)", name.c_str(), id);
throw mjCError(this, "tendon must be limited in sensor");
}
// set
@@ -5539,9 +5476,7 @@ void mjCSensor::Compile(void) {
// must be attached to object with spatial frame
if (objtype!=mjOBJ_BODY && objtype!=mjOBJ_XBODY &&
objtype!=mjOBJ_GEOM && objtype!=mjOBJ_SITE && objtype!=mjOBJ_CAMERA) {
throw mjCError(this,
"sensor must be attached to (x)body, geom, site or camera:"
" sensor '%s' (id = %d)", name.c_str(), id);
throw mjCError(this, "sensor must be attached to (x)body, geom, site or camera");
}
// set dim
@@ -5575,8 +5510,7 @@ void mjCSensor::Compile(void) {
case mjSENS_SUBTREEANGMOM:
// must be attached to body
if (objtype!=mjOBJ_BODY) {
throw mjCError(this,
"sensor must be attached to body: sensor '%s' (id = %d)", name.c_str(), id);
throw mjCError(this, "sensor must be attached to body: sensor");
}
// set
@@ -5598,18 +5532,16 @@ void mjCSensor::Compile(void) {
case mjSENS_USER:
// check for negative dim
if (dim<0) {
throw mjCError(this, "sensor dim must be positive: sensor '%s' (id = %d)", name.c_str(), id);
throw mjCError(this, "sensor dim must be positive in sensor");
}
// make sure dim is consistent with datatype
if (datatype==mjDATATYPE_AXIS && dim!=3) {
throw mjCError(this,
"datatype AXIS requires dim=3 in sensor '%s' (id = %d)", name.c_str(), id);
"datatype AXIS requires dim=3 in sensor");
}
if (datatype==mjDATATYPE_QUATERNION && dim!=4) {
throw mjCError(this,
"datatype QUATERNION requires dim=4 in sensor '%s' (id = %d)",
name.c_str(), id);
throw mjCError(this, "datatype QUATERNION requires dim=4 in sensor");
}
break;
@@ -5618,9 +5550,7 @@ void mjCSensor::Compile(void) {
datatype = mjDATATYPE_REAL; // no noise added to plugin sensors, this attribute is unused
if (plugin_name.empty() && plugin_instance_name.empty()) {
throw mjCError(
this, "neither 'plugin' nor 'instance' is specified for sensor '%s', (id = %d)",
name.c_str(), id);
throw mjCError(this, "neither 'plugin' nor 'instance' is specified for sensor");
}
// resolve plugin instance, or create one if using the "plugin" attribute shortcut
@@ -5643,9 +5573,7 @@ void mjCSensor::Compile(void) {
// check cutoff for incompatible data types
if (cutoff>0 && (datatype==mjDATATYPE_AXIS || datatype==mjDATATYPE_QUATERNION)) {
throw mjCError(this,
"cutoff applied to axis or quaternion datatype in sensor '%s' (id = %d)",
name.c_str(), id);
throw mjCError(this, "cutoff applied to axis or quaternion datatype in sensor");
}
}
+24 -24
View File
@@ -1344,7 +1344,7 @@ void mjXReader::OneFlex(XMLElement* elem, mjsFlex* pflex) {
}
// write error info
mjs_setString(pflex->info, ("line = " + std::to_string(elem->GetLineNum())).c_str());
mjs_setString(pflex->info, ("line " + std::to_string(elem->GetLineNum())).c_str());
}
@@ -1414,7 +1414,7 @@ void mjXReader::OneMesh(XMLElement* elem, mjsMesh* pmesh) {
}
// write error info
mjs_setString(pmesh->info, ("line = " + std::to_string(elem->GetLineNum())).c_str());
mjs_setString(pmesh->info, ("line " + std::to_string(elem->GetLineNum())).c_str());
}
@@ -1502,7 +1502,7 @@ void mjXReader::OneSkin(XMLElement* elem, mjsSkin* pskin) {
mjs_setFloat(pskin->bindquat, bindquat.data(), bindquat.size());
// write error info
mjs_setString(pskin->info, ("line = " + std::to_string(elem->GetLineNum())).c_str());
mjs_setString(pskin->info, ("line " + std::to_string(elem->GetLineNum())).c_str());
}
@@ -1535,7 +1535,7 @@ void mjXReader::OneMaterial(XMLElement* elem, mjsMaterial* pmat) {
ReadAttr(elem, "rgba", 4, pmat->rgba, text);
// write error info
mjs_setString(pmat->info, ("line = " + std::to_string(elem->GetLineNum())).c_str());
mjs_setString(pmat->info, ("line " + std::to_string(elem->GetLineNum())).c_str());
}
@@ -1585,7 +1585,7 @@ void mjXReader::OneJoint(XMLElement* elem, mjsJoint* pjoint) {
}
// write error info
mjs_setString(pjoint->info, ("line = " + std::to_string(elem->GetLineNum())).c_str());
mjs_setString(pjoint->info, ("line " + std::to_string(elem->GetLineNum())).c_str());
}
@@ -1660,7 +1660,7 @@ void mjXReader::OneGeom(XMLElement* elem, mjsGeom* pgeom) {
}
// write error info
mjs_setString(pgeom->info, ("line = " + std::to_string(elem->GetLineNum())).c_str());
mjs_setString(pgeom->info, ("line " + std::to_string(elem->GetLineNum())).c_str());
}
@@ -1697,7 +1697,7 @@ void mjXReader::OneSite(XMLElement* elem, mjsSite* site) {
}
// write error info
mjs_setString(site->info, ("line = " + std::to_string(elem->GetLineNum())).c_str());
mjs_setString(site->info, ("line " + std::to_string(elem->GetLineNum())).c_str());
}
@@ -1751,7 +1751,7 @@ void mjXReader::OneCamera(XMLElement* elem, mjsCamera* pcam) {
mjs_setDouble(pcam->userdata, userdata.data(), userdata.size());
// write error info
mjs_setString(pcam->info, ("line = " + std::to_string(elem->GetLineNum())).c_str());
mjs_setString(pcam->info, ("line " + std::to_string(elem->GetLineNum())).c_str());
}
@@ -1794,7 +1794,7 @@ void mjXReader::OneLight(XMLElement* elem, mjsLight* plight) {
ReadAttr(elem, "specular", 3, plight->specular, text);
// write error info
mjs_setString(plight->info, ("line = " + std::to_string(elem->GetLineNum())).c_str());
mjs_setString(plight->info, ("line " + std::to_string(elem->GetLineNum())).c_str());
}
@@ -1829,7 +1829,7 @@ void mjXReader::OnePair(XMLElement* elem, mjsPair* ppair) {
ReadAttr(elem, "friction", 5, ppair->friction, text, false, false);
// write error info
mjs_setString(ppair->info, ("line = " + std::to_string(elem->GetLineNum())).c_str());
mjs_setString(ppair->info, ("line " + std::to_string(elem->GetLineNum())).c_str());
}
@@ -1907,7 +1907,7 @@ void mjXReader::OneEquality(XMLElement* elem, mjsEquality* pequality) {
ReadAttr(elem, "solimp", mjNIMP, pequality->solimp, text, false, false);
// write error info
mjs_setString(pequality->info, ("line = " + std::to_string(elem->GetLineNum())).c_str());
mjs_setString(pequality->info, ("line " + std::to_string(elem->GetLineNum())).c_str());
}
@@ -1951,7 +1951,7 @@ void mjXReader::OneTendon(XMLElement* elem, mjsTendon* pten) {
}
// write error info
mjs_setString(pten->info, ("line = " + std::to_string(elem->GetLineNum())).c_str());
mjs_setString(pten->info, ("line " + std::to_string(elem->GetLineNum())).c_str());
}
@@ -2241,7 +2241,7 @@ void mjXReader::OneActuator(XMLElement* elem, mjsActuator* pact) {
}
// write info
mjs_setString(pact->info, ("line = " + std::to_string(elem->GetLineNum())).c_str());
mjs_setString(pact->info, ("line " + std::to_string(elem->GetLineNum())).c_str());
}
@@ -2762,7 +2762,7 @@ void mjXReader::Extension(XMLElement* section) {
}
string name;
mjsPlugin* p = mjs_addPlugin(model);
mjs_setString(p->info, ("line = " + std::to_string(elem->GetLineNum())).c_str());
mjs_setString(p->info, ("line " + std::to_string(elem->GetLineNum())).c_str());
ReadAttrTxt(child, "name", name, /* required = */ true);
mjs_setString(p->name, name.c_str());
if (!p->name) {
@@ -2803,7 +2803,7 @@ void mjXReader::Custom(XMLElement* section) {
mjsNumeric* pnum = mjs_addNumeric(model);
// write error info
mjs_setString(pnum->info, ("line = " + std::to_string(elem->GetLineNum())).c_str());
mjs_setString(pnum->info, ("line " + std::to_string(elem->GetLineNum())).c_str());
// read attributes
ReadAttrTxt(elem, "name", elname, true);
@@ -2834,7 +2834,7 @@ void mjXReader::Custom(XMLElement* section) {
mjsText* pte = mjs_addText(model);
// write error info
mjs_setString(pte->info, ("line = " + std::to_string(elem->GetLineNum())).c_str());
mjs_setString(pte->info, ("line " + std::to_string(elem->GetLineNum())).c_str());
// read attributes
ReadAttrTxt(elem, "name", elname, true);
@@ -2854,7 +2854,7 @@ void mjXReader::Custom(XMLElement* section) {
mjsTuple* ptu = mjs_addTuple(model);
// write error info
mjs_setString(ptu->info, ("line = " + std::to_string(elem->GetLineNum())).c_str());
mjs_setString(ptu->info, ("line " + std::to_string(elem->GetLineNum())).c_str());
// read attributes
ReadAttrTxt(elem, "name", elname, true);
@@ -3061,7 +3061,7 @@ void mjXReader::Asset(XMLElement* section) {
mjsTexture* ptex = mjs_addTexture(model);
// write error info
mjs_setString(ptex->info, ("line = " + std::to_string(elem->GetLineNum())).c_str());
mjs_setString(ptex->info, ("line " + std::to_string(elem->GetLineNum())).c_str());
// read attributes
if (MapValue(elem, "type", &n, texture_map, texture_sz)) {
@@ -3150,7 +3150,7 @@ void mjXReader::Asset(XMLElement* section) {
mjsHField* phf = mjs_addHField(model);
// write error info
mjs_setString(phf->info, ("line = " + std::to_string(elem->GetLineNum())).c_str());
mjs_setString(phf->info, ("line " + std::to_string(elem->GetLineNum())).c_str());
// read attributes
string name, content_type;
@@ -3353,7 +3353,7 @@ void mjXReader::Body(XMLElement* section, mjsBody* pbody, mjsFrame* frame) {
// create frame
mjsFrame* pframe = mjs_addFrame(pbody, frame);
mjs_setString(pframe->info, ("line = " + std::to_string(elem->GetLineNum())).c_str());
mjs_setString(pframe->info, ("line " + std::to_string(elem->GetLineNum())).c_str());
mjs_setDefault(pframe->element, childdef ? childdef : def);
// read attributes
@@ -3386,7 +3386,7 @@ void mjXReader::Body(XMLElement* section, mjsBody* pbody, mjsFrame* frame) {
// create child body
mjsBody* pchild = mjs_addBody(pbody, childdef);
mjs_setString(pchild->info,
std::string("line = " + std::to_string(elem->GetLineNum())).c_str());
std::string("line " + std::to_string(elem->GetLineNum())).c_str());
// read attributes
std::string name, childclass;
@@ -3460,7 +3460,7 @@ void mjXReader::Contact(XMLElement* section) {
string exname, exbody1, exbody2;
// write error info
mjs_setString(pexclude->info, ("line = " + std::to_string(elem->GetLineNum())).c_str());
mjs_setString(pexclude->info, ("line " + std::to_string(elem->GetLineNum())).c_str());
// read name and body names
if (ReadAttrTxt(elem, "name", exname)) {
@@ -3596,7 +3596,7 @@ void mjXReader::Tendon(XMLElement* section) {
throw mjXError(sub, "unknown wrap type"); // SHOULD NOT OCCUR
}
mjs_setString(pwrap->info, ("line = " + std::to_string(sub->GetLineNum())).c_str());
mjs_setString(pwrap->info, ("line " + std::to_string(sub->GetLineNum())).c_str());
// advance to next sub-element
sub = NextSiblingElement(sub);
@@ -3935,7 +3935,7 @@ void mjXReader::Sensor(XMLElement* section) {
}
// write info
mjs_setString(psen->info, ("line = " + std::to_string(elem->GetLineNum())).c_str());
mjs_setString(psen->info, ("line " + std::to_string(elem->GetLineNum())).c_str());
// advance to next element
elem = NextSiblingElement(elem);
+64 -22
View File
@@ -543,8 +543,9 @@ TEST_F(RelativeFrameSensorParsingTest, BadRefName) {
)";
std::array<char, 1024> error;
LoadModelFromString(xml, error.data(), error.size());
EXPECT_THAT(error.data(), HasSubstr("unrecognized name of reference frame"));
EXPECT_THAT(error.data(), HasSubstr("line = 8"));
EXPECT_THAT(error.data(),
HasSubstr("unrecognized name 'wrong_name' of reference frame"));
EXPECT_THAT(error.data(), HasSubstr("line 8"));
}
TEST_F(RelativeFrameSensorParsingTest, BadRefType) {
@@ -563,7 +564,48 @@ TEST_F(RelativeFrameSensorParsingTest, BadRefType) {
std::array<char, 1024> error;
LoadModelFromString(xml, error.data(), error.size());
EXPECT_THAT(error.data(), HasSubstr("reference frame object must be"));
EXPECT_THAT(error.data(), HasSubstr("line = 8"));
EXPECT_THAT(error.data(), HasSubstr("line 8"));
}
TEST_F(RelativeFrameSensorParsingTest, BadObjName) {
static constexpr char xml[] = R"(
<mujoco>
<worldbody>
<site name="a"/>
</worldbody>
<sensor>
<framepos name="tom" objtype="site" objname="alessio" reftype="site" refname="a"/>
</sensor>
</mujoco>
)";
std::array<char, 1024> error;
mjModel* model = LoadModelFromString(xml, error.data(), error.size());
ASSERT_THAT(model, IsNull());
EXPECT_THAT(error.data(),
HasSubstr("unrecognized name 'alessio' of sensorized object"));
EXPECT_THAT(error.data(), HasSubstr("name 'tom'"));
EXPECT_THAT(error.data(), HasSubstr("line 7"));
}
TEST_F(RelativeFrameSensorParsingTest, BadObjRefName) {
static constexpr char xml[] = R"(
<mujoco>
<worldbody>
<site name="a"/>
</worldbody>
<sensor>
<framepos name="tom" objtype="site" objname="a" reftype="site" refname="alessio"/>
</sensor>
</mujoco>
)";
std::array<char, 1024> error;
mjModel* model = LoadModelFromString(xml, error.data(), error.size());
ASSERT_THAT(model, IsNull());
EXPECT_THAT(
error.data(),
HasSubstr("unrecognized name 'alessio' of reference frame object"));
EXPECT_THAT(error.data(), HasSubstr("name 'tom'"));
EXPECT_THAT(error.data(), HasSubstr("line 7"));
}
// ------------- sensor compilation --------------------------------------------
@@ -710,7 +752,7 @@ TEST_F(MjCGeomTest, NanSize) {
mjModel* model = LoadModelFromString(xml, error.data(), error.size());
ASSERT_THAT(model, testing::IsNull());
ASSERT_THAT(error.data(), HasSubstr("nan"));
EXPECT_THAT(error.data(), HasSubstr("line = 5"));
EXPECT_THAT(error.data(), HasSubstr("line 5"));
}
// ------------- test height fields --------------------------------------------
@@ -785,7 +827,7 @@ TEST_F(CameraSpecTest, FovyLimits) {
mjModel* m = LoadModelFromString(xml, error.data(), error.size());
EXPECT_THAT(m, IsNull()) << error.data();
EXPECT_THAT(error.data(), HasSubstr("fovy too large"));
EXPECT_THAT(error.data(), HasSubstr("line = 6"));
EXPECT_THAT(error.data(), HasSubstr("line 6"));
mj_deleteModel(m);
}
@@ -1071,7 +1113,7 @@ TEST_F(ActRangeTest, ActRangeBad) {
mjModel* model = LoadModelFromString(xml, error.data(), error.size());
ASSERT_THAT(model, IsNull());
EXPECT_THAT(error.data(), HasSubstr("invalid actrange"));
EXPECT_THAT(error.data(), HasSubstr("line = 10"));
EXPECT_THAT(error.data(), HasSubstr("line 10"));
}
TEST_F(ActRangeTest, ActRangeUndefined) {
@@ -1092,7 +1134,7 @@ TEST_F(ActRangeTest, ActRangeUndefined) {
mjModel* model = LoadModelFromString(xml, error.data(), error.size());
ASSERT_THAT(model, IsNull());
EXPECT_THAT(error.data(), HasSubstr("invalid actrange"));
EXPECT_THAT(error.data(), HasSubstr("line = 10"));
EXPECT_THAT(error.data(), HasSubstr("line 10"));
}
TEST_F(ActRangeTest, ActRangeNoDyntype) {
@@ -1199,7 +1241,7 @@ TEST_F(ActDimTest, NonzeroNotAllowedInStateless) {
ASSERT_THAT(model, IsNull());
EXPECT_THAT(error.data(), HasSubstr("invalid actdim 1 in stateless"));
EXPECT_THAT(error.data(), HasSubstr("line = 10"));
EXPECT_THAT(error.data(), HasSubstr("line 10"));
}
TEST_F(ActDimTest, ZeroNotAllowedInStateful) {
@@ -1221,7 +1263,7 @@ TEST_F(ActDimTest, ZeroNotAllowedInStateful) {
ASSERT_THAT(model, IsNull());
EXPECT_THAT(error.data(), HasSubstr("invalid actdim 0 in stateful"));
EXPECT_THAT(error.data(), HasSubstr("line = 10"));
EXPECT_THAT(error.data(), HasSubstr("line 10"));
}
// ------------- test nuser_xxx fields -----------------------------------------
@@ -1241,7 +1283,7 @@ TEST_F(UserDataTest, NBodyTooSmall) {
mjModel* model = LoadModelFromString(xml, error.data(), error.size());
ASSERT_THAT(model, IsNull());
EXPECT_THAT(error.data(), HasSubstr("nuser_body"));
EXPECT_THAT(error.data(), HasSubstr("line = 5"));
EXPECT_THAT(error.data(), HasSubstr("line 5"));
}
TEST_F(UserDataTest, NJointTooSmall) {
@@ -1260,7 +1302,7 @@ TEST_F(UserDataTest, NJointTooSmall) {
mjModel* model = LoadModelFromString(xml, error.data(), error.size());
ASSERT_THAT(model, IsNull());
EXPECT_THAT(error.data(), HasSubstr("nuser_jnt"));
EXPECT_THAT(error.data(), HasSubstr("line = 7"));
EXPECT_THAT(error.data(), HasSubstr("line 7"));
}
TEST_F(UserDataTest, NGeomTooSmall) {
@@ -1276,7 +1318,7 @@ TEST_F(UserDataTest, NGeomTooSmall) {
mjModel* model = LoadModelFromString(xml, error.data(), error.size());
ASSERT_THAT(model, IsNull());
EXPECT_THAT(error.data(), HasSubstr("nuser_geom"));
EXPECT_THAT(error.data(), HasSubstr("line = 5"));
EXPECT_THAT(error.data(), HasSubstr("line 5"));
}
TEST_F(UserDataTest, NSiteTooSmall) {
@@ -1292,7 +1334,7 @@ TEST_F(UserDataTest, NSiteTooSmall) {
mjModel* model = LoadModelFromString(xml, error.data(), error.size());
ASSERT_THAT(model, IsNull());
EXPECT_THAT(error.data(), HasSubstr("nuser_site"));
EXPECT_THAT(error.data(), HasSubstr("line = 5"));
EXPECT_THAT(error.data(), HasSubstr("line 5"));
}
TEST_F(UserDataTest, NCameraTooSmall) {
@@ -1308,7 +1350,7 @@ TEST_F(UserDataTest, NCameraTooSmall) {
mjModel* model = LoadModelFromString(xml, error.data(), error.size());
ASSERT_THAT(model, IsNull());
EXPECT_THAT(error.data(), HasSubstr("nuser_cam"));
EXPECT_THAT(error.data(), HasSubstr("line = 5"));
EXPECT_THAT(error.data(), HasSubstr("line 5"));
}
TEST_F(UserDataTest, NTendonTooSmall) {
@@ -1331,7 +1373,7 @@ TEST_F(UserDataTest, NTendonTooSmall) {
mjModel* model = LoadModelFromString(xml, error.data(), error.size());
ASSERT_THAT(model, IsNull());
EXPECT_THAT(error.data(), HasSubstr("nuser_tendon"));
EXPECT_THAT(error.data(), HasSubstr("line = 9"));
EXPECT_THAT(error.data(), HasSubstr("line 9"));
}
TEST_F(UserDataTest, NActuatorTooSmall) {
@@ -1353,7 +1395,7 @@ TEST_F(UserDataTest, NActuatorTooSmall) {
mjModel* model = LoadModelFromString(xml, error.data(), error.size());
ASSERT_THAT(model, IsNull());
EXPECT_THAT(error.data(), HasSubstr("nuser_actuator"));
EXPECT_THAT(error.data(), HasSubstr("line = 11"));
EXPECT_THAT(error.data(), HasSubstr("line 11"));
}
TEST_F(UserDataTest, NSensorTooSmall) {
@@ -1372,7 +1414,7 @@ TEST_F(UserDataTest, NSensorTooSmall) {
mjModel* model = LoadModelFromString(xml, error.data(), error.size());
ASSERT_THAT(model, IsNull());
EXPECT_THAT(error.data(), HasSubstr("nuser_sensor"));
EXPECT_THAT(error.data(), HasSubstr("line = 8"));
EXPECT_THAT(error.data(), HasSubstr("line 8"));
}
// ------------- test for auto parsing of *limited fields ----------------------
@@ -1415,7 +1457,7 @@ TEST_F(LimitedTest, ErrorIfLimitedMissingOnJoint) {
mjModel* model = LoadModelFromString(xml, error.data(), error.size());
ASSERT_THAT(model, IsNull());
EXPECT_THAT(error.data(), HasSubstr("limited"));
EXPECT_THAT(error.data(), HasSubstr("line = 6"));
EXPECT_THAT(error.data(), HasSubstr("line 6"));
}
TEST_F(LimitedTest, ExplicitLimitedFalseIsOk) {
@@ -1465,7 +1507,7 @@ TEST_F(LimitedTest, ErrorIfLimitedMissingOnTendon) {
ASSERT_THAT(model, IsNull());
EXPECT_THAT(error.data(), HasSubstr("limited"));
EXPECT_THAT(error.data(), HasSubstr("tendon"));
EXPECT_THAT(error.data(), HasSubstr("line = 13"));
EXPECT_THAT(error.data(), HasSubstr("line 13"));
}
TEST_F(LimitedTest, ErrorIfForceLimitedMissingOnActuator) {
@@ -1490,7 +1532,7 @@ TEST_F(LimitedTest, ErrorIfForceLimitedMissingOnActuator) {
EXPECT_THAT(error.data(), HasSubstr("forcelimited"));
EXPECT_THAT(error.data(), HasSubstr("forcerange"));
EXPECT_THAT(error.data(), HasSubstr("actuator"));
EXPECT_THAT(error.data(), HasSubstr("line = 11"));
EXPECT_THAT(error.data(), HasSubstr("line 11"));
}
// ------------- tests for tendon ----------------------------------------------
@@ -1518,7 +1560,7 @@ TEST_F(TendonTest, SiteBetweenPulleyNotAllowed) {
mjModel* model = LoadModelFromString(xml, error.data(), error.size());
EXPECT_THAT(model, IsNull());
EXPECT_THAT(error.data(), HasSubstr("needs a neighbor that is not a pulley"));
EXPECT_THAT(error.data(), HasSubstr("line = 9"));
EXPECT_THAT(error.data(), HasSubstr("line 9"));
}
// ------------- tests for tendon springrange ----------------------------------
@@ -1573,7 +1615,7 @@ TEST_F(SpringrangeTest, InvalidRange) {
mjModel* model = LoadModelFromString(xml, error.data(), error.size());
ASSERT_THAT(model, IsNull());
EXPECT_THAT(error.data(), HasSubstr("invalid springlength in tendon"));
EXPECT_THAT(error.data(), HasSubstr("line = 9"));
EXPECT_THAT(error.data(), HasSubstr("line 9"));
}
// ------------- test frame ----------------------------------------------------
+2 -2
View File
@@ -1289,7 +1289,7 @@ TEST_F(ActuatorParseTest, DamperRequiresControlRange) {
mjModel* model = LoadModelFromString(xml, error.data(), error.size());
ASSERT_THAT(model, IsNull());
EXPECT_THAT(error.data(), HasSubstr("invalid control range"));
EXPECT_THAT(error.data(), HasSubstr("line = 10"));
EXPECT_THAT(error.data(), HasSubstr("line 10"));
}
TEST_F(ActuatorParseTest, DamperPositiveControlRange) {
@@ -1505,7 +1505,7 @@ TEST_F(ActuatorParseTest, IntvelocityNoActrangeThrowsError) {
mjModel* model = LoadModelFromString(xml, error.data(), error.size());
ASSERT_THAT(model, IsNull());
EXPECT_THAT(error.data(), HasSubstr("invalid actrange for actuator"));
EXPECT_THAT(error.data(), HasSubstr("line = 10"));
EXPECT_THAT(error.data(), HasSubstr("line 10"));
}
TEST_F(ActuatorParseTest, IntvelocityDefaultsPropagate) {