41 #include "physical_constants.h"
44 #ifdef PIOS_INCLUDE_SIMSENSORS
47 #include "actuatordesired.h"
48 #include "airspeedactual.h"
49 #include "attitudeactual.h"
50 #include "attitudesimulated.h"
51 #include "attitudesettings.h"
52 #include "baroairspeed.h"
53 #include "baroaltitude.h"
55 #include "gyrosbias.h"
56 #include "flightstatus.h"
57 #include "gpsposition.h"
58 #include "gpsvelocity.h"
59 #include "homelocation.h"
60 #include "magnetometer.h"
62 #include "ratedesired.h"
63 #include "systemsettings.h"
68 #define STACK_SIZE_BYTES 1540
69 #define TASK_PRIORITY PIOS_THREAD_PRIO_HIGH
70 #define SENSOR_PERIOD 2
77 static float rand_gauss();
79 static int sens_rate = 500;
81 enum sensor_sim_type {MODEL_YASIM, MODEL_QUADCOPTER, MODEL_AIRPLANE, MODEL_CAR} sensor_sim_type;
83 static bool have_gyro_data, have_accel_data, have_mag_data, have_baro_data;
90 #ifdef PIOS_INCLUDE_SIMSENSORS_YASIM
91 extern bool use_yasim;
92 static void simulateYasim();
96 static void simsensors_step();
97 static void simulateModelQuadcopter();
98 static void simulateModelAirplane();
99 static void simulateModelCar();
101 static bool simsensors_callback_gyro(
void *ctx,
void *output,
102 int ms_to_wait,
int *next_call)
104 *next_call = 1000 / sens_rate;
108 if (have_gyro_data) {
109 have_gyro_data =
false;
111 memcpy(output, &gyro_data,
sizeof(gyro_data));
119 static bool simsensors_callback_accel(
void *ctx,
void *output,
120 int ms_to_wait,
int *next_call)
124 if (have_accel_data) {
125 have_accel_data =
false;
127 memcpy(output, &accel_data,
sizeof(accel_data));
135 static bool simsensors_callback_mag(
void *ctx,
void *output,
136 int ms_to_wait,
int *next_call)
141 have_mag_data =
false;
143 memcpy(output, &mag_data,
sizeof(mag_data));
151 static bool simsensors_callback_baro(
void *ctx,
void *output,
152 int ms_to_wait,
int *next_call)
156 if (have_baro_data) {
157 have_baro_data =
false;
159 memcpy(output, &baro_data,
sizeof(baro_data));
171 int32_t simsensors_init(
void)
174 printf(
"SimSensorsInitialize: Declining to do anything, real sensors!\n");
178 printf(
"SimSensorsInitialize: Using simulated sensors.\n");
181 simsensors_callback_gyro, NULL);
183 simsensors_callback_accel, NULL);
185 simsensors_callback_mag, NULL);
187 simsensors_callback_baro, NULL);
189 #ifdef PIOS_INCLUDE_SIMSENSORS_YASIM
204 AttitudeSimulatedInitialize();
205 BaroAltitudeInitialize();
208 BaroAirspeedInitialize();
209 GPSPositionInitialize();
210 GPSVelocityInitialize();
216 printf(
"SimSensorsInitialize: starting SIMULATED sensors\n");
225 static void simsensors_step()
227 SystemSettingsData systemSettings;
228 SystemSettingsGet(&systemSettings);
230 switch(systemSettings.AirframeType) {
231 case SYSTEMSETTINGS_AIRFRAMETYPE_FIXEDWING:
232 case SYSTEMSETTINGS_AIRFRAMETYPE_FIXEDWINGELEVON:
233 case SYSTEMSETTINGS_AIRFRAMETYPE_FIXEDWINGVTAIL:
234 sensor_sim_type = MODEL_AIRPLANE;
236 case SYSTEMSETTINGS_AIRFRAMETYPE_QUADX:
237 case SYSTEMSETTINGS_AIRFRAMETYPE_QUADP:
238 case SYSTEMSETTINGS_AIRFRAMETYPE_VTOL:
239 case SYSTEMSETTINGS_AIRFRAMETYPE_HEXA:
240 case SYSTEMSETTINGS_AIRFRAMETYPE_OCTO:
242 sensor_sim_type = MODEL_QUADCOPTER;
244 case SYSTEMSETTINGS_AIRFRAMETYPE_GROUNDVEHICLECAR:
245 sensor_sim_type = MODEL_CAR;
249 #ifdef PIOS_INCLUDE_SIMSENSORS_YASIM
251 sensor_sim_type = MODEL_YASIM;
257 switch(sensor_sim_type) {
258 case MODEL_QUADCOPTER:
260 simulateModelQuadcopter();
263 simulateModelAirplane();
268 #ifdef PIOS_INCLUDE_SIMSENSORS_YASIM
276 static void simsensors_scale_controls(
float *rpy,
float *thrust_out,
279 const float ACTUATOR_ALPHA = 0.81f;
281 FlightStatusData flightStatus;
282 FlightStatusGet(&flightStatus);
283 ActuatorDesiredData actuatorDesired;
284 ActuatorDesiredGet(&actuatorDesired);
286 float thrust = (flightStatus.Armed == FLIGHTSTATUS_ARMED_ARMED) ? actuatorDesired.Thrust * max_thrust : 0;
288 if (thrust != thrust)
291 *thrust_out = thrust;
293 float control_scaling = 3000.0f;
295 if (flightStatus.Armed != FLIGHTSTATUS_ARMED_ARMED) {
301 rpy[0] = control_scaling * actuatorDesired.Roll * (1 - ACTUATOR_ALPHA) + rpy[0] * ACTUATOR_ALPHA;
302 rpy[1] = control_scaling * actuatorDesired.Pitch * (1 - ACTUATOR_ALPHA) + rpy[1] * ACTUATOR_ALPHA;
303 rpy[2] = control_scaling * actuatorDesired.Yaw * (1 - ACTUATOR_ALPHA) + rpy[2] * ACTUATOR_ALPHA;
306 static void simsensors_gyro_set(
float *rpy,
float noise_scale,
309 assert(isfinite(rpy[0]));
310 assert(isfinite(rpy[1]));
311 assert(isfinite(rpy[2]));
314 .x = rpy[0] + rand_gauss() * noise_scale +
315 (temperature - 20) * 1 + powf(temperature - 20,2) * 0.11,
316 .y = rpy[1] + rand_gauss() * noise_scale +
317 (temperature - 20) * 1 + powf(temperature - 20,2) * 0.11,
318 .z = rpy[2] + rand_gauss() * noise_scale +
319 (temperature - 20) * 1 + powf(temperature - 20,2) * 0.11,
323 have_gyro_data =
true;
326 static void simsensors_accels_set(
float *xyz,
float *
accel_bias,
330 .x = xyz[0] + accel_bias[0],
331 .y = xyz[1] + accel_bias[1],
332 .z = xyz[2] + accel_bias[2],
336 assert(isfinite(accel_data.x));
337 assert(isfinite(accel_data.y));
338 assert(isfinite(accel_data.z));
340 have_accel_data =
true;
343 static void simsensors_accels_setfromned(
double *ned_accel,
344 float (*Rbe)[3][3],
float *accel_bias,
float temperature)
348 xyz[0] = ned_accel[0] * (*Rbe)[0][0] + ned_accel[1] * (*Rbe)[0][1] + ned_accel[2] * (*Rbe)[0][2];
349 xyz[1] = ned_accel[0] * (*Rbe)[1][0] + ned_accel[1] * (*Rbe)[1][1] + ned_accel[2] * (*Rbe)[1][2];
350 xyz[2] = ned_accel[0] * (*Rbe)[2][0] + ned_accel[1] * (*Rbe)[2][1] + ned_accel[2] * (*Rbe)[2][2];
352 simsensors_accels_set(xyz, accel_bias, temperature);
355 static void simsensors_quat_timestep(
float *q,
float *qdot) {
356 assert(isfinite(qdot[0]));
357 assert(isfinite(qdot[1]));
358 assert(isfinite(qdot[2]));
359 assert(isfinite(qdot[3]));
362 q[0] = q[0] + qdot[0];
363 q[1] = q[1] + qdot[1];
364 q[2] = q[2] + qdot[2];
365 q[3] = q[3] + qdot[3];
367 float qmag = sqrtf(q[0]*q[0] + q[1]*q[1] + q[2]*q[2] + q[3]*q[3]);
381 assert(isfinite(q[0]));
382 assert(isfinite(q[1]));
383 assert(isfinite(q[2]));
384 assert(isfinite(q[3]));
387 static void simsensors_baro_set(
float down,
float baro_offset) {
391 .altitude = -down + baro_offset,
394 have_baro_data =
true;
397 static void simsensors_baro_drift(
float *baro_offset)
399 if (*baro_offset == 0) {
404 *baro_offset += rand_gauss() / 100;
408 static void simsensors_mag_set(
float *be,
float (*Rbe)[3][3])
412 be[0] * (*Rbe)[0][0] +
413 be[1] * (*Rbe)[0][1] +
414 be[2] * (*Rbe)[0][2],
416 be[0] * (*Rbe)[1][0] +
417 be[1] * (*Rbe)[1][1] +
418 be[2] * (*Rbe)[1][2],
420 be[0] * (*Rbe)[2][0] +
421 be[1] * (*Rbe)[2][1] +
422 be[2] * (*Rbe)[2][2],
425 have_mag_data =
true;
428 #ifdef PIOS_INCLUDE_SIMSENSORS_YASIM
429 static void simulateYasim()
431 const float GYRO_NOISE_SCALE = 1.0f;
432 const float MAG_PERIOD = 1.0 / 75.0;
433 const float BARO_PERIOD = 1.0 / 20.0;
434 const float GPS_PERIOD = 1.0 / 10.0;
464 static bool inited =
false;
468 static float baro_offset;
471 fprintf(stderr,
"Initing external yasim instance\n");
475 int child_in, child_out;
479 int ret = pipe(pipe_tmp);
486 child_in = pipe_tmp[0];
489 ret = pipe(pipe_tmp);
497 child_out = pipe_tmp[1];
508 if (dup2(child_in, STDIN_FILENO) < 0) {
513 if (dup2(child_out, STDOUT_FILENO) < 0) {
518 for (
int i = 3;
i < 1024;
i++) {
523 execlp(
"yasim-svr",
"yasim-svr",
"pa22-160-yasim.xml",
537 if (ret !=
sizeof(
status)) {
538 fprintf(stderr,
"failed: read-from-yasim %d\n", ret);
542 if (
status.magic != 0x00700799) {
543 fprintf(stderr,
"Bad magic on read from yasim\n");
547 memset(&
cmd, 0,
sizeof(
cmd));
549 cmd.magic = 0xb33fbeef;
551 FlightStatusData flightStatus;
552 FlightStatusGet(&flightStatus);
553 ActuatorDesiredData actuatorDesired;
554 ActuatorDesiredGet(&actuatorDesired);
556 if (isfinite(actuatorDesired.Roll) && isfinite(actuatorDesired.Pitch)
557 && isfinite(actuatorDesired.Yaw)
558 && isfinite(actuatorDesired.Thrust)) {
559 cmd.roll = actuatorDesired.Roll;
560 cmd.pitch = actuatorDesired.Pitch;
561 cmd.yaw = actuatorDesired.Yaw;
563 if (actuatorDesired.Thrust >= 0) {
564 cmd.throttle = actuatorDesired.Thrust;
578 cmd.armed = flightStatus.Armed == FLIGHTSTATUS_ARMED_ARMED;
580 ret = write(wfd, &
cmd,
sizeof(
cmd));
582 if (ret !=
sizeof(
cmd)) {
583 fprintf(stderr,
"failed: write-to-yasim %d\n", ret);
587 simsensors_gyro_set(&
status.p, GYRO_NOISE_SCALE, 30);
588 simsensors_accels_set(
status.acc, accel_bias, 31);
590 float rpy[3] = {
status.roll * RAD2DEG,
status.pitch * RAD2DEG,
602 HomeLocationGet(&homeLocation);
603 if (homeLocation.Set == HOMELOCATION_SET_FALSE) {
604 homeLocation.Be[0] = 100;
605 homeLocation.Be[1] = 0;
606 homeLocation.Be[2] = 400;
607 homeLocation.Set = HOMELOCATION_SET_TRUE;
609 HomeLocationSet(&homeLocation);
612 uint32_t last_mag_time = 0;
614 simsensors_mag_set(homeLocation.Be, &Rbe);
619 simsensors_baro_drift(&baro_offset);
622 static uint32_t last_baro_time = 0;
624 simsensors_baro_set(
status.alt, baro_offset);
629 static uint32_t last_gps_time = 0;
630 static float gps_vel_drift[3] = {0,0,0};
634 T[0] = homeLocation.Altitude+6.378137E6f * DEG2RAD;
635 T[1] = cosf(homeLocation.Latitude / 10e6 * DEG2RAD)*(homeLocation.Altitude+6.378137E6) * DEG2RAD;
638 static float gps_drift[3] = {0,0,0};
639 gps_drift[0] = gps_drift[0] * 0.95 + rand_gauss() / 10.0;
640 gps_drift[1] = gps_drift[1] * 0.95 + rand_gauss() / 10.0;
641 gps_drift[2] = gps_drift[2] * 0.95 + rand_gauss() / 10.0;
643 GPSPositionData gpsPosition;
644 GPSPositionGet(&gpsPosition);
645 gpsPosition.Latitude = (
status.lat + gps_drift[0] / T[0]) * 10.0e6;
646 gpsPosition.Longitude = (
status.lon + gps_drift[1] / T[1]) * 10.0e6;
647 gpsPosition.Altitude = (
status.alt + gps_drift[2]) / T[2];
648 gpsPosition.Groundspeed = sqrtf(pow(
status.vel[0] + gps_vel_drift[0],2) + pow(
status.vel[1] + gps_vel_drift[1],2));
649 gpsPosition.Heading = 180 / M_PI * atan2f(
status.vel[1] + gps_vel_drift[1],
status.vel[0] + gps_vel_drift[0]);
650 gpsPosition.Satellites = 7;
651 gpsPosition.PDOP = 1;
652 gpsPosition.Accuracy = 3.0;
653 gpsPosition.Status = GPSPOSITION_STATUS_FIX3D;
654 GPSPositionSet(&gpsPosition);
659 static uint32_t last_gps_vel_time = 1000;
661 gps_vel_drift[0] = gps_vel_drift[0] * 0.65 + rand_gauss() / 5.0;
662 gps_vel_drift[1] = gps_vel_drift[1] * 0.65 + rand_gauss() / 5.0;
663 gps_vel_drift[2] = gps_vel_drift[2] * 0.65 + rand_gauss() / 5.0;
665 GPSVelocityData gpsVelocity;
666 GPSVelocityGet(&gpsVelocity);
667 gpsVelocity.North =
status.vel[0] + gps_vel_drift[0];
668 gpsVelocity.East =
status.vel[1] + gps_vel_drift[1];
669 gpsVelocity.Down =
status.vel[2] + gps_vel_drift[2];
670 gpsVelocity.Accuracy = 0.75;
671 GPSVelocitySet(&gpsVelocity);
675 AttitudeSimulatedData attitudeSimulated;
676 AttitudeSimulatedGet(&attitudeSimulated);
677 attitudeSimulated.q1 = q[0];
678 attitudeSimulated.q2 = q[1];
679 attitudeSimulated.q3 = q[2];
680 attitudeSimulated.q4 = q[3];
683 attitudeSimulated.Position[0] =
status.lat;
684 attitudeSimulated.Position[1] =
status.lon;
685 attitudeSimulated.Position[2] =
status.alt;
687 attitudeSimulated.Velocity[0] =
status.vel[0];
688 attitudeSimulated.Velocity[1] =
status.vel[1];
689 attitudeSimulated.Velocity[2] =
status.vel[2];
691 AttitudeSimulatedSet(&attitudeSimulated);
695 static void simulateModelQuadcopter()
697 static double pos[3] = {0,0,0};
698 static double vel[3] = {0,0,0};
699 static double ned_accel[3] = {0,0,0};
700 static float q[4] = {1,0,0,0};
701 static float rpy[3] = {0,0,0};
702 static float baro_offset = 0.0f;
705 const float MAX_THRUST = GRAVITY * 2;
706 const float K_FRICTION = 1;
707 const float GPS_PERIOD = 0.1f;
708 const float MAG_PERIOD = 1.0 / 75.0;
709 const float BARO_PERIOD = 1.0 / 20.0;
710 const float GYRO_NOISE_SCALE = 1.0f;
715 simsensors_scale_controls(rpy, &thrust, MAX_THRUST);
716 simsensors_gyro_set(rpy, GYRO_NOISE_SCALE, 20);
720 qdot[0] = (-q[1] * rpy[0] - q[2] * rpy[1] - q[3] * rpy[2]) * dT * DEG2RAD / 2;
721 qdot[1] = (q[0] * rpy[0] - q[3] * rpy[1] + q[2] * rpy[2]) * dT * DEG2RAD / 2;
722 qdot[2] = (q[3] * rpy[0] + q[0] * rpy[1] - q[1] * rpy[2]) * dT * DEG2RAD / 2;
723 qdot[3] = (-q[2] * rpy[0] + q[1] * rpy[1] + q[0] * rpy[2]) * dT * DEG2RAD / 2;
725 simsensors_quat_timestep(q, qdot);
727 static float wind[3] = {0,0,0};
728 wind[0] = wind[0] * 0.95 + rand_gauss() / 10.0;
729 wind[1] = wind[1] * 0.95 + rand_gauss() / 10.0;
730 wind[2] = wind[2] * 0.95 + rand_gauss() / 10.0;
734 ned_accel[0] = -thrust * Rbe[2][0];
735 ned_accel[1] = -thrust * Rbe[2][1];
737 ned_accel[2] = -thrust * Rbe[2][2] + GRAVITY;
740 ned_accel[0] -= K_FRICTION * (vel[0] - wind[0]);
741 ned_accel[1] -= K_FRICTION * (vel[1] - wind[1]);
742 ned_accel[2] -= K_FRICTION * (vel[2] - wind[2]);
745 vel[0] = vel[0] + ned_accel[0] * dT;
746 vel[1] = vel[1] + ned_accel[1] * dT;
747 vel[2] = vel[2] + ned_accel[2] * dT;
750 pos[0] = pos[0] + vel[0] * dT;
751 pos[1] = pos[1] + vel[1] * dT;
752 pos[2] = pos[2] + vel[2] * dT;
762 ned_accel[2] -= GRAVITY;
764 simsensors_accels_setfromned(ned_accel, &Rbe, accel_bias, 30);
766 simsensors_baro_drift(&baro_offset);
769 static uint32_t last_baro_time = 0;
771 simsensors_baro_set(pos[2], baro_offset);
776 HomeLocationGet(&homeLocation);
777 if (homeLocation.Set == HOMELOCATION_SET_FALSE) {
778 homeLocation.Be[0] = 100;
779 homeLocation.Be[1] = 0;
780 homeLocation.Be[2] = 400;
781 homeLocation.Set = HOMELOCATION_SET_TRUE;
783 HomeLocationSet(&homeLocation);
786 static float gps_vel_drift[3] = {0,0,0};
787 gps_vel_drift[0] = gps_vel_drift[0] * 0.65 + rand_gauss() / 5.0;
788 gps_vel_drift[1] = gps_vel_drift[1] * 0.65 + rand_gauss() / 5.0;
789 gps_vel_drift[2] = gps_vel_drift[2] * 0.65 + rand_gauss() / 5.0;
792 static uint32_t last_gps_time = 0;
796 T[0] = homeLocation.Altitude+6.378137E6f * DEG2RAD;
797 T[1] = cosf(homeLocation.Latitude / 10e6 * DEG2RAD)*(homeLocation.Altitude+6.378137E6) * DEG2RAD;
800 static float gps_drift[3] = {0,0,0};
801 gps_drift[0] = gps_drift[0] * 0.95 + rand_gauss() / 10.0;
802 gps_drift[1] = gps_drift[1] * 0.95 + rand_gauss() / 10.0;
803 gps_drift[2] = gps_drift[2] * 0.95 + rand_gauss() / 10.0;
805 GPSPositionData gpsPosition;
806 GPSPositionGet(&gpsPosition);
807 gpsPosition.Latitude = homeLocation.Latitude + ((pos[0] + gps_drift[0]) / T[0] * 10.0e6);
808 gpsPosition.Longitude = homeLocation.Longitude + ((pos[1] + gps_drift[1])/ T[1] * 10.0e6);
809 gpsPosition.Altitude = homeLocation.Altitude + ((pos[2] + gps_drift[2]) / T[2]);
810 gpsPosition.Groundspeed = sqrtf(pow(vel[0] + gps_vel_drift[0],2) + pow(vel[1] + gps_vel_drift[1],2));
811 gpsPosition.Heading = 180 / M_PI * atan2f(vel[1] + gps_vel_drift[1],vel[0] + gps_vel_drift[0]);
812 gpsPosition.Satellites = 7;
813 gpsPosition.PDOP = 1;
814 gpsPosition.Accuracy = 3.0;
815 gpsPosition.Status = GPSPOSITION_STATUS_FIX3D;
816 GPSPositionSet(&gpsPosition);
821 static uint32_t last_gps_vel_time = 1000;
823 GPSVelocityData gpsVelocity;
824 GPSVelocityGet(&gpsVelocity);
825 gpsVelocity.North = vel[0] + gps_vel_drift[0];
826 gpsVelocity.East = vel[1] + gps_vel_drift[1];
827 gpsVelocity.Down = vel[2] + gps_vel_drift[2];
828 gpsVelocity.Accuracy = 0.75;
829 GPSVelocitySet(&gpsVelocity);
834 static uint32_t last_mag_time = 0;
836 simsensors_mag_set(homeLocation.Be, &Rbe);
840 AttitudeSimulatedData attitudeSimulated;
841 AttitudeSimulatedGet(&attitudeSimulated);
842 attitudeSimulated.q1 = q[0];
843 attitudeSimulated.q2 = q[1];
844 attitudeSimulated.q3 = q[2];
845 attitudeSimulated.q4 = q[3];
847 attitudeSimulated.Position[0] = pos[0];
848 attitudeSimulated.Position[1] = pos[1];
849 attitudeSimulated.Position[2] = pos[2];
850 attitudeSimulated.Velocity[0] = vel[0];
851 attitudeSimulated.Velocity[1] = vel[1];
852 attitudeSimulated.Velocity[2] = vel[2];
853 AttitudeSimulatedSet(&attitudeSimulated);
866 static void simulateModelAirplane()
868 static double pos[3] = {0,0,0};
869 static double vel[3] = {0,0,0};
870 static double ned_accel[3] = {0,0,0};
871 static float q[4] = {1,0,0,0};
872 static float rpy[3] = {0,0,0};
873 static float baro_offset = 0.0f;
876 const float LIFT_SPEED = 8;
877 const float MAX_THRUST = 9.81 * 2;
878 const float K_FRICTION = 0.2;
879 const float GPS_PERIOD = 0.1;
880 const float MAG_PERIOD = 1.0 / 75.0;
881 const float BARO_PERIOD = 1.0 / 20.0;
882 const float ROLL_HEADING_COUPLING = 0.1;
883 const float PITCH_THRUST_COUPLING = 0.2;
884 const float GYRO_NOISE_SCALE = 1.0f;
892 AttitudeActualData attitudeActual;
893 AttitudeActualGet(&attitudeActual);
894 double roll = attitudeActual.Roll;
895 double pitch = attitudeActual.Pitch;
897 simsensors_scale_controls(rpy, &thrust, MAX_THRUST);
898 rpy[2] += roll * ROLL_HEADING_COUPLING;
900 simsensors_gyro_set(rpy, GYRO_NOISE_SCALE, 20);
904 qdot[0] = (-q[1] * rpy[0] - q[2] * rpy[1] - q[3] * rpy[2]) * dT * DEG2RAD / 2;
905 qdot[1] = (q[0] * rpy[0] - q[3] * rpy[1] + q[2] * rpy[2]) * dT * DEG2RAD / 2;
906 qdot[2] = (q[3] * rpy[0] + q[0] * rpy[1] - q[1] * rpy[2]) * dT * DEG2RAD / 2;
907 qdot[3] = (-q[2] * rpy[0] + q[1] * rpy[1] + q[0] * rpy[2]) * dT * DEG2RAD / 2;
909 simsensors_quat_timestep(q, qdot);
912 static float wind[3] = {0,0,0};
913 wind[0] = wind[0] * 0.95 + rand_gauss() / 10.0;
914 wind[1] = wind[1] * 0.95 + rand_gauss() / 10.0;
915 wind[2] = wind[2] * 0.95 + rand_gauss() / 10.0;
924 double airspeed[3] = {vel[0] - wind[0], vel[1] - wind[1], vel[2] - wind[2]};
925 double forwardAirspeed = Rbe[0][0] * airspeed[0] + Rbe[0][1] * airspeed[1] + Rbe[0][2] * airspeed[2];
926 double sidewaysAirspeed = Rbe[1][0] * airspeed[0] + Rbe[1][1] * airspeed[1] + Rbe[1][2] * airspeed[2];
927 double downwardAirspeed = Rbe[2][0] * airspeed[0] + Rbe[2][1] * airspeed[1] + Rbe[2][2] * airspeed[2];
929 assert(isfinite(forwardAirspeed));
930 assert(isfinite(sidewaysAirspeed));
931 assert(isfinite(downwardAirspeed));
933 AirspeedActualData airspeedObj;
934 airspeedObj.CalibratedAirspeed = forwardAirspeed;
938 airspeedObj.TrueAirspeed = forwardAirspeed;
939 AirspeedActualSet(&airspeedObj);
945 forces[0] = thrust - pitch * PITCH_THRUST_COUPLING - forwardAirspeed * K_FRICTION;
946 forces[1] = 0 - sidewaysAirspeed * K_FRICTION * 100;
947 forces[2] = GRAVITY * (forwardAirspeed - LIFT_SPEED) + downwardAirspeed * K_FRICTION * 100;
950 ned_accel[0] = forces[0] * Rbe[0][0] + forces[1] * Rbe[1][0] - forces[2] * Rbe[2][0];
951 ned_accel[1] = forces[0] * Rbe[0][1] + forces[1] * Rbe[1][1] - forces[2] * Rbe[2][1];
952 ned_accel[2] = forces[0] * Rbe[0][2] + forces[1] * Rbe[1][2] - forces[2] * Rbe[2][2];
954 ned_accel[2] += 9.81;
957 ned_accel[0] -= K_FRICTION * (vel[0] - wind[0]);
958 ned_accel[1] -= K_FRICTION * (vel[1] - wind[1]);
959 ned_accel[2] -= K_FRICTION * (vel[2] - wind[2]);
962 vel[0] = vel[0] + ned_accel[0] * dT;
963 vel[1] = vel[1] + ned_accel[1] * dT;
964 vel[2] = vel[2] + ned_accel[2] * dT;
966 assert(isfinite(vel[0]));
967 assert(isfinite(vel[1]));
968 assert(isfinite(vel[2]));
971 pos[0] = pos[0] + vel[0] * dT;
972 pos[1] = pos[1] + vel[1] * dT;
973 pos[2] = pos[2] + vel[2] * dT;
975 assert(isfinite(pos[0]));
976 assert(isfinite(pos[1]));
977 assert(isfinite(pos[2]));
987 ned_accel[2] -= GRAVITY;
989 simsensors_accels_setfromned(ned_accel, &Rbe, accel_bias, 30);
991 simsensors_baro_drift(&baro_offset);
994 static uint32_t last_baro_time = 0;
996 simsensors_baro_set(pos[2], baro_offset);
1001 static uint32_t last_airspeed_time = 0;
1003 BaroAirspeedData baroAirspeed;
1004 baroAirspeed.BaroConnected = BAROAIRSPEED_BAROCONNECTED_TRUE;
1005 baroAirspeed.CalibratedAirspeed = forwardAirspeed;
1006 baroAirspeed.GPSAirspeed = forwardAirspeed;
1007 baroAirspeed.TrueAirspeed = forwardAirspeed;
1008 BaroAirspeedSet(&baroAirspeed);
1013 HomeLocationGet(&homeLocation);
1014 if (homeLocation.Set == HOMELOCATION_SET_FALSE) {
1015 homeLocation.Be[0] = 100;
1016 homeLocation.Be[1] = 0;
1017 homeLocation.Be[2] = 400;
1018 homeLocation.Set = HOMELOCATION_SET_TRUE;
1020 HomeLocationSet(&homeLocation);
1023 static float gps_vel_drift[3] = {0,0,0};
1024 gps_vel_drift[0] = gps_vel_drift[0] * 0.65 + rand_gauss() / 5.0;
1025 gps_vel_drift[1] = gps_vel_drift[1] * 0.65 + rand_gauss() / 5.0;
1026 gps_vel_drift[2] = gps_vel_drift[2] * 0.65 + rand_gauss() / 5.0;
1029 static uint32_t last_gps_time = 0;
1033 T[0] = homeLocation.Altitude+6.378137E6f * DEG2RAD;
1034 T[1] = cosf(homeLocation.Latitude / 10e6 * DEG2RAD)*(homeLocation.Altitude+6.378137E6) * DEG2RAD;
1037 static float gps_drift[3] = {0,0,0};
1038 gps_drift[0] = gps_drift[0] * 0.95 + rand_gauss() / 10.0;
1039 gps_drift[1] = gps_drift[1] * 0.95 + rand_gauss() / 10.0;
1040 gps_drift[2] = gps_drift[2] * 0.95 + rand_gauss() / 10.0;
1042 GPSPositionData gpsPosition;
1043 GPSPositionGet(&gpsPosition);
1044 gpsPosition.Latitude = homeLocation.Latitude + ((pos[0] + gps_drift[0]) / T[0] * 10.0e6);
1045 gpsPosition.Longitude = homeLocation.Longitude + ((pos[1] + gps_drift[1])/ T[1] * 10.0e6);
1046 gpsPosition.Altitude = homeLocation.Altitude + ((pos[2] + gps_drift[2]) / T[2]);
1047 gpsPosition.Groundspeed = sqrtf(pow(vel[0] + gps_vel_drift[0],2) + pow(vel[1] + gps_vel_drift[1],2));
1048 gpsPosition.Heading = 180 / M_PI * atan2f(vel[1] + gps_vel_drift[1],vel[0] + gps_vel_drift[0]);
1049 gpsPosition.Satellites = 7;
1050 gpsPosition.PDOP = 1;
1051 GPSPositionSet(&gpsPosition);
1056 static uint32_t last_gps_vel_time = 1000;
1058 GPSVelocityData gpsVelocity;
1059 GPSVelocityGet(&gpsVelocity);
1060 gpsVelocity.North = vel[0] + gps_vel_drift[0];
1061 gpsVelocity.East = vel[1] + gps_vel_drift[1];
1062 gpsVelocity.Down = vel[2] + gps_vel_drift[2];
1063 GPSVelocitySet(&gpsVelocity);
1068 static uint32_t last_mag_time = 0;
1070 simsensors_mag_set(homeLocation.Be, &Rbe);
1074 AttitudeSimulatedData attitudeSimulated;
1075 AttitudeSimulatedGet(&attitudeSimulated);
1076 attitudeSimulated.q1 = q[0];
1077 attitudeSimulated.q2 = q[1];
1078 attitudeSimulated.q3 = q[2];
1079 attitudeSimulated.q4 = q[3];
1081 attitudeSimulated.Position[0] = pos[0];
1082 attitudeSimulated.Position[1] = pos[1];
1083 attitudeSimulated.Position[2] = pos[2];
1084 attitudeSimulated.Velocity[0] = vel[0];
1085 attitudeSimulated.Velocity[1] = vel[1];
1086 attitudeSimulated.Velocity[2] = vel[2];
1087 AttitudeSimulatedSet(&attitudeSimulated);
1100 static void simulateModelCar()
1102 static double pos[3] = {0,0,0};
1103 static double vel[3] = {0,0,0};
1104 static double ned_accel[3] = {0,0,0};
1105 static float q[4] = {1,0,0,0};
1106 static float rpy[3] = {0,0,0};
1107 static float baro_offset = 0.0f;
1110 const float MAX_THRUST = 9.81 * 0.5;
1111 const float K_FRICTION = 0.2;
1112 const float GPS_PERIOD = 0.1;
1113 const float MAG_PERIOD = 1.0 / 75.0;
1114 const float BARO_PERIOD = 1.0 / 20.0;
1115 const float GYRO_NOISE_SCALE = 1.0;
1120 FlightStatusData flightStatus;
1121 FlightStatusGet(&flightStatus);
1122 ActuatorDesiredData actuatorDesired;
1123 ActuatorDesiredGet(&actuatorDesired);
1126 simsensors_scale_controls(rpy, &thrust, MAX_THRUST);
1132 simsensors_gyro_set(rpy, GYRO_NOISE_SCALE, 20);
1136 qdot[0] = (-q[1] * rpy[0] - q[2] * rpy[1] - q[3] * rpy[2]) * dT * DEG2RAD / 2;
1137 qdot[1] = (q[0] * rpy[0] - q[3] * rpy[1] + q[2] * rpy[2]) * dT * DEG2RAD / 2;
1138 qdot[2] = (q[3] * rpy[0] + q[0] * rpy[1] - q[1] * rpy[2]) * dT * DEG2RAD / 2;
1139 qdot[3] = (-q[2] * rpy[0] + q[1] * rpy[1] + q[0] * rpy[2]) * dT * DEG2RAD / 2;
1141 simsensors_quat_timestep(q, qdot);
1148 double groundspeed[3] = {vel[0], vel[1], vel[2] };
1149 double forwardSpeed = Rbe[0][0] * groundspeed[0] + Rbe[0][1] * groundspeed[1] + Rbe[0][2] * groundspeed[2];
1150 double sidewaysSpeed = Rbe[1][0] * groundspeed[0] + Rbe[1][1] * groundspeed[1] + Rbe[1][2] * groundspeed[2];
1153 forces[0] = thrust - forwardSpeed * K_FRICTION;
1154 forces[1] = 0 - sidewaysSpeed * K_FRICTION * 100;
1158 ned_accel[0] = forces[0] * Rbe[0][0] + forces[1] * Rbe[1][0] - forces[2] * Rbe[2][0];
1159 ned_accel[1] = forces[0] * Rbe[0][1] + forces[1] * Rbe[1][1] - forces[2] * Rbe[2][1];
1163 ned_accel[0] -= K_FRICTION * (vel[0]);
1164 ned_accel[1] -= K_FRICTION * (vel[1]);
1167 vel[0] = vel[0] + ned_accel[0] * dT;
1168 vel[1] = vel[1] + ned_accel[1] * dT;
1169 vel[2] = vel[2] + ned_accel[2] * dT;
1172 pos[0] = pos[0] + vel[0] * dT;
1173 pos[1] = pos[1] + vel[1] * dT;
1174 pos[2] = pos[2] + vel[2] * dT;
1184 ned_accel[2] -= GRAVITY;
1187 simsensors_accels_setfromned(ned_accel, &Rbe, accel_bias, 30);
1189 simsensors_baro_drift(&baro_offset);
1192 static uint32_t last_baro_time = 0;
1194 simsensors_baro_set(pos[2], baro_offset);
1199 HomeLocationGet(&homeLocation);
1200 if (homeLocation.Set == HOMELOCATION_SET_FALSE) {
1201 homeLocation.Be[0] = 100;
1202 homeLocation.Be[1] = 0;
1203 homeLocation.Be[2] = 400;
1204 homeLocation.Set = HOMELOCATION_SET_TRUE;
1206 HomeLocationSet(&homeLocation);
1209 static float gps_vel_drift[3] = {0,0,0};
1210 gps_vel_drift[0] = gps_vel_drift[0] * 0.65 + rand_gauss() / 5.0;
1211 gps_vel_drift[1] = gps_vel_drift[1] * 0.65 + rand_gauss() / 5.0;
1212 gps_vel_drift[2] = gps_vel_drift[2] * 0.65 + rand_gauss() / 5.0;
1215 static uint32_t last_gps_time = 0;
1219 T[0] = homeLocation.Altitude+6.378137E6f * DEG2RAD;
1220 T[1] = cosf(homeLocation.Latitude / 10e6 * DEG2RAD)*(homeLocation.Altitude+6.378137E6) * DEG2RAD;
1223 static float gps_drift[3] = {0,0,0};
1224 gps_drift[0] = gps_drift[0] * 0.95 + rand_gauss() / 10.0;
1225 gps_drift[1] = gps_drift[1] * 0.95 + rand_gauss() / 10.0;
1226 gps_drift[2] = gps_drift[2] * 0.95 + rand_gauss() / 10.0;
1228 GPSPositionData gpsPosition;
1229 GPSPositionGet(&gpsPosition);
1230 gpsPosition.Latitude = homeLocation.Latitude + ((pos[0] + gps_drift[0]) / T[0] * 10.0e6);
1231 gpsPosition.Longitude = homeLocation.Longitude + ((pos[1] + gps_drift[1])/ T[1] * 10.0e6);
1232 gpsPosition.Altitude = homeLocation.Altitude + ((pos[2] + gps_drift[2]) / T[2]);
1233 gpsPosition.Groundspeed = sqrtf(pow(vel[0] + gps_vel_drift[0],2) + pow(vel[1] + gps_vel_drift[1],2));
1234 gpsPosition.Heading = 180 / M_PI * atan2f(vel[1] + gps_vel_drift[1],vel[0] + gps_vel_drift[0]);
1235 gpsPosition.Satellites = 7;
1236 gpsPosition.PDOP = 1;
1237 GPSPositionSet(&gpsPosition);
1242 static uint32_t last_gps_vel_time = 1000;
1244 GPSVelocityData gpsVelocity;
1245 GPSVelocityGet(&gpsVelocity);
1246 gpsVelocity.North = vel[0] + gps_vel_drift[0];
1247 gpsVelocity.East = vel[1] + gps_vel_drift[1];
1248 gpsVelocity.Down = vel[2] + gps_vel_drift[2];
1249 GPSVelocitySet(&gpsVelocity);
1254 static uint32_t last_mag_time = 0;
1256 simsensors_mag_set(homeLocation.Be, &Rbe);
1260 AttitudeSimulatedData attitudeSimulated;
1261 AttitudeSimulatedGet(&attitudeSimulated);
1262 attitudeSimulated.q1 = q[0];
1263 attitudeSimulated.q2 = q[1];
1264 attitudeSimulated.q3 = q[2];
1265 attitudeSimulated.q4 = q[3];
1267 attitudeSimulated.Position[0] = pos[0];
1268 attitudeSimulated.Position[1] = pos[1];
1269 attitudeSimulated.Position[2] = pos[2];
1270 attitudeSimulated.Velocity[0] = vel[0];
1271 attitudeSimulated.Velocity[1] = vel[1];
1272 attitudeSimulated.Velocity[2] = vel[2];
1273 AttitudeSimulatedSet(&attitudeSimulated);
1277 static float rand_gauss (
void) {
1281 v1 = 2.0 * ((float) rand()/RAND_MAX) - 1;
1282 v2 = 2.0 * ((float) rand()/RAND_MAX) - 1;
1285 }
while ( s >= 1.0 );
1290 return (v1*sqrtf(-2.0 * log(s) / s));
uint32_t PIOS_Thread_Systime(void)
void PIOS_SENSORS_SetMaxGyro(int32_t rate)
Set the maximum gyro rate in deg/s.
Main PiOS header to include all the compiled in PiOS options.
void Quaternion2R(float q[4], float Rbe[3][3])
void RPY2Quaternion(const float rpy[3], float q[4])
struct _msp_pid_item pitch
struct _msp_pid_item roll
static float T[3]
Scales used in NED transform (local tangent plane approx).
static float accel_bias[3]
bool PIOS_SENSORS_IsRegistered(enum pios_sensor_type type)
Checks if a sensor type is registered with the PIOS_SENSORS interface.
Pios sensor structure for generic accel data.
Pios sensor structure for generic baro data.
static HomeLocationData homeLocation
int32_t PIOS_SENSORS_RegisterCallback(enum pios_sensor_type type, PIOS_SENSOR_Callback_t callback, void *ctx)
Register a callback-based sensor with the PIOS_SENSORS interface.
Pios sensor structure for generic gyro data.
bool PIOS_Thread_Period_Elapsed(const uint32_t prev_systime, const uint32_t increment_ms)
Determine if a period has elapsed since a datum.
Header for Coordinate conversions library in coordinate_conversions.c.
Pios sensor structure for generic mag data.
void PIOS_SENSORS_SetSampleRate(enum pios_sensor_type type, uint32_t sample_rate)
Set the sample rate of a sensor (Hz)
Includes PiOS and core architecture components.
int32_t AlarmsClear(SystemAlarmsAlarmElem alarm)
int printf(const char *format,...)
if(BaroAltitudeHandle()!=NULL)
static ManualControlCommandData cmd
void Quaternion2RPY(const float q[4], float rpy[3])