Skip to content

Commit 64e8bc7

Browse files
committed
Changed use_tx_time to sv_rx_time
Changed the keyword name for readability
1 parent 57654a7 commit 64e8bc7

3 files changed

Lines changed: 42 additions & 63 deletions

File tree

gnss_lib_py/algorithms/snapshot.py

Lines changed: 22 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919

2020
def solve_wls(measurements, weight_type = None, only_bias = False,
2121
receiver_state=None, tol = 1e-7, max_count = 20,
22-
use_tx_time=False, delta_t_decimals=-2):
22+
sv_rx_time=False, delta_t_decimals=-2):
2323
"""Runs weighted least squares across each timestep.
2424
2525
Runs weighted least squares across each timestep and adds a new
@@ -51,11 +51,14 @@ def solve_wls(measurements, weight_type = None, only_bias = False,
5151
max_count : int
5252
Number of maximum iterations before process is aborted and
5353
solution returned.
54-
use_tx_time : bool
55-
Flag that specifies whether the SV positions at transmit time
56-
should be used as is or if they should be transformed to the
57-
corresponding ECEF coordinates when the signal is received. If
58-
True, the SV positions will not be modified.
54+
sv_rx_time : bool
55+
Flag that specifies whether the input SV positions are in the ECEF
56+
frame of reference corresponding to when the measurements were
57+
received. If set to `True`, the satellite positions are used as
58+
is. The default value is `False`, in which case the ECEF positions
59+
are assumed to in the ECEF frame at the time of signal transmission
60+
and are converted to the ECEF frame at the time of signal reception,
61+
while solving the WLS problem.
5962
delta_t_decimals : int
6063
Decimal places after which times are considered equal.
6164
@@ -119,7 +122,7 @@ def solve_wls(measurements, weight_type = None, only_bias = False,
119122
,0].reshape(-1,1),
120123
position[3])) # clock bias
121124
position = wls(position, pos_sv_m, corr_pr_m, weights,
122-
only_bias, tol, max_count, use_tx_time)
125+
only_bias, tol, max_count, sv_rx_time=sv_rx_time)
123126
states.append([timestamp] + np.squeeze(position).tolist())
124127
except RuntimeError as error:
125128
if str(error) not in runtime_error_idxs:
@@ -156,7 +159,7 @@ def solve_wls(measurements, weight_type = None, only_bias = False,
156159
return state_estimate
157160

158161
def wls(rx_est_m, pos_sv_m, corr_pr_m, weights = None,
159-
only_bias = False, tol = 1e-7, max_count = 20, use_tx_time=False):
162+
only_bias = False, tol = 1e-7, max_count = 20, sv_rx_time=False):
160163
"""Weighted least squares solver for GNSS measurements.
161164
162165
The option for only_bias allows the user to only calculate the clock
@@ -187,14 +190,17 @@ def wls(rx_est_m, pos_sv_m, corr_pr_m, weights = None,
187190
max_count : int
188191
Number of maximum iterations before process is aborted and
189192
solution returned.
190-
use_tx_time : bool
193+
sv_rx_time : bool
191194
Flag to indicate if the satellite positions at the time of
192195
transmission should be used as is or if they should be transformed
193196
to the ECEF frame of reference at the time of reception. For real
194-
measurements, use ``use_tx_time=False`` to account for the Earth's
195-
rotation. For simulations, ``use_tx_time=True`` can be used to
196-
simplify the simulation and estimation. By default,
197-
``use_tx_time=True``.
197+
measurements, use ``sv_rx_time=False`` to account for the Earth's
198+
rotation and convert SV positions from the ECEF frame at the time
199+
of signal transmission to the ECEF frame at the time of signal
200+
reception. If the SV positions should be used as is, set
201+
``sv_rx_time=True`` to indicate that the given positions are in
202+
the ECEF frame of reference for when the signals are received.
203+
By default, ``sv_rx_time=False``.
198204
199205
Returns
200206
-------
@@ -278,11 +284,11 @@ def wls(rx_est_m, pos_sv_m, corr_pr_m, weights = None,
278284
else:
279285
rx_est_m += pos_x_delta
280286

281-
if not use_tx_time:
287+
if not sv_rx_time:
282288
# Update the satellite positions based on the time taken for
283289
# the signal to reach the Earth and the satellite clock bias.
284-
tx_time = (corr_pr_m.reshape(-1) - rx_est_m[3,0])/consts.C
285-
dtheta = consts.OMEGA_E_DOT*tx_time
290+
delta_t = (corr_pr_m.reshape(-1) - rx_est_m[3,0])/consts.C
291+
dtheta = consts.OMEGA_E_DOT*delta_t
286292
pos_sv_m[:, 0] = np.cos(dtheta)*rx_time_pos_sv_m[:,0] + \
287293
np.sin(dtheta)*rx_time_pos_sv_m[:,1]
288294
pos_sv_m[:, 1] = -np.sin(dtheta)*rx_time_pos_sv_m[:,0] + \

notebooks/tutorials/algorithms.ipynb

Lines changed: 4 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@
4040
"When obtaining WLS estimates for real measurements, the rotation of the Earth between the signal transmission and reception has to be accounted for.\n",
4141
"`solve_wls` accounts for this by default and rotates the given SV positions into the ECEF frame of reference when the signals were received rather using the ECEF frame of reference of when the signals were transmitted.\n",
4242
"\n",
43-
"If you assume that the satellite positions are given in the ECEF frame of reference when the signals were received (and not transmitted), set the parameter `tx_time = False` in the function call."
43+
"If you assume that the satellite positions are given in the ECEF frame of reference when the signals were received (and not transmitted), set the parameter `sv_rx_time = True` in the function call."
4444
]
4545
},
4646
{
@@ -52,7 +52,7 @@
5252
"source": [
5353
"state_wls = glp.solve_wls(derived_data)\n",
5454
"# When assuming that SV positions are given in the ECEF frame when signals are received use\n",
55-
"# state_wls = glp.solve_wls(derived_data, use_tx_time=True)"
55+
"# state_wls = glp.solve_wls(derived_data, sv_rx_time=True)"
5656
]
5757
},
5858
{
@@ -108,34 +108,7 @@
108108
"id": "0387e03e",
109109
"metadata": {},
110110
"source": [
111-
"Solve for the extended Kalman filter position estimate simply by passing the measurement data.\n",
112-
"\n",
113-
"The implemented EKF also assumes that the satellite positions are given for when the signals were transmitted (and not received), so the satellite positions must be rotated to account for the change in the ECEF frame of reference due to the rotation of the Earth between transmission time and received time.\n",
114-
"\n",
115-
"In this case, to change this default behaviour, pass a dictionary `init_dict` with the key-value pair `\"use_tx_time\": True`."
116-
]
117-
},
118-
{
119-
"cell_type": "markdown",
120-
"id": "31e7b493",
121-
"metadata": {},
122-
"source": [
123-
"To prevent accidental usage of untuned process and measurement noises, `solve_gnss_ekf` requires an initialization \\\n",
124-
"dictionary containing values for the process noise `\"Q\"` and the measurement noise `\"R\"`.\n",
125-
"\n",
126-
"In the naive implementation, the noise matrix is set to the size of the measurement vector using the scalar value `\"R\"`."
127-
]
128-
},
129-
{
130-
"cell_type": "code",
131-
"execution_count": null,
132-
"id": "2dfb8d75",
133-
"metadata": {},
134-
"outputs": [],
135-
"source": [
136-
"import numpy as np\n",
137-
"init_dict = {\"Q\": np.eye(7),\n",
138-
" \"R\" : np.eye(1)}"
111+
"Solve for the extended Kalman filter position estimate simply by passing the measurement data."
139112
]
140113
},
141114
{
@@ -147,7 +120,7 @@
147120
},
148121
"outputs": [],
149122
"source": [
150-
"state_ekf = glp.solve_gnss_ekf(derived_data, init_dict)"
123+
"state_ekf = glp.solve_gnss_ekf(derived_data)"
151124
]
152125
},
153126
{

tests/algorithms/test_snapshot.py

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ def test_wls(set_user_states, set_sv_states, tolerance):
101101
keepdims = True) + rx_truth_m[3,0]
102102

103103
rx_est_m = np.zeros((4,1))
104-
user_fix = wls(rx_est_m, pos_sv_m, gt_pr_m, use_tx_time=True)
104+
user_fix = wls(rx_est_m, pos_sv_m, gt_pr_m, sv_rx_time=True)
105105
truth_fix = rx_truth_m
106106

107107
np.testing.assert_array_almost_equal(user_fix, truth_fix,
@@ -229,15 +229,15 @@ def test_wls_only_bias(set_user_states, set_sv_states, tolerance):
229229

230230
# check that position doesn't change but clock bias does change
231231
rx_est_m = np.zeros((4,1))
232-
user_fix = wls(rx_est_m, pos_sv_m, gt_pr_m, None, True, use_tx_time=True)
232+
user_fix = wls(rx_est_m, pos_sv_m, gt_pr_m, None, True, sv_rx_time=True)
233233
np.testing.assert_array_almost_equal(user_fix[:3], np.zeros((3,1)),
234234
decimal=tolerance)
235235
assert abs(user_fix[3]) >= 1E5
236236

237237
# check that correct clock bias is calculated
238238
rx_est_m = np.zeros((4,1))
239239
rx_est_m[:3] = rx_truth_m[:3]
240-
user_fix = wls(rx_est_m, pos_sv_m, gt_pr_m, None, True, use_tx_time=True)
240+
user_fix = wls(rx_est_m, pos_sv_m, gt_pr_m, None, True, sv_rx_time=True)
241241
truth_fix = rx_truth_m
242242

243243
np.testing.assert_array_almost_equal(user_fix, truth_fix,
@@ -362,7 +362,7 @@ def test_solve_wls(derived):
362362
Instance of AndroidDerived2021 for testing.
363363
364364
"""
365-
state_estimate = solve_wls(derived, use_tx_time=False)
365+
state_estimate = solve_wls(derived, sv_rx_time=False)
366366

367367
# result should be a NavData Class instance
368368
assert isinstance(state_estimate,type(NavData()))
@@ -403,12 +403,12 @@ def test_solve_wls_weights(derived, tolerance):
403403
Error threshold for test pass/fail
404404
"""
405405

406-
state_estimate_1 = solve_wls(derived, use_tx_time=False)
407-
state_estimate_2 = solve_wls(derived, None, use_tx_time=False)
406+
state_estimate_1 = solve_wls(derived, sv_rx_time=False)
407+
state_estimate_2 = solve_wls(derived, None, sv_rx_time=False)
408408

409409
# create new column of unity weights
410410
derived["unity_weights"] = 1
411-
state_estimate_3 = solve_wls(derived, "unity_weights", use_tx_time=False)
411+
state_estimate_3 = solve_wls(derived, "unity_weights", sv_rx_time=False)
412412

413413
# all of the above should be the same
414414
np.testing.assert_array_almost_equal(state_estimate_1.array,
@@ -418,7 +418,7 @@ def test_solve_wls_weights(derived, tolerance):
418418
state_estimate_3.array,
419419
decimal=tolerance)
420420

421-
state_estimate_4 = solve_wls(derived, "raw_pr_sigma_m", use_tx_time=False)
421+
state_estimate_4 = solve_wls(derived, "raw_pr_sigma_m", sv_rx_time=False)
422422
with np.testing.assert_raises(AssertionError):
423423
np.testing.assert_array_almost_equal(state_estimate_1.array,
424424
state_estimate_4.array,
@@ -464,10 +464,10 @@ def test_wls_weights(set_user_states, set_sv_states, tolerance,
464464

465465
# should work if None is passed
466466
user_fix_1 = wls(rx_est_m, pos_sv_m, noisy_pr_m, weights=None,
467-
use_tx_time=True)
467+
sv_rx_time=True)
468468
user_fix_2 = wls(rx_est_m, pos_sv_m, noisy_pr_m,
469469
weights=np.ones((pos_sv_m.shape[0],1)),
470-
use_tx_time=True)
470+
sv_rx_time=True)
471471
# both should be unity weights and return the same result
472472
np.testing.assert_array_almost_equal(user_fix_1,
473473
user_fix_2,
@@ -476,7 +476,7 @@ def test_wls_weights(set_user_states, set_sv_states, tolerance,
476476
# result should be different if different weights are used
477477
user_fix_3 = wls(rx_est_m, pos_sv_m, noisy_pr_m,
478478
weights=np.arange(pos_sv_m.shape[0]).reshape(-1,1),
479-
use_tx_time=True)
479+
sv_rx_time=True)
480480
with np.testing.assert_raises(AssertionError):
481481
np.testing.assert_array_almost_equal(user_fix_1,
482482
user_fix_3,
@@ -531,7 +531,7 @@ def test_solve_wls_bias_only(derived_2022):
531531
input_position[row, col] = measure_frame[row, 0]
532532
col += 1
533533
state_estimate = solve_wls(derived_2022, only_bias=True,
534-
receiver_state=derived_2022, use_tx_time=False)
534+
receiver_state=derived_2022, sv_rx_time=False)
535535
# Verify that both structures have the same length
536536
assert len(input_position) == len(state_estimate)
537537
# Verify that solved positions are the same as input positions
@@ -560,11 +560,11 @@ def test_solve_wls_bias_only(derived_2022):
560560
derived_2022.remove(ecef_rows, inplace=True)
561561
with pytest.raises(KeyError):
562562
solve_wls(derived_2022, only_bias=True,
563-
receiver_state=derived_2022, use_tx_time=False)
563+
receiver_state=derived_2022, sv_rx_time=False)
564564

565565
# check error raised when receiver_state is not present in only_bias
566566
with pytest.raises(RuntimeError):
567-
solve_wls(derived_2022, only_bias=True, use_tx_time=False)
567+
solve_wls(derived_2022, only_bias=True, sv_rx_time=False)
568568

569569

570570
def test_wls_fails(capsys):
@@ -632,13 +632,13 @@ def test_rotation_of_earth_fix(derived_2022):
632632
google_wls[:, idx] = frame[['x_rx_m', 'y_rx_m', 'z_rx_m'], 0]
633633
derived_2022['wls_weights'] = 1/derived_2022['raw_pr_sigma_m']
634634
state_with_rotn = solve_wls(derived_2022, weight_type='wls_weights',
635-
use_tx_time=False)
635+
sv_rx_time=False)
636636
glp_wls = state_with_rotn[['x_rx_wls_m', 'y_rx_wls_m', 'z_rx_wls_m']]
637637
# Verify that the mean error between both estimates is less than 10m
638638
for idx in range(3):
639639
assert np.mean(np.abs(google_wls[idx, :] - glp_wls[idx, :])) < 30
640640
state_without_rotn = solve_wls(derived_2022, weight_type='wls_weights',
641-
use_tx_time=True)
641+
sv_rx_time=True)
642642
glp_wls_no_rotn = state_without_rotn[['x_rx_wls_m',
643643
'y_rx_wls_m',
644644
'z_rx_wls_m']]

0 commit comments

Comments
 (0)