WIP screen: Show min and max end time
TODO: only on big screen!?
This commit is contained in:
parent
ba344f5e22
commit
f2960f36af
4 changed files with 126 additions and 35 deletions
|
|
@ -106,7 +106,54 @@ pub struct GlosaSignalInfo {
|
|||
pub struct SignalGroupData {
|
||||
pub phase: SignalPhase,
|
||||
pub maneuver: map::Maneuvers,
|
||||
pub end_sec: Option<i16>,
|
||||
pub timing: Option<TimingData>,
|
||||
}
|
||||
|
||||
#[cfg(feature = "spat")]
|
||||
#[derive(Debug, Default, Clone, PartialEq, Eq)]
|
||||
pub struct TimingData {
|
||||
pub min_end_sec: i16,
|
||||
pub likely_end_sec: Option<i16>,
|
||||
pub max_end_sec: Option<i16>,
|
||||
}
|
||||
|
||||
impl TimingData {
|
||||
pub fn new(value: &map::SignalGroup, now: chrono::DateTime<chrono::Utc>) -> Option<Self> {
|
||||
let min = value
|
||||
.min_end_time()
|
||||
.map(|val| Self::time_to_duration_sec(now, val));
|
||||
let likely_end_sec = value
|
||||
.likely_time()
|
||||
.map(|val| Self::time_to_duration_sec(now, val));
|
||||
let max_end_sec = value
|
||||
.min_end_time()
|
||||
.map(|val| Self::time_to_duration_sec(now, val));
|
||||
|
||||
if let Some(min_end_sec) = min {
|
||||
Some(Self {
|
||||
min_end_sec,
|
||||
likely_end_sec,
|
||||
max_end_sec,
|
||||
})
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
fn time_to_duration_sec(
|
||||
now: chrono::DateTime<chrono::Utc>,
|
||||
time_point: chrono::DateTime<chrono::Utc>,
|
||||
) -> i16 {
|
||||
use core::ops::Sub as _;
|
||||
|
||||
use num_traits::Float as _;
|
||||
|
||||
let dur = time_point.sub(now).as_seconds_f32();
|
||||
#[allow(clippy::cast_possible_truncation)]
|
||||
let duration_sec = dur.round() as i16;
|
||||
|
||||
duration_sec
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "spat")]
|
||||
|
|
@ -357,33 +404,17 @@ impl State {
|
|||
let sig_grps = approach_sig_grps
|
||||
.iter()
|
||||
.filter_map(|sig| {
|
||||
if let Some(manv) = sig.maneuvers() {
|
||||
use core::ops::Sub;
|
||||
|
||||
use num_traits::Float;
|
||||
|
||||
if let Some(maneuver) = sig.maneuvers() {
|
||||
let phase = sig
|
||||
.phase()
|
||||
.map(core::convert::Into::into)
|
||||
.unwrap_or_default();
|
||||
|
||||
let end_sec = sig
|
||||
.likely_time()
|
||||
.or_else(|| sig.min_end_time())
|
||||
.map(|time| {
|
||||
let dur =
|
||||
time.sub(self.time.and_utc()).as_seconds_f32();
|
||||
|
||||
#[allow(clippy::cast_possible_truncation)]
|
||||
let end_sec = dur.round() as i16;
|
||||
|
||||
end_sec
|
||||
});
|
||||
let timing = TimingData::new(*sig, self.time.and_utc());
|
||||
|
||||
Some(SignalGroupData {
|
||||
phase,
|
||||
maneuver: manv,
|
||||
end_sec,
|
||||
maneuver,
|
||||
timing,
|
||||
})
|
||||
} else {
|
||||
None
|
||||
|
|
|
|||
|
|
@ -173,6 +173,12 @@ impl Intersection {
|
|||
{
|
||||
sig_grp.likely_time = Some(likely.to_datetime_from_moy(moy, year));
|
||||
}
|
||||
if let Some(max) = &timing.max_end_time
|
||||
&& !max.is_out_of_range()
|
||||
&& !max.is_unknown()
|
||||
{
|
||||
sig_grp.max_end_time = Some(max.to_datetime_from_moy(moy, year));
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
|
@ -223,6 +229,7 @@ impl Intersection {
|
|||
target_lanes,
|
||||
phase: None,
|
||||
min_end_time: None,
|
||||
max_end_time: None,
|
||||
likely_time: None,
|
||||
}
|
||||
})
|
||||
|
|
@ -410,7 +417,7 @@ pub struct SignalGroup {
|
|||
/// current signal phase
|
||||
phase: Option<etsi_its_dsrc::MovementPhaseState>,
|
||||
min_end_time: Option<chrono::DateTime<chrono::Utc>>,
|
||||
// max_end_time: Option<chrono::DateTime<chrono::Utc>>,
|
||||
max_end_time: Option<chrono::DateTime<chrono::Utc>>,
|
||||
likely_time: Option<chrono::DateTime<chrono::Utc>>,
|
||||
}
|
||||
|
||||
|
|
@ -443,6 +450,9 @@ impl SignalGroup {
|
|||
pub fn likely_time(&self) -> Option<chrono::prelude::DateTime<chrono::prelude::Utc>> {
|
||||
self.likely_time
|
||||
}
|
||||
pub fn max_end_time(&self) -> Option<chrono::prelude::DateTime<chrono::prelude::Utc>> {
|
||||
self.max_end_time
|
||||
}
|
||||
|
||||
pub fn phase_to_str(&self) -> Option<String> {
|
||||
self.phase.map(|v| {
|
||||
|
|
|
|||
33
src/main.rs
33
src/main.rs
|
|
@ -207,7 +207,33 @@ async fn main(spawner: Spawner) -> ! {
|
|||
staight_allowed: false,
|
||||
right_allowed: false
|
||||
},
|
||||
end_sec: Some(23)
|
||||
timing: Some(applogic::TimingData {
|
||||
min_end_sec: 23,
|
||||
likely_end_sec: None,
|
||||
max_end_sec: None
|
||||
})
|
||||
}],
|
||||
},
|
||||
))
|
||||
.inspect_err(log_screen_error);
|
||||
embassy_time::Timer::after(embassy_time::Duration::from_secs(2)).await;
|
||||
|
||||
let _ = screen
|
||||
.update(screen::ScreenState::GlosaLocked(
|
||||
applogic::GlosaSignalInfo {
|
||||
intersection_id: 1234,
|
||||
signal_groups: alloc::vec![applogic::SignalGroupData {
|
||||
phase: applogic::SignalPhase::Red,
|
||||
maneuver: applogic::v2x::map::Maneuvers {
|
||||
left_allowed: true,
|
||||
staight_allowed: false,
|
||||
right_allowed: false
|
||||
},
|
||||
timing: Some(applogic::TimingData {
|
||||
min_end_sec: 23,
|
||||
likely_end_sec: Some(24),
|
||||
max_end_sec: Some(42)
|
||||
})
|
||||
}],
|
||||
},
|
||||
))
|
||||
|
|
@ -508,8 +534,9 @@ async fn main(spawner: Spawner) -> ! {
|
|||
if let applogic::GlosaOutput::Locked(data) = &glosa_data {
|
||||
for sig in &data.signal_groups {
|
||||
let duration_str = sig
|
||||
.end_sec
|
||||
.map(|v| alloc::format!("for {v} s"))
|
||||
.timing
|
||||
.as_ref()
|
||||
.map(|v| alloc::format!("for {} s", v.min_end_sec))
|
||||
.unwrap_or_default();
|
||||
println!("GLOSA: {} {} {duration_str}", sig.maneuver, sig.phase);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -86,6 +86,8 @@ where
|
|||
|
||||
const DEFAULT_TEXT_STYLE: mono_font::MonoTextStyle<'static, pixelcolor::Rgb565> =
|
||||
mono_font::MonoTextStyle::new(&profont::PROFONT_24_POINT, Self::COLOR_FG);
|
||||
const MID_TEXT_STYLE: mono_font::MonoTextStyle<'static, pixelcolor::Rgb565> =
|
||||
mono_font::MonoTextStyle::new(&profont::PROFONT_18_POINT, Self::COLOR_FG);
|
||||
const SMALL_TEXT_STYLE: mono_font::MonoTextStyle<'static, pixelcolor::Rgb565> =
|
||||
mono_font::MonoTextStyle::new(&profont::PROFONT_14_POINT, Self::COLOR_FG);
|
||||
|
||||
|
|
@ -169,7 +171,7 @@ where
|
|||
self.gnss_hb_state
|
||||
);
|
||||
|
||||
// TODO: print on screen!
|
||||
// TODO: print on screen?
|
||||
|
||||
self.gnss_hb_state = !self.gnss_hb_state;
|
||||
|
||||
|
|
@ -324,18 +326,39 @@ where
|
|||
)
|
||||
.draw(&mut self.target)?;
|
||||
|
||||
// draw timing indicator
|
||||
if let Some(end_sec) = sig.end_sec {
|
||||
text::Text::with_alignment(
|
||||
&alloc::format!("{end_sec}s"),
|
||||
geometry::Point::new(centerline, 160 + self.size.offset_top),
|
||||
Self::DEFAULT_TEXT_STYLE,
|
||||
text::Alignment::Center,
|
||||
)
|
||||
.draw(&mut self.target)?;
|
||||
// draw timing indicator(s)
|
||||
if let Some(timing) = &sig.timing {
|
||||
if let (Some(likely), Some(max)) = (timing.likely_end_sec, timing.max_end_sec) {
|
||||
text::Text::with_alignment(
|
||||
&alloc::format!("{likely}s"),
|
||||
geometry::Point::new(centerline, 160 + self.size.offset_top),
|
||||
Self::DEFAULT_TEXT_STYLE,
|
||||
text::Alignment::Center,
|
||||
)
|
||||
.draw(&mut self.target)?;
|
||||
|
||||
// TODO: only on big screen!?
|
||||
text::Text::with_alignment(
|
||||
&alloc::format!("{}-{max}s", timing.min_end_sec),
|
||||
geometry::Point::new(centerline, 185 + self.size.offset_top),
|
||||
Self::MID_TEXT_STYLE,
|
||||
text::Alignment::Center,
|
||||
)
|
||||
.draw(&mut self.target)?;
|
||||
} else {
|
||||
text::Text::with_alignment(
|
||||
&alloc::format!("{}s", timing.min_end_sec),
|
||||
geometry::Point::new(centerline, 160 + self.size.offset_top),
|
||||
Self::DEFAULT_TEXT_STYLE,
|
||||
text::Alignment::Center,
|
||||
)
|
||||
.draw(&mut self.target)?;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Add current speed and ETA
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue