#![warn(missing_docs)]
use nalgebra::{Isometry3, Matrix3, UnitQuaternion, Vector2, Vector3};
#[cfg(feature = "grawoow")]
pub mod grawoow;
#[cfg(feature = "mad_gaze")]
pub mod mad_gaze;
#[cfg(feature = "nreal")]
pub mod nreal_air;
#[cfg(feature = "nreal")]
pub mod nreal_light;
#[cfg(feature = "rokid")]
pub mod rokid;
mod util;
#[derive(Debug)]
pub enum Error {
IoError(std::io::Error),
#[cfg(feature = "rusb")]
UsbError(rusb::Error),
#[cfg(feature = "hidapi")]
HidError(hidapi::HidError),
#[cfg(feature = "serialport")]
SerialPortError(serialport::Error),
NotFound,
PacketTimeout,
Other(&'static str),
}
type Result<T> = std::result::Result<T, Error>;
impl std::error::Error for Error {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
match self {
Error::IoError(e) => Some(e),
#[cfg(feature = "rusb")]
Error::UsbError(e) => Some(e),
#[cfg(feature = "hidapi")]
Error::HidError(e) => Some(e),
#[cfg(feature = "serialport")]
Error::SerialPortError(e) => Some(e),
_ => None,
}
}
}
impl std::fmt::Display for Error {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_str(match self {
Error::IoError(_) => "I/O error",
#[cfg(feature = "rusb")]
Error::UsbError(_) => "Libusb error",
#[cfg(feature = "hidapi")]
Error::HidError(_) => "Hidapi error",
#[cfg(feature = "serialport")]
Error::SerialPortError(_) => "Serial error",
Error::NotFound => "Glasses not found",
Error::PacketTimeout => "Packet timeout",
Error::Other(s) => s,
})
}
}
#[derive(Debug, Clone)]
pub enum GlassesEvent {
AccGyro {
accelerometer: Vector3<f32>,
gyroscope: Vector3<f32>,
timestamp: u64,
},
Magnetometer {
magnetometer: Vector3<f32>,
timestamp: u64,
},
KeyPress(u8),
ProximityNear,
ProximityFar,
AmbientLight(u16),
VSync,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum DisplayMode {
SameOnBoth,
Stereo,
HalfSBS,
HighRefreshRate,
HighRefreshRateSBS,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Side {
Left,
Right,
}
pub trait ARGlasses: Send {
fn serial(&mut self) -> Result<String>;
fn read_event(&mut self) -> Result<GlassesEvent>;
fn get_display_mode(&mut self) -> Result<DisplayMode>;
fn set_display_mode(&mut self, display_mode: DisplayMode) -> Result<()>;
fn display_fov(&self) -> f32;
fn imu_to_display_matrix(&self, side: Side, ipd: f32) -> Isometry3<f64>;
fn name(&self) -> &'static str;
fn cameras(&self) -> Result<Vec<CameraDescriptor>> {
Ok(Vec::new())
}
fn display_delay(&self) -> u64;
}
#[derive(Debug, Clone)]
pub struct CameraDescriptor {
pub name: &'static str,
pub resolution: Vector2<f64>,
pub intrinsic_matrix: Matrix3<f64>,
pub distortion: [f64; 5],
pub stereo_rotation: UnitQuaternion<f64>,
pub imu_to_camera: Isometry3<f64>,
}
#[cfg(not(target_os = "android"))]
pub fn any_glasses() -> Result<Box<dyn ARGlasses>> {
#[cfg(feature = "rokid")]
if let Ok(glasses) = rokid::RokidAir::new() {
return Ok(Box::new(glasses));
};
#[cfg(feature = "nreal")]
if let Ok(glasses) = nreal_air::NrealAir::new() {
return Ok(Box::new(glasses));
};
#[cfg(feature = "nreal")]
if let Ok(glasses) = nreal_light::NrealLight::new() {
return Ok(Box::new(glasses));
};
#[cfg(feature = "grawoow")]
if let Ok(glasses) = grawoow::GrawoowG530::new() {
return Ok(Box::new(glasses));
};
#[cfg(feature = "mad_gaze")]
if let Ok(glasses) = mad_gaze::MadGazeGlow::new() {
return Ok(Box::new(glasses));
};
Err(Error::NotFound)
}
impl From<std::io::Error> for Error {
fn from(e: std::io::Error) -> Self {
Error::IoError(e)
}
}
#[cfg(feature = "rusb")]
impl From<rusb::Error> for Error {
fn from(e: rusb::Error) -> Self {
Error::UsbError(e)
}
}
#[cfg(feature = "hidapi")]
impl From<hidapi::HidError> for Error {
fn from(e: hidapi::HidError) -> Self {
Error::HidError(e)
}
}
#[cfg(feature = "serialport")]
impl From<serialport::Error> for Error {
fn from(e: serialport::Error) -> Self {
Error::SerialPortError(e)
}
}
impl From<&'static str> for Error {
fn from(e: &'static str) -> Self {
Error::Other(e)
}
}