Runtime disabling of actuators according to group.

Added `option-actuatorgroupdisable` attribute and associated `mjOption.disableactuator` integer bitfield, used to disable sets of actuators at runtime according to their group.

- The first 6 actuator groups are toggleable in the `simulate` viewer.
- Minor refactor and cleanup of actuator documentation.

https://youtu.be/H9qG9Zf2W44

Fixes #1092.

PiperOrigin-RevId: 578335600
Change-Id: I4cf663b90ea768e4380acfa2fe3b8c15c7cbb568
This commit is contained in:
Yuval Tassa
2023-10-31 16:23:58 -07:00
committed by Copybara-Service
parent 45878b7eef
commit 893c404230
25 changed files with 525 additions and 125 deletions
+71 -14
View File
@@ -716,6 +716,16 @@ void MakePhysicsSection(mj::Simulate* sim, int oldstate) {
{mjITEM_EDITNUM, "Friction", 2, &(opt->o_friction), "5"},
{mjITEM_END}
};
mjuiDef defDisableActuator[] = {
{mjITEM_SEPARATOR, "Actuator Group Enable", 1},
{mjITEM_CHECKBYTE, "Act Group 0", 2, sim->enableactuator+0, " 0"},
{mjITEM_CHECKBYTE, "Act Group 1", 2, sim->enableactuator+1, " 1"},
{mjITEM_CHECKBYTE, "Act Group 2", 2, sim->enableactuator+2, " 2"},
{mjITEM_CHECKBYTE, "Act Group 3", 2, sim->enableactuator+3, " 3"},
{mjITEM_CHECKBYTE, "Act Group 4", 2, sim->enableactuator+4, " 4"},
{mjITEM_CHECKBYTE, "Act Group 5", 2, sim->enableactuator+5, " 5"},
{mjITEM_END}
};
// add physics
mjui_add(&sim->ui0, defPhysics);
@@ -736,9 +746,11 @@ void MakePhysicsSection(mj::Simulate* sim, int oldstate) {
defFlag[0].pdata = sim->enable + i;
mjui_add(&sim->ui0, defFlag);
}
// add contact override
mjui_add(&sim->ui0, defOverride);
// add actuator group enable/disable
mjui_add(&sim->ui0, defDisableActuator);
}
@@ -1002,7 +1014,7 @@ void MakeJointSection(mj::Simulate* sim, int oldstate) {
// add scalar joints, exit if UI limit reached
int itemcnt = 0;
for (int i=0; i < sim->jnt_type_.size() && itemcnt<mjMAXUIITEM; i++)
for (int i=0; i < sim->jnt_type_.size() && itemcnt<mjMAXUIITEM; i++) {
if ((sim->jnt_type_[i]==mjJNT_HINGE || sim->jnt_type_[i]==mjJNT_SLIDE)) {
// skip if joint group is disabled
if (!sim->opt.jointgroup[mjMAX(0, mjMIN(mjNGROUP-1, sim->jnt_group_[i]))]) {
@@ -1035,6 +1047,7 @@ void MakeJointSection(mj::Simulate* sim, int oldstate) {
mjui_add(&sim->ui1, defSlider);
itemcnt++;
}
}
}
// make control section of UI
@@ -1051,15 +1064,21 @@ void MakeControlSection(mj::Simulate* sim, int oldstate) {
// add section
mjui_add(&sim->ui1, defControl);
defSlider[0].state = 2;
// add controls, exit if UI limit reached (Clear button already added)
int itemcnt = 1;
for (int i=0; i < sim->actuator_ctrlrange_.size() && itemcnt<mjMAXUIITEM; i++) {
// skip if actuator group is disabled
if (!sim->opt.actuatorgroup[mjMAX(0, mjMIN(mjNGROUP-1, sim->actuator_group_[i]))]) {
// skip if actuator vis group is disabled
int group = sim->actuator_group_[i];
if (!sim->opt.actuatorgroup[mjMAX(0, mjMIN(mjNGROUP-1, group))]) {
continue;
}
// grey out if actuator group is disabled
if (group >= 0 && group <= 30 && sim->m_->opt.disableactuator & (1 << group)) {
defSlider[0].state = 0;
} else {
defSlider[0].state = 2;
}
// set data and name
if (!sim->is_passive_) {
@@ -1189,19 +1208,27 @@ void CopyCamera(mj::Simulate* sim) {
void UpdateSettings(mj::Simulate* sim, const mjModel* m) {
// physics flags
for (int i=0; i<mjNDISABLE; i++) {
int new_value = ((m->opt.disableflags & (1<<i)) !=0);
int new_value = ((m->opt.disableflags & (1<<i)) != 0);
if (sim->disable[i] != new_value) {
sim->disable[i] = new_value;
sim->pending_.ui_update_physics = true;
}
}
for (int i=0; i<mjNENABLE; i++) {
int new_value = ((m->opt.enableflags & (1<<i)) !=0);
int new_value = ((m->opt.enableflags & (1<<i)) != 0);
if (sim->enable[i] != new_value) {
sim->enable[i] = new_value;
sim->pending_.ui_update_physics = true;
}
}
for (int i=0; i<mjNGROUP; i++) {
int enabled = ((m->opt.disableactuator & (1<<i)) == 0);
if (sim->enableactuator[i] != enabled) {
sim->enableactuator[i] = enabled;
sim->pending_.ui_update_physics = true;
sim->pending_.ui_remake_ctrl = true;
}
}
// camera
int old_camera = sim->camera;
@@ -1404,17 +1431,39 @@ void UiEvent(mjuiState* state) {
// update disable flags in mjOption
opt->disableflags = 0;
for (int i=0; i<mjNDISABLE; i++)
for (int i=0; i<mjNDISABLE; i++) {
if (sim->disable[i]) {
opt->disableflags |= (1<<i);
}
}
// update enable flags in mjOption
opt->enableflags = 0;
for (int i=0; i<mjNENABLE; i++)
for (int i=0; i<mjNENABLE; i++) {
if (sim->enable[i]) {
opt->enableflags |= (1<<i);
}
}
// update disableactuator bitflag in mjOption
bool group_changed = false;
for (int i=0; i<mjNGROUP; i++) {
if ((!sim->enableactuator[i]) != (opt->disableactuator & (1<<i))) {
group_changed = true;
if (!sim->enableactuator[i]) {
// disable actuator group i
opt->disableactuator |= (1<<i);
} else {
// enable actuator group i
opt->disableactuator &= ~(1<<i);
}
}
}
// remake control section if actuator disable group changed
if (group_changed) {
sim->pending_.ui_remake_ctrl = true;
}
}
// rendering section
@@ -1461,10 +1510,7 @@ void UiEvent(mjuiState* state) {
// remake control section if actuator group changed
if (it->name[0]=='A' && it->name[1]=='c') {
sim->ui1.nsect = SECT_CONTROL;
MakeControlSection(sim, sim->ui1.sect[SECT_CONTROL].state);
sim->ui1.nsect = NSECT1;
UiModify(&sim->ui1, state, &sim->platform_ui->mjr_context());
sim->pending_.ui_remake_ctrl = true;
}
}
@@ -1790,7 +1836,7 @@ void Simulate::Sync() {
range.emplace(m_->actuator_ctrlrange[2*i], m_->actuator_ctrlrange[2*i + 1]);
}
if (actuator_ctrlrange_[i] != range) {
pending_.ui_update_ctrl = true;
pending_.ui_remake_ctrl = true;
actuator_ctrlrange_[i].swap(range);
}
}
@@ -1851,6 +1897,7 @@ void Simulate::Sync() {
X(mpr_iterations);
X(disableflags);
X(enableflags);
X(disableactuator);
X(sdf_initpoints);
X(sdf_iterations);
@@ -2399,6 +2446,16 @@ void Simulate::Render() {
pending_.ui_update_joint = false;
}
if (pending_.ui_remake_ctrl) {
if (this->ui1_enable && this->ui1.sect[SECT_CONTROL].state) {
this->ui1.nsect = SECT_CONTROL;
MakeControlSection(this, this->ui1.sect[SECT_CONTROL].state);
this->ui1.nsect = NSECT1;
UiModify(&this->ui1, &this->uistate, &this->platform_ui->mjr_context());
}
pending_.ui_remake_ctrl = false;
}
if (pending_.ui_update_ctrl) {
if (this->ui1_enable && this->ui1.sect[SECT_CONTROL].state) {
mjui_update(SECT_CONTROL, -1, &this->ui1, &this->uistate, &this->platform_ui->mjr_context());
+2
View File
@@ -153,6 +153,7 @@ class Simulate {
bool ui_update_rendering;
bool ui_update_joint;
bool ui_update_ctrl;
bool ui_remake_ctrl;
} pending_ = {};
SimulateMutex mtx;
@@ -228,6 +229,7 @@ class Simulate {
// physics: need sync
int disable[mjNDISABLE] = {0};
int enable[mjNENABLE] = {0};
int enableactuator[mjNGROUP] = {0};
// rendering: need sync
int camera = 0;