1 /*
2  * Copyright (C) 2017 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 /*
18  * This module provides a containing class (NanoSensorCal) for dynamic runtime
19  * calibration algorithms that affect the following sensors:
20  *       - Accelerometer (offset)
21  *       - Gyroscope (offset, with over-temperature compensation)
22  *       - Magnetometer (offset)
23  *
24  * Sensor Units:
25  *       - Accelerometer [meters/sec^2]
26  *       - Gyroscope     [radian/sec]
27  *       - Magnetometer  [micro Tesla, uT]
28  *       - Temperature   [Celsius].
29  *
30  * NOTE1: Define NANO_SENSOR_CAL_DBG_ENABLED to enable debug messaging.
31  *
32  * NOTE2: This module uses pointers to runtime calibration algorithm objects.
33  * These must be constructed and initialized outside of this class. The owner
34  * bares the burden of managing the lifetime of these objects with respect to
35  * the NanoSensorCal class which depends on these objects and handles their
36  * interaction with the Android ASH/CHRE system. This arrangement makes it
37  * convenient to modify the specific algorithm implementations (i.e., choice of
38  * calibration algorithm, parameter tuning, etc.) at the nanoapp level without
39  * the need to specialize the standard functionality implemented here.
40  */
41 
42 #ifndef LOCATION_LBS_CONTEXTHUB_NANOAPPS_CALIBRATION_NANO_CALIBRATION_NANO_CALIBRATION_H_
43 #define LOCATION_LBS_CONTEXTHUB_NANOAPPS_CALIBRATION_NANO_CALIBRATION_NANO_CALIBRATION_H_
44 
45 #include <stdbool.h>
46 #include <stdint.h>
47 
48 #include <ash.h>
49 #include <chre.h>
50 #include <cstdint>
51 
52 #include "calibration/online_calibration/common_data/calibration_callback.h"
53 #include "calibration/online_calibration/common_data/calibration_data.h"
54 #include "calibration/online_calibration/common_data/online_calibration.h"
55 #include "calibration/online_calibration/common_data/sensor_data.h"
56 #include "common/math/macros.h"
57 
58 namespace nano_calibration {
59 
60 /*
61  * NanoSensorCal is a container class for dynamic runtime calibration sensor
62  * algorithms used by the IMU_Cal CHRE nanoapp. The main purpose of this class
63  * is to transfer sensor data to the sensor calibration algorithms and provide
64  * calibration updates to CHRE using the ASH API.
65  */
66 class NanoSensorCal {
67  public:
68   // Alias used to reference the three-axis OnlineCalibration baseclass used by
69   // the runtime calibration sensor wrappers. This is for convenience and to
70   // help with code readability.
71   using OnlineCalibrationThreeAxis = online_calibration::OnlineCalibration<
72       online_calibration::CalibrationDataThreeAxis>;
73 
74   NanoSensorCal() = default;
75 
76   // Sets the sensor calibration object pointers and initializes the algorithms
77   // using runtime values recalled using Android Sensor Hub (ASH). A nullptr may
78   // be passed in to disable a particular sensor calibration.
79   void Initialize(OnlineCalibrationThreeAxis *accel_cal,
80                   OnlineCalibrationThreeAxis *gyro_cal,
81                   OnlineCalibrationThreeAxis *mag_cal);
82 
83   // Sends new sensor samples to the calibration algorithms.
84   void HandleSensorSamples(uint16_t event_type,
85                            const chreSensorThreeAxisData *event_data);
86 
87   // Provides temperature updates to the calibration algorithms.
88   void HandleTemperatureSamples(uint16_t event_type,
89                                 const chreSensorFloatData *event_data);
90 
91  private:
92   // Passes sensor data to the runtime calibration algorithms.
93   void ProcessSample(const online_calibration::SensorData &sample);
94 
95   // Loads runtime calibration data using the Android Sensor Hub API. Returns
96   // 'true' when runtime calibration values were successfully recalled and used
97   // for algorithm initialization. 'sensor_tag' is a string that identifies a
98   // sensor-specific identifier for log messages. Updates 'flags' to indicate
99   // which runtime calibration parameters were recalled.
100   bool LoadAshCalibration(uint8_t chreSensorType,
101                           OnlineCalibrationThreeAxis *online_cal,
102                           online_calibration::CalibrationTypeFlags* flags,
103                           const char *sensor_tag);
104 
105   // Provides sensor calibration updates using the ASH API for the specified
106   // sensor type. 'cal_data' contains the new calibration data. 'flags' is used
107   // to indicate all of the valid calibration values that should be provided
108   // with the update. Returns 'true' with a successful ASH update.
109   bool NotifyAshCalibration(
110       uint8_t chreSensorType,
111       const online_calibration::CalibrationDataThreeAxis &cal_data,
112       online_calibration::CalibrationTypeFlags flags, const char *sensor_tag);
113 
114   // Checks whether 'ash_cal_parameters' is a valid set of runtime calibration
115   // data and can be used for algorithm initialization. Updates 'flags' to
116   // indicate which runtime calibration parameters were detected.
117   bool DetectRuntimeCalibration(uint8_t chreSensorType, const char *sensor_tag,
118                                 online_calibration::CalibrationTypeFlags *flags,
119                                 ashCalParams *ash_cal_parameters);
120 
121   // Helper functions for logging calibration information.
122   void PrintAshCalParams(const ashCalParams &cal_params,
123                          const char *sensor_tag);
124 
125   void PrintCalibration(
126       const online_calibration::CalibrationDataThreeAxis &cal_data,
127       online_calibration::CalibrationTypeFlags flags, const char *sensor_tag);
128 
129   void HandleGyroLogMessage(uint64_t timestamp_nanos);
130 
131   // Pointer to the accelerometer runtime calibration object.
132   OnlineCalibrationThreeAxis *accel_cal_ = nullptr;
133 
134   // Pointer to the gyroscope runtime calibration object.
135   OnlineCalibrationThreeAxis *gyro_cal_ = nullptr;
136 
137   // Limits the log messaging update rate for the gyro calibrations since these
138   // can occur frequently with rapid temperature changes.
139   uint64_t gyro_notification_time_nanos_ = 0;
140   uint64_t initialization_start_time_nanos_ = 0;
141 
142   // Pointer to the magnetometer runtime calibration object.
143   OnlineCalibrationThreeAxis *mag_cal_ = nullptr;
144 
145   // Flags that determine which calibration elements are updated with the ASH
146   // API. These are reset during initialization, and latched when a particular
147   // calibration update is detected upon a valid recall of parameters and/or
148   // during runtime. The latching behavior is used to start sending calibration
149   // values of a given type (e.g., bias, over-temp model, etc.) once they are
150   // detected and thereafter.
151   online_calibration::CalibrationTypeFlags accel_cal_update_flags_ =
152       online_calibration::CalibrationTypeFlags::NONE;
153   online_calibration::CalibrationTypeFlags gyro_cal_update_flags_ =
154       online_calibration::CalibrationTypeFlags::NONE;
155   online_calibration::CalibrationTypeFlags mag_cal_update_flags_ =
156       online_calibration::CalibrationTypeFlags::NONE;
157 };
158 
159 }  // namespace nano_calibration
160 
161 #endif  // LOCATION_LBS_CONTEXTHUB_NANOAPPS_CALIBRATION_NANO_CALIBRATION_NANO_CALIBRATION_H_
162