use crate::{Env, Agent, ReplayBufferBase, StepProcessorBase, record::Record};
use anyhow::Result;
pub struct SyncSampler<E, P>
where
E: Env,
P: StepProcessorBase<E>,
{
env: E,
prev_obs: Option<E::Obs>,
producer: P,
n_frames: usize,
time: f32,
}
impl<E, P> SyncSampler<E, P>
where
E: Env,
P: StepProcessorBase<E>,
{
pub fn new(env: E, producer: P) -> Self {
Self {
env,
prev_obs: None,
producer,
n_frames: 0,
time: 0f32,
}
}
pub fn sample_and_push<A, R, R_>(&mut self, agent: &mut A, buffer: &mut R_) -> Result<Record>
where
A: Agent<E, R>,
R: ReplayBufferBase<PushedItem = P::Output>,
R_: ReplayBufferBase<PushedItem = R::PushedItem>,
{
let now = std::time::SystemTime::now();
if self.prev_obs.is_none() {
self.prev_obs = Some(self.env.reset(None)?);
self.producer.reset(self.prev_obs.as_ref().unwrap().clone());
}
let act = agent.sample(self.prev_obs.as_ref().unwrap());
let (step, record) = self.env.step_with_reset(&act);
self.prev_obs = Some(step.obs.clone());
let transition = self.producer.process(step);
buffer.push(transition)?;
if let Ok(time) = now.elapsed() {
self.n_frames += 1;
self.time += time.as_millis() as f32;
}
Ok(record)
}
pub fn fps(&self) -> f32 {
self.n_frames as f32 / self.time * 1000f32
}
pub fn reset(&mut self) {
self.n_frames = 0;
self.time = 0f32;
}
}