Remove `mjWARN_VGEOMFULL, handle visual geom buffer full warnings in mjvScene`.
PiperOrigin-RevId: 896483023 Change-Id: I6dde2c20d8e8e229cf95e1f002dd10525d3376e6
This commit is contained in:
committed by
Copybara-Service
parent
5a2cc6cee3
commit
0e04436d51
@@ -44,6 +44,8 @@ General
|
|||||||
- The ``vertcollide`` field in :ref:`mjsFlex` has been removed. It is no longer required since
|
- The ``vertcollide`` field in :ref:`mjsFlex` has been removed. It is no longer required since
|
||||||
:doc:`MuJoCo Warp <mjwarp/index>` supports native flex collisions.
|
:doc:`MuJoCo Warp <mjwarp/index>` supports native flex collisions.
|
||||||
|
|
||||||
|
- The :ref:`mjtWarning` enum value ``mjWARN_VGEOMFULL`` is removed. Exhaustion of visual geoms is now handled
|
||||||
|
internally by the :ref:`mjvScene`.
|
||||||
|
|
||||||
Bug fixes
|
Bug fixes
|
||||||
^^^^^^^^^
|
^^^^^^^^^
|
||||||
|
|||||||
@@ -63,7 +63,6 @@ typedef enum mjtWarning_ { // warning types
|
|||||||
mjWARN_INERTIA = 0, // (near) singular inertia matrix
|
mjWARN_INERTIA = 0, // (near) singular inertia matrix
|
||||||
mjWARN_CONTACTFULL, // too many contacts in contact list
|
mjWARN_CONTACTFULL, // too many contacts in contact list
|
||||||
mjWARN_CNSTRFULL, // too many constraints
|
mjWARN_CNSTRFULL, // too many constraints
|
||||||
mjWARN_VGEOMFULL, // too many visual geoms
|
|
||||||
mjWARN_BADQPOS, // bad number in qpos
|
mjWARN_BADQPOS, // bad number in qpos
|
||||||
mjWARN_BADQVEL, // bad number in qvel
|
mjWARN_BADQVEL, // bad number in qvel
|
||||||
mjWARN_BADQACC, // bad number in qacc
|
mjWARN_BADQACC, // bad number in qacc
|
||||||
@@ -3096,7 +3095,9 @@ struct mjvScene_ { // abstract scene passed to OpenGL renderer
|
|||||||
// framing
|
// framing
|
||||||
int framewidth; // frame pixel width; 0: disable framing
|
int framewidth; // frame pixel width; 0: disable framing
|
||||||
float framergb[3]; // frame color
|
float framergb[3]; // frame color
|
||||||
int status; // status; 0: ok, 1: geoms exhausted
|
|
||||||
|
// geom buffer status
|
||||||
|
int status; // 0: ok, 1: geoms exhausted, warning issued
|
||||||
};
|
};
|
||||||
typedef struct mjvScene_ mjvScene;
|
typedef struct mjvScene_ mjvScene;
|
||||||
struct mjvFigure_ { // abstract 2D figure passed to OpenGL renderer
|
struct mjvFigure_ { // abstract 2D figure passed to OpenGL renderer
|
||||||
|
|||||||
@@ -77,7 +77,6 @@ typedef enum mjtWarning_ { // warning types
|
|||||||
mjWARN_INERTIA = 0, // (near) singular inertia matrix
|
mjWARN_INERTIA = 0, // (near) singular inertia matrix
|
||||||
mjWARN_CONTACTFULL, // too many contacts in contact list
|
mjWARN_CONTACTFULL, // too many contacts in contact list
|
||||||
mjWARN_CNSTRFULL, // too many constraints
|
mjWARN_CNSTRFULL, // too many constraints
|
||||||
mjWARN_VGEOMFULL, // too many visual geoms
|
|
||||||
mjWARN_BADQPOS, // bad number in qpos
|
mjWARN_BADQPOS, // bad number in qpos
|
||||||
mjWARN_BADQVEL, // bad number in qvel
|
mjWARN_BADQVEL, // bad number in qvel
|
||||||
mjWARN_BADQACC, // bad number in qacc
|
mjWARN_BADQACC, // bad number in qacc
|
||||||
|
|||||||
@@ -355,7 +355,9 @@ struct mjvScene_ { // abstract scene passed to OpenGL renderer
|
|||||||
// framing
|
// framing
|
||||||
int framewidth; // frame pixel width; 0: disable framing
|
int framewidth; // frame pixel width; 0: disable framing
|
||||||
float framergb[3]; // frame color
|
float framergb[3]; // frame color
|
||||||
int status; // status; 0: ok, 1: geoms exhausted
|
|
||||||
|
// geom buffer status
|
||||||
|
int status; // 0: ok, 1: geoms exhausted, warning issued
|
||||||
};
|
};
|
||||||
typedef struct mjvScene_ mjvScene;
|
typedef struct mjvScene_ mjvScene;
|
||||||
|
|
||||||
|
|||||||
+5
-1
@@ -91,7 +91,11 @@ void SdfVisualizer::Visualize(const mjModel* m, const mjData* d,
|
|||||||
for (int k = 0; k < 2; k++) {
|
for (int k = 0; k < 2; k++) {
|
||||||
for (int j = 0; j < (k == 0 ? 2 : n-1); j++) {
|
for (int j = 0; j < (k == 0 ? 2 : n-1); j++) {
|
||||||
if (scn->ngeom >= scn->maxgeom) {
|
if (scn->ngeom >= scn->maxgeom) {
|
||||||
mj_warning((mjData*)d, mjWARN_VGEOMFULL, scn->maxgeom);
|
if (!scn->status) {
|
||||||
|
mju_warning("Pre-allocated visual geom buffer is full. "
|
||||||
|
"Increase maxgeom above %d.", scn->maxgeom);
|
||||||
|
scn->status = 1;
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
mjvGeom* thisgeom = scn->geoms + scn->ngeom;
|
mjvGeom* thisgeom = scn->geoms + scn->ngeom;
|
||||||
|
|||||||
@@ -427,7 +427,11 @@ void TouchGrid::Visualize(const mjModel* m, mjData* d, const mjvOption* opt,
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (scn->ngeom >= scn->maxgeom) {
|
if (scn->ngeom >= scn->maxgeom) {
|
||||||
mj_warning(d, mjWARN_VGEOMFULL, scn->maxgeom);
|
if (!scn->status) {
|
||||||
|
mju_warning("Pre-allocated visual geom buffer is full. "
|
||||||
|
"Increase maxgeom above %d.", scn->maxgeom);
|
||||||
|
scn->status = 1;
|
||||||
|
}
|
||||||
mj_freeStack(d);
|
mj_freeStack(d);
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -578,12 +578,11 @@ ENUMS: Mapping[str, EnumDecl] = dict([
|
|||||||
('mjWARN_INERTIA', 0),
|
('mjWARN_INERTIA', 0),
|
||||||
('mjWARN_CONTACTFULL', 1),
|
('mjWARN_CONTACTFULL', 1),
|
||||||
('mjWARN_CNSTRFULL', 2),
|
('mjWARN_CNSTRFULL', 2),
|
||||||
('mjWARN_VGEOMFULL', 3),
|
('mjWARN_BADQPOS', 3),
|
||||||
('mjWARN_BADQPOS', 4),
|
('mjWARN_BADQVEL', 4),
|
||||||
('mjWARN_BADQVEL', 5),
|
('mjWARN_BADQACC', 5),
|
||||||
('mjWARN_BADQACC', 6),
|
('mjWARN_BADCTRL', 6),
|
||||||
('mjWARN_BADCTRL', 7),
|
('mjNWARNING', 7),
|
||||||
('mjNWARNING', 8),
|
|
||||||
]),
|
]),
|
||||||
)),
|
)),
|
||||||
('mjtTimer',
|
('mjtTimer',
|
||||||
|
|||||||
@@ -5416,7 +5416,7 @@ STRUCTS: Mapping[str, StructDecl] = dict([
|
|||||||
name='warning',
|
name='warning',
|
||||||
type=ArrayType(
|
type=ArrayType(
|
||||||
inner_type=ValueType(name='mjWarningStat'),
|
inner_type=ValueType(name='mjWarningStat'),
|
||||||
extents=(8,),
|
extents=(7,),
|
||||||
),
|
),
|
||||||
doc='warning statistics (mutable)',
|
doc='warning statistics (mutable)',
|
||||||
),
|
),
|
||||||
@@ -10524,7 +10524,7 @@ STRUCTS: Mapping[str, StructDecl] = dict([
|
|||||||
StructFieldDecl(
|
StructFieldDecl(
|
||||||
name='status',
|
name='status',
|
||||||
type=ValueType(name='int'),
|
type=ValueType(name='int'),
|
||||||
doc='status; 0: ok, 1: geoms exhausted',
|
doc='0: ok, 1: geoms exhausted, warning issued',
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
)),
|
)),
|
||||||
|
|||||||
@@ -14,8 +14,6 @@
|
|||||||
# ==============================================================================
|
# ==============================================================================
|
||||||
"""Tests for structs.py."""
|
"""Tests for structs.py."""
|
||||||
|
|
||||||
import re
|
|
||||||
|
|
||||||
from absl.testing import absltest
|
from absl.testing import absltest
|
||||||
|
|
||||||
from . import ast_nodes
|
from . import ast_nodes
|
||||||
@@ -36,7 +34,7 @@ class StructsTest(absltest.TestCase):
|
|||||||
field_names.add(field.name)
|
field_names.add(field.name)
|
||||||
if field.name == 'warning':
|
if field.name == 'warning':
|
||||||
self.assertEqual(field.type,
|
self.assertEqual(field.type,
|
||||||
type_parsing.parse_type('mjWarningStat[8]'))
|
type_parsing.parse_type('mjWarningStat[7]'))
|
||||||
self.assertEqual(field.doc, 'warning statistics (mutable)')
|
self.assertEqual(field.doc, 'warning statistics (mutable)')
|
||||||
elif field.name == 'qpos':
|
elif field.name == 'qpos':
|
||||||
self.assertEqual(field.type, type_parsing.parse_type('mjtNum*'))
|
self.assertEqual(field.type, type_parsing.parse_type('mjtNum*'))
|
||||||
|
|||||||
@@ -2142,11 +2142,7 @@ void Simulate::Sync(bool state_only) {
|
|||||||
m_->stat = m_passive_->stat;
|
m_->stat = m_passive_->stat;
|
||||||
}
|
}
|
||||||
|
|
||||||
// synchronize number of mjWARN_VGEOMFULL warnings
|
|
||||||
if (d_passive_->warning[mjWARN_VGEOMFULL].number > warn_vgeomfull_prev_) {
|
|
||||||
d_->warning[mjWARN_VGEOMFULL].number +=
|
|
||||||
d_passive_->warning[mjWARN_VGEOMFULL].number - warn_vgeomfull_prev_;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pending_.save_xml) {
|
if (pending_.save_xml) {
|
||||||
@@ -2334,7 +2330,7 @@ void Simulate::Sync(bool state_only) {
|
|||||||
mjopt_prev_ = m_passive_->opt;
|
mjopt_prev_ = m_passive_->opt;
|
||||||
mjvis_prev_ = m_passive_->vis;
|
mjvis_prev_ = m_passive_->vis;
|
||||||
mjstat_prev_ = m_passive_->stat;
|
mjstat_prev_ = m_passive_->stat;
|
||||||
warn_vgeomfull_prev_ = d_passive_->warning[mjWARN_VGEOMFULL].number;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// update settings
|
// update settings
|
||||||
@@ -2550,7 +2546,7 @@ void Simulate::LoadOnRenderThread() {
|
|||||||
mjopt_prev_ = m_->opt;
|
mjopt_prev_ = m_->opt;
|
||||||
opt_prev_ = opt;
|
opt_prev_ = opt;
|
||||||
cam_prev_ = cam;
|
cam_prev_ = cam;
|
||||||
warn_vgeomfull_prev_ = d_->warning[mjWARN_VGEOMFULL].number;
|
|
||||||
|
|
||||||
// full copy on init
|
// full copy on init
|
||||||
m_passive_ = mj_copyModel(nullptr, m_);
|
m_passive_ = mj_copyModel(nullptr, m_);
|
||||||
@@ -3022,7 +3018,11 @@ void Simulate::RenderLoop() {
|
|||||||
int nusergeom = user_scn_geoms_.size();
|
int nusergeom = user_scn_geoms_.size();
|
||||||
int ngeom = std::min(nusergeom, this->scn.maxgeom - this->scn.ngeom);
|
int ngeom = std::min(nusergeom, this->scn.maxgeom - this->scn.ngeom);
|
||||||
if (ngeom < nusergeom) {
|
if (ngeom < nusergeom) {
|
||||||
mj_warning(d_passive_, mjWARN_VGEOMFULL, this->scn.maxgeom);
|
if (!this->scn.status) {
|
||||||
|
mju_warning("Pre-allocated visual geom buffer is full. "
|
||||||
|
"Increase maxgeom above %d.", this->scn.maxgeom);
|
||||||
|
this->scn.status = 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
std::memcpy(this->scn.geoms + this->scn.ngeom, user_scn_geoms_.data(),
|
std::memcpy(this->scn.geoms + this->scn.ngeom, user_scn_geoms_.data(),
|
||||||
ngeom * sizeof(mjvGeom));
|
ngeom * sizeof(mjvGeom));
|
||||||
|
|||||||
@@ -147,8 +147,6 @@ class Simulate {
|
|||||||
mjvOption opt_prev_;
|
mjvOption opt_prev_;
|
||||||
mjvCamera cam_prev_;
|
mjvCamera cam_prev_;
|
||||||
|
|
||||||
int warn_vgeomfull_prev_;
|
|
||||||
|
|
||||||
// pending GUI-driven actions, to be applied at the next call to Sync
|
// pending GUI-driven actions, to be applied at the next call to Sync
|
||||||
struct {
|
struct {
|
||||||
std::optional<std::string> save_xml;
|
std::optional<std::string> save_xml;
|
||||||
|
|||||||
@@ -1595,10 +1595,6 @@ const char* mju_warningText(int warning, size_t info) {
|
|||||||
"Increase arena memory allocation above %s bytes.", mju_writeNumBytes(info));
|
"Increase arena memory allocation above %s bytes.", mju_writeNumBytes(info));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case mjWARN_VGEOMFULL:
|
|
||||||
mjSNPRINTF(str, "Pre-allocated visual geom buffer is full. Increase maxgeom above %zu.", info);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case mjWARN_BADQPOS:
|
case mjWARN_BADQPOS:
|
||||||
mjSNPRINTF(str, "Nan, Inf or huge value in QPOS at DOF %zu. The simulation is unstable.", info);
|
mjSNPRINTF(str, "Nan, Inf or huge value in QPOS at DOF %zu. The simulation is unstable.", info);
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -169,7 +169,11 @@ static int bodycategory(const mjModel* m, int bodyid) {
|
|||||||
mjvGeom* acquireGeom(mjvScene* scn, int objid, int category, int objtype) {
|
mjvGeom* acquireGeom(mjvScene* scn, int objid, int category, int objtype) {
|
||||||
// check for overflow, SHOULD NOT OCCUR
|
// check for overflow, SHOULD NOT OCCUR
|
||||||
if (scn->ngeom >= scn->maxgeom) {
|
if (scn->ngeom >= scn->maxgeom) {
|
||||||
scn->status = 1;
|
if (!scn->status) {
|
||||||
|
mju_warning("Pre-allocated visual geom buffer is full. "
|
||||||
|
"Increase maxgeom above %d.", scn->maxgeom);
|
||||||
|
scn->status = 1;
|
||||||
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3379,7 +3383,6 @@ void mjv_updateScene(const mjModel* m, mjData* d, const mjvOption* opt,
|
|||||||
const mjvPerturb* pert, mjvCamera* cam, int catmask, mjvScene* scn) {
|
const mjvPerturb* pert, mjvCamera* cam, int catmask, mjvScene* scn) {
|
||||||
// clear geoms
|
// clear geoms
|
||||||
scn->ngeom = 0;
|
scn->ngeom = 0;
|
||||||
scn->status = 0;
|
|
||||||
|
|
||||||
// trigger plugin visualization hooks
|
// trigger plugin visualization hooks
|
||||||
if (m->nplugin) {
|
if (m->nplugin) {
|
||||||
@@ -3416,10 +3419,6 @@ void mjv_updateScene(const mjModel* m, mjData* d, const mjvOption* opt,
|
|||||||
if (opt->flags[mjVIS_SKIN]) {
|
if (opt->flags[mjVIS_SKIN]) {
|
||||||
mjv_updateActiveSkin(m, d, scn, opt);
|
mjv_updateActiveSkin(m, d, scn, opt);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (scn->status) {
|
|
||||||
mj_warning(d, mjWARN_VGEOMFULL, scn->maxgeom);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -101,7 +101,6 @@ TEST_F(MjvSceneTest, UpdateSceneGeomsExhausted) {
|
|||||||
mjv_updateScene(model, data, &opt_, &pert_, &cam_, mjCAT_ALL, &scn_);
|
mjv_updateScene(model, data, &opt_, &pert_, &cam_, mjCAT_ALL, &scn_);
|
||||||
EXPECT_EQ(scn_.status, 1);
|
EXPECT_EQ(scn_.status, 1);
|
||||||
EXPECT_EQ(scn_.ngeom, maxgeoms);
|
EXPECT_EQ(scn_.ngeom, maxgeoms);
|
||||||
EXPECT_EQ(data->warning[mjWARN_VGEOMFULL].number, 1);
|
|
||||||
|
|
||||||
mj_deleteData(data);
|
mj_deleteData(data);
|
||||||
FreeSceneObjects();
|
FreeSceneObjects();
|
||||||
|
|||||||
@@ -489,12 +489,11 @@ public enum mjtWarning : int{
|
|||||||
mjWARN_INERTIA = 0,
|
mjWARN_INERTIA = 0,
|
||||||
mjWARN_CONTACTFULL = 1,
|
mjWARN_CONTACTFULL = 1,
|
||||||
mjWARN_CNSTRFULL = 2,
|
mjWARN_CNSTRFULL = 2,
|
||||||
mjWARN_VGEOMFULL = 3,
|
mjWARN_BADQPOS = 3,
|
||||||
mjWARN_BADQPOS = 4,
|
mjWARN_BADQVEL = 4,
|
||||||
mjWARN_BADQVEL = 5,
|
mjWARN_BADQACC = 5,
|
||||||
mjWARN_BADQACC = 6,
|
mjWARN_BADCTRL = 6,
|
||||||
mjWARN_BADCTRL = 7,
|
mjNWARNING = 7,
|
||||||
mjNWARNING = 8,
|
|
||||||
}
|
}
|
||||||
public enum mjtTimer : int{
|
public enum mjtTimer : int{
|
||||||
mjTIMER_STEP = 0,
|
mjTIMER_STEP = 0,
|
||||||
@@ -5699,7 +5698,6 @@ public unsafe struct mjData_ {
|
|||||||
public mjWarningStat_ warning4;
|
public mjWarningStat_ warning4;
|
||||||
public mjWarningStat_ warning5;
|
public mjWarningStat_ warning5;
|
||||||
public mjWarningStat_ warning6;
|
public mjWarningStat_ warning6;
|
||||||
public mjWarningStat_ warning7;
|
|
||||||
public mjTimerStat_ timer0;
|
public mjTimerStat_ timer0;
|
||||||
public mjTimerStat_ timer1;
|
public mjTimerStat_ timer1;
|
||||||
public mjTimerStat_ timer2;
|
public mjTimerStat_ timer2;
|
||||||
|
|||||||
@@ -359,22 +359,18 @@ public class MjScene : MonoBehaviour {
|
|||||||
}
|
}
|
||||||
if (Data->warning3.number > 0) {
|
if (Data->warning3.number > 0) {
|
||||||
Data->warning3.number = 0;
|
Data->warning3.number = 0;
|
||||||
throw new PhysicsRuntimeException("VGEOMFULL: who constructed a mjvScene?!");
|
throw new PhysicsRuntimeException("BADQPOS: NaN/inf in qpos.");
|
||||||
}
|
}
|
||||||
if (Data->warning4.number > 0) {
|
if (Data->warning4.number > 0) {
|
||||||
Data->warning4.number = 0;
|
Data->warning4.number = 0;
|
||||||
throw new PhysicsRuntimeException("BADQPOS: NaN/inf in qpos.");
|
throw new PhysicsRuntimeException("BADQVEL: NaN/inf in qvel.");
|
||||||
}
|
}
|
||||||
if (Data->warning5.number > 0) {
|
if (Data->warning5.number > 0) {
|
||||||
Data->warning5.number = 0;
|
Data->warning5.number = 0;
|
||||||
throw new PhysicsRuntimeException("BADQVEL: NaN/inf in qvel.");
|
throw new PhysicsRuntimeException("BADQACC: NaN/inf in qacc.");
|
||||||
}
|
}
|
||||||
if (Data->warning6.number > 0) {
|
if (Data->warning6.number > 0) {
|
||||||
Data->warning6.number = 0;
|
Data->warning6.number = 0;
|
||||||
throw new PhysicsRuntimeException("BADQACC: NaN/inf in qacc.");
|
|
||||||
}
|
|
||||||
if (Data->warning7.number > 0) {
|
|
||||||
Data->warning7.number = 0;
|
|
||||||
throw new PhysicsRuntimeException("BADCTRL: NaN/inf in ctrl.");
|
throw new PhysicsRuntimeException("BADCTRL: NaN/inf in ctrl.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11380,7 +11380,6 @@ EMSCRIPTEN_BINDINGS(mujoco_bindings) {
|
|||||||
.value("mjWARN_INERTIA", mjWARN_INERTIA)
|
.value("mjWARN_INERTIA", mjWARN_INERTIA)
|
||||||
.value("mjWARN_CONTACTFULL", mjWARN_CONTACTFULL)
|
.value("mjWARN_CONTACTFULL", mjWARN_CONTACTFULL)
|
||||||
.value("mjWARN_CNSTRFULL", mjWARN_CNSTRFULL)
|
.value("mjWARN_CNSTRFULL", mjWARN_CNSTRFULL)
|
||||||
.value("mjWARN_VGEOMFULL", mjWARN_VGEOMFULL)
|
|
||||||
.value("mjWARN_BADQPOS", mjWARN_BADQPOS)
|
.value("mjWARN_BADQPOS", mjWARN_BADQPOS)
|
||||||
.value("mjWARN_BADQVEL", mjWARN_BADQVEL)
|
.value("mjWARN_BADQVEL", mjWARN_BADQVEL)
|
||||||
.value("mjWARN_BADQACC", mjWARN_BADQACC)
|
.value("mjWARN_BADQACC", mjWARN_BADQACC)
|
||||||
|
|||||||
Reference in New Issue
Block a user