Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

orb-ui: show car simulation #223

Closed
wants to merge 52 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
52 commits
Select commit Hold shift + click to select a range
7438e93
orb-ui: self-serve ui
fouge Sep 12, 2024
487a972
orb-ui: colors
fouge Sep 13, 2024
580b153
orb-ui: set repeat count to wave animation
fouge Sep 16, 2024
fe2fbaf
orb-ui: diamond: remove shutdown animation
fouge Sep 16, 2024
4067caf
orb-ui: diamond: newest colors & animations
fouge Sep 16, 2024
1af4f5c
orb-ui: logs: dbus logging set to trace instead of debug
fouge Sep 17, 2024
683084a
orb-ui: diamond: shroud with 3 second-periods
fouge Sep 17, 2024
4557078
orb-ui: diamond: fix delays in shroud breathing and outer ring progress
fouge Sep 17, 2024
853d625
orb-ui: diamond: simulation adds QR scan capture clicks
fouge Sep 17, 2024
0c52cda
orb-ui: diamond: tweak a bit more the colors
fouge Sep 17, 2024
41d6b71
orb-ui: diamond: clippy
fouge Sep 17, 2024
3e400cb
orb-ui: sound: add delay to sound
fouge Sep 17, 2024
0143fde
orb-ui: simulation
fouge Sep 17, 2024
a6111be
rgb: dimmer shroud
fouge Sep 19, 2024
38f813f
orb-ui: diamond: simulation with gimbal motion
fouge Sep 17, 2024
46171e7
orb-ui: diamond: gimbal facing user as much as possible in idle state
fouge Sep 17, 2024
08f5a0c
orb-ui: diamond: special show-car mode with gimbal movement
fouge Sep 18, 2024
aa69b69
orb-ui: new "show-car" spectacle
fouge Sep 19, 2024
5fb35cd
orb-ui: adapt brightness with ring location
fouge Sep 20, 2024
8517f46
orb-ui: latest ui
fouge Sep 20, 2024
c7d34c5
orb-ui: milkyway with more frank colors
fouge Sep 23, 2024
02239f9
orb-ui: fix clippy
fouge Sep 23, 2024
e38652b
orb-ui: simulation with updated mirror movements
fouge Sep 23, 2024
cd8b2b4
orb-ui: one sound on capture start
fouge Sep 23, 2024
e46e909
orb-ui: rolled back shroud color
fouge Sep 23, 2024
9aa7bae
orb-ui: simulations tweaked
fouge Sep 23, 2024
8311ca1
orb-ui: sounds to start capture in self-serve
fouge Sep 24, 2024
fb7bce6
orb-ui: fix faster spinner
fouge Sep 24, 2024
737e441
orb-ui: fix force stop for animations
fouge Sep 25, 2024
9cc18c9
orb-ui: add names to animations
fouge Sep 25, 2024
af120fd
orb-ui: more tweaks
fouge Sep 25, 2024
ec70645
orb-ui: send mirror only once
fouge Sep 25, 2024
6da0ac4
orb-ui: fix operator leds pulse animation
fouge Sep 25, 2024
f0ed3ba
orb-ui: revert new event BiometricCaptureStart
fouge Sep 26, 2024
d585702
orb-ui: better transitions for shroud
fouge Sep 26, 2024
dde16fc
orb-ui: tweaked simulations once again
fouge Sep 26, 2024
1869544
orb-ui: progress ring with restart from scratch
fouge Sep 26, 2024
de0da6d
orb-ui: simulation, 7 seconds on capture
fouge Sep 26, 2024
034cd1f
orb-ui: fix 7-seconds progress ring
fouge Sep 26, 2024
1b3818e
orb-ui: reset sound loop in between captures
fouge Sep 26, 2024
f270558
orb-ui: off background for when no animation is running
fouge Sep 26, 2024
1bd14bc
orb-ui: gitattributes
fouge Sep 27, 2024
a687796
orb-ui: clamp to u8::MAX
fouge Sep 27, 2024
d371470
orb-ui: fix mul_assign: don't use brightness/dimming byte
fouge Sep 27, 2024
af54325
orb-ui: refactor rgb color names
fouge Sep 27, 2024
9d20832
orb-ui: replace SystemTime to Instant
fouge Sep 27, 2024
aa5311c
orb-ui: use std::any::type_name::<Self>() to print transitions (debug)
fouge Sep 27, 2024
7f7e295
orb-ui: print new events with debug level on pearl
fouge Sep 27, 2024
cf72393
orb-ui: transition_from return bool instead of result
fouge Sep 27, 2024
f7fd9c4
orb-ui: improved milkyway animation
fouge Sep 27, 2024
8564548
orb-ui: fix regression on Pearl
fouge Sep 27, 2024
e6d410f
orb-ui: use expect(dead_code) instead of allow
fouge Sep 27, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions orb-ui/cone/examples/cone-simulation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,11 +54,11 @@ async fn simulation_task(cone: &mut Cone) -> eyre::Result<()> {
let state_res = match counter {
SimulationState::Idle => {
for pixel in pixels.iter_mut() {
*pixel = Argb::DIAMOND_USER_IDLE;
*pixel = Argb::DIAMOND_CONE_AMBER;
}
cone.lcd
.tx()
.try_send(LcdCommand::try_from(Argb::DIAMOND_USER_IDLE)?)
.try_send(LcdCommand::try_from(Argb::DIAMOND_CONE_AMBER)?)
.wrap_err("unable to send DIAMOND_USER_IDLE to lcd")
}
SimulationState::Red => {
Expand Down Expand Up @@ -134,7 +134,7 @@ async fn simulation_task(cone: &mut Cone) -> eyre::Result<()> {
}
SimulationState::QrCode => {
for pixel in pixels.iter_mut() {
*pixel = Argb::DIAMOND_USER_AMBER;
*pixel = Argb::DIAMOND_SHROUD_SUMMON_USER_AMBER;
}

let cmd =
Expand Down
73 changes: 37 additions & 36 deletions orb-ui/rgb/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use serde::{Deserialize, Serialize};
use std::ops;
use std::ops::Add;

/// RGB LED color.
#[derive(Eq, PartialEq, Copy, Clone, Default, Debug, Serialize, Deserialize)]
Expand All @@ -15,39 +16,34 @@ impl ops::Mul<f64> for Argb {

#[allow(clippy::cast_possible_truncation, clippy::cast_sign_loss)]
fn mul(self, rhs: f64) -> Self::Output {
// if intensity is led by the dimming value, use it
// otherwise, modify the color values
if let Some(dim) = self.0 {
Argb(
Some(((f64::from(dim) * rhs) as u8).clamp(0, Self::DIMMING_MAX_VALUE)),
self.1,
self.2,
self.3,
)
} else {
Argb(
None,
((f64::from(self.1) * rhs) as u8).clamp(0, 255),
((f64::from(self.2) * rhs) as u8).clamp(0, 255),
((f64::from(self.3) * rhs) as u8).clamp(0, 255),
)
}
Argb(
self.0,
((f64::from(self.1) * rhs) as u8).clamp(0, u8::MAX),
((f64::from(self.2) * rhs) as u8).clamp(0, u8::MAX),
((f64::from(self.3) * rhs) as u8).clamp(0, u8::MAX),
)
}
}

impl ops::MulAssign<f64> for Argb {
#[allow(clippy::cast_possible_truncation, clippy::cast_sign_loss)]
fn mul_assign(&mut self, rhs: f64) {
// if intensity is led by the dimming value, use it
// otherwise, modify the color values
if let Some(dim) = self.0 {
self.0 =
Some(((f64::from(dim) * rhs) as u8).clamp(0, Self::DIMMING_MAX_VALUE));
} else {
self.1 = ((f64::from(self.1) * rhs) as u8).clamp(0, 255);
self.2 = ((f64::from(self.2) * rhs) as u8).clamp(0, 255);
self.3 = ((f64::from(self.3) * rhs) as u8).clamp(0, 255);
};
self.1 = ((f64::from(self.1) * rhs) as u8).clamp(0, u8::MAX);
self.2 = ((f64::from(self.2) * rhs) as u8).clamp(0, u8::MAX);
self.3 = ((f64::from(self.3) * rhs) as u8).clamp(0, u8::MAX);
}
}

impl Add for Argb {
type Output = Self;

fn add(self, rhs: Self) -> Self::Output {
Argb(
self.0,
self.1.saturating_add(rhs.1),
self.2.saturating_add(rhs.2),
self.3.saturating_add(rhs.3),
)
}
}

Expand Down Expand Up @@ -77,16 +73,21 @@ impl Argb {
Argb(Some(Self::DIMMING_MAX_VALUE), 128, 128, 0);
pub const DIAMOND_OPERATOR_VERSIONS_OUTDATED: Argb =
Argb(Some(Self::DIMMING_MAX_VALUE), 255, 0, 0);
pub const DIAMOND_USER_AMBER: Argb = Argb(Some(Self::DIMMING_MAX_VALUE), 20, 16, 1);
#[allow(dead_code)]
pub const DIAMOND_USER_IDLE: Argb = Argb(Some(Self::DIMMING_MAX_VALUE), 18, 23, 18);
pub const DIAMOND_USER_QR_SCAN: Argb =
Argb(Some(Self::DIMMING_MAX_VALUE), 24, 29, 24);
pub const DIAMOND_USER_SIGNUP: Argb =
Argb(Some(Self::DIMMING_MAX_VALUE), 32, 26, 1);
pub const DIAMOND_USER_FLASH: Argb =
Argb(Some(Self::DIMMING_MAX_VALUE), 255, 255, 255);
/// Outer-ring color during operator QR scans
pub const DIAMOND_RING_OPERATOR_QR_SCAN: Argb = Argb(Some(4), 55, 10, 0);
pub const DIAMOND_RING_OPERATOR_QR_SCAN_SPINNER: Argb = Argb(Some(7), 80, 50, 30);
/// Outer-ring color during user QR scans
pub const DIAMOND_RING_USER_QR_SCAN: Argb = Argb(Some(4), 50, 40, 3);
pub const DIAMOND_RING_USER_QR_SCAN_SPINNER: Argb = Argb(Some(7), 80, 60, 40);
/// Shroud color to invite user to scan / reposition in front of the orb
pub const DIAMOND_SHROUD_SUMMON_USER_AMBER: Argb = Argb(Some(3), 95, 40, 3);
/// Shroud color during user scan/capture (in progress)
pub const DIAMOND_SHROUD_USER_CAPTURE: Argb = Argb(Some(3), 118, 51, 3);
/// Outer-ring color during user scan/capture (in progress)
pub const DIAMOND_RING_USER_CAPTURE: Argb = Argb(Some(10), 100, 80, 3);
pub const DIAMOND_CONE_AMBER: Argb = Argb(Some(Self::DIMMING_MAX_VALUE), 25, 18, 1);
/// Error color for outer ring
pub const DIAMOND_RING_ERROR_SALMON: Argb = Argb(Some(3), 127, 20, 0);

pub const FULL_RED: Argb = Argb(None, 255, 0, 0);
pub const FULL_GREEN: Argb = Argb(None, 0, 255, 0);
Expand Down
4 changes: 2 additions & 2 deletions orb-ui/sound/assets/sound_user_qr_load_success.wav
Git LFS file not shown
3 changes: 3 additions & 0 deletions orb-ui/sound/assets/sound_user_start_capture.wav
Git LFS file not shown
18 changes: 18 additions & 0 deletions orb-ui/sound/src/queue.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use libc::{
c_int, c_void, fd_set, suseconds_t, time_t, timeval, EFD_CLOEXEC, FD_ISSET, FD_SET,
FD_ZERO,
};
use std::ops::Add;
use std::{
ffi::CString,
io,
Expand Down Expand Up @@ -37,6 +38,7 @@ pub struct SoundBuilder<'a> {
reader: Option<Box<dyn Reader>>,
cancel_all: bool,
priority: u8,
delay: Option<Duration>,
max_delay: Duration,
volume: f64,
}
Expand All @@ -50,6 +52,7 @@ struct Sound {
id: u64,
reader: Box<dyn Reader>,
name: String,
start_time: Instant,
deadline: Duration,
volume: f64,
state: SharedState,
Expand Down Expand Up @@ -118,6 +121,7 @@ impl Queue {
reader: reader.map(|reader| Box::new(reader) as _),
cancel_all: false,
priority: 0,
delay: None,
max_delay: Duration::MAX,
volume: 1.0,
}
Expand Down Expand Up @@ -197,6 +201,13 @@ impl SoundBuilder<'_> {
self
}

/// Adds delay before playing the sound.
#[must_use]
pub fn delay(mut self, delay: Option<Duration>) -> Self {
self.delay = delay;
self
}

/// Inserts the sound to the queue returning a future that resolves when the
/// sound has left the queue. The boolean output represents whether the
/// sound has been played.
Expand All @@ -210,6 +221,7 @@ impl SoundBuilder<'_> {
reader,
cancel_all,
priority,
delay,
max_delay,
volume,
} = self;
Expand All @@ -229,11 +241,13 @@ impl SoundBuilder<'_> {
.duration_since(UNIX_EPOCH)
.map_err(|err| io::Error::new(io::ErrorKind::Other, err))?
.saturating_add(max_delay);
let start_time = Instant::now().add(delay.unwrap_or(Duration::ZERO));
let state = Arc::new(Mutex::new(State::Pending));
let sound = Sound {
id,
name,
reader,
start_time,
deadline,
state: Arc::clone(&state),
volume,
Expand Down Expand Up @@ -313,6 +327,10 @@ fn queue_loop(
let now = SystemTime::now()
.duration_since(UNIX_EPOCH)
.map_err(|err| io::Error::new(io::ErrorKind::Other, err))?;
if Instant::now() < sound.start_time {
let duration = sound.start_time.duration_since(Instant::now());
cancellable_sleep(duration, cancel_event)?;
}
let play = now < sound.deadline;
if play {
let volume = sound.volume;
Expand Down
2 changes: 1 addition & 1 deletion orb-ui/src/dbus.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ impl Interface {
/// Forward events to UI engine by sending serialized engine::Event to the event channel.
async fn orb_signup_state_event(&mut self, event: String) -> zbus::fdo::Result<()> {
// parse event to engine::Event using json_serde
tracing::debug!("received JSON event: {}", event);
tracing::trace!("received JSON event: {}", event);
let event: engine::Event = serde_json::from_str(&event).map_err(|e| {
zbus::fdo::Error::InvalidArgs(format!(
"invalid event: failed to parse {}",
Expand Down
15 changes: 15 additions & 0 deletions orb-ui/src/engine/animations/alert.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ pub struct Alert<const N: usize> {
phase: f64,
/// first edge from pattern\[0\] to pattern\[1\] has LEDs on
active_at_start: bool,
/// initial delay, in seconds, before starting the animation
initial_delay: f64,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Usually we should always use std::time::Duration. Is there a reason you chose a f64 here?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

dt is f64 so it's very simple to use it like this

}

impl<const N: usize> Alert<N> {
Expand All @@ -60,8 +62,15 @@ impl<const N: usize> Alert<N> {
blinks,
phase: 0.0,
active_at_start,
initial_delay: 0.0,
}
}

#[expect(dead_code)]
pub fn with_delay(mut self, delay: f64) -> Self {
self.initial_delay = delay;
self
}
}

impl<const N: usize> Animation for Alert<N> {
Expand All @@ -84,6 +93,12 @@ impl<const N: usize> Animation for Alert<N> {
let mut duration_acc = 0.0;
let mut color = Argb::OFF;

// initial delay
if self.initial_delay > 0.0 {
self.initial_delay -= dt;
return AnimationState::Running;
}

// sum up each edge duration and quit when the phase is in the current edge
for (i, &edge_duration) in self.blinks.0.iter().enumerate() {
duration_acc += edge_duration;
Expand Down
2 changes: 1 addition & 1 deletion orb-ui/src/engine/animations/arc_dash.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ impl<const N: usize> Animation for ArcDash<N> {
if N == PEARL_RING_LED_COUNT {
current_color = Argb::PEARL_USER_FLASH;
} else {
current_color = Argb::DIAMOND_USER_FLASH;
current_color = Argb::DIAMOND_RING_USER_CAPTURE;
}
*phase += dt;
if *phase >= FLASH_ON_TIME {
Expand Down
5 changes: 4 additions & 1 deletion orb-ui/src/engine/animations/arc_pulse.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,9 +60,12 @@ impl<const N: usize> Animation for ArcPulse<N> {
AnimationState::Running
}

fn transition_from(&mut self, superseded: &dyn Any) {
fn transition_from(&mut self, superseded: &dyn Any) -> bool {
if let Some(other) = superseded.downcast_ref::<ArcPulse<N>>() {
self.shape = other.shape.clone();
true
} else {
false
}
}
}
Expand Down
2 changes: 0 additions & 2 deletions orb-ui/src/engine/animations/idle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,4 @@ impl<const N: usize> Animation for Idle<N> {
}
AnimationState::Running
}

fn transition_from(&mut self, _superseded: &dyn Any) {}
}
Loading
Loading