Skip to content

Commit 4e3366e

Browse files
authored
Update user profile: this is a runtime, not a config (#78)
* Update user profile: this is a runtime, not a config Signed-off-by: Guillaume W. Bres <guillaume.bressaix@gmail.com> --------- Signed-off-by: Guillaume W. Bres <guillaume.bressaix@gmail.com>
1 parent 5141d82 commit 4e3366e

File tree

5 files changed

+43
-98
lines changed

5 files changed

+43
-98
lines changed

.github/workflows/rust.yml

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -45,18 +45,12 @@ jobs:
4545

4646
- name: Config documentation
4747
run: |
48-
cargo test generate_static_cpp_preset --all-features
49-
echo "Static CPP" >> $GITHUB_STEP_SUMMARY
50-
echo "==========" >> $GITHUB_STEP_SUMMARY
51-
python3 tools/jsonmd.py static_cpp.json >> $GITHUB_STEP_SUMMARY
52-
rm static_cpp.json
48+
cargo test generate_default_preset --all-features
49+
echo "Default Preset" >> $GITHUB_STEP_SUMMARY
50+
echo "==============" >> $GITHUB_STEP_SUMMARY
51+
python3 tools/jsonmd.py default.json >> $GITHUB_STEP_SUMMARY
52+
rm default.json
5353
54-
cargo test generate_static_ppp_preset --all-features
55-
echo "Static PPP" >> $GITHUB_STEP_SUMMARY
56-
echo "==========" >> $GITHUB_STEP_SUMMARY
57-
python3 tools/jsonmd.py static_ppp.json >> $GITHUB_STEP_SUMMARY
58-
rm static_ppp.json
59-
6054
publish:
6155
name: Publish Library
6256
runs-on: ubuntu-latest

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,3 +18,5 @@ Cargo.lock
1818
*.patch
1919
*.rs~
2020
*.cache
21+
22+
default.json

src/cfg/mod.rs

Lines changed: 4 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ const fn max_iono_bias() -> f64 {
4141
}
4242

4343
const fn min_sv_elev() -> Option<f64> {
44-
Some(10.0)
44+
Some(12.5)
4545
}
4646

4747
const fn default_code_smoothing() -> usize {
@@ -80,10 +80,6 @@ pub struct Config {
8080
#[cfg_attr(feature = "serde", serde(default))]
8181
pub method: Method,
8282

83-
/// [Profile] defines the type of application.
84-
#[cfg_attr(feature = "serde", serde(default))]
85-
pub user: User,
86-
8783
/// Select a prefered signal.
8884
/// When defined, this signal will strictly be used in the navigation process.
8985
/// When undefined, the algorithm will prefer the best SNR available, and the
@@ -179,7 +175,6 @@ impl Default for Config {
179175
Self {
180176
timescale: default_timescale(),
181177
method: Method::default(),
182-
user: User::default(),
183178
solver: SolverOpts::default(),
184179
int_delay: Default::default(),
185180
modeling: Modeling::default(),
@@ -200,46 +195,6 @@ impl Default for Config {
200195
}
201196

202197
impl Config {
203-
/// Returns [Config] for static PPP positioning, with desired [Method].
204-
/// You can then customize [Self] as you will.
205-
pub fn static_preset(method: Method) -> Self {
206-
let mut s = Self::default();
207-
208-
s.method = method;
209-
s.user.profile = None;
210-
211-
// consider that static applications can afford stringent criterias
212-
s.solver.max_gdop = 3.0;
213-
s.max_tropo_bias = 15.0;
214-
s
215-
}
216-
217-
/// Returns [Config] for dynamic PPP positioning, with desired [Method]
218-
/// and rover [Profile]. You can then customize [Self] as you will.
219-
pub fn dynamic_preset(method: Method, profile: Profile) -> Self {
220-
let mut s = Self::default();
221-
222-
s.method = method;
223-
s.user.profile = Some(profile);
224-
225-
s.solver.max_gdop = 5.0;
226-
s.max_tropo_bias = 15.0;
227-
s
228-
}
229-
230-
/// Returns [Config] for static RTK positioning, with desired [Method],
231-
/// Remote site coordinates expressed in meters ECEF.
232-
/// You can then customize [Self] as you will.
233-
pub fn static_rtk_preset(method: Method) -> Self {
234-
Self::static_preset(method) // strictly identical
235-
}
236-
237-
/// Returns [Config] for dynamic RTK positioning, with desired [Method],
238-
/// rover [Profile].
239-
pub fn dynamic_rtk_preset(method: Method, profile: Profile) -> Self {
240-
Self::dynamic_preset(method, profile)
241-
}
242-
243198
/// Returns new [Config] with desired navigation [Method]
244199
pub fn with_navigation_method(&self, method: Method) -> Self {
245200
let mut s = self.clone();
@@ -264,18 +219,10 @@ mod test {
264219
use std::io::Write;
265220

266221
#[test]
267-
fn generate_static_cpp_preset() {
268-
let cfg = Config::static_preset(Method::CPP);
269-
let string = serde_json::to_string_pretty(&cfg).unwrap();
270-
let mut fd = std::fs::File::create("static_cpp.json").unwrap();
271-
write!(fd, "{}", string).unwrap();
272-
}
273-
274-
#[test]
275-
fn generate_static_ppp_preset() {
276-
let cfg = Config::static_preset(Method::PPP);
222+
fn generate_default_preset() {
223+
let cfg = Config::default();
277224
let string = serde_json::to_string_pretty(&cfg).unwrap();
278-
let mut fd = std::fs::File::create("static_ppp.json").unwrap();
225+
let mut fd = std::fs::File::create("default.json").unwrap();
279226
write!(fd, "{}", string).unwrap();
280227
}
281228
}

src/cfg/user.rs

Lines changed: 20 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -9,25 +9,36 @@ const fn default_clock_sigma() -> f64 {
99
}
1010

1111
/// Default user [Profile]
12-
const fn default_user_profile() -> Option<Profile> {
13-
Some(Profile::Pedestrian)
12+
const fn default_user_profile() -> Profile {
13+
Profile::Pedestrian
1414
}
1515

16-
/// Receiver [Profile], which is application dependent.
17-
/// [Profile::Static] is our default value: any roaming application needs to customize its profile.
16+
/// Receiver [Profile], which is application dependent.
17+
/// Operating under incorrect parametrization ([Profile] not matching your use case),
18+
/// will not prohibit obtaining results. It's just that they could be improved
19+
/// by adapting your profile to your use case correctly.
1820
#[derive(Default, Debug, Clone, Copy, PartialEq)]
1921
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2022
pub enum Profile {
21-
/// [Profile::Pedestrian]: < 10 km/h very low velocity
23+
/// [Profile::Static] applies to user applications where
24+
/// the receiver antenna is held static at all times.
25+
/// This is not our prefered mode, because this apply to particular use cases.
26+
Static,
27+
28+
/// [Profile::Pedestrian]: < 10 km/h very low velocity.
29+
/// This is our default mode.
2230
#[cfg_attr(feature = "serde", serde(alias = "pedestrian", alias = "Pedestrian"))]
2331
#[default]
2432
Pedestrian,
33+
2534
/// [Profile::Car]: < 100 km/h slow velocity
2635
#[cfg_attr(feature = "serde", serde(alias = "car", alias = "Car"))]
2736
Car,
37+
2838
/// [Profile::Airplane]: < 1000 km/h high velocity
2939
#[cfg_attr(feature = "serde", serde(alias = "airplane", alias = "airplane"))]
3040
Airplane,
41+
3142
/// [Profile::Rocket]: > 1000 km/h ultra high velocity
3243
#[cfg_attr(feature = "serde", serde(alias = "rocket", alias = "rocket"))]
3344
Rocket,
@@ -39,6 +50,7 @@ impl std::str::FromStr for Profile {
3950
let s = s.to_lowercase();
4051
let trimmed = s.trim();
4152
match trimmed {
53+
"static" => Ok(Self::Static),
4254
"pedestrian" => Ok(Self::Pedestrian),
4355
"car" => Ok(Self::Car),
4456
"airplane" => Ok(Self::Airplane),
@@ -51,6 +63,7 @@ impl std::str::FromStr for Profile {
5163
impl std::fmt::Display for Profile {
5264
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
5365
match self {
66+
Self::Static => write!(f, "Static"),
5467
Self::Pedestrian => write!(f, "Pedestrian"),
5568
Self::Car => write!(f, "car"),
5669
Self::Airplane => write!(f, "airplane"),
@@ -65,9 +78,8 @@ impl std::fmt::Display for Profile {
6578
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6679
pub struct User {
6780
/// Custom user [Profile] which is application dependent.
68-
/// This is disregarded by solvers dedicated to static applications.
6981
#[cfg_attr(feature = "serde", serde(default))]
70-
pub profile: Option<Profile>,
82+
pub profile: Profile,
7183

7284
/// Receiver clock prediction perturbation (instantaneous bias) in seconds.
7385
/// Standard values are:
@@ -88,12 +100,7 @@ pub struct User {
88100

89101
impl std::fmt::Display for User {
90102
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
91-
if let Some(profile) = self.profile {
92-
write!(f, "Profile=\"{}\" ", profile)?;
93-
} else {
94-
write!(f, "Profile=Static ")?;
95-
}
96-
103+
write!(f, "Profile=\"{}\" ", self.profile)?;
97104
write!(f, "clock-sigma={}s", self.clock_sigma_s)
98105
}
99106
}

src/navigation/mod.rs

Lines changed: 12 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -126,13 +126,11 @@ where
126126
}
127127
}
128128

129+
// TODO: improve this model
129130
q_k[(0, 0)] = 1.0;
130131
q_k[(1, 1)] = 1.0;
131132
q_k[(2, 2)] = 1.0;
132133

133-
q_k[(Self::clock_index(), Self::clock_index())] =
134-
(cfg.user.clock_sigma_s * SPEED_OF_LIGHT_M_S).powi(2);
135-
136134
Self {
137135
f_k,
138136
q_k,
@@ -156,11 +154,18 @@ where
156154
}
157155

158156
/// Reset [Navigation] filter.
157+
///
158+
/// To this day, it has not been demonstrated that this
159+
/// operation is needed by any real-world application, even
160+
/// real-time processing. But anyways.. this exists.
161+
///
162+
/// After reset, the [Navigation] solver is in the same state as deployment,
163+
/// ready to consume a first measurement.
159164
pub fn reset(&mut self) {
160165
self.clear();
161166
self.kalman.reset();
162167

163-
if let Some(postfit) = &mut self.postfit {
168+
if self.postfit.is_some() {
164169
self.postfit = None;
165170
}
166171

@@ -177,7 +182,7 @@ where
177182
/// Iterates mutable [Navigation] filter.
178183
/// ## Input
179184
/// - t: sampling [Epoch]
180-
/// - user: [User]
185+
/// - user: [User] profile
181186
/// - past_state: past [State]
182187
/// - candidates: proposed [Candidate]s
183188
/// - size: number of proposed [Cadndidate]s
@@ -195,18 +200,8 @@ where
195200
) -> Result<(), Error> {
196201
self.clear();
197202

198-
if self.cfg.user != user {
199-
// profile update
200-
if user.profile != self.cfg.user.profile {
201-
if let Some(profile) = user.profile {
202-
info!("{}: switching to {} profile", t, profile);
203-
self.cfg.user.profile = Some(profile);
204-
}
205-
}
206-
207-
self.q_k[(Self::clock_index(), Self::clock_index())] =
208-
(user.clock_sigma_s * SPEED_OF_LIGHT_M_S).powi(2);
209-
}
203+
self.q_k[(Self::clock_index(), Self::clock_index())] =
204+
(user.clock_sigma_s * SPEED_OF_LIGHT_M_S).powi(2);
210205

211206
if !self.kalman.initialized {
212207
self.kf_initialization(t, past_state, candidates, size, rtk_base, bias)?;

0 commit comments

Comments
 (0)