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

BNX-05 #278

Merged
merged 14 commits into from
Nov 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
7 changes: 3 additions & 4 deletions binex/benches/decoding.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
use binex::prelude::{
EphemerisFrame, Epoch, Message, Meta, MonumentGeoMetadata, MonumentGeoRecord, Record,
TimeResolution,
};
use criterion::{black_box, criterion_group, criterion_main, Criterion};

Expand All @@ -22,7 +21,7 @@ pub fn criterion_benchmark(c: &mut Criterion) {
record.meta = geo_meta;

let record = Record::new_monument_geo(record);
let msg = Message::new(meta, TimeResolution::QuarterSecond, record);
let msg = Message::new(meta, record);

let mut buf = [0; 256];
msg.encode(&mut buf, 256).unwrap();
Expand All @@ -34,7 +33,7 @@ pub fn criterion_benchmark(c: &mut Criterion) {
});

let record = Record::new_ephemeris_frame(EphemerisFrame::GPSRaw(Default::default()));
let msg = Message::new(meta, TimeResolution::QuarterSecond, record);
let msg = Message::new(meta, record);

let mut buf = [0; 256];
msg.encode(&mut buf, 256).unwrap();
Expand All @@ -46,7 +45,7 @@ pub fn criterion_benchmark(c: &mut Criterion) {
});

let record = Record::new_ephemeris_frame(EphemerisFrame::GPS(Default::default()));
let msg = Message::new(meta, TimeResolution::QuarterSecond, record);
let msg = Message::new(meta, record);

let mut buf = [0; 256];
msg.encode(&mut buf, 256).unwrap();
Expand Down
7 changes: 3 additions & 4 deletions binex/benches/encoding.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
use binex::prelude::{
EphemerisFrame, Epoch, Message, Meta, MonumentGeoMetadata, MonumentGeoRecord, Record,
TimeResolution,
};
use criterion::{black_box, criterion_group, criterion_main, Criterion};

Expand All @@ -24,7 +23,7 @@ pub fn criterion_benchmark(c: &mut Criterion) {
record.meta = geo_meta;

let record = Record::new_monument_geo(record);
let msg = Message::new(meta, TimeResolution::QuarterSecond, record);
let msg = Message::new(meta, record);

c.bench_function("encoding-00", |b| {
b.iter(|| {
Expand All @@ -33,7 +32,7 @@ pub fn criterion_benchmark(c: &mut Criterion) {
});

let record = Record::new_ephemeris_frame(EphemerisFrame::GPSRaw(Default::default()));
let msg = Message::new(meta, TimeResolution::QuarterSecond, record);
let msg = Message::new(meta, record);

c.bench_function("encoding-01-00", |b| {
b.iter(|| {
Expand All @@ -42,7 +41,7 @@ pub fn criterion_benchmark(c: &mut Criterion) {
});

let record = Record::new_ephemeris_frame(EphemerisFrame::GPS(Default::default()));
let msg = Message::new(meta, TimeResolution::QuarterSecond, record);
let msg = Message::new(meta, record);

c.bench_function("encoding-01-01", |b| {
b.iter(|| {
Expand Down
7 changes: 5 additions & 2 deletions binex/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,14 @@ pub mod prelude {
decoder::Decoder,
message::{
EphemerisFrame, GALEphemeris, GLOEphemeris, GPSEphemeris, GPSRaw, Message, Meta,
MonumentGeoMetadata, MonumentGeoRecord, Record, SBASEphemeris, TimeResolution,
MonumentGeoMetadata, MonumentGeoRecord, PositionEcef3d, PositionGeo3d, Record,
SBASEphemeris, Solutions, TemporalSolution, Velocity3d, VelocityNED3d,
},
stream::{ClosedSourceElement, Provider, StreamElement},
ClosedSourceMeta, Error,
};
// re-export
pub use hifitime::Epoch;
pub use hifitime::{Epoch, TimeScale};
}

use crate::message::Meta;
Expand Down Expand Up @@ -75,6 +76,8 @@ pub enum Error {
IncompleteMessage(usize),
/// Library limitation: not all open source Messages supported yet
NonSupportedMesssage(usize),
/// Library limtation: not all subrecords supported yet
NonSupportedSubRecord,
/// Library limtation: should never happen, because this library
/// will be designed to parse all open source [Message]s.
/// This may happen as either we're still in development (bad internal design)
Expand Down
131 changes: 102 additions & 29 deletions binex/src/message/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,26 +6,24 @@ mod time; // Epoch encoding/decoding // checksum calc.

pub use record::{
EphemerisFrame, GALEphemeris, GLOEphemeris, GPSEphemeris, GPSRaw, MonumentGeoMetadata,
MonumentGeoRecord, Record, SBASEphemeris,
MonumentGeoRecord, PositionEcef3d, PositionGeo3d, Record, SBASEphemeris, Solutions,
SolutionsFrame, TemporalSolution, Velocity3d, VelocityNED3d,
};

pub use meta::Meta;
pub use time::TimeResolution;

pub(crate) use mid::MessageID;

use checksum::Checksum;

use crate::{stream::Provider, ClosedSourceMeta, Error};
use checksum::Checksum;

#[derive(Debug, Clone, PartialEq, Default)]
pub struct Message {
/// [Meta] data
pub meta: Meta,
/// [Record]
pub record: Record,
/// Time Resolution in use
time_res: TimeResolution,
}

impl Message {
Expand All @@ -38,12 +36,8 @@ impl Message {
const BNXI_BYTE_MASK: u8 = 0x7f;

/// Creates a new [Message] ready to be encoded.
pub fn new(meta: Meta, time_res: TimeResolution, record: Record) -> Self {
Self {
meta,
record,
time_res,
}
pub fn new(meta: Meta, record: Record) -> Self {
Self { meta, record }
}

/// Returns total size required to encode this [Message].
Expand Down Expand Up @@ -73,8 +67,6 @@ impl Message {
pub fn decode(buf: &[u8]) -> Result<Self, Error> {
let buf_len = buf.len();

let time_res = TimeResolution::QuarterSecond;

// 1. locate SYNC byte
let meta = Meta::find_and_parse(buf, buf_len);
if meta.is_none() {
Expand Down Expand Up @@ -113,12 +105,11 @@ impl Message {

// 2. parse MID
let (bnxi, mid_1_4) = Self::decode_bnxi(&buf[ptr..], big_endian);

let mid = MessageID::from(bnxi);

if mid == MessageID::Unknown {
return Err(Error::UnknownMessage);
}

ptr += mid_1_4;

// make sure we can parse up to 4 byte MLEN
Expand All @@ -135,20 +126,25 @@ impl Message {
// buffer does not contain complete message!
return Err(Error::IncompleteMessage(mlen));
}

ptr += mlen_1_4;

// 4. parse RECORD
let record = match mid {
MessageID::SiteMonumentMarker => {
let rec =
MonumentGeoRecord::decode(mlen as usize, time_res, big_endian, &buf[ptr..])?;
let rec = MonumentGeoRecord::decode(mlen as usize, big_endian, &buf[ptr..])?;
Record::new_monument_geo(rec)
},
MessageID::Ephemeris => {
let fr = EphemerisFrame::decode(big_endian, &buf[ptr..])?;
Record::new_ephemeris_frame(fr)
},
MessageID::ProcessedSolutions => {
let solutions = Solutions::decode(mlen as usize, big_endian, &buf[ptr..])?;
Record::new_solutions(solutions)
},
MessageID::Unknown => {
return Err(Error::UnknownMessage);
},
_ => {
// check whether this message is undisclosed or not
if let Some(provider) = Provider::match_any(mid.into()) {
Expand Down Expand Up @@ -184,11 +180,7 @@ impl Message {
if expected != ck {
Err(Error::CorrupctBadCRC)
} else {
Ok(Self {
meta,
record,
time_res,
})
Ok(Self { meta, record })
}
}

Expand Down Expand Up @@ -232,6 +224,9 @@ impl Message {
Record::MonumentGeo(geo) => {
ptr += geo.encode(big_endian, &mut buf[ptr..])?;
},
Record::Solutions(fr) => {
ptr += fr.encode(big_endian, &mut buf[ptr..])?;
},
}

// encode CRC
Expand Down Expand Up @@ -432,8 +427,10 @@ impl Message {
#[cfg(test)]
mod test {
use super::Message;
use crate::message::{EphemerisFrame, GPSRaw, MonumentGeoMetadata, MonumentGeoRecord, Record};
use crate::message::{GALEphemeris, GPSEphemeris, Meta, TimeResolution};
use crate::message::{
EphemerisFrame, GALEphemeris, GPSEphemeris, GPSRaw, Meta, MonumentGeoMetadata,
MonumentGeoRecord, PositionEcef3d, Record, Solutions, SolutionsFrame, Velocity3d,
};
use crate::prelude::Epoch;
use crate::Error;

Expand Down Expand Up @@ -597,7 +594,7 @@ mod test {
let geo_len = geo.encoding_size();
let record = Record::new_monument_geo(geo);

let msg = Message::new(meta, TimeResolution::QuarterSecond, record);
let msg = Message::new(meta, record);

// SYNC + MID(1) +FID + MLEN + CRC(8)
assert_eq!(msg.encoding_size(), 1 + 1 + 1 + geo_len + 1);
Expand All @@ -624,7 +621,7 @@ mod test {
let gps_raw_len = gps_raw.encoding_size();
let record = Record::new_ephemeris_frame(gps_raw);

let msg = Message::new(meta, TimeResolution::QuarterSecond, record);
let msg = Message::new(meta, record);

// SYNC + MID(1) + MLEN(1) + RLEN + CRC(1)
assert_eq!(msg.encoding_size(), 1 + 1 + 1 + gps_raw_len + 1);
Expand Down Expand Up @@ -653,7 +650,7 @@ mod test {

assert_eq!(gps_eph_len, 129);

let msg = Message::new(meta, TimeResolution::QuarterSecond, record);
let msg = Message::new(meta, record);

// SYNC + MID(1) + MLEN(2) + RLEN + CRC(2)
assert_eq!(msg.encoding_size(), 1 + 1 + 2 + gps_eph_len + 2);
Expand All @@ -680,7 +677,7 @@ mod test {

assert_eq!(eph_len, 129);

let msg = Message::new(meta, TimeResolution::QuarterSecond, record);
let msg = Message::new(meta, record);

// SYNC + MID(1) + MLEN(2) + RLEN + CRC(2)
assert_eq!(msg.encoding_size(), 1 + 1 + 2 + eph_len + 2);
Expand All @@ -692,4 +689,80 @@ mod test {
let parsed = Message::decode(&encoded).unwrap();
assert_eq!(parsed, msg);
}

#[test]
fn test_pvt_wgs84() {
let mut meta = Meta::default();

meta.reversed = false;
meta.big_endian = true;
meta.enhanced_crc = false;

let mut solutions = Solutions::new(Epoch::from_gpst_seconds(1.100));

solutions.frames.push(SolutionsFrame::AntennaEcefPosition(
PositionEcef3d::new_wgs84(1.0, 2.0, 3.0),
));

let sol_len = solutions.encoding_size();
assert_eq!(sol_len, 6 + 1 + 3 * 8 + 1); // ts | fid | 3*8 | wgs

let mut buf = [0; 32];
let size = solutions.encode(true, &mut buf).unwrap();
assert_eq!(size, 6 + 1 + 3 * 8 + 1);

assert_eq!(
buf,
[
0, 0, 0, 0, 4, 76, 1, 0, 63, 240, 0, 0, 0, 0, 0, 0, 64, 0, 0, 0, 0, 0, 0, 0, 64, 8,
0, 0, 0, 0, 0, 0
]
);

let record = Record::new_solutions(solutions.clone());
let msg = Message::new(meta, record);

// SYNC + MID(1) + MLEN(1) + RLEN + CRC(1)
let mlen = 1 + 1 + 1 + sol_len + 1;
assert_eq!(msg.encoding_size(), mlen);

let mut encoded = [0; 40];
msg.encode(&mut encoded, 40).unwrap();

assert_eq!(
encoded,
[
226, 5, 32, 0, 0, 0, 0, 4, 76, 1, 0, 63, 240, 0, 0, 0, 0, 0, 0, 64, 0, 0, 0, 0, 0,
0, 0, 64, 8, 0, 0, 0, 0, 0, 0, 171, 0, 0, 0, 0
]
);

// parse back
let parsed = Message::decode(&encoded).unwrap();
assert_eq!(parsed, msg);

// add velocity
solutions
.frames
.push(SolutionsFrame::AntennaEcefVelocity(Velocity3d {
x_m_s: 1.0,
y_m_s: 1.0,
z_m_s: 1.0,
}));

let sol_len = solutions.encoding_size();
assert_eq!(sol_len, 6 + 1 + 3 * 8 + 1 + 3 * 8 + 1);

let mut buf = [0; 64];
let size = solutions.encode(true, &mut buf).unwrap();
assert_eq!(size, sol_len);

let record = Record::new_solutions(solutions.clone());
let msg = Message::new(meta, record);

// add temporal
// add system time
// add comment
// add extra
}
}
4 changes: 2 additions & 2 deletions binex/src/message/record/ephemeris/galileo.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ impl GALEphemeris {
pub(crate) const fn encoding_size() -> usize {
128
}
pub fn encode(&self, big_endian: bool, buf: &mut [u8]) -> Result<usize, Error> {
pub(crate) fn encode(&self, big_endian: bool, buf: &mut [u8]) -> Result<usize, Error> {
let size = Self::encoding_size();
if buf.len() < size {
return Err(Error::NotEnoughBytes);
Expand Down Expand Up @@ -264,7 +264,7 @@ impl GALEphemeris {
Ok(Self::encoding_size())
}

pub fn decode(big_endian: bool, buf: &[u8]) -> Result<Self, Error> {
pub(crate) fn decode(big_endian: bool, buf: &[u8]) -> Result<Self, Error> {
if buf.len() < Self::encoding_size() {
return Err(Error::NotEnoughBytes);
}
Expand Down
4 changes: 2 additions & 2 deletions binex/src/message/record/ephemeris/glonass.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ impl GLOEphemeris {
pub(crate) const fn encoding_size() -> usize {
135
}
pub fn encode(&self, big_endian: bool, buf: &mut [u8]) -> Result<usize, Error> {
pub(crate) fn encode(&self, big_endian: bool, buf: &mut [u8]) -> Result<usize, Error> {
let size = Self::encoding_size();
if buf.len() < size {
return Err(Error::NotEnoughBytes);
Expand Down Expand Up @@ -174,7 +174,7 @@ impl GLOEphemeris {
Ok(135)
}

pub fn decode(big_endian: bool, buf: &[u8]) -> Result<Self, Error> {
pub(crate) fn decode(big_endian: bool, buf: &[u8]) -> Result<Self, Error> {
if buf.len() < Self::encoding_size() {
return Err(Error::NotEnoughBytes);
}
Expand Down
4 changes: 2 additions & 2 deletions binex/src/message/record/ephemeris/gps/eph.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ impl GPSEphemeris {
pub(crate) const fn encoding_size() -> usize {
128
}
pub fn encode(&self, big_endian: bool, buf: &mut [u8]) -> Result<usize, Error> {
pub(crate) fn encode(&self, big_endian: bool, buf: &mut [u8]) -> Result<usize, Error> {
let size = Self::encoding_size();
if buf.len() < size {
return Err(Error::NotEnoughBytes);
Expand Down Expand Up @@ -284,7 +284,7 @@ impl GPSEphemeris {
buf[125..127].copy_from_slice(&uint2);
Ok(size)
}
pub fn decode(big_endian: bool, buf: &[u8]) -> Result<Self, Error> {
pub(crate) fn decode(big_endian: bool, buf: &[u8]) -> Result<Self, Error> {
if buf.len() < Self::encoding_size() {
return Err(Error::NotEnoughBytes);
}
Expand Down
Loading
Loading