Skip to content

Commit 1577a5f

Browse files
authored
Merge pull request #730 from ut-issl/feature/gnss-receiver-update-pseudorange
Add GNSS receiver pseudorange calculation
2 parents 0eeb42a + ff9a039 commit 1577a5f

File tree

4 files changed

+179
-12
lines changed

4 files changed

+179
-12
lines changed
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
#
2+
# Plot GNSS Receiver Pseudorange
3+
#
4+
# arg[1] : read_file_tag : time tag for default CSV output log file. ex. 220627_142946
5+
#
6+
7+
#
8+
# Import
9+
#
10+
# plots
11+
import matplotlib.pyplot as plt
12+
# numpy
13+
import numpy as np
14+
# local function
15+
from common import find_latest_log_tag
16+
from common import add_log_file_arguments
17+
from common import read_3d_vector_from_csv
18+
from common import read_scalar_from_csv
19+
# arguments
20+
import argparse
21+
22+
# Arguments
23+
aparser = argparse.ArgumentParser()
24+
aparser = add_log_file_arguments(aparser)
25+
aparser.add_argument('--no-gui', action='store_true')
26+
args = aparser.parse_args()
27+
28+
#
29+
# Read Arguments
30+
#
31+
# log file path
32+
path_to_logs = args.logs_dir
33+
34+
read_file_tag = args.file_tag
35+
if read_file_tag == None:
36+
print("file tag does not found. use latest.")
37+
read_file_tag = find_latest_log_tag(path_to_logs)
38+
39+
print("log: " + read_file_tag)
40+
41+
#
42+
# CSV file name
43+
#
44+
read_file_name = path_to_logs + '/' + 'logs_' + read_file_tag + '/' + read_file_tag + '_default.csv'
45+
46+
#
47+
# Data read and edit
48+
#
49+
# Read S2E CSV
50+
time = read_scalar_from_csv(read_file_name, 'elapsed_time[s]')
51+
52+
plt.figure(0)
53+
for gps_idx in range(32):
54+
gps_str = 'GPS' + str(gps_idx)
55+
pseudorange = read_scalar_from_csv(read_file_name, gps_str + '_pseudorange[m]')
56+
plt.scatter(time[0][1:], pseudorange[0][1:], marker=".", label=gps_str)
57+
58+
plt.title("GPS Psuedorange")
59+
plt.xlabel("Time [s]")
60+
plt.ylabel("Psuedorange [m]")
61+
plt.legend(fontsize=7, loc="upper right")
62+
63+
64+
plt.figure(1)
65+
spacecraft_position_ecef_m = read_3d_vector_from_csv(read_file_name, 'spacecraft_position_ecef', 'm')[:, :-1]
66+
for gps_idx in range(32):
67+
gps_str = 'GPS' + str(gps_idx)
68+
pseudorange = read_scalar_from_csv(read_file_name, gps_str + '_pseudorange[m]')[:, 1:]
69+
gps_position = read_3d_vector_from_csv(read_file_name, gps_str + '_position_ecef', 'm')[:, 1:]
70+
geometric_range = np.linalg.norm(gps_position - spacecraft_position_ecef_m, axis=0)
71+
pseudorange_error = pseudorange - geometric_range
72+
plt.scatter(time[0][:-1], pseudorange_error, marker=".", label=gps_str)
73+
74+
plt.title("GPS Pseudorange Error")
75+
plt.xlabel("Time [s]")
76+
plt.ylabel("Pseudorange Error [m]")
77+
plt.legend(fontsize=7, loc="upper right")
78+
79+
# Data save
80+
if args.no_gui:
81+
plt.savefig(read_file_tag + "_gnss_receiver_pseudorange.png") # save last figure only
82+
else:
83+
plt.show()

settings/sample_satellite/components/gnss_receiver.ini

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,9 @@ antenna_model = SIMPLE
2424
// Antenna half width [deg]
2525
antenna_half_width_deg = 60
2626

27+
// Random noise for pseudorange observation
28+
white_noise_standard_deviation_pseudorange_m = 10.0
29+
2730
// Random noise for simple position observation
2831
white_noise_standard_deviation_position_ecef_m(0) = 2000.0
2932
white_noise_standard_deviation_position_ecef_m(1) = 1000.0

src/components/real/aocs/gnss_receiver.cpp

Lines changed: 48 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@ namespace s2e::components {
1515

1616
GnssReceiver::GnssReceiver(const int prescaler, environment::ClockGenerator* clock_generator, const size_t component_id,
1717
const AntennaModel antenna_model, const math::Vector<3> antenna_position_b_m, const math::Quaternion quaternion_b2c,
18-
const double half_width_deg, const math::Vector<3> position_noise_standard_deviation_ecef_m,
18+
const double half_width_deg, const double pseudorange_noise_standard_deviation_m,
19+
const math::Vector<3> position_noise_standard_deviation_ecef_m,
1920
const math::Vector<3> velocity_noise_standard_deviation_ecef_m_s, const dynamics::Dynamics* dynamics,
2021
const environment::GnssSatellites* gnss_satellites, const environment::SimulationTime* simulation_time)
2122
: Component(prescaler, clock_generator),
@@ -32,11 +33,13 @@ GnssReceiver::GnssReceiver(const int prescaler, environment::ClockGenerator* clo
3233
velocity_random_noise_ecef_m_s_[i].SetParameters(0.0, velocity_noise_standard_deviation_ecef_m_s[i],
3334
randomization::global_randomization.MakeSeed());
3435
}
36+
pseudorange_random_noise_m_.SetParameters(0.0, pseudorange_noise_standard_deviation_m, randomization::global_randomization.MakeSeed());
3537
}
3638

3739
GnssReceiver::GnssReceiver(const int prescaler, environment::ClockGenerator* clock_generator, PowerPort* power_port, const size_t component_id,
3840
const AntennaModel antenna_model, const math::Vector<3> antenna_position_b_m, const math::Quaternion quaternion_b2c,
39-
const double half_width_deg, const math::Vector<3> position_noise_standard_deviation_ecef_m,
41+
const double half_width_deg, const double pseudorange_noise_standard_deviation_m,
42+
const math::Vector<3> position_noise_standard_deviation_ecef_m,
4043
const math::Vector<3> velocity_noise_standard_deviation_ecef_m_s, const dynamics::Dynamics* dynamics,
4144
const environment::GnssSatellites* gnss_satellites, const environment::SimulationTime* simulation_time)
4245
: Component(prescaler, clock_generator, power_port),
@@ -53,6 +56,7 @@ GnssReceiver::GnssReceiver(const int prescaler, environment::ClockGenerator* clo
5356
velocity_random_noise_ecef_m_s_[i].SetParameters(0.0, velocity_noise_standard_deviation_ecef_m_s[i],
5457
randomization::global_randomization.MakeSeed());
5558
}
59+
pseudorange_random_noise_m_.SetParameters(0.0, pseudorange_noise_standard_deviation_m, randomization::global_randomization.MakeSeed());
5660
}
5761

5862
void GnssReceiver::MainRoutine(const int time_count) {
@@ -64,6 +68,9 @@ void GnssReceiver::MainRoutine(const int time_count) {
6468
math::Quaternion quaternion_i2b = dynamics_->GetAttitude().GetQuaternion_i2b();
6569
CheckAntenna(position_true_eci, quaternion_i2b);
6670

71+
// Pseudorange calculation
72+
SetGnssObservationList();
73+
6774
if (is_gnss_visible_) {
6875
// Antenna of GNSS-R can detect GNSS signal
6976
position_ecef_m_ = dynamics_->GetOrbit().GetPosition_ecef_m();
@@ -179,6 +186,32 @@ void GnssReceiver::SetGnssInfo(const math::Vector<3> antenna_to_satellite_i_m, c
179186
gnss_information_list_.push_back(gnss_info_new);
180187
}
181188

189+
double GnssReceiver::CalcGeometricDistance_m(const size_t gnss_system_id) {
190+
math::Vector<3> gnss_satellite_position_ecef_m = gnss_satellites_->GetPosition_ecef_m(gnss_system_id);
191+
math::Vector<3> position_true_ecef_m = dynamics_->GetOrbit().GetPosition_ecef_m();
192+
double geometric_distance_m = (gnss_satellite_position_ecef_m - position_true_ecef_m).CalcNorm();
193+
return geometric_distance_m;
194+
}
195+
196+
double GnssReceiver::CalcPseudorange_m(const size_t gnss_system_id) {
197+
// TODO: Add effect of radio wave propagation time
198+
// TODO: Add effect of clock bias
199+
// TODO: Add ionospheric delay
200+
double geometric_distance_m = CalcGeometricDistance_m(gnss_system_id);
201+
double pseudorange_m = geometric_distance_m + pseudorange_random_noise_m_;
202+
return pseudorange_m;
203+
}
204+
205+
void GnssReceiver::SetGnssObservationList() {
206+
// TODO: Add carrier phase observation
207+
pseudorange_list_m_.assign(kTotalNumberOfGnssSatellite, 0.0);
208+
for (size_t i = 0; i < gnss_information_list_.size(); i++) {
209+
size_t gnss_system_id = gnss_information_list_[i].gnss_id;
210+
double pseudorange_m = CalcPseudorange_m(gnss_system_id);
211+
pseudorange_list_m_[gnss_system_id] = pseudorange_m;
212+
}
213+
}
214+
182215
void GnssReceiver::AddNoise(const math::Vector<3> position_true_ecef_m, const math::Vector<3> velocity_true_ecef_m_s) {
183216
for (size_t i = 0; i < 3; i++) {
184217
position_ecef_m_[i] = position_true_ecef_m[i] + position_random_noise_ecef_m_[i];
@@ -217,6 +250,9 @@ std::string GnssReceiver::GetLogHeader() const // For logs
217250
str_tmp += logger::WriteScalar(sensor_name + "measured_altitude", "m");
218251
str_tmp += logger::WriteScalar(sensor_name + "satellite_visible_flag");
219252
str_tmp += logger::WriteScalar(sensor_name + "number_of_visible_satellites");
253+
for (size_t gps_index = 0; gps_index < kNumberOfGpsSatellite; gps_index++) {
254+
str_tmp += logger::WriteScalar("GPS" + std::to_string(gps_index) + "_pseudorange", "m");
255+
}
220256

221257
return str_tmp;
222258
}
@@ -237,6 +273,9 @@ std::string GnssReceiver::GetLogValue() const // For logs
237273
str_tmp += logger::WriteScalar(geodetic_position_.GetAltitude_m(), 10);
238274
str_tmp += logger::WriteScalar(is_gnss_visible_);
239275
str_tmp += logger::WriteScalar(visible_satellite_number_);
276+
for (size_t gps_index = 0; gps_index < kNumberOfGpsSatellite; gps_index++) {
277+
str_tmp += logger::WriteScalar(pseudorange_list_m_[gps_index], 16);
278+
}
240279

241280
return str_tmp;
242281
}
@@ -259,6 +298,7 @@ typedef struct _gnss_receiver_param {
259298
math::Vector<3> antenna_pos_b;
260299
math::Quaternion quaternion_b2c;
261300
double half_width_deg;
301+
double pseudorange_noise_standard_deviation_m;
262302
math::Vector<3> position_noise_standard_deviation_ecef_m;
263303
math::Vector<3> velocity_noise_standard_deviation_ecef_m_s;
264304
} GnssReceiverParam;
@@ -287,6 +327,7 @@ GnssReceiverParam ReadGnssReceiverIni(const std::string file_name, const environ
287327
gnssr_conf.ReadVector(GSection, "antenna_position_b_m", gnss_receiver_param.antenna_pos_b);
288328
gnssr_conf.ReadQuaternion(GSection, "quaternion_b2c", gnss_receiver_param.quaternion_b2c);
289329
gnss_receiver_param.half_width_deg = gnssr_conf.ReadDouble(GSection, "antenna_half_width_deg");
330+
gnss_receiver_param.pseudorange_noise_standard_deviation_m = gnssr_conf.ReadDouble(GSection, "white_noise_standard_deviation_pseudorange_m");
290331
gnssr_conf.ReadVector(GSection, "white_noise_standard_deviation_position_ecef_m", gnss_receiver_param.position_noise_standard_deviation_ecef_m);
291332
gnssr_conf.ReadVector(GSection, "white_noise_standard_deviation_velocity_ecef_m_s", gnss_receiver_param.velocity_noise_standard_deviation_ecef_m_s);
292333

@@ -299,8 +340,8 @@ GnssReceiver InitGnssReceiver(environment::ClockGenerator* clock_generator, cons
299340
GnssReceiverParam gr_param = ReadGnssReceiverIni(file_name, gnss_satellites, component_id);
300341

301342
GnssReceiver gnss_r(gr_param.prescaler, clock_generator, component_id, gr_param.antenna_model, gr_param.antenna_pos_b, gr_param.quaternion_b2c,
302-
gr_param.half_width_deg, gr_param.position_noise_standard_deviation_ecef_m, gr_param.velocity_noise_standard_deviation_ecef_m_s,
303-
dynamics, gnss_satellites, simulation_time);
343+
gr_param.half_width_deg, gr_param.pseudorange_noise_standard_deviation_m, gr_param.position_noise_standard_deviation_ecef_m,
344+
gr_param.velocity_noise_standard_deviation_ecef_m_s, dynamics, gnss_satellites, simulation_time);
304345
return gnss_r;
305346
}
306347

@@ -313,8 +354,9 @@ GnssReceiver InitGnssReceiver(environment::ClockGenerator* clock_generator, Powe
313354
power_port->InitializeWithInitializeFile(file_name);
314355

315356
GnssReceiver gnss_r(gr_param.prescaler, clock_generator, power_port, component_id, gr_param.antenna_model, gr_param.antenna_pos_b,
316-
gr_param.quaternion_b2c, gr_param.half_width_deg, gr_param.position_noise_standard_deviation_ecef_m,
317-
gr_param.velocity_noise_standard_deviation_ecef_m_s, dynamics, gnss_satellites, simulation_time);
357+
gr_param.quaternion_b2c, gr_param.half_width_deg, gr_param.pseudorange_noise_standard_deviation_m,
358+
gr_param.position_noise_standard_deviation_ecef_m, gr_param.velocity_noise_standard_deviation_ecef_m_s, dynamics,
359+
gnss_satellites, simulation_time);
318360
return gnss_r;
319361
}
320362

src/components/real/aocs/gnss_receiver.hpp

Lines changed: 45 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ class GnssReceiver : public Component, public logger::ILoggable {
5454
* @param [in] antenna_position_b_m: GNSS antenna position at the body-fixed frame [m]
5555
* @param [in] quaternion_b2c: Quaternion from body frame to component frame (antenna frame)
5656
* @param [in] half_width_deg: Half width of the antenna cone model [deg]
57+
* @param [in] pseudorange_noise_standard_deviation_m: Standard deviation of normal random noise for pseudorange [m]
5758
* @param [in] position_noise_standard_deviation_ecef_m: Standard deviation of normal random noise for position in the ECEF frame [m]
5859
* @param [in] velocity_noise_standard_deviation_ecef_m_s: Standard deviation of normal random noise for velocity in the ECEF frame [m/s]
5960
* @param [in] dynamics: Dynamics information
@@ -62,9 +63,9 @@ class GnssReceiver : public Component, public logger::ILoggable {
6263
*/
6364
GnssReceiver(const int prescaler, environment::ClockGenerator* clock_generator, const size_t component_id, const AntennaModel antenna_model,
6465
const math::Vector<3> antenna_position_b_m, const math::Quaternion quaternion_b2c, const double half_width_deg,
65-
const math::Vector<3> position_noise_standard_deviation_ecef_m, const math::Vector<3> velocity_noise_standard_deviation_ecef_m_s,
66-
const dynamics::Dynamics* dynamics, const environment::GnssSatellites* gnss_satellites,
67-
const environment::SimulationTime* simulation_time);
66+
const double pseudorange_noise_standard_deviation_m, const math::Vector<3> position_noise_standard_deviation_ecef_m,
67+
const math::Vector<3> velocity_noise_standard_deviation_ecef_m_s, const dynamics::Dynamics* dynamics,
68+
const environment::GnssSatellites* gnss_satellites, const environment::SimulationTime* simulation_time);
6869
/**
6970
* @fn GnssReceiver
7071
* @brief Constructor with power port
@@ -75,6 +76,7 @@ class GnssReceiver : public Component, public logger::ILoggable {
7576
* @param [in] antenna_position_b_m: GNSS antenna position at the body-fixed frame [m]
7677
* @param [in] quaternion_b2c: Quaternion from body frame to component frame (antenna frame)
7778
* @param [in] half_width_deg: Half width of the antenna cone model [rad]
79+
* @param [in] pseudorange_noise_standard_deviation_m: Standard deviation of normal random noise for pseudorange [m]
7880
* @param [in] position_noise_standard_deviation_ecef_m: Standard deviation of normal random noise for position in the ECEF frame [m]
7981
* @param [in] velocity_noise_standard_deviation_ecef_m_s: Standard deviation of normal random noise for velocity in the ECEF frame [m/s]
8082
* @param [in] dynamics: Dynamics information
@@ -83,9 +85,10 @@ class GnssReceiver : public Component, public logger::ILoggable {
8385
*/
8486
GnssReceiver(const int prescaler, environment::ClockGenerator* clock_generator, PowerPort* power_port, const size_t component_id,
8587
const AntennaModel antenna_model, const math::Vector<3> antenna_position_b_m, const math::Quaternion quaternion_b2c,
86-
const double half_width_deg, const math::Vector<3> position_noise_standard_deviation_ecef_m,
87-
const math::Vector<3> velocity_noise_standard_deviation_ecef_m_s, const dynamics::Dynamics* dynamics,
88-
const environment::GnssSatellites* gnss_satellites, const environment::SimulationTime* simulation_time);
88+
const double half_width_deg, const double pseudorange_noise_standard_deviation_m,
89+
const math::Vector<3> position_noise_standard_deviation_ecef_m, const math::Vector<3> velocity_noise_standard_deviation_ecef_m_s,
90+
const dynamics::Dynamics* dynamics, const environment::GnssSatellites* gnss_satellites,
91+
const environment::SimulationTime* simulation_time);
8992

9093
// Override functions for Component
9194
/**
@@ -130,6 +133,19 @@ class GnssReceiver : public Component, public logger::ILoggable {
130133
virtual std::string GetLogValue() const;
131134

132135
protected:
136+
// GNSS satellite number definition
137+
// TODO: Move to initialized file?
138+
static const size_t kNumberOfGpsSatellite = 32; //!< Number of GPS satellites
139+
static const size_t kNumberOfGlonassSatellite = 26; //!< Number of GLONASS satellites
140+
static const size_t kNumberOfGalileoSatellite = 28; //!< Number of Galileo satellites
141+
static const size_t kNumberOfBeidouSatellite = 62; //!< Number of BeiDou satellites
142+
static const size_t kNumberOfQzssSatellite = 5; //!< Number of QZSS satellites
143+
static const size_t kNumberOfNavicSatellite = 7; //!< Number of NavIC satellites
144+
145+
static const size_t kTotalNumberOfGnssSatellite = kNumberOfGpsSatellite + kNumberOfGlonassSatellite + kNumberOfGalileoSatellite +
146+
kNumberOfBeidouSatellite + kNumberOfQzssSatellite +
147+
kNumberOfNavicSatellite; //<! Total number of GNSS satellites
148+
133149
// Parameters for receiver
134150
const size_t component_id_; //!< Receiver ID
135151

@@ -139,6 +155,10 @@ class GnssReceiver : public Component, public logger::ILoggable {
139155
double half_width_deg_ = 0.0; //!< Half width of the antenna cone model [deg]
140156
AntennaModel antenna_model_; //!< Antenna model
141157

158+
// GNSS observation
159+
randomization::NormalRand pseudorange_random_noise_m_; //!< Random noise for pseudorange [m]
160+
std::vector<double> pseudorange_list_m_{kTotalNumberOfGnssSatellite, 0.0}; //!< Pseudorange list for each GPS satellite
161+
142162
// Simple position observation
143163
randomization::NormalRand position_random_noise_ecef_m_[3]; //!< Random noise for position at the ECEF frame [m]
144164
randomization::NormalRand velocity_random_noise_ecef_m_s_[3]; //!< Random noise for velocity at the ECEF frame [m]
@@ -194,6 +214,25 @@ class GnssReceiver : public Component, public logger::ILoggable {
194214
* @param [in] gnss_system_id: ID of target GNSS satellite
195215
*/
196216
void SetGnssInfo(const math::Vector<3> antenna_to_satellite_i_m, const math::Quaternion quaternion_i2b, const size_t gnss_system_id);
217+
/**
218+
* @fn CalcGeometricDistance
219+
* @brief Calculate the geometric distance between the GNSS satellite and the GNSS receiver antenna
220+
* @param [in] gnss_system_id: ID of target GNSS satellite
221+
* @return Geometric distance between the GNSS satellite and the GNSS receiver antenna [m]
222+
*/
223+
double CalcGeometricDistance_m(const size_t gnss_system_id);
224+
/**
225+
* @fn CalcPseudorange
226+
* @brief Calculate the pseudorange between the GNSS satellite and the GNSS receiver antenna
227+
* @param [in] gnss_system_id: ID of target GNSS satellite
228+
* @return Pseudorange between the GNSS satellite and the GNSS receiver antenna [m]
229+
*/
230+
double CalcPseudorange_m(const size_t gnss_id);
231+
/**
232+
* @fn SetGnssObservationList
233+
* @brief Calculate and set the GNSS observation list for each GNSS satellite
234+
*/
235+
void SetGnssObservationList();
197236
/**
198237
* @fn AddNoise
199238
* @brief Substitutional method for "Measure" in other sensor models inherited Sensor class

0 commit comments

Comments
 (0)