use std::fs::File;
use std::io::{BufRead, BufReader, Read};
use std::path::Path;
use crate::types::combined_position_orientation_array_to_isometry;
use crate::{BodyId, Error, Velocity};
use nalgebra::{DVector, Isometry3, Vector6};
use std::convert::TryInto;
use std::fmt;
use std::fmt::{Display, Formatter};
use std::time::Duration;
#[derive(Debug)]
pub struct GenericRobotLog {
pub chunk_number: usize,
pub step_count: usize,
pub time_stamp: Duration,
pub body: BodyId,
pub base_pose: Isometry3<f64>,
pub base_velocity: Velocity,
pub num_joints: usize,
pub joint_positions: DVector<f64>,
pub joint_velocities: DVector<f64>,
}
impl Display for GenericRobotLog {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
writeln!(f, "chunk # {}", self.chunk_number)?;
writeln!(f, "step count = {}", self.step_count)?;
writeln!(f, "body = {:?}", self.body)?;
writeln!(f, "Base Pose:")?;
writeln!(f, "{}", self.base_pose.to_homogeneous())?;
writeln!(f, "Base Velocity:")?;
writeln!(f, "{}", self.base_velocity.to_vector())?;
writeln!(f, "num joints = {}", self.num_joints)?;
writeln!(f, "joint positions:")?;
writeln!(f, "{:?}", self.joint_positions.as_slice())?;
writeln!(f, "joint velocities:")?;
writeln!(f, "{:?}", self.joint_velocities.as_slice())
}
}
impl Default for GenericRobotLog {
fn default() -> Self {
GenericRobotLog {
chunk_number: 0,
step_count: 0,
time_stamp: Default::default(),
body: BodyId(-1),
base_pose: Isometry3::identity(),
base_velocity: Vector6::zeros().into(),
num_joints: 0,
joint_positions: DVector::identity(1),
joint_velocities: DVector::identity(1),
}
}
}
fn calc_size(fmt: &str) -> usize {
let mut size = 0;
for c in fmt.chars() {
size += match c {
'I' | 'i' | 'f' => 4,
'B' => 1,
_ => {
panic!("can not determine data type")
}
};
}
size
}
pub fn read_generic_robot_log<P: AsRef<Path>>(filename: P) -> Result<Vec<GenericRobotLog>, Error> {
let file = File::open(filename).map_err(|_| Error::new("could not open file"))?;
let mut reader = BufReader::new(file);
let mut key_buf = String::new();
reader
.read_line(&mut key_buf)
.expect("error while reading file");
let mut fmt_buf = String::new();
reader
.read_line(&mut fmt_buf)
.expect("error while reading file");
let fmt = fmt_buf.strip_suffix("\n").unwrap();
assert_eq!("IfifffffffffffffI", &fmt[0..17]);
let sz = calc_size(fmt);
let mut chunk_index = 0;
let mut logs = Vec::<GenericRobotLog>::new();
loop {
let mut check_buf = [0_u8; 2];
match reader.read_exact(&mut check_buf) {
Ok(_) => {}
Err(_) => {
return Ok(logs);
}
}
assert_eq!(
&check_buf,
&[170_u8, 187_u8],
"Error, expected aabb terminal"
);
let mut buf = vec![0_u8; sz];
reader.read_exact(&mut buf).unwrap();
let mut log = GenericRobotLog {
chunk_number: chunk_index,
..Default::default()
};
chunk_index += 1;
log.step_count = u32::from_le_bytes(buf[0..4].try_into().unwrap()) as usize;
log.time_stamp = Duration::from_secs_f32(f32::from_le_bytes(buf[4..8].try_into().unwrap()));
log.body = BodyId(i32::from_le_bytes(buf[8..12].try_into().unwrap()));
assert!(log.body.0 >= 0);
let mut pose_elements = [0.; 7];
for i in 0..7 {
pose_elements[i] =
f32::from_le_bytes(buf[12 + 4 * i..16 + 4 * i].try_into().unwrap()) as f64;
}
log.base_pose = combined_position_orientation_array_to_isometry(pose_elements);
let mut velocity_elements = [0.; 6];
for i in 0..6 {
velocity_elements[i] =
f32::from_le_bytes(buf[40 + 4 * i..44 + 4 * i].try_into().unwrap()) as f64;
}
let vel_vec: Vector6<f64> = velocity_elements.into();
log.base_velocity = vel_vec.into();
log.num_joints = u32::from_le_bytes(buf[64..68].try_into().unwrap()) as usize;
let remaining = sz - 68;
assert_eq!(remaining % 8, 0);
let mut joint_positions = DVector::<f64>::from(vec![0.; log.num_joints]);
for i in 0..log.num_joints {
joint_positions[i] =
f32::from_le_bytes(buf[68 + 4 * i..72 + 4 * i].try_into().unwrap()) as f64;
}
let mut joint_velocities = DVector::<f64>::from(vec![0.; log.num_joints]);
let start_byte = 68 + remaining / 2;
for i in 0..log.num_joints {
joint_velocities[i] = f32::from_le_bytes(
buf[start_byte + 4 * i..start_byte + 4 + 4 * i]
.try_into()
.unwrap(),
) as f64;
}
log.joint_positions = joint_positions;
log.joint_velocities = joint_velocities;
logs.push(log);
}
}