Add actuator and sensor delays. Fixes #1004
PiperOrigin-RevId: 866478839 Change-Id: Id21a6da0f98454c8fa39ea5af8a5e213d6eae497
This commit is contained in:
committed by
Copybara-Service
parent
84fa527723
commit
6419534bad
+113
-1
@@ -132,6 +132,7 @@ static inline int mj_stateElemSize(const mjModel* m, mjtState sig) {
|
||||
case mjSTATE_QPOS: return m->nq;
|
||||
case mjSTATE_QVEL: return m->nv;
|
||||
case mjSTATE_ACT: return m->na;
|
||||
case mjSTATE_HISTORY: return m->nhistory;
|
||||
case mjSTATE_WARMSTART: return m->nv;
|
||||
case mjSTATE_CTRL: return m->nu;
|
||||
case mjSTATE_QFRC_APPLIED: return m->nv;
|
||||
@@ -155,6 +156,7 @@ static inline mjtNum* mj_stateElemPtr(const mjModel* m, mjData* d, mjtState sig)
|
||||
case mjSTATE_QPOS: return d->qpos;
|
||||
case mjSTATE_QVEL: return d->qvel;
|
||||
case mjSTATE_ACT: return d->act;
|
||||
case mjSTATE_HISTORY: return d->history;
|
||||
case mjSTATE_WARMSTART: return d->qacc_warmstart;
|
||||
case mjSTATE_CTRL: return d->ctrl;
|
||||
case mjSTATE_QFRC_APPLIED: return d->qfrc_applied;
|
||||
@@ -619,7 +621,7 @@ void mj_differentiatePos(const mjModel* m, mjtNum* qvel, mjtNum dt,
|
||||
vadr += 3;
|
||||
padr += 3;
|
||||
|
||||
// continute with rotations
|
||||
// continue with rotations
|
||||
mjFALLTHROUGH;
|
||||
|
||||
case mjJNT_BALL:
|
||||
@@ -806,3 +808,113 @@ void mju_camIntrinsics(const mjModel* m, int camid,
|
||||
// extent only used for orthographic cameras
|
||||
*extent = m->cam_fovy[camid];
|
||||
}
|
||||
|
||||
|
||||
// read delayed ctrl value for actuator at given time
|
||||
mjtNum mj_readCtrl(const mjModel* m, const mjData* d, int id, mjtNum time, int interp) {
|
||||
// validate actuator id
|
||||
if (id < 0 || id >= m->nu) {
|
||||
mjERROR("invalid actuator id %d", id);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// no delay: return current ctrl value
|
||||
int nsample = m->actuator_history[2*id];
|
||||
if (nsample == 0) {
|
||||
return d->ctrl[id];
|
||||
}
|
||||
|
||||
// resolve interpolation order: use model's interp if argument is -1
|
||||
if (interp < 0) interp = m->actuator_history[2*id+1];
|
||||
|
||||
// get buffer pointer and read from history buffer
|
||||
mjtNum delay = m->actuator_delay[id];
|
||||
const mjtNum* buf = d->history + m->actuator_historyadr[id];
|
||||
mjtNum res;
|
||||
const mjtNum* ptr = mju_delayRead(buf, nsample, /*dim=*/1, &res, time - delay, interp);
|
||||
return ptr ? *ptr : res;
|
||||
}
|
||||
|
||||
|
||||
// read sensor value from history buffer at given time
|
||||
const mjtNum* mj_readSensor(const mjModel* m, const mjData* d, int id, mjtNum time,
|
||||
mjtNum* result, int interp) {
|
||||
// validate sensor id
|
||||
if (id < 0 || id >= m->nsensor) {
|
||||
mjERROR("invalid sensor id %d", id);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// no history: return current sensor value
|
||||
int nsample = m->sensor_history[2*id];
|
||||
if (nsample == 0) {
|
||||
return d->sensordata + m->sensor_adr[id];
|
||||
}
|
||||
|
||||
// resolve interpolation order: use model's interp if argument is -1
|
||||
if (interp < 0) interp = m->sensor_history[2*id+1];
|
||||
|
||||
// get buffer pointer and read from history buffer
|
||||
int dim = m->sensor_dim[id];
|
||||
mjtNum delay = m->sensor_delay[id];
|
||||
const mjtNum* buf = d->history + m->sensor_historyadr[id];
|
||||
return mju_delayRead(buf, nsample, dim, result, time - delay, interp);
|
||||
}
|
||||
|
||||
|
||||
// initialize history buffer for actuator
|
||||
void mj_initCtrlHistory(const mjModel* m, mjData* d, int id,
|
||||
const mjtNum* times, const mjtNum* values) {
|
||||
// validate actuator id
|
||||
if (id < 0 || id >= m->nu) {
|
||||
mjERROR("invalid actuator id %d", id);
|
||||
return;
|
||||
}
|
||||
|
||||
// check that actuator has a history buffer
|
||||
int nsample = m->actuator_history[2*id];
|
||||
if (nsample == 0) {
|
||||
mjERROR("actuator %d has no history buffer", id);
|
||||
return;
|
||||
}
|
||||
|
||||
// get buffer pointer
|
||||
mjtNum* buf = d->history + m->actuator_historyadr[id];
|
||||
|
||||
// if times is NULL, use existing buffer times
|
||||
const mjtNum* buf_times = times ? times : buf + 2;
|
||||
|
||||
// get existing user value (preserve it)
|
||||
mjtNum user = buf[0];
|
||||
|
||||
// initialize history buffer
|
||||
mju_delayInit(buf, nsample, 1, buf_times, values, user);
|
||||
}
|
||||
|
||||
|
||||
// initialize history buffer for sensor
|
||||
void mj_initSensorHistory(const mjModel* m, mjData* d, int id,
|
||||
const mjtNum* times, const mjtNum* values, mjtNum phase) {
|
||||
// validate sensor id
|
||||
if (id < 0 || id >= m->nsensor) {
|
||||
mjERROR("invalid sensor id %d", id);
|
||||
return;
|
||||
}
|
||||
|
||||
// check that sensor has a history buffer
|
||||
int nsample = m->sensor_history[2*id];
|
||||
if (nsample == 0) {
|
||||
mjERROR("sensor %d has no history buffer", id);
|
||||
return;
|
||||
}
|
||||
|
||||
// get buffer pointer and dimension
|
||||
mjtNum* buf = d->history + m->sensor_historyadr[id];
|
||||
int dim = m->sensor_dim[id];
|
||||
|
||||
// if times is NULL, use existing buffer times
|
||||
const mjtNum* buf_times = times ? times : buf + 2;
|
||||
|
||||
// initialize history buffer with provided phase
|
||||
mju_delayInit(buf, nsample, dim, buf_times, values, phase);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user