Rleg  2
 All Data Structures Files Functions Variables Typedefs Macros Groups Pages
threads_linux.c
Go to the documentation of this file.
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <unistd.h>
4 #include <signal.h>
5 #include <string.h>
6 #include <time.h>
7 #include <sys/time.h>
8 #include "gmatrix.h"
9 #include "imu.h"
10 #include "magnetometer.h"
11 #include "gps.h"
12 #include "sonar.h"
13 #include "sensors.h"
14 #include "calibration.h"
15 #include "protocol.h"
16 #include "estimation.h"
17 #include "control.h"
18 #include "datalogger.h"
19 #include "ui.h"
20 #include "mavlink_module.h"
21 #include "threads_linux.h"
22 
23 /* This runs tasks in three points:
24  * 1) In the while(quittask == 0) loop: background (semi-periodic, usleep governed) tasks (datalogger update)
25  * 2) In the int threads_linux_periodic_task_1(void) function, periodic (low-precision), set by the TASK1_PERIOD_US define:
26  * (main data acquisition/control task)
27  * 3) In the int threads_linux_periodic_task_2(void) function, periodic (low-precision), set by the TASK2_PERIOD_US define:
28  * (UI task)
29  */
30 
31 // Configuration
32 #define TASK1_PERIOD_US 20000 //20ms
33 #define TASK2_PERIOD_US 100000 //100ms
34 
35 // Internal functions
36 void threads_linux_timer_task_1(union sigval sigval);
37 void threads_linux_timer_task_2(union sigval sigval);
38 
39 // Module variables
40 extern unsigned char quittask;
41 int total = 0;
42 int failure = 0;
43 
44 // Task 1: Data acquisition/control task
45 timer_t timer_task_1;
46 volatile double t_task_1_global = 0.0;
47 volatile double T_task_1_exec_global = 0.0;
48 volatile double T_task_1_mean_global = 0.0;
49 volatile double T_task_1_min_global = 0.0;
50 volatile double T_task_1_max_global = 0.0;
52 volatile int flag_task_1_firstexecution = 1;
53 volatile double t0 = 0.0;
54 
55 // Task 2: UI task
56 timer_t timer_task_2;
57 volatile double t_task_2_global = 0.0;
58 volatile double T_task_2_exec_global = 0.0;
59 volatile double T_task_2_mean_global = 0.0;
60 volatile double T_task_2_min_global = 0.0;
61 volatile double T_task_2_max_global = 0.0;
63 volatile int flag_task_2_firstexecution = 1;
65 
66 // Shared data structures
67 // Raw data
68 BATTERY_DATA_STRUCT battery_data;
69 GPS_DATA_STRUCT gps_data;
71 PITOT_DATA_STRUCT pitot_data;
72 PWM_READ_DATA_STRUCT pwm_read_data;
73 PWM_WRITE_DATA_STRUCT pwm_write_data;
74 SCP1000_DATA_STRUCT scp1000_data;
75 SONAR_DATA_STRUCT sonar_data;
76 
77 // Calibrated data
78 GPSMEASURE gps_measure;
79 IMUMEASURE imu_measure;
80 MAGNETOMETERMEASURE magnetometer_measure;
81 SONARMEASURE sonar_measure;
82 
83 // Coordinate systems, local fields and pressure
84 CALIBRATION_ALTIMETER_STRUCT calibration_altimeter_data;
85 CALIBRATION_LOCAL_COORDINATE_SYSTEM_STRUCT calibration_local_coordinate_system_data;
86 CALIBRATION_LOCAL_FIELDS_STRUCT calibration_local_fields_data;
87 
88 // State estimate
89 ESTIMATION_DATA_STRUCT estimation_data;
90 
91 // Controllers
92 CONTROL_DATA_STRUCT control_data;
93 
95 {
96  int status = 0;
97  int n = 0;
98  int return_value = THREADS_LINUX_SUCCESS;
99 
100  // Init data
101  status = sensors_init(&battery_data, &gps_data, &imu_data, &pitot_data, &pwm_read_data, &pwm_write_data, &scp1000_data, &sonar_data);
102  if(status != SENSORS_SUCCESS)
103  {
104  return_value = THREADS_LINUX_FAILURE;
105  }
106 
107  if(return_value != THREADS_LINUX_FAILURE)
108  {
110  if(status != CALIBRATION_SUCCESS)
111  {
112  return_value = THREADS_LINUX_FAILURE;
113  }
114  }
115 
116  if(return_value != THREADS_LINUX_FAILURE)
117  {
118  status = gps_init(&gps_measure);
119  if(status != 1)
120  {
121  return_value = THREADS_LINUX_FAILURE;
122  }
123  }
124 
125  if(return_value != THREADS_LINUX_FAILURE)
126  {
127  status = imu_init(&imu_measure);
128  if(status != 1)
129  {
130  return_value = THREADS_LINUX_FAILURE;
131  }
132  }
133 
134  if(return_value != THREADS_LINUX_FAILURE)
135  {
136  status = magnetometer_init(&magnetometer_measure);
137  if(status != 1)
138  {
139  return_value = THREADS_LINUX_FAILURE;
140  }
141  }
142 
143  if(return_value != THREADS_LINUX_FAILURE)
144  {
145  status = sonar_init(&sonar_measure);
146  if(status != 1)
147  {
148  return_value = THREADS_LINUX_FAILURE;
149  }
150  }
151 
152  if(return_value != THREADS_LINUX_FAILURE)
153  {
154  status = estimation_init(ESTIMATION_DO_NOT_ESTIMATE_ACCEL_BIAS, &estimation_data);
155  if(status != ESTIMATION_SUCCESS)
156  {
157  return_value = THREADS_LINUX_FAILURE;
158  }
159  }
160 
161  if(return_value != THREADS_LINUX_FAILURE)
162  {
163  status = control_init(&control_data);
164  if(status != CONTROL_SUCCESS)
165  {
166  return_value = THREADS_LINUX_FAILURE;
167  }
168  }
169 
170  if(return_value != THREADS_LINUX_FAILURE)
171  {
172  status = protocol_init();
173  if(status != PROTOCOL_SUCCESS)
174  {
175  return_value = THREADS_LINUX_FAILURE;
176  }
177  }
178 
179  if(return_value != THREADS_LINUX_FAILURE)
180  {
181  status = ui_init();
182  if(status != UI_SUCCESS)
183  {
184  return_value = THREADS_LINUX_FAILURE;
185  }
186  }
187 
188  if(return_value != THREADS_LINUX_FAILURE)
189  {
190  status = datalogger_init();
191  if(status != DATALOGGER_SUCCESS)
192  {
193  return_value = THREADS_LINUX_FAILURE;
194  }
195  }
196 
197  // Main Loop
198  if(return_value != THREADS_LINUX_FAILURE)
199  {
201  usleep(0.5*task_1_period_us);
203  usleep(5*task_1_period_us);
204 
205  while(quittask == 0)
206  {
207  #if ANU_COMPILE_FOR_OVERO
208  #else
210  #endif
211  if(++n>100)
212  {
214  n = 0;
215  }
216  usleep(5*task_1_period_us);
217  }
218 
220  usleep(TASK1_PERIOD_US);
222  usleep(TASK2_PERIOD_US);
223  }
224 
225  status = datalogger_close();
226  if(status != DATALOGGER_SUCCESS)
227  {
228  return_value = THREADS_LINUX_FAILURE;
229  }
230 
231  status = ui_close();
232  if(status != UI_SUCCESS)
233  {
234  return_value = THREADS_LINUX_FAILURE;
235  }
236 
237  status = protocol_close();
238  if(status != PROTOCOL_SUCCESS)
239  {
240  return_value = THREADS_LINUX_FAILURE;
241  }
242 
243  status = control_close();
244  if(status != CONTROL_SUCCESS)
245  {
246  return_value = THREADS_LINUX_FAILURE;
247  }
248 
249  status = estimation_close(&estimation_data);
250  if(status != ESTIMATION_SUCCESS)
251  {
252  return_value = THREADS_LINUX_FAILURE;
253  }
254 
255  status = magnetometer_close(&magnetometer_measure);
256  if(status != 1)
257  {
258  return_value = THREADS_LINUX_FAILURE;
259  }
260 
261  status = imu_close(&imu_measure);
262  if(status != 1)
263  {
264  return_value = THREADS_LINUX_FAILURE;
265  }
266  status = gps_close(&gps_measure);
267  if(status != 1)
268  {
269  return_value = THREADS_LINUX_FAILURE;
270  }
271 
273  if(status != CALIBRATION_SUCCESS)
274  {
275  return_value = THREADS_LINUX_FAILURE;
276  }
277 
278  status = sensors_close();
279  if(status != SENSORS_SUCCESS)
280  {
281  return_value = THREADS_LINUX_FAILURE;
282  }
283 
284  return return_value;
285 }
286 
288 {
289  static int previous_calibration_status = CALIBRATION_NOT_RUNNING;
290  int current_calibration_status; // Used to detect lowering edge
291  static int previous_datalogger_status = DATALOGGER_NOT_RUNNING;
292  int current_datalogger_status; // Used to detect rising edge
293 
294  // Main communication/control thread
295 
296  //Acquire
297  total++;
298  if(protocol_request_all_data(&battery_data, &gps_data, &imu_data, &pitot_data, &pwm_read_data, &pwm_write_data, &scp1000_data, &sonar_data) != PROTOCOL_SUCCESS)
299  {
300  failure++;
301  }
302 
303  // Calibrate and Estimate
306 
307  // Control
309 
310  // Actuate
311  protocol_send_actuation_data(&pwm_write_data);
312 
313  // Log
314  current_datalogger_status = datalogger_status();
315  if(current_datalogger_status == DATALOGGER_RUNNING)
316  {
317  if(previous_datalogger_status == DATALOGGER_NOT_RUNNING) // Rising edge
318  {
320  datalogger_set_initial_altimeter_parameters(&calibration_altimeter_data);
321  datalogger_set_local_coordinate_system(&calibration_local_coordinate_system_data);
322  datalogger_set_local_fields(&calibration_local_fields_data);
324  }
326  }
327  previous_datalogger_status = current_datalogger_status;
328 
329  current_calibration_status = calibration_get_status();
330  if(current_calibration_status == CALIBRATION_RUNNING)
331  {
332  calibration_imu_add_sample_bias_estimate(&imu_data);
333  calibration_altimeter_add_sample_initial_pressure(&scp1000_data, &calibration_altimeter_data);
334  }
335  else // Calibration not running
336  {
337  if(previous_calibration_status == CALIBRATION_RUNNING) // Lowering edge
338  {
339  calibration_imu_finish_bias_estimate(&imu_data);
340  calibration_altimeter_finish_initial_pressure_estimate(&calibration_altimeter_data);
341  }
342  }
343  previous_calibration_status = current_calibration_status;
344 
345  return THREADS_LINUX_SUCCESS;
346 }
347 
349 {
350  // UI thread
352  {
354  }
355  if(telemetry_mode == UI_MAVLINK_MODE)
356  {
358  }
359 
360  return THREADS_LINUX_SUCCESS;
361 }
362 
363 void threads_linux_timer_task_1(union sigval sigval)
364 {
365  sigval.sival_int = 0; // Remove warning
367 }
368 
369 void threads_linux_timer_task_2(union sigval sigval)
370 {
371  sigval.sival_int = 0; // Remove warning
373 }
374 
376 {
377  struct itimerspec itimer;
378  struct sigevent sigev;
379  int errno = 0;
380 
382 
383  itimer.it_interval.tv_sec=0;
384  itimer.it_interval.tv_nsec=task_1_period_us * 1000;
385  itimer.it_value=itimer.it_interval;
386 
387  memset(&sigev, 0, sizeof (struct sigevent));
388  sigev.sigev_value.sival_int = 0;
389  sigev.sigev_notify = SIGEV_THREAD;
390  sigev.sigev_notify_attributes = NULL;
391  sigev.sigev_notify_function = threads_linux_timer_task_1;
392 
393  if (timer_create(CLOCK_REALTIME, &sigev, &timer_task_1) < 0)
394  {
395  fprintf(stderr, "[%d]: %s\n", __LINE__, strerror(errno));
396  exit(errno);
397  }
398 
399  if(timer_settime(timer_task_1, 0, &itimer, NULL) < 0)
400  {
401  fprintf(stderr, "[%d]: %s\n", __LINE__, strerror(errno));
402  exit(errno);
403  }
404 }
405 
407 {
408  struct itimerspec itimer;
409  struct sigevent sigev;
410  int errno = 0;
411 
413 
414  itimer.it_interval.tv_sec=0;
415  itimer.it_interval.tv_nsec=task_2_period_us * 1000;
416  itimer.it_value=itimer.it_interval;
417 
418  memset (&sigev, 0, sizeof (struct sigevent));
419  sigev.sigev_value.sival_int = 0;
420  sigev.sigev_notify = SIGEV_THREAD;
421  sigev.sigev_notify_attributes = NULL;
422  sigev.sigev_notify_function = threads_linux_timer_task_2;
423 
424  if(timer_create(CLOCK_REALTIME, &sigev, &timer_task_2) < 0)
425  {
426  fprintf(stderr, "[%d]: %s\n", __LINE__, strerror(errno));
427  exit(errno);
428  }
429 
430  if(timer_settime(timer_task_2, 0, &itimer, NULL) < 0)
431  {
432  fprintf(stderr, "[%d]: %s\n", __LINE__, strerror(errno));
433  exit(errno);
434  }
435 }
436 
438 {
439  int errno = 0;
440  if(timer_delete(timer_task_1) < 0)
441  {
442  fprintf(stderr, "[%d]: %s\n", __LINE__, strerror(errno));
443  exit(errno);
444  }
445 }
446 
448 {
449  int errno = 0;
450  if(timer_delete(timer_task_2) < 0)
451  {
452  fprintf(stderr, "[%d]: %s\n", __LINE__, strerror(errno));
453  exit(errno);
454  }
455 }
456 
458 {
459  int status = 0;
460  static struct timeval timereset;
461  static struct timeval time;
462  static struct timeval time_exec_start;
463  static struct timeval time_exec_end;
464  static double T_task,t_task,t_task_previous;
465  static double T_task_mean,T_task_min,T_task_max,T_task_exec;
466 
467  gettimeofday(&time_exec_start, NULL);
468 
469  // Time calculation
471  {
472  gettimeofday(&timereset, NULL);
473  t_task = 0.0;
474  T_task_mean = 0.0;
475  T_task_min = 0.0;
476  T_task_max = 0.0;
477  T_task_exec = 0.0;
478  }
479 
480  gettimeofday(&time, NULL);
481  t_task = ((time.tv_sec - timereset.tv_sec) + (time.tv_usec - timereset.tv_usec)*1e-6);
482  T_task = t_task - t_task_previous;
483  t_task_previous = t_task;
484 
486  {
487  T_task_mean = T_task;
488  T_task_min = 1e200;
489  T_task_max = 0.0;
490  t0 = t_task;
491  }
492  else
493  {
494  T_task_mean = 0.05*T_task + 0.95*T_task_mean;
495  if(T_task < T_task_min) T_task_min = T_task;
496  if(T_task > T_task_max) T_task_max = T_task;
497  }
498 
499  // Run the thread
501 
502  gettimeofday(&time_exec_end, NULL);
503  T_task_exec = ((time_exec_end.tv_sec - time_exec_start.tv_sec) + (time_exec_end.tv_usec - time_exec_start.tv_usec)*1e-6);
504 
505  t_task_1_global = t_task;
506  T_task_1_mean_global = T_task_mean;
507  T_task_1_min_global = T_task_min;
508  T_task_1_max_global = T_task_max;
509  T_task_1_exec_global = T_task_exec;
510 
512 }
513 
515 {
516  int status = 0;
517  static struct timeval timereset;
518  static struct timeval time;
519  static struct timeval time_exec_start;
520  static struct timeval time_exec_end;
521  static double T_task,t_task,t_task_previous;
522  static double T_task_mean,T_task_min,T_task_max,T_task_exec;
523 
524  gettimeofday(&time_exec_start, NULL);
525 
526  // Time calculation
528  {
529  gettimeofday(&timereset, NULL);
530  t_task = 0.0;
531  T_task_mean = 0.0;
532  T_task_min = 0.0;
533  T_task_max = 0.0;
534  T_task_exec = 0.0;
535  }
536 
537  gettimeofday(&time, NULL);
538  t_task = ((time.tv_sec - timereset.tv_sec) + (time.tv_usec - timereset.tv_usec)*1e-6);
539  T_task = t_task - t_task_previous;
540  t_task_previous = t_task;
541 
543  {
544  T_task_mean = T_task;
545  T_task_min = 1e200;
546  T_task_max = 0.0;
547  }
548  else
549  {
550  T_task_mean = 0.05*T_task + 0.95*T_task_mean;
551  if(T_task < T_task_min) T_task_min = T_task;
552  if(T_task > T_task_max) T_task_max = T_task;
553  }
554 
555  // Run the thread
557 
558  gettimeofday(&time_exec_end, NULL);
559  T_task_exec = ((time_exec_end.tv_sec - time_exec_start.tv_sec) + (time_exec_end.tv_usec - time_exec_start.tv_usec)*1e-6);
560 
561  t_task_2_global = t_task;
562  T_task_2_mean_global = T_task_mean;
563  T_task_2_min_global = T_task_min;
564  T_task_2_max_global = T_task_max;
565  T_task_2_exec_global = T_task_exec;
566 
568 }
569 
571 {
573  return THREADS_LINUX_SUCCESS;
574 }
575 
576 int threads_get_time(double *time_control_task_s, double *Ts_control_task_s, double *mean_time_control_task_s, double *t0_control_task_s)
577 {
578  *time_control_task_s = t_task_1_global;
579  *Ts_control_task_s = task_1_period_us/1e6;
580  *mean_time_control_task_s = T_task_1_mean_global;
581  *t0_control_task_s = t0;
582  return THREADS_LINUX_SUCCESS;
583 }
timer_t timer_task_2
Definition: threads_linux.c:56
volatile double T_task_2_max_global
Definition: threads_linux.c:61
ESTIMATION_DATA_STRUCT estimation_data
Definition: threads_linux.c:89
volatile double T_task_1_min_global
Definition: threads_linux.c:49
volatile double T_task_1_max_global
Definition: threads_linux.c:50
void threads_linux_timer_function_task_1(void)
volatile double t_task_1_global
Definition: threads_linux.c:46
volatile int task_1_period_us
Definition: threads_linux.c:51
volatile int flag_task_1_firstexecution
Definition: threads_linux.c:52
int ui_close(void)
Close UI.
Definition: ui.c:41
int datalogger_set_Ts(double Ts)
Definition: datalogger.c:540
volatile double T_task_1_mean_global
Definition: threads_linux.c:48
BATTERY_DATA_STRUCT battery_data
Definition: threads_linux.c:68
void threads_linux_timer_task_2(union sigval sigval)
#define DATALOGGER_RUNNING
Definition: datalogger.h:30
unsigned int telemetry_mode
Definition: threads_linux.c:64
Data of IMU structure.
Definition: communication.h:93
volatile double T_task_2_exec_global
Definition: threads_linux.c:58
int threads_linux_periodic_task_2(void)
int datalogger_update_IPC(void)
Definition: datalogger.c:256
CALIBRATION_LOCAL_COORDINATE_SYSTEM_STRUCT calibration_local_coordinate_system_data
Definition: threads_linux.c:85
CALIBRATION_LOCAL_FIELDS_STRUCT calibration_local_fields_data
Definition: threads_linux.c:86
int threads_reset_timer(void)
int failure
Definition: threads_linux.c:42
int datalogger_close(void)
Definition: datalogger.c:215
MAGNETOMETERMEASURE magnetometer_measure
Definition: threads_linux.c:80
IMU_DATA_STRUCT imu_data
Definition: threads_linux.c:70
#define TASK2_PERIOD_US
Definition: threads_linux.c:33
int datalogger_write_file(void)
Definition: datalogger.c:240
volatile double T_task_1_exec_global
Definition: threads_linux.c:47
timer_t timer_task_1
Definition: threads_linux.c:45
int datalogger_init(void)
Definition: datalogger.c:41
int total
Definition: threads_linux.c:41
SONARMEASURE sonar_measure
Definition: threads_linux.c:81
int datalogger_update(double t_s, double t_control_exec_s, double t_ui_exec_s, double t0_s, IMU_DATA_STRUCT *pimu_data, EFF_DATA_STRUCT *peff_data, MRA_DATA_STRUCT *pmra_data)
Definition: datalogger.c:272
volatile int flag_task_2_firstexecution
Definition: threads_linux.c:63
void threads_linux_timer_start_task_1(void)
void threads_linux_timer_stop_task_2(void)
#define TASK1_PERIOD_US
Definition: threads_linux.c:32
int status
Definition: communication.c:10
GPS_DATA_STRUCT gps_data
Definition: threads_linux.c:69
int threads_linux_init(void)
Definition: threads_linux.c:94
volatile double T_task_2_min_global
Definition: threads_linux.c:60
volatile double T_task_2_mean_global
Definition: threads_linux.c:59
#define DATALOGGER_NOT_RUNNING
Definition: datalogger.h:29
#define DATALOGGER_SUCCESS
Definition: datalogger.h:35
int threads_get_time(double *time_control_task_s, double *Ts_control_task_s, double *mean_time_control_task_s, double *t0_control_task_s)
CALIBRATION_ALTIMETER_STRUCT calibration_altimeter_data
Definition: threads_linux.c:84
GPSMEASURE gps_measure
Definition: threads_linux.c:78
int threads_linux_periodic_task_1(void)
#define UI_NCURSES_MODE
Definition: ui.h:5
PITOT_DATA_STRUCT pitot_data
Definition: threads_linux.c:71
volatile double t0
Definition: threads_linux.c:53
unsigned char quittask
Definition: main.c:39
volatile int task_2_period_us
Definition: threads_linux.c:62
int ui_init(void)
Initialize UI.
Definition: ui.c:26
IMUMEASURE imu_measure
Definition: threads_linux.c:79
int ui_update(IMU_DATA_STRUCT *pimu_data, EFF_DATA_STRUCT *peff_data, MRA_DATA_STRUCT *pmra_data, ENC_DATA_STRUCT *enc_data, int total, int failure)
Update Screen with new data of sensors.
Definition: ui.c:53
void threads_linux_timer_task_1(union sigval sigval)
volatile double t_task_2_global
Definition: threads_linux.c:57
void threads_linux_timer_start_task_2(void)
void threads_linux_timer_stop_task_1(void)
SONAR_DATA_STRUCT sonar_data
Definition: threads_linux.c:75
PWM_READ_DATA_STRUCT pwm_read_data
Definition: threads_linux.c:72
SCP1000_DATA_STRUCT scp1000_data
Definition: threads_linux.c:74
int datalogger_status(void)
Definition: datalogger.c:571
PWM_WRITE_DATA_STRUCT pwm_write_data
Definition: threads_linux.c:73
CONTROL_DATA_STRUCT control_data
Definition: threads_linux.c:92
void threads_linux_timer_function_task_2(void)