Improvements to object launcher.

PiperOrigin-RevId: 965834305
Change-Id: Ied8cea0e8eff8002d14f63b9ddea25f78a9a2985
This commit is contained in:
Yuval Tassa
2026-08-17 02:15:21 -07:00
committed by Copybara-Service
parent 2f1843f4a7
commit ba3f8cf180
@@ -36,7 +36,7 @@ class ObjectLauncher {
using platform::ImGui_ResetButton; using platform::ImGui_ResetButton;
using platform::ImGui_SliderLog; using platform::ImGui_SliderLog;
constexpr mjtNum kLifeDefault = 5.0; constexpr mjtNum kLifeDefault = 2.0;
ImGui_SliderLog("Size", &size_, size_seed_ * 0.1, size_seed_ * 10); ImGui_SliderLog("Size", &size_, size_seed_ * 0.1, size_seed_ * 10);
ImGui::BeginDisabled(size_ == size_seed_); ImGui::BeginDisabled(size_ == size_seed_);
if (ImGui_ResetButton("Size")) size_ = size_seed_; if (ImGui_ResetButton("Size")) size_ = size_seed_;
@@ -81,28 +81,44 @@ class ObjectLauncher {
void OnModelLoaded(const mjModel* model) { void OnModelLoaded(const mjModel* model) {
if (!model) return; if (!model) return;
Seed(model->stat.meansize, &size_, &size_seed_); // Geometric mean of two length estimates -- the mean geom size, and the
Seed(model->stat.meanmass, &mass_, &mass_seed_); // length implied by the mean mass at density 1000 -- so a bad meansize or
// meanmass only half-poisons the seed (they agree for a consistent model).
const mjtNum len_size = model->stat.meansize;
const mjtNum len_mass = std::cbrt(model->stat.meanmass / 1000.0);
mjtNum len = mju_sqrt(len_size * len_mass);
if (!(len > 0)) len = len_size > 0 ? len_size : len_mass;
const mjtNum size = 0.5 * len;
Seed(size, &size_, &size_seed_);
// Mass giving the default box (volume (2*size)^3) density 1000, MuJoCo's
// default geom density. Units are unspecified, so 1000 is just a convention.
const mjtNum box_volume = 8.0 * size * size * size;
Seed(1000.0 * box_volume, &mass_, &mass_seed_);
const mjtNum gravity = mju_norm3(model->opt.gravity); const mjtNum gravity = mju_norm3(model->opt.gravity);
const mjtNum g = gravity > mjMINVAL ? gravity : 9.81; const mjtNum g = gravity > mjMINVAL ? gravity : 9.81;
// Ballistic scale: the launch arc spans a few model extents. // Ballistic scale: the launch arc spans a few model extents.
Seed(1.5 * mju_sqrt(model->stat.extent * g), &speed_, &speed_seed_); Seed(3.0 * mju_sqrt(model->stat.extent * g), &speed_, &speed_seed_);
} }
bool UpdateSpecPreCompile(mjSpec* spec, const mjModel* model, bool UpdateSpecPreCompile(mjSpec* spec, const mjModel* model,
const mjData* data, const mjvCamera* camera) { const mjData* data, const mjvCamera* camera) {
// Remove expired objects. // Objects live on [creation_time, expiration]: drop them when the lifetime
// elapses, or when the sim rewinds before launch (so a reset clears them).
auto it = std::remove_if( auto it = std::remove_if(
objects_.begin(), objects_.end(), [&](const ObjectInfo& o) { objects_.begin(), objects_.end(), [&](const ObjectInfo& o) {
const bool expired = if (o.body_id < 0) {
o.body_id >= 0 && o.expiration != 0 && o.expiration < data->time; return false; // not yet compiled into the model
if (expired) { }
const bool expired = o.expiration != 0 && o.expiration < data->time;
const bool rewound = data->time < o.creation_time;
const bool remove = expired || rewound;
if (remove) {
mjsBody* body = mjs_findBody(spec, o.name.c_str()); mjsBody* body = mjs_findBody(spec, o.name.c_str());
if (body) { if (body) {
mjs_delete(spec, body->element); mjs_delete(spec, body->element);
} }
} }
return expired; return remove;
}); });
if (it != objects_.end()) { if (it != objects_.end()) {
objects_.erase(it, objects_.end()); objects_.erase(it, objects_.end());
@@ -123,7 +139,7 @@ class ObjectLauncher {
ObjectInfo& object = objects_.emplace_back(); ObjectInfo& object = objects_.emplace_back();
object.name = "projectile" + std::to_string(counter_++); object.name = "projectile" + std::to_string(counter_++);
; object.creation_time = data->time;
object.expiration = data->time + lifetime_; object.expiration = data->time + lifetime_;
mjtNum pos[3]; mjtNum pos[3];
@@ -193,6 +209,7 @@ class ObjectLauncher {
struct ObjectInfo { struct ObjectInfo {
std::string name; std::string name;
int body_id = -1; int body_id = -1;
mjtNum creation_time = 0;
mjtNum expiration = 0; mjtNum expiration = 0;
bool launched = false; bool launched = false;
}; };
@@ -203,7 +220,7 @@ class ObjectLauncher {
mjtNum size_ = 0.1; mjtNum size_ = 0.1;
mjtNum speed_ = 10.0; mjtNum speed_ = 10.0;
mjtNum mass_ = 10.0; mjtNum mass_ = 10.0;
mjtNum lifetime_ = 5.0; mjtNum lifetime_ = 2.0;
mjtNum size_seed_ = 0.1; mjtNum size_seed_ = 0.1;
mjtNum speed_seed_ = 10.0; mjtNum speed_seed_ = 10.0;
mjtNum mass_seed_ = 10.0; mjtNum mass_seed_ = 10.0;