OSDN Git Service

Configurable calibration steps
[android-x86/hardware-intel-libsensors.git] / gyro-calibration.c
1 /*
2  * Copyright (C) 2014 Intel Corporation.
3  */
4
5 #include <stdio.h>
6 #include <math.h>
7 #include <sys/time.h>
8 #include <utils/Log.h>
9 #include <hardware/sensors.h>
10 #include "common.h"
11 #include "calibration.h"
12
13 static void reset (struct gyro_cal* cal_data)
14 {
15         cal_data->count = 0;
16
17         cal_data->bias_x = cal_data->bias_y = cal_data->bias_z = 0;
18
19         cal_data->min_x  = cal_data->min_y  = cal_data->min_z  = 1.0;
20         cal_data->max_x  = cal_data->max_y  = cal_data->max_z  =-1.0;
21 }
22
23
24 void gyro_cal_init (struct sensor_info_t* info)
25 {
26         int ret;
27         struct gyro_cal* cal_data = (struct gyro_cal*) info->cal_data;
28         FILE* data_file;
29
30         info->cal_level = 0;
31
32         if (cal_data == NULL)
33                 return;
34
35         reset(cal_data);
36
37         data_file = fopen (GYRO_CALIBRATION_PATH, "r");
38         if (data_file == NULL)
39                 return;
40
41         ret = fscanf(data_file, "%f %f %f",
42                         &cal_data->bias_x, &cal_data->bias_y, &cal_data->bias_z);
43         fclose(data_file);
44 }
45
46 void gyro_store_data (struct sensor_info_t* info)
47 {
48         int ret;
49         struct gyro_cal* cal_data = (struct gyro_cal*) info->cal_data;
50         FILE* data_file;
51
52         if (cal_data == NULL)
53                 return;
54
55         data_file = fopen (GYRO_CALIBRATION_PATH, "w");
56
57         if (data_file == NULL)
58                 return;
59
60         ret = fprintf(data_file, "%f %f %f",
61                 cal_data->bias_x, cal_data->bias_y, cal_data->bias_z);
62
63         if (ret < 0)
64                 ALOGE ("Gyro calibration - store data failed!");
65
66         fclose(data_file);
67 }
68
69
70 static int gyro_collect (float x, float y, float z, struct gyro_cal* cal_data)
71 {
72         /* Analyze gyroscope data */
73
74         if (fabs(x) >= 1 || fabs(y) >= 1 || fabs(z) >= 1) {
75
76                 /* We're supposed to be standing still ; start over */
77                 reset(cal_data);
78
79                 return 0; /* Uncalibrated */
80         }
81
82         if (cal_data->count < GYRO_DS_SIZE) {
83
84                 if (x < cal_data->min_x)
85                         cal_data->min_x = x;
86
87                 if (y < cal_data->min_y)
88                         cal_data->min_y = y;
89
90                 if (z < cal_data->min_z)
91                         cal_data->min_z = z;
92
93                 if (x > cal_data->max_x)
94                         cal_data->max_x = x;
95
96                 if (y > cal_data->max_y)
97                         cal_data->max_y = y;
98
99                 if (z > cal_data->max_z)
100                         cal_data->max_z = z;
101
102                 if (fabs(cal_data->max_x - cal_data->min_x) <= GYRO_MAX_ERR &&
103                     fabs(cal_data->max_y - cal_data->min_y) <= GYRO_MAX_ERR &&
104                     fabs(cal_data->max_z - cal_data->min_z) <= GYRO_MAX_ERR)
105                         cal_data->count++; /* One more conformant sample */
106                 else
107                         reset(cal_data); /* Out of spec sample ; start over */
108
109                 return 0; /* Still uncalibrated */
110         }
111
112         /* We got enough stable samples to estimate gyroscope bias */
113         cal_data->bias_x = (cal_data->max_x + cal_data->min_x) / 2;
114         cal_data->bias_y = (cal_data->max_y + cal_data->min_y) / 2;
115         cal_data->bias_z = (cal_data->max_z + cal_data->min_z) / 2;
116
117         return 1; /* Calibrated! */
118 }
119
120 void calibrate_gyro(struct sensors_event_t* event, struct sensor_info_t* info)
121 {
122         struct gyro_cal* cal_data = (struct gyro_cal*) info->cal_data;
123
124         if (cal_data == NULL)
125                 return;
126
127         /* Attempt gyroscope calibration if we have not reached this state */
128         if (info->cal_level == 0)
129                 info->cal_level = gyro_collect(event->data[0], event->data[1],
130                                                event->data[2], cal_data);
131
132         switch (event->type) {
133                 case SENSOR_TYPE_GYROSCOPE:
134                         /* For the gyroscope apply the bias */
135                         event->data[0] = event->data[0] - cal_data->bias_x;
136                         event->data[1] = event->data[1] - cal_data->bias_y;
137                         event->data[2] = event->data[2] - cal_data->bias_z;
138
139                         if (info->cal_level)
140                                event->gyro.status = SENSOR_STATUS_ACCURACY_HIGH;
141                         break;
142
143                 case SENSOR_TYPE_GYROSCOPE_UNCALIBRATED:
144                         /*
145                          * For the uncalibrated gyroscope don't apply the bias,
146                          * but tell he Android framework what we think it is.
147                          */
148                         event->uncalibrated_gyro.bias[0] = cal_data->bias_x;
149                         event->uncalibrated_gyro.bias[1] = cal_data->bias_y;
150                         event->uncalibrated_gyro.bias[2] = cal_data->bias_z;
151                         break;
152         }
153 }