$(src_path)/transform.c \
$(src_path)/compass-calibration.c \
$(src_path)/matrix-ops.c \
+ $(src_path)/gyro-calibration.c \
LOCAL_C_INCLUDES += $(LOCAL_PATH) vendor/intel/hardware/iio-sensors
LOCAL_MODULE := sensors.$(TARGET_BOARD_PLATFORM)
#ifndef __CALIBRATION_H__
#define __CALIBRATION_H__
+#include "common.h"
+
+/* compass defines */
#define COMPASS_CALIBRATION_PATH "/data/compass.conf"
#define DS_SIZE 48
#define EPSILON 0.000000001
#define RAW_DATA_SELECTED_PATH "/data/raw_compass_data_selected_%d.txt"
#endif
+/* gyro defines */
+#define GYRO_MAX_ERR 0.05f
+#define GYRO_DS_SIZE 8
+
typedef struct {
/* hard iron offsets */
double offset[3][1];
} calibration_data;
+struct gyro_cal {
+ float bias[3];
+ int start;
+ int count;
+ float sample[GYRO_DS_SIZE][3];
+};
+
typedef double mat_input_t[DS_SIZE][3];
void calibrate_compass (struct sensors_event_t* event, int64_t time);
void compass_read_data (const char* config_path);
void compass_store_data (const char* config_path);
+void calibrate_gyro(struct sensors_event_t* event, struct sensor_info_t* info);
+void gyro_cal_init(struct sensor_info_t* info);
#endif
struct sample_ops_t ops;
+ int calibrated;
+ void* cal_data;
/* Note: we may have to explicitely serialize access to some fields */
};
} else {
if (sensor_type == SENSOR_TYPE_MAGNETIC_FIELD)
compass_read_data(COMPASS_CALIBRATION_PATH);
+
+ if (sensor_type == SENSOR_TYPE_GYROSCOPE)
+ gyro_cal_init(&sensor_info[s]);
}
} else {
if (sensor_info[s].enable_count == 0)
*/
#include <dirent.h>
+#include <stdlib.h>
#include <utils/Log.h>
#include <hardware/sensors.h>
#include "enumeration.h"
#include "transform.h"
#include "description.h"
#include "control.h"
+#include "calibration.h"
/*
* This table maps syfs entries in scan_elements directories to sensor types,
strcpy(sensor_info[s].internal_name, "(null)");
}
+ if (sensor_catalog[catalog_index].type == SENSOR_TYPE_GYROSCOPE) {
+ struct gyro_cal* calibration_data = calloc(1, sizeof(struct gyro_cal));
+ sensor_info[s].cal_data = calibration_data;
+ }
/* Select one of the available sensor sample processing styles */
select_transform(s);
void delete_enumeration_data (void)
{
+
+ int i;
+ for (i = 0; i < sensor_count; i++)
+ switch (sensor_catalog[sensor_info[i].catalog_index].type) {
+ case SENSOR_TYPE_GYROSCOPE:
+ if (sensor_info[i].cal_data != NULL) {
+ free(sensor_info[i].cal_data);
+ sensor_info[i].cal_data = NULL;
+ sensor_info[i].calibrated = 0;
+ }
+ break;
+ default:
+ break;
+ }
/* Reset sensor count */
sensor_count = 0;
}
--- /dev/null
+/*
+ * Copyright (C) 2014 Intel Corporation.
+ */
+
+#include <stdio.h>
+#include <math.h>
+#include <sys/time.h>
+#include <utils/Log.h>
+#include <hardware/sensors.h>
+#include "common.h"
+#include "calibration.h"
+
+
+void gyro_cal_init(struct sensor_info_t* info)
+{
+ info->calibrated = 0;
+
+ struct gyro_cal* gyro_data = (struct gyro_cal*) info->cal_data;
+
+ if (gyro_data == NULL)
+ return;
+
+ gyro_data->start = 0;
+ gyro_data->count = 0;
+ gyro_data->bias[0] = gyro_data->bias[1] = gyro_data->bias[2] = 0;
+}
+
+/* Collect points - circular queue for the last GYRO_DS_SIZE
+ elements. If the points are sufficiently close compute bias */
+static void gyro_collect(float x, float y, float z, struct sensor_info_t* info)
+{
+ int offset, k;
+ float min[3], max[3];
+
+ struct gyro_cal* gyro_data = (struct gyro_cal*) info->cal_data;
+
+ if (gyro_data == NULL)
+ return;
+
+ int pos = (gyro_data->start + gyro_data->count) % GYRO_DS_SIZE;
+ gyro_data->sample[pos][0] = x;
+ gyro_data->sample[pos][1] = y;
+ gyro_data->sample[pos][2] = z;
+
+ if (gyro_data->count < GYRO_DS_SIZE)
+ gyro_data->count++;
+ else
+ gyro_data->start = (gyro_data->start + 1) % GYRO_DS_SIZE;
+
+ for (k = 0; k < 3; k++)
+ min[k] = max[k] = gyro_data->sample[gyro_data->start][k];
+
+ /* Search for min-max values */
+ for (offset = 1; offset < gyro_data->count; offset++) {
+ int pos2 = (gyro_data->start + offset) % GYRO_DS_SIZE;
+ for (k = 0; k < 3; k++) {
+ if (min[k] > gyro_data->sample[pos2][k])
+ min[k] = gyro_data->sample[pos2][k];
+ else if (max[k] < gyro_data->sample[pos2][k])
+ max[k] = gyro_data->sample[pos2][k];
+ }
+ }
+
+ if (gyro_data->count == GYRO_DS_SIZE &&
+ fabs(max[0] - min[0]) < GYRO_MAX_ERR &&
+ fabs(max[1] - min[1]) < GYRO_MAX_ERR &&
+ fabs(max[2] - min[2]) < GYRO_MAX_ERR) {
+ info->calibrated = 1;
+ gyro_data->bias[0] = (max[0] + min[0]) / 2;
+ gyro_data->bias[1] = (max[1] + min[1]) / 2;
+ gyro_data->bias[2] = (max[2] + min[2]) / 2;
+ }
+}
+
+void calibrate_gyro(struct sensors_event_t* event, struct sensor_info_t* info)
+{
+ if (!info->calibrated) {
+ gyro_collect(event->data[0], event->data[1], event->data[2], info);
+ }
+ else {
+ struct gyro_cal* gyro_data = (struct gyro_cal*) info->cal_data;
+
+ if (gyro_data == NULL)
+ return;
+
+ event->data[0] = event->gyro.x = event->data[0] - gyro_data->bias[0];
+ event->data[1] = event->gyro.y = event->data[1] - gyro_data->bias[1];
+ event->data[2] = event->gyro.z = event->data[2] - gyro_data->bias[2];
+ }
+}
\ No newline at end of file
y = data->data[1];
z = -data->data[2];
- /* Limit drift */
- if (fabs(x) < 0.1 && fabs(y) < 0.1 && fabs(z) < 0.1)
- x = y = z = 0;
-
data->data[0] = x;
data->data[1] = y;
data->data[2] = z;
+
+ calibrate_gyro(data, &sensor_info[s]);
break;
case SENSOR_TYPE_AMBIENT_TEMPERATURE: