use crate::environment::{FrankaEnvironment, FrankaRealEnvironment, FrankaSimEnvironment};
use crate::{FrankaReal, FrankaSim, FrankaSimWithoutClient, Robot, RobotArguments};
use rubullet::image::RgbaImage;
use rubullet::PhysicsClient;
use std::cell::{RefCell, RefMut};
use std::path::PathBuf;
use std::rc::Rc;
use std::time::Duration;
pub enum Mode {
Simulation,
Real,
}
pub trait SimulationSetup {
fn set_simulation_time_step(&self) -> Duration {
Duration::from_secs_f64(1. / 240.)
}
fn set_franka_urdf_path(&self) -> PathBuf;
fn setup_simulation(&mut self, _client: Rc<RefCell<PhysicsClient>>) {}
fn setup_camera(&mut self, _client: Rc<RefCell<PhysicsClient>>) {}
fn get_camera_image(&mut self, _client: Rc<RefCell<PhysicsClient>>) -> RgbaImage {
RgbaImage::default()
}
}
pub trait RealSetup {
fn setup_real(&mut self) {}
fn setup_camera(&mut self) {}
fn get_camera_image(&mut self) -> RgbaImage {
RgbaImage::default()
}
}
pub struct Experiment<Sim: ?Sized + SimulationSetup, Real: ?Sized + RealSetup> {
pub environment: FrankaEnvironment,
pub sim_setup: Box<Sim>,
pub real_setup: Box<Real>,
}
impl Experiment<dyn SimulationSetup, dyn RealSetup> {
pub fn new(
mode: Mode,
mut sim_setup: impl SimulationSetup + 'static,
mut real_setup: impl RealSetup + 'static,
) -> Experiment<dyn SimulationSetup, dyn RealSetup> {
match mode {
Mode::Simulation => {
let environment = Box::new(FrankaSimEnvironment::new(
sim_setup.set_simulation_time_step(),
));
sim_setup.setup_simulation(environment.client.clone());
sim_setup.setup_camera(environment.client.clone());
let environment = FrankaEnvironment::Simulation(environment);
Experiment {
environment,
sim_setup: Box::new(sim_setup),
real_setup: Box::new(real_setup),
}
}
Mode::Real => {
let environment = FrankaEnvironment::Real(Box::new(FrankaRealEnvironment::new()));
real_setup.setup_real();
real_setup.setup_camera();
Experiment {
environment,
sim_setup: Box::new(sim_setup),
real_setup: Box::new(real_setup),
}
}
}
}
pub fn get_image(&mut self) -> RgbaImage {
match &self.environment {
FrankaEnvironment::Real(_) => self.real_setup.get_camera_image(),
FrankaEnvironment::Simulation(environment) => {
self.sim_setup.get_camera_image(environment.client.clone())
}
}
}
pub fn new_robot(&mut self, config: RobotArguments) -> Robot {
match &mut self.environment {
FrankaEnvironment::Real(_environment) => {
Robot::Real(FrankaReal::new(config.hostname.as_str()))
}
FrankaEnvironment::Simulation(environment) => {
let args = FrankaSimWithoutClient {
urdf_path: self.sim_setup.set_franka_urdf_path(),
base_pose: config.base_pose,
initial_config: config.initial_config,
};
Robot::Sim(FrankaSim::new(
environment.client.clone(),
args,
&environment.time_step,
))
}
}
}
pub fn is_simulation(&self) -> bool {
match self.environment {
FrankaEnvironment::Simulation(_) => true,
FrankaEnvironment::Real(_) => false,
}
}
pub fn use_physics_client<F: FnMut(RefMut<PhysicsClient>) -> T, T>(
&mut self,
mut client_cb: F,
) -> Option<T> {
match &self.environment {
FrankaEnvironment::Simulation(sim) => Some(client_cb(sim.client.borrow_mut())),
FrankaEnvironment::Real(_) => None,
}
}
}