Skip to content

Commit be99d2f

Browse files
committedJul 28, 2019
sih: fix code style
1 parent 09eaef8 commit be99d2f

File tree

1 file changed

+295
-293
lines changed

1 file changed

+295
-293
lines changed
 

‎src/modules/sih/sih.cpp

+295-293
Original file line numberDiff line numberDiff line change
@@ -57,334 +57,296 @@
5757
using namespace math;
5858
using namespace matrix;
5959

60-
int Sih::print_usage(const char *reason)
61-
{
62-
if (reason) {
63-
PX4_WARN("%s\n", reason);
64-
}
65-
66-
PRINT_MODULE_DESCRIPTION(
67-
R"DESCR_STR(
68-
### Description
69-
This module provide a simulator for quadrotors running fully
70-
inside the hardware autopilot.
71-
72-
This simulator subscribes to "actuator_outputs" which are the actuator pwm
73-
signals given by the mixer.
74-
75-
This simulator publishes the sensors signals corrupted with realistic noise
76-
in order to incorporate the state estimator in the loop.
77-
78-
### Implementation
79-
The simulator implements the equations of motion using matrix algebra.
80-
Quaternion representation is used for the attitude.
81-
Forward Euler is used for integration.
82-
Most of the variables are declared global in the .hpp file to avoid stack overflow.
83-
84-
85-
)DESCR_STR");
86-
87-
PRINT_MODULE_USAGE_NAME("sih", "simulation");
88-
PRINT_MODULE_USAGE_COMMAND("start");
89-
PRINT_MODULE_USAGE_DEFAULT_COMMANDS();
90-
91-
return 0;
92-
}
93-
9460
int Sih::print_status()
9561
{
96-
PX4_INFO("Running");
97-
return 0;
62+
PX4_INFO("Running");
63+
return 0;
9864
}
9965

10066
int Sih::custom_command(int argc, char *argv[])
10167
{
102-
return print_usage("unknown command");
68+
return print_usage("unknown command");
10369
}
10470

10571

10672
int Sih::task_spawn(int argc, char *argv[])
10773
{
108-
_task_id = px4_task_spawn_cmd("sih",
109-
SCHED_DEFAULT,
110-
SCHED_PRIORITY_MAX,
111-
1024,
112-
(px4_main_t)&run_trampoline,
113-
(char *const *)argv);
114-
115-
if (_task_id < 0) {
116-
_task_id = -1;
117-
return -errno;
118-
}
74+
_task_id = px4_task_spawn_cmd("sih",
75+
SCHED_DEFAULT,
76+
SCHED_PRIORITY_MAX,
77+
1024,
78+
(px4_main_t)&run_trampoline,
79+
(char *const *)argv);
80+
81+
if (_task_id < 0) {
82+
_task_id = -1;
83+
return -errno;
84+
}
11985

120-
return 0;
86+
return 0;
12187
}
12288

12389
Sih *Sih::instantiate(int argc, char *argv[])
12490
{
125-
Sih *instance = new Sih();
91+
Sih *instance = new Sih();
12692

127-
if (instance == nullptr) {
128-
PX4_ERR("alloc failed");
129-
}
93+
if (instance == nullptr) {
94+
PX4_ERR("alloc failed");
95+
}
13096

131-
return instance;
97+
return instance;
13298
}
13399

134-
Sih::Sih()
135-
: ModuleParams(nullptr),
136-
_loop_perf(perf_alloc(PC_ELAPSED, "sih_execution")),
137-
_sampling_perf(perf_alloc(PC_ELAPSED, "sih_sampling"))
100+
Sih::Sih() :
101+
ModuleParams(nullptr),
102+
_loop_perf(perf_alloc(PC_ELAPSED, "sih_execution")),
103+
_sampling_perf(perf_alloc(PC_ELAPSED, "sih_sampling"))
138104
{
139105
}
140106

141107
void Sih::run()
142108
{
109+
// to subscribe to (read) the actuators_out pwm
110+
_actuator_out_sub = orb_subscribe(ORB_ID(actuator_outputs));
143111

144-
// to subscribe to (read) the actuators_out pwm
145-
_actuator_out_sub = orb_subscribe(ORB_ID(actuator_outputs));
146-
147-
// initialize parameters
148-
_parameter_update_sub = orb_subscribe(ORB_ID(parameter_update));
149-
parameters_update_poll();
150-
151-
init_variables();
152-
init_sensors();
112+
// initialize parameters
113+
_parameter_update_sub = orb_subscribe(ORB_ID(parameter_update));
114+
parameters_update_poll();
153115

154-
const hrt_abstime task_start = hrt_absolute_time();
155-
_last_run = task_start;
156-
_gps_time = task_start;
157-
_serial_time = task_start;
116+
init_variables();
117+
init_sensors();
158118

159-
px4_sem_init(&_data_semaphore, 0, 0);
119+
const hrt_abstime task_start = hrt_absolute_time();
120+
_last_run = task_start;
121+
_gps_time = task_start;
122+
_serial_time = task_start;
160123

161-
hrt_call_every(&_timer_call, LOOP_INTERVAL, LOOP_INTERVAL, timer_callback, &_data_semaphore);
124+
px4_sem_init(&_data_semaphore, 0, 0);
162125

163-
perf_begin(_sampling_perf);
126+
hrt_call_every(&_timer_call, LOOP_INTERVAL, LOOP_INTERVAL, timer_callback, &_data_semaphore);
164127

165-
while (!should_exit())
166-
{
167-
px4_sem_wait(&_data_semaphore); // periodic real time wakeup
128+
perf_begin(_sampling_perf);
168129

169-
perf_end(_sampling_perf);
170-
perf_begin(_sampling_perf);
130+
while (!should_exit()) {
131+
px4_sem_wait(&_data_semaphore); // periodic real time wakeup
171132

172-
perf_begin(_loop_perf);
133+
perf_end(_sampling_perf);
134+
perf_begin(_sampling_perf);
173135

174-
inner_loop(); // main execution function
136+
perf_begin(_loop_perf);
175137

176-
perf_end(_loop_perf);
177-
}
138+
inner_loop(); // main execution function
178139

179-
hrt_cancel(&_timer_call); // close the periodic timer interruption
180-
px4_sem_destroy(&_data_semaphore);
181-
orb_unsubscribe(_actuator_out_sub);
182-
orb_unsubscribe(_parameter_update_sub);
140+
perf_end(_loop_perf);
141+
}
183142

143+
hrt_cancel(&_timer_call); // close the periodic timer interruption
144+
px4_sem_destroy(&_data_semaphore);
145+
orb_unsubscribe(_actuator_out_sub);
146+
orb_unsubscribe(_parameter_update_sub);
184147
}
185148

186149
// timer_callback() is used as a real time callback to post the semaphore
187150
void Sih::timer_callback(void *sem)
188151
{
189-
px4_sem_post((px4_sem_t *)sem);
152+
px4_sem_post((px4_sem_t *)sem);
190153
}
191154

192155
// this is the main execution waken up periodically by the semaphore
193156
void Sih::inner_loop()
194157
{
195-
_now = hrt_absolute_time();
196-
_dt = (_now - _last_run) * 1e-6f;
197-
_last_run = _now;
158+
_now = hrt_absolute_time();
159+
_dt = (_now - _last_run) * 1e-6f;
160+
_last_run = _now;
198161

199-
read_motors();
162+
read_motors();
200163

201-
generate_force_and_torques();
164+
generate_force_and_torques();
202165

203-
equations_of_motion();
166+
equations_of_motion();
204167

205-
reconstruct_sensors_signals();
168+
reconstruct_sensors_signals();
206169

207-
send_IMU();
170+
send_IMU();
208171

209-
if (_now - _gps_time >= 50000) // gps published at 20Hz
210-
{
211-
_gps_time=_now;
212-
send_gps();
213-
}
172+
if (_now - _gps_time >= 50000) { // gps published at 20Hz
173+
_gps_time = _now;
174+
send_gps();
175+
}
214176

215-
// send uart message every 40 ms
216-
if (_now - _serial_time >= 40000)
217-
{
218-
_serial_time=_now;
177+
// send uart message every 40 ms
178+
if (_now - _serial_time >= 40000) {
179+
_serial_time = _now;
219180

220-
publish_sih(); // publish _sih message for debug purpose
181+
publish_sih(); // publish _sih message for debug purpose
221182

222-
parameters_update_poll(); // update the parameters if needed
223-
}
183+
parameters_update_poll(); // update the parameters if needed
184+
}
224185
}
225186

226187
void Sih::parameters_update_poll()
227188
{
228-
bool updated;
229-
struct parameter_update_s param_upd;
189+
bool updated = false;
190+
struct parameter_update_s param_upd;
230191

231-
orb_check(_parameter_update_sub, &updated);
192+
orb_check(_parameter_update_sub, &updated);
232193

233-
if (updated) {
234-
orb_copy(ORB_ID(parameter_update), _parameter_update_sub, &param_upd);
235-
updateParams();
236-
parameters_updated();
237-
}
194+
if (updated) {
195+
orb_copy(ORB_ID(parameter_update), _parameter_update_sub, &param_upd);
196+
updateParams();
197+
parameters_updated();
198+
}
238199
}
239200

240201
// store the parameters in a more convenient form
241202
void Sih::parameters_updated()
242203
{
204+
_T_MAX = _sih_t_max.get();
205+
_Q_MAX = _sih_q_max.get();
206+
_L_ROLL = _sih_l_roll.get();
207+
_L_PITCH = _sih_l_pitch.get();
208+
_KDV = _sih_kdv.get();
209+
_KDW = _sih_kdw.get();
210+
_H0 = _sih_h0.get();
243211

244-
_T_MAX = _sih_t_max.get();
245-
_Q_MAX = _sih_q_max.get();
246-
_L_ROLL = _sih_l_roll.get();
247-
_L_PITCH = _sih_l_pitch.get();
248-
_KDV = _sih_kdv.get();
249-
_KDW = _sih_kdw.get();
250-
_H0 = _sih_h0.get();
251-
252-
_LAT0 = (double)_sih_lat0.get()*1.0e-7;
253-
_LON0 = (double)_sih_lon0.get()*1.0e-7;
254-
_COS_LAT0=cosl(radians(_LAT0));
212+
_LAT0 = (double)_sih_lat0.get() * 1.0e-7;
213+
_LON0 = (double)_sih_lon0.get() * 1.0e-7;
214+
_COS_LAT0 = cosl(radians(_LAT0));
255215

256-
_MASS=_sih_mass.get();
216+
_MASS = _sih_mass.get();
257217

258-
_W_I=Vector3f(0.0f,0.0f,_MASS*CONSTANTS_ONE_G);
218+
_W_I = Vector3f(0.0f, 0.0f, _MASS * CONSTANTS_ONE_G);
259219

260-
_I=diag(Vector3f(_sih_ixx.get(),_sih_iyy.get(),_sih_izz.get()));
261-
_I(0,1)=_I(1,0)=_sih_ixy.get();
262-
_I(0,2)=_I(2,0)=_sih_ixz.get();
263-
_I(1,2)=_I(2,1)=_sih_iyz.get();
220+
_I = diag(Vector3f(_sih_ixx.get(), _sih_iyy.get(), _sih_izz.get()));
221+
_I(0, 1) = _I(1, 0) = _sih_ixy.get();
222+
_I(0, 2) = _I(2, 0) = _sih_ixz.get();
223+
_I(1, 2) = _I(2, 1) = _sih_iyz.get();
264224

265-
_Im1=inv(_I);
266-
267-
_mu_I=Vector3f(_sih_mu_x.get(), _sih_mu_y.get(), _sih_mu_z.get());
225+
_Im1 = inv(_I);
268226

227+
_mu_I = Vector3f(_sih_mu_x.get(), _sih_mu_y.get(), _sih_mu_z.get());
269228
}
270229

271230
// initialization of the variables for the simulator
272231
void Sih::init_variables()
273232
{
274-
srand(1234); // initialize the random seed once before calling generate_wgn()
275-
276-
_p_I=Vector3f(0.0f,0.0f,0.0f);
277-
_v_I=Vector3f(0.0f,0.0f,0.0f);
278-
_q=Quatf(1.0f,0.0f,0.0f,0.0f);
279-
_w_B=Vector3f(0.0f,0.0f,0.0f);
233+
srand(1234); // initialize the random seed once before calling generate_wgn()
280234

281-
_u[0]=_u[1]=_u[2]=_u[3]=0.0f;
235+
_p_I = Vector3f(0.0f, 0.0f, 0.0f);
236+
_v_I = Vector3f(0.0f, 0.0f, 0.0f);
237+
_q = Quatf(1.0f, 0.0f, 0.0f, 0.0f);
238+
_w_B = Vector3f(0.0f, 0.0f, 0.0f);
282239

240+
_u[0] = _u[1] = _u[2] = _u[3] = 0.0f;
283241
}
284242

285243
void Sih::init_sensors()
286244
{
287-
_vehicle_gps_pos.fix_type=3; // 3D fix
288-
_vehicle_gps_pos.satellites_used=8;
289-
_vehicle_gps_pos.heading=NAN;
290-
_vehicle_gps_pos.heading_offset=NAN;
291-
_vehicle_gps_pos.s_variance_m_s = 0.5f;
292-
_vehicle_gps_pos.c_variance_rad = 0.1f;
293-
_vehicle_gps_pos.eph = 0.9f;
294-
_vehicle_gps_pos.epv = 1.78f;
295-
_vehicle_gps_pos.hdop = 0.7f;
296-
_vehicle_gps_pos.vdop = 1.1f;
245+
_vehicle_gps_pos.fix_type = 3; // 3D fix
246+
_vehicle_gps_pos.satellites_used = 8;
247+
_vehicle_gps_pos.heading = NAN;
248+
_vehicle_gps_pos.heading_offset = NAN;
249+
_vehicle_gps_pos.s_variance_m_s = 0.5f;
250+
_vehicle_gps_pos.c_variance_rad = 0.1f;
251+
_vehicle_gps_pos.eph = 0.9f;
252+
_vehicle_gps_pos.epv = 1.78f;
253+
_vehicle_gps_pos.hdop = 0.7f;
254+
_vehicle_gps_pos.vdop = 1.1f;
297255
}
298256

299257
// read the motor signals outputted from the mixer
300258
void Sih::read_motors()
301259
{
302-
struct actuator_outputs_s actuators_out {};
260+
actuator_outputs_s actuators_out {};
261+
262+
// read the actuator outputs
263+
bool updated = false;
264+
orb_check(_actuator_out_sub, &updated);
303265

304-
// read the actuator outputs
305-
bool updated;
306-
orb_check(_actuator_out_sub, &updated);
266+
if (updated) {
267+
orb_copy(ORB_ID(actuator_outputs), _actuator_out_sub, &actuators_out);
307268

308-
if (updated) {
309-
orb_copy(ORB_ID(actuator_outputs), _actuator_out_sub, &actuators_out);
310-
for (int i=0; i<NB_MOTORS; i++) // saturate the motor signals
311-
_u[i]=constrain((actuators_out.output[i]-PWM_DEFAULT_MIN)/(PWM_DEFAULT_MAX-PWM_DEFAULT_MIN),0.0f, 1.0f);
312-
}
269+
for (int i = 0; i < NB_MOTORS; i++) { // saturate the motor signals
270+
_u[i] = constrain((actuators_out.output[i] - PWM_DEFAULT_MIN) / (PWM_DEFAULT_MAX - PWM_DEFAULT_MIN), 0.0f, 1.0f);
271+
}
272+
}
313273
}
314274

315275
// generate the motors thrust and torque in the body frame
316276
void Sih::generate_force_and_torques()
317277
{
318-
_T_B=Vector3f(0.0f,0.0f,-_T_MAX*(+_u[0]+_u[1]+_u[2]+_u[3]));
319-
_Mt_B=Vector3f( _L_ROLL*_T_MAX* (-_u[0]+_u[1]+_u[2]-_u[3]),
320-
_L_PITCH*_T_MAX*(+_u[0]-_u[1]+_u[2]-_u[3]),
321-
_Q_MAX * (+_u[0]+_u[1]-_u[2]-_u[3]));
278+
_T_B = Vector3f(0.0f, 0.0f, -_T_MAX * (+_u[0] + _u[1] + _u[2] + _u[3]));
279+
_Mt_B = Vector3f(_L_ROLL * _T_MAX * (-_u[0] + _u[1] + _u[2] - _u[3]),
280+
_L_PITCH * _T_MAX * (+_u[0] - _u[1] + _u[2] - _u[3]),
281+
_Q_MAX * (+_u[0] + _u[1] - _u[2] - _u[3]));
322282

323-
_Fa_I=-_KDV*_v_I; // first order drag to slow down the aircraft
324-
_Ma_B=-_KDW*_w_B; // first order angular damper
283+
_Fa_I = -_KDV * _v_I; // first order drag to slow down the aircraft
284+
_Ma_B = -_KDW * _w_B; // first order angular damper
325285
}
326286

327287
// apply the equations of motion of a rigid body and integrate one step
328288
void Sih::equations_of_motion()
329289
{
330-
_C_IB=_q.to_dcm(); // body to inertial transformation
331-
332-
// Equations of motion of a rigid body
333-
_p_I_dot=_v_I; // position differential
334-
_v_I_dot=(_W_I+_Fa_I+_C_IB*_T_B)/_MASS; // conservation of linear momentum
335-
_q_dot=_q.derivative1(_w_B); // attitude differential
336-
_w_B_dot=_Im1*(_Mt_B+_Ma_B-_w_B.cross(_I*_w_B)); // conservation of angular momentum
337-
338-
// fake ground, avoid free fall
339-
if(_p_I(2)>0.0f && (_v_I_dot(2)>0.0f || _v_I(2)>0.0f)) {
340-
if (!_grounded) { // if we just hit the floor
341-
// for the accelerometer, compute the acceleration that will stop the vehicle in one time step
342-
_v_I_dot=-_v_I/_dt;
343-
} else {
344-
_v_I_dot.setZero();
345-
}
346-
_v_I.setZero();
347-
_w_B.setZero();
348-
_grounded = true;
349-
} else {
350-
// integration: Euler forward
351-
_p_I = _p_I + _p_I_dot*_dt;
352-
_v_I = _v_I + _v_I_dot*_dt;
353-
_q = _q+_q_dot*_dt; // as given in attitude_estimator_q_main.cpp
354-
_q.normalize();
355-
_w_B = _w_B + _w_B_dot*_dt;
356-
_grounded = false;
357-
}
290+
_C_IB = _q.to_dcm(); // body to inertial transformation
291+
292+
// Equations of motion of a rigid body
293+
_p_I_dot = _v_I; // position differential
294+
_v_I_dot = (_W_I + _Fa_I + _C_IB * _T_B) / _MASS; // conservation of linear momentum
295+
_q_dot = _q.derivative1(_w_B); // attitude differential
296+
_w_B_dot = _Im1 * (_Mt_B + _Ma_B - _w_B.cross(_I * _w_B)); // conservation of angular momentum
297+
298+
// fake ground, avoid free fall
299+
if (_p_I(2) > 0.0f && (_v_I_dot(2) > 0.0f || _v_I(2) > 0.0f)) {
300+
if (!_grounded) { // if we just hit the floor
301+
// for the accelerometer, compute the acceleration that will stop the vehicle in one time step
302+
_v_I_dot = -_v_I / _dt;
303+
304+
} else {
305+
_v_I_dot.setZero();
306+
}
307+
308+
_v_I.setZero();
309+
_w_B.setZero();
310+
_grounded = true;
311+
312+
} else {
313+
// integration: Euler forward
314+
_p_I = _p_I + _p_I_dot * _dt;
315+
_v_I = _v_I + _v_I_dot * _dt;
316+
_q = _q + _q_dot * _dt; // as given in attitude_estimator_q_main.cpp
317+
_q.normalize();
318+
_w_B = _w_B + _w_B_dot * _dt;
319+
_grounded = false;
320+
}
358321
}
359322

360323
// reconstruct the noisy sensor signals
361324
void Sih::reconstruct_sensors_signals()
362325
{
363-
364-
// The sensor signals reconstruction and noise levels are from
365-
// Bulka, Eitan, and Meyer Nahon. "Autonomous fixed-wing aerobatics: from theory to flight."
366-
// In 2018 IEEE International Conference on Robotics and Automation (ICRA), pp. 6573-6580. IEEE, 2018.
367-
368-
// IMU
369-
_acc=_C_IB.transpose()*(_v_I_dot-Vector3f(0.0f,0.0f,CONSTANTS_ONE_G))+noiseGauss3f(0.5f,1.7f,1.4f);
370-
_gyro=_w_B+noiseGauss3f(0.14f,0.07f,0.03f);
371-
_mag=_C_IB.transpose()*_mu_I+noiseGauss3f(0.02f,0.02f,0.03f);
372-
373-
// barometer
374-
float altitude=(_H0-_p_I(2))+generate_wgn()*0.14f; // altitude with noise
375-
_baro_p_mBar=CONSTANTS_STD_PRESSURE_MBAR* // reconstructed pressure in mBar
376-
powf((1.0f+altitude*TEMP_GRADIENT/T1_K),-CONSTANTS_ONE_G/(TEMP_GRADIENT*CONSTANTS_AIR_GAS_CONST));
377-
_baro_temp_c=T1_K+CONSTANTS_ABSOLUTE_NULL_CELSIUS+TEMP_GRADIENT*altitude; // reconstructed temperture in celcius
378-
379-
// GPS
380-
_gps_lat_noiseless=_LAT0+degrees((double)_p_I(0)/CONSTANTS_RADIUS_OF_EARTH);
381-
_gps_lon_noiseless=_LON0+degrees((double)_p_I(1)/CONSTANTS_RADIUS_OF_EARTH)/_COS_LAT0;
382-
_gps_alt_noiseless=_H0-_p_I(2);
383-
384-
_gps_lat=_gps_lat_noiseless+(double)(generate_wgn()*7.2e-6f); // latitude in degrees
385-
_gps_lon=_gps_lon_noiseless+(double)(generate_wgn()*1.75e-5f); // longitude in degrees
386-
_gps_alt=_gps_alt_noiseless+generate_wgn()*1.78f;
387-
_gps_vel=_v_I+noiseGauss3f(0.06f,0.077f,0.158f);
326+
// The sensor signals reconstruction and noise levels are from
327+
// Bulka, Eitan, and Meyer Nahon. "Autonomous fixed-wing aerobatics: from theory to flight."
328+
// In 2018 IEEE International Conference on Robotics and Automation (ICRA), pp. 6573-6580. IEEE, 2018.
329+
330+
// IMU
331+
_acc = _C_IB.transpose() * (_v_I_dot - Vector3f(0.0f, 0.0f, CONSTANTS_ONE_G)) + noiseGauss3f(0.5f, 1.7f, 1.4f);
332+
_gyro = _w_B + noiseGauss3f(0.14f, 0.07f, 0.03f);
333+
_mag = _C_IB.transpose() * _mu_I + noiseGauss3f(0.02f, 0.02f, 0.03f);
334+
335+
// barometer
336+
float altitude = (_H0 - _p_I(2)) + generate_wgn() * 0.14f; // altitude with noise
337+
_baro_p_mBar = CONSTANTS_STD_PRESSURE_MBAR * // reconstructed pressure in mBar
338+
powf((1.0f + altitude * TEMP_GRADIENT / T1_K), -CONSTANTS_ONE_G / (TEMP_GRADIENT * CONSTANTS_AIR_GAS_CONST));
339+
_baro_temp_c = T1_K + CONSTANTS_ABSOLUTE_NULL_CELSIUS + TEMP_GRADIENT * altitude; // reconstructed temperture in celcius
340+
341+
// GPS
342+
_gps_lat_noiseless = _LAT0 + degrees((double)_p_I(0) / CONSTANTS_RADIUS_OF_EARTH);
343+
_gps_lon_noiseless = _LON0 + degrees((double)_p_I(1) / CONSTANTS_RADIUS_OF_EARTH) / _COS_LAT0;
344+
_gps_alt_noiseless = _H0 - _p_I(2);
345+
346+
_gps_lat = _gps_lat_noiseless + (double)(generate_wgn() * 7.2e-6f); // latitude in degrees
347+
_gps_lon = _gps_lon_noiseless + (double)(generate_wgn() * 1.75e-5f); // longitude in degrees
348+
_gps_alt = _gps_alt_noiseless + generate_wgn() * 1.78f;
349+
_gps_vel = _v_I + noiseGauss3f(0.06f, 0.077f, 0.158f);
388350
}
389351

390352
void Sih::send_IMU()
@@ -422,93 +384,133 @@ void Sih::send_IMU()
422384

423385
void Sih::send_gps()
424386
{
425-
_vehicle_gps_pos.timestamp=_now;
426-
_vehicle_gps_pos.lat=(int32_t)(_gps_lat*1e7); // Latitude in 1E-7 degrees
427-
_vehicle_gps_pos.lon=(int32_t)(_gps_lon*1e7); // Longitude in 1E-7 degrees
428-
_vehicle_gps_pos.alt=(int32_t)(_gps_alt*1000.0f); // Altitude in 1E-3 meters above MSL, (millimetres)
429-
_vehicle_gps_pos.alt_ellipsoid = (int32_t)(_gps_alt*1000); // Altitude in 1E-3 meters bove Ellipsoid, (millimetres)
430-
_vehicle_gps_pos.vel_ned_valid=true; // True if NED velocity is valid
431-
_vehicle_gps_pos.vel_m_s=sqrtf(_gps_vel(0)*_gps_vel(0)+_gps_vel(1)*_gps_vel(1)); // GPS ground speed, (metres/sec)
432-
_vehicle_gps_pos.vel_n_m_s=_gps_vel(0); // GPS North velocity, (metres/sec)
433-
_vehicle_gps_pos.vel_e_m_s=_gps_vel(1); // GPS East velocity, (metres/sec)
434-
_vehicle_gps_pos.vel_d_m_s=_gps_vel(2); // GPS Down velocity, (metres/sec)
435-
_vehicle_gps_pos.cog_rad=atan2(_gps_vel(1),_gps_vel(0)); // Course over ground (NOT heading, but direction of movement), -PI..PI, (radians)
436-
if (_vehicle_gps_pos_pub != nullptr) {
437-
orb_publish(ORB_ID(vehicle_gps_position), _vehicle_gps_pos_pub, &_vehicle_gps_pos);
438-
} else {
439-
_vehicle_gps_pos_pub = orb_advertise(ORB_ID(vehicle_gps_position), &_vehicle_gps_pos);
440-
}
387+
_vehicle_gps_pos.timestamp = _now;
388+
_vehicle_gps_pos.lat = (int32_t)(_gps_lat * 1e7); // Latitude in 1E-7 degrees
389+
_vehicle_gps_pos.lon = (int32_t)(_gps_lon * 1e7); // Longitude in 1E-7 degrees
390+
_vehicle_gps_pos.alt = (int32_t)(_gps_alt * 1000.0f); // Altitude in 1E-3 meters above MSL, (millimetres)
391+
_vehicle_gps_pos.alt_ellipsoid = (int32_t)(_gps_alt * 1000); // Altitude in 1E-3 meters bove Ellipsoid, (millimetres)
392+
_vehicle_gps_pos.vel_ned_valid = true; // True if NED velocity is valid
393+
_vehicle_gps_pos.vel_m_s = sqrtf(_gps_vel(0) * _gps_vel(0) + _gps_vel(1) * _gps_vel(
394+
1)); // GPS ground speed, (metres/sec)
395+
_vehicle_gps_pos.vel_n_m_s = _gps_vel(0); // GPS North velocity, (metres/sec)
396+
_vehicle_gps_pos.vel_e_m_s = _gps_vel(1); // GPS East velocity, (metres/sec)
397+
_vehicle_gps_pos.vel_d_m_s = _gps_vel(2); // GPS Down velocity, (metres/sec)
398+
_vehicle_gps_pos.cog_rad = atan2(_gps_vel(1),
399+
_gps_vel(0)); // Course over ground (NOT heading, but direction of movement), -PI..PI, (radians)
400+
401+
if (_vehicle_gps_pos_pub != nullptr) {
402+
orb_publish(ORB_ID(vehicle_gps_position), _vehicle_gps_pos_pub, &_vehicle_gps_pos);
403+
404+
} else {
405+
_vehicle_gps_pos_pub = orb_advertise(ORB_ID(vehicle_gps_position), &_vehicle_gps_pos);
406+
}
441407
}
442408

443409
void Sih::publish_sih()
444410
{
411+
_gpos_gt.timestamp = hrt_absolute_time();
412+
_gpos_gt.lat = _gps_lat_noiseless;
413+
_gpos_gt.lon = _gps_lon_noiseless;
414+
_gpos_gt.alt = _gps_alt_noiseless;
415+
_gpos_gt.vel_n = _v_I(0);
416+
_gpos_gt.vel_e = _v_I(1);
417+
_gpos_gt.vel_d = _v_I(2);
418+
419+
if (_gpos_gt_sub != nullptr) {
420+
orb_publish(ORB_ID(vehicle_global_position_groundtruth), _gpos_gt_sub, &_gpos_gt);
421+
422+
} else {
423+
_gpos_gt_sub = orb_advertise(ORB_ID(vehicle_global_position_groundtruth), &_gpos_gt);
424+
}
445425

446-
_gpos_gt.timestamp=hrt_absolute_time();
447-
_gpos_gt.lat=_gps_lat_noiseless;
448-
_gpos_gt.lon=_gps_lon_noiseless;
449-
_gpos_gt.alt=_gps_alt_noiseless;
450-
_gpos_gt.vel_n=_v_I(0);
451-
_gpos_gt.vel_e=_v_I(1);
452-
_gpos_gt.vel_d=_v_I(2);
453-
454-
if (_gpos_gt_sub != nullptr) {
455-
orb_publish(ORB_ID(vehicle_global_position_groundtruth), _gpos_gt_sub, &_gpos_gt);
456-
} else {
457-
_gpos_gt_sub = orb_advertise(ORB_ID(vehicle_global_position_groundtruth), &_gpos_gt);
458-
}
459-
460-
// publish attitude groundtruth
461-
_att_gt.timestamp=hrt_absolute_time();
462-
_att_gt.q[0]=_q(0);
463-
_att_gt.q[1]=_q(1);
464-
_att_gt.q[2]=_q(2);
465-
_att_gt.q[3]=_q(3);
466-
_att_gt.rollspeed=_w_B(0);
467-
_att_gt.pitchspeed=_w_B(1);
468-
_att_gt.yawspeed=_w_B(2);
469-
if (_att_gt_sub != nullptr) {
470-
orb_publish(ORB_ID(vehicle_attitude_groundtruth), _att_gt_sub, &_att_gt);
471-
} else {
472-
_att_gt_sub = orb_advertise(ORB_ID(vehicle_attitude_groundtruth), &_att_gt);
473-
}
426+
// publish attitude groundtruth
427+
_att_gt.timestamp = hrt_absolute_time();
428+
_att_gt.q[0] = _q(0);
429+
_att_gt.q[1] = _q(1);
430+
_att_gt.q[2] = _q(2);
431+
_att_gt.q[3] = _q(3);
432+
_att_gt.rollspeed = _w_B(0);
433+
_att_gt.pitchspeed = _w_B(1);
434+
_att_gt.yawspeed = _w_B(2);
435+
436+
if (_att_gt_sub != nullptr) {
437+
orb_publish(ORB_ID(vehicle_attitude_groundtruth), _att_gt_sub, &_att_gt);
438+
439+
} else {
440+
_att_gt_sub = orb_advertise(ORB_ID(vehicle_attitude_groundtruth), &_att_gt);
441+
}
474442
}
475443

476444
float Sih::generate_wgn() // generate white Gaussian noise sample with std=1
477445
{
478-
// algorithm 1:
479-
// float temp=((float)(rand()+1))/(((float)RAND_MAX+1.0f));
480-
// return sqrtf(-2.0f*logf(temp))*cosf(2.0f*M_PI_F*rand()/RAND_MAX);
481-
// algorithm 2: from BlockRandGauss.hpp
482-
static float V1, V2, S;
483-
static bool phase = true;
484-
float X;
485-
486-
if (phase) {
487-
do {
488-
float U1 = (float)rand() / RAND_MAX;
489-
float U2 = (float)rand() / RAND_MAX;
490-
V1 = 2.0f * U1 - 1.0f;
491-
V2 = 2.0f * U2 - 1.0f;
492-
S = V1 * V1 + V2 * V2;
493-
} while (S >= 1.0f || fabsf(S) < 1e-8f);
494-
495-
X = V1 * float(sqrtf(-2.0f * float(logf(S)) / S));
496-
497-
} else {
498-
X = V2 * float(sqrtf(-2.0f * float(logf(S)) / S));
499-
}
500-
501-
phase = !phase;
502-
return X;
446+
// algorithm 1:
447+
// float temp=((float)(rand()+1))/(((float)RAND_MAX+1.0f));
448+
// return sqrtf(-2.0f*logf(temp))*cosf(2.0f*M_PI_F*rand()/RAND_MAX);
449+
// algorithm 2: from BlockRandGauss.hpp
450+
static float V1, V2, S;
451+
static bool phase = true;
452+
float X;
453+
454+
if (phase) {
455+
do {
456+
float U1 = (float)rand() / RAND_MAX;
457+
float U2 = (float)rand() / RAND_MAX;
458+
V1 = 2.0f * U1 - 1.0f;
459+
V2 = 2.0f * U2 - 1.0f;
460+
S = V1 * V1 + V2 * V2;
461+
} while (S >= 1.0f || fabsf(S) < 1e-8f);
462+
463+
X = V1 * float(sqrtf(-2.0f * float(logf(S)) / S));
464+
465+
} else {
466+
X = V2 * float(sqrtf(-2.0f * float(logf(S)) / S));
467+
}
468+
469+
phase = !phase;
470+
return X;
503471
}
504472

505473
// generate white Gaussian noise sample vector with specified std
506-
Vector3f Sih::noiseGauss3f(float stdx,float stdy, float stdz)
474+
Vector3f Sih::noiseGauss3f(float stdx, float stdy, float stdz)
507475
{
508-
return Vector3f(generate_wgn()*stdx,generate_wgn()*stdy,generate_wgn()*stdz);
476+
return Vector3f(generate_wgn() * stdx, generate_wgn() * stdy, generate_wgn() * stdz);
509477
}
510478

511479
int sih_main(int argc, char *argv[])
512480
{
513-
return Sih::main(argc, argv);
481+
return Sih::main(argc, argv);
482+
}
483+
484+
int Sih::print_usage(const char *reason)
485+
{
486+
if (reason) {
487+
PX4_WARN("%s\n", reason);
488+
}
489+
490+
PRINT_MODULE_DESCRIPTION(
491+
R"DESCR_STR(
492+
### Description
493+
This module provide a simulator for quadrotors running fully
494+
inside the hardware autopilot.
495+
496+
This simulator subscribes to "actuator_outputs" which are the actuator pwm
497+
signals given by the mixer.
498+
499+
This simulator publishes the sensors signals corrupted with realistic noise
500+
in order to incorporate the state estimator in the loop.
501+
502+
### Implementation
503+
The simulator implements the equations of motion using matrix algebra.
504+
Quaternion representation is used for the attitude.
505+
Forward Euler is used for integration.
506+
Most of the variables are declared global in the .hpp file to avoid stack overflow.
507+
508+
509+
)DESCR_STR");
510+
511+
PRINT_MODULE_USAGE_NAME("sih", "simulation");
512+
PRINT_MODULE_USAGE_COMMAND("start");
513+
PRINT_MODULE_USAGE_DEFAULT_COMMANDS();
514+
515+
return 0;
514516
}

0 commit comments

Comments
 (0)
Please sign in to comment.