Skip to content

Commit d1e3af1

Browse files
committed
feat(simulation): add ranging beacon simulation in SIH
1 parent ddcc485 commit d1e3af1

File tree

3 files changed

+98
-20
lines changed

3 files changed

+98
-20
lines changed

src/modules/simulation/simulator_sih/sih.cpp

Lines changed: 58 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ void Sih::run()
7878
_last_run = task_start;
7979
_airspeed_time = task_start;
8080
_dist_snsr_time = task_start;
81+
_ranging_beacon_time = task_start;
8182
_vehicle = static_cast<VehicleType>(constrain(_sih_vtype.get(),
8283
static_cast<int32_t>(VehicleType::First),
8384
static_cast<int32_t>(VehicleType::Last)));
@@ -232,6 +233,12 @@ void Sih::sensor_step()
232233
send_dist_snsr(now);
233234
}
234235

236+
// ranging beacon published at 2 Hz (each beacon at 0.5 Hz)
237+
if (now - _ranging_beacon_time >= 500_ms) {
238+
_ranging_beacon_time = now;
239+
send_ranging_beacon(now);
240+
}
241+
235242
publish_ground_truth(now);
236243

237244
perf_end(_loop_perf);
@@ -259,7 +266,7 @@ void Sih::parameters_updated()
259266
_lla.setAltitude(_lpos_ref_alt);
260267
_p_E = _lla.toEcef();
261268

262-
const Dcmf R_E2N = computeRotEcefToNed(_lla);
269+
const Dcmf R_E2N = _lla.computeRotEcefToNed();
263270
_R_N2E = R_E2N.transpose();
264271
_v_E = _R_N2E * _v_N;
265272

@@ -571,7 +578,7 @@ void Sih::ecefToNed()
571578
{
572579
_lla = LatLonAlt::fromEcef(_p_E);
573580

574-
const Dcmf C_SE = computeRotEcefToNed(_lla);
581+
const Dcmf C_SE = _lla.computeRotEcefToNed();
575582
_R_N2E = C_SE.transpose();
576583

577584
// Transform velocity to NED frame
@@ -582,22 +589,6 @@ void Sih::ecefToNed()
582589
_q.normalize();
583590
}
584591

585-
Dcmf Sih::computeRotEcefToNed(const LatLonAlt &lla)
586-
{
587-
// Calculate the ECEF to NED coordinate transformation matrix
588-
const double cos_lat = cos(lla.latitude_rad());
589-
const double sin_lat = sin(lla.latitude_rad());
590-
const double cos_lon = cos(lla.longitude_rad());
591-
const double sin_lon = sin(lla.longitude_rad());
592-
593-
const float val[] = {(float)(-sin_lat * cos_lon), (float)(-sin_lat * sin_lon), (float)cos_lat,
594-
(float) - sin_lon, (float)cos_lon, 0.f,
595-
(float)(-cos_lat * cos_lon), (float)(-cos_lat * sin_lon), (float) - sin_lat
596-
};
597-
598-
return Dcmf(val);
599-
}
600-
601592
void Sih::reconstruct_sensors_signals(const hrt_abstime &time_now_us)
602593
{
603594
// The sensor signals reconstruction and noise levels are from [1]
@@ -678,6 +669,55 @@ void Sih::send_dist_snsr(const hrt_abstime &time_now_us)
678669
_distance_snsr_pub.publish(distance_sensor);
679670
}
680671

672+
void Sih::send_ranging_beacon(const hrt_abstime &time_now_us)
673+
{
674+
if (_lpos_ref.isInitialized()) {
675+
676+
if (!_beacons_configured) {
677+
_beacons_configured = true;
678+
679+
for (uint8_t i = 0; i < NUM_RANGING_BEACONS; i++) {
680+
_lpos_ref.reproject(RANGING_BEACON_OFFSETS[i].north_m, RANGING_BEACON_OFFSETS[i].east_m,
681+
_ranging_beacons[i].lat_deg, _ranging_beacons[i].lon_deg);
682+
_ranging_beacons[i].alt_m = _sih_h0.get() + RANGING_BEACON_OFFSETS[i].alt_offset_m;
683+
}
684+
}
685+
686+
const RangingBeaconConfig &beacon = _ranging_beacons[_ranging_beacon_idx];
687+
const LatLonAlt beacon_lla(beacon.lat_deg, beacon.lon_deg, beacon.alt_m);
688+
const matrix::Vector3d beacon_ecef = beacon_lla.toEcef();
689+
690+
// Compute true range in ECEF
691+
const matrix::Vector3d delta_ecef = beacon_ecef - _p_E;
692+
const double true_range_m = delta_ecef.norm();
693+
694+
const float noise_std = _sih_ranging_beacon_noise.get();
695+
const float noise_m = (noise_std > 0.f) ? generate_wgn() * noise_std : 0.f;
696+
const double measured_range_m = math::max(0.0, true_range_m + static_cast<double>(noise_m));
697+
698+
ranging_beacon_s msg{};
699+
msg.timestamp = hrt_absolute_time();
700+
msg.timestamp_sample = time_now_us;
701+
msg.beacon_id = _ranging_beacon_idx;
702+
msg.range = static_cast<float>(measured_range_m);
703+
msg.lat = beacon.lat_deg;
704+
msg.lon = beacon.lon_deg;
705+
msg.alt = beacon.alt_m;
706+
msg.alt_type = 0; // WGS84
707+
msg.hacc = 1.0f;
708+
msg.vacc = 1.0f;
709+
msg.range_accuracy = noise_std;
710+
msg.sequence_nr = 0;
711+
msg.status = 0;
712+
msg.carrier_freq = 0;
713+
714+
_ranging_beacon_pub.publish(msg);
715+
716+
// cycle through the beacons
717+
_ranging_beacon_idx = (_ranging_beacon_idx + 1) % NUM_RANGING_BEACONS;
718+
}
719+
}
720+
681721
void Sih::publish_ground_truth(const hrt_abstime &time_now_us)
682722
{
683723
{

src/modules/simulation/simulator_sih/sih.hpp

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@
7979
#include <uORB/topics/vehicle_attitude.h>
8080
#include <uORB/topics/vehicle_global_position.h>
8181
#include <uORB/topics/vehicle_local_position.h>
82+
#include <uORB/topics/ranging_beacon.h>
8283

8384
#if defined(ENABLE_LOCKSTEP_SCHEDULER)
8485
#include <sys/time.h>
@@ -128,6 +129,7 @@ class Sih : public ModuleBase, public ModuleParams
128129
PX4Gyroscope _px4_gyro{1310988}; // 1310988: DRV_IMU_DEVTYPE_SIM, BUS: 1, ADDR: 1, TYPE: SIMULATION
129130
uORB::Publication<distance_sensor_s> _distance_snsr_pub{ORB_ID(distance_sensor)};
130131
uORB::Publication<airspeed_s> _airspeed_pub{ORB_ID(airspeed)};
132+
uORB::Publication<ranging_beacon_s> _ranging_beacon_pub{ORB_ID(ranging_beacon)};
131133

132134
// groundtruth
133135
uORB::Publication<vehicle_angular_velocity_s> _angular_velocity_ground_truth_pub{ORB_ID(vehicle_angular_velocity_groundtruth)};
@@ -140,6 +142,29 @@ class Sih : public ModuleBase, public ModuleParams
140142

141143
// hard constants
142144
static constexpr uint16_t NUM_ACTUATORS_MAX = 9;
145+
146+
// Ranging beacon simulation constants
147+
static constexpr uint8_t NUM_RANGING_BEACONS = 4;
148+
bool _beacons_configured{false};
149+
struct RangingBeaconConfig {
150+
double lat_deg;
151+
double lon_deg;
152+
float alt_m;
153+
};
154+
struct RangingBeaconOffset {
155+
float north_m;
156+
float east_m;
157+
float alt_offset_m;
158+
};
159+
// NED offsets from SIH_LOC_LAT0/LON0/H0, resolved once in init_variables()
160+
static constexpr RangingBeaconOffset RANGING_BEACON_OFFSETS[NUM_RANGING_BEACONS] = {
161+
{ 5000.f, 0.f, 30.f}, // ~5 km North
162+
{ 0.f, 10000.f, 0.f}, // ~10 km East
163+
{-20000.f, -15000.f, 110.f}, // ~20 km South-West
164+
{ 35000.f, 45000.f, 310.f} // ~50 km North-East
165+
};
166+
RangingBeaconConfig _ranging_beacons[NUM_RANGING_BEACONS] {};
167+
143168
static constexpr float T1_C = 15.0f; // ground temperature in Celsius
144169
static constexpr float T1_K = T1_C - atmosphere::kAbsoluteNullCelsius; // ground temperature in Kelvin
145170
static constexpr float TEMP_GRADIENT = -6.5f / 1000.0f; // temperature gradient in degrees per metre
@@ -163,6 +188,7 @@ class Sih : public ModuleBase, public ModuleParams
163188
void reconstruct_sensors_signals(const hrt_abstime &time_now_us);
164189
void send_airspeed(const hrt_abstime &time_now_us);
165190
void send_dist_snsr(const hrt_abstime &time_now_us);
191+
void send_ranging_beacon(const hrt_abstime &time_now_us);
166192
void publish_ground_truth(const hrt_abstime &time_now_us);
167193
void generate_fw_aerodynamics(const float roll_cmd, const float pitch_cmd, const float yaw_cmd, const float thrust);
168194
void generate_ts_aerodynamics();
@@ -171,7 +197,6 @@ class Sih : public ModuleBase, public ModuleParams
171197
static float computeGravity(double lat);
172198

173199
void ecefToNed();
174-
static matrix::Dcmf computeRotEcefToNed(const LatLonAlt &lla);
175200

176201
struct Wgs84 {
177202
static constexpr double equatorial_radius = 6378137.0;
@@ -199,6 +224,8 @@ class Sih : public ModuleBase, public ModuleParams
199224
hrt_abstime _last_actuator_output_time{0};
200225
hrt_abstime _airspeed_time{0};
201226
hrt_abstime _dist_snsr_time{0};
227+
hrt_abstime _ranging_beacon_time{0};
228+
uint8_t _ranging_beacon_idx{0};
202229

203230
bool _grounded{true}; // whether the vehicle is on the ground
204231

@@ -301,6 +328,7 @@ class Sih : public ModuleBase, public ModuleParams
301328
(ParamFloat<px4::params::SIH_T_TAU>) _sih_thrust_tau,
302329
(ParamInt<px4::params::SIH_VEHICLE_TYPE>) _sih_vtype,
303330
(ParamFloat<px4::params::SIH_WIND_N>) _sih_wind_n,
304-
(ParamFloat<px4::params::SIH_WIND_E>) _sih_wind_e
331+
(ParamFloat<px4::params::SIH_WIND_E>) _sih_wind_e,
332+
(ParamFloat<px4::params::SIH_RNGBC_NOISE>) _sih_ranging_beacon_noise
305333
)
306334
};

src/modules/simulation/simulator_sih/sih_params.yaml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -271,3 +271,13 @@ parameters:
271271
type: float
272272
default: 0.0
273273
unit: m/s
274+
SIH_RNGBC_NOISE:
275+
description:
276+
short: Ranging beacon measurement noise standard deviation
277+
long: Gaussian noise added to simulated ranging beacon measurements. Set to 0 to disable noise.
278+
type: float
279+
default: 30.0
280+
unit: m
281+
min: 0.0
282+
max: 100.0
283+
decimal: 1

0 commit comments

Comments
 (0)