Fix bug in simulate noise injection logic.

Noise injection was occurring at every iteration of the physics thread, rather than before every call to `mj_step`, leading to time-step-dependent noise rate.

- Moved the logic from main.cc to a `Simulate::` method, called before `mj_step`.
- Reduced the maximum time-scale slider value back to 4 seconds (recent increase was due to this bug).

PiperOrigin-RevId: 643350296
Change-Id: I96832905e6614f92ac725298b16fcabe64ea1df1
This commit is contained in:
Yuval Tassa
2024-06-14 08:12:12 -07:00
committed by Copybara-Service
parent 3d63c873aa
commit 6a532fc53e
3 changed files with 40 additions and 29 deletions
+33
View File
@@ -2741,6 +2741,39 @@ void Simulate::AddToHistory() {
mj_getState(m_, d_, state, mjSTATE_INTEGRATION);
}
// inject Brownian noise
void Simulate::InjectNoise() {
// no noise, return
if (ctrl_noise_std <= 0) {
return;
}
// convert rate and scale to discrete time (Ornstein–Uhlenbeck)
mjtNum rate = mju_exp(-m_->opt.timestep / ctrl_noise_rate);
mjtNum scale = ctrl_noise_std * mju_sqrt(1-rate*rate);
for (int i=0; i<m_->nu; i++) {
mjtNum bottom = 0, top = 0, midpoint = 0, halfrange = 1;
if (m_->actuator_ctrllimited[i]) {
bottom = m_->actuator_ctrlrange[2*i];
top = m_->actuator_ctrlrange[2*i+1];
midpoint = 0.5 * (top + bottom); // target of exponential decay
halfrange = 0.5 * (top - bottom); // scales noise
}
// exponential convergence to midpoint at ctrl_noise_rate
d_->ctrl[i] = rate * d_->ctrl[i] + (1-rate) * midpoint;
// add noise
d_->ctrl[i] += scale * halfrange * mju_standardNormal(nullptr);
// clip to range if limited
if (m_->actuator_ctrllimited[i]) {
d_->ctrl[i] = mju_clip(d_->ctrl[i], bottom, top);
}
}
}
void Simulate::UpdateHField(int hfieldid) {
MutexLock lock(this->mtx);
if (!m_ || hfieldid < 0 || hfieldid >= m_->nhfield) {