PX4 Firmware
PX4 Autopilot Software http://px4.io
gyro.cpp
Go to the documentation of this file.
1 /****************************************************************************
2  *
3  * Copyright (c) 2017 PX4 Development Team. All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * 1. Redistributions of source code must retain the above copyright
10  * notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  * notice, this list of conditions and the following disclaimer in
13  * the documentation and/or other materials provided with the
14  * distribution.
15  * 3. Neither the name PX4 nor the names of its contributors may be
16  * used to endorse or promote products derived from this software
17  * without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
22  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
23  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
24  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
25  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
26  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
27  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
29  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30  * POSSIBILITY OF SUCH DAMAGE.
31  *
32  ****************************************************************************/
33 
34 /**
35  * @file gyro.cpp
36  * Implementation of the Gyro Temperature Calibration for onboard sensors.
37  *
38  * @author Siddharth Bharat Purohit
39  * @author Beat Küng <beat-kueng@gmx.net>
40  */
41 
42 #include <mathlib/mathlib.h>
44 #include "gyro.h"
45 #include <drivers/drv_hrt.h>
46 
47 TemperatureCalibrationGyro::TemperatureCalibrationGyro(float min_temperature_rise, float min_start_temperature,
48  float max_start_temperature, int gyro_subs[], int num_gyros)
49  : TemperatureCalibrationCommon(min_temperature_rise, min_start_temperature, max_start_temperature)
50 {
51  for (int i = 0; i < num_gyros; ++i) {
52  _sensor_subs[i] = gyro_subs[i];
53  }
54 
55  _num_sensor_instances = num_gyros;
56 
57 }
58 
60 {
61  /* reset all driver level calibrations */
62  float offset = 0.0f;
63  float scale = 1.0f;
64 
65  for (unsigned s = 0; s < 3; s++) {
66  set_parameter("CAL_GYRO%u_XOFF", s, &offset);
67  set_parameter("CAL_GYRO%u_YOFF", s, &offset);
68  set_parameter("CAL_GYRO%u_ZOFF", s, &offset);
69  set_parameter("CAL_GYRO%u_XSCALE", s, &scale);
70  set_parameter("CAL_GYRO%u_YSCALE", s, &scale);
71  set_parameter("CAL_GYRO%u_ZSCALE", s, &scale);
72  }
73 }
74 
75 int TemperatureCalibrationGyro::update_sensor_instance(PerSensorData &data, int sensor_sub)
76 {
77  bool finished = data.hot_soaked;
78 
79  bool updated;
80  orb_check(sensor_sub, &updated);
81 
82  if (!updated) {
83  return finished ? 0 : 1;
84  }
85 
86  sensor_gyro_s gyro_data;
87  orb_copy(ORB_ID(sensor_gyro), sensor_sub, &gyro_data);
88 
89  if (finished) {
90  // if we're done, return, but we need to return after orb_copy because of poll()
91  return 0;
92  }
93 
94  data.device_id = gyro_data.device_id;
95 
96  data.sensor_sample_filt[0] = gyro_data.x;
97  data.sensor_sample_filt[1] = gyro_data.y;
98  data.sensor_sample_filt[2] = gyro_data.z;
99  data.sensor_sample_filt[3] = gyro_data.temperature;
100 
101  // wait for min start temp to be reached before starting calibration
102  if (data.sensor_sample_filt[3] < _min_start_temperature) {
103  return 1;
104  }
105 
106  if (!data.cold_soaked) {
107  // allow time for sensors and filters to settle
108  if (hrt_absolute_time() > 10E6) {
109  // If intial temperature exceeds maximum declare an error condition and exit
110  if (data.sensor_sample_filt[3] > _max_start_temperature) {
112 
113  } else {
114  data.cold_soaked = true;
115  data.low_temp = data.sensor_sample_filt[3]; // Record the low temperature
116  data.high_temp = data.low_temp; // Initialise the high temperature to the initial temperature
117  data.ref_temp = data.sensor_sample_filt[3] + 0.5f * _min_temperature_rise;
118  return 1;
119  }
120 
121  } else {
122  return 1;
123  }
124  }
125 
126  // check if temperature increased
127  if (data.sensor_sample_filt[3] > data.high_temp) {
128  data.high_temp = data.sensor_sample_filt[3];
129  data.hot_soak_sat = 0;
130 
131  } else {
132  return 1;
133  }
134 
135  //TODO: Detect when temperature has stopped rising for more than TBD seconds
136  if (data.hot_soak_sat == 10 || (data.high_temp - data.low_temp) > _min_temperature_rise) {
137  data.hot_soaked = true;
138  }
139 
140  if (sensor_sub == _sensor_subs[0]) { // debug output, but only for the first sensor
141  TC_DEBUG("\nGyro: %.20f,%.20f,%.20f,%.20f, %.6f, %.6f, %.6f\n\n", (double)data.sensor_sample_filt[0],
142  (double)data.sensor_sample_filt[1],
143  (double)data.sensor_sample_filt[2], (double)data.sensor_sample_filt[3], (double)data.low_temp, (double)data.high_temp,
144  (double)(data.high_temp - data.low_temp));
145  }
146 
147  //update linear fit matrices
148  double relative_temperature = (double)data.sensor_sample_filt[3] - (double)data.ref_temp;
149  data.P[0].update(relative_temperature, (double)data.sensor_sample_filt[0]);
150  data.P[1].update(relative_temperature, (double)data.sensor_sample_filt[1]);
151  data.P[2].update(relative_temperature, (double)data.sensor_sample_filt[2]);
152 
153  return 1;
154 }
155 
157 {
158  for (unsigned uorb_index = 0; uorb_index < _num_sensor_instances; uorb_index++) {
159  finish_sensor_instance(_data[uorb_index], uorb_index);
160  }
161 
162  int32_t enabled = 1;
163  int result = param_set_no_notification(param_find("TC_G_ENABLE"), &enabled);
164 
165  if (result != PX4_OK) {
166  PX4_ERR("unable to reset TC_G_ENABLE (%i)", result);
167  }
168 
169  return result;
170 }
171 
172 int TemperatureCalibrationGyro::finish_sensor_instance(PerSensorData &data, int sensor_index)
173 {
174  if (!data.hot_soaked || data.tempcal_complete) {
175  return 0;
176  }
177 
178  double res[3][4] = {};
179  data.P[0].fit(res[0]);
180  PX4_INFO("Result Gyro %d Axis 0: %.20f %.20f %.20f %.20f", sensor_index, (double)res[0][0], (double)res[0][1],
181  (double)res[0][2],
182  (double)res[0][3]);
183  data.P[1].fit(res[1]);
184  PX4_INFO("Result Gyro %d Axis 1: %.20f %.20f %.20f %.20f", sensor_index, (double)res[1][0], (double)res[1][1],
185  (double)res[1][2],
186  (double)res[1][3]);
187  data.P[2].fit(res[2]);
188  PX4_INFO("Result Gyro %d Axis 2: %.20f %.20f %.20f %.20f", sensor_index, (double)res[2][0], (double)res[2][1],
189  (double)res[2][2],
190  (double)res[2][3]);
191  data.tempcal_complete = true;
192 
193  char str[30];
194  float param = 0.0f;
195  int result = PX4_OK;
196 
197  set_parameter("TC_G%d_ID", sensor_index, &data.device_id);
198 
199  for (unsigned axis_index = 0; axis_index < 3; axis_index++) {
200  for (unsigned coef_index = 0; coef_index <= 3; coef_index++) {
201  sprintf(str, "TC_G%d_X%d_%d", sensor_index, 3 - coef_index, axis_index);
202  param = (float)res[axis_index][coef_index];
203  result = param_set_no_notification(param_find(str), &param);
204 
205  if (result != PX4_OK) {
206  PX4_ERR("unable to reset %s", str);
207  }
208  }
209  }
210 
211  set_parameter("TC_G%d_TMAX", sensor_index, &data.high_temp);
212  set_parameter("TC_G%d_TMIN", sensor_index, &data.low_temp);
213  set_parameter("TC_G%d_TREF", sensor_index, &data.ref_temp);
214  return 0;
215 }
int _sensor_subs[SENSOR_COUNT_MAX]
Definition: common.h:194
int orb_copy(const struct orb_metadata *meta, int handle, void *buffer)
Definition: uORB.cpp:90
__EXPORT int param_set_no_notification(param_t param, const void *val)
Set the value of a parameter, but do not notify the system about the change.
Definition: parameters.cpp:820
float _min_temperature_rise
minimum difference in temperature before the process finishes
Definition: common.h:95
#define TC_ERROR_INITIAL_TEMP_TOO_HIGH
starting temperature was above the configured allowed temperature
Definition: common.h:52
class TemperatureCalibrationCommon Common base class for all sensor types, contains shared code & dat...
Definition: common.h:120
TemperatureCalibrationGyro(float min_temperature_rise, float min_start_temperature, float max_start_temperature, int gyro_subs[], int num_gyros)
Definition: gyro.cpp:47
High-resolution timer with callouts and timekeeping.
int set_parameter(const char *format_str, unsigned index, const void *value)
set a system parameter (without system notification) and print an error if it fails ...
Definition: common.h:102
#define ORB_ID(_name)
Generates a pointer to the uORB metadata structure for a given topic.
Definition: uORB.h:87
virtual int update_sensor_instance(PerSensorData &data, int sensor_sub)
update a single sensor instance
Definition: gyro.cpp:75
uint8_t * data
Definition: dataman.cpp:149
uint32_t device_id
Definition: sensor_gyro.h:55
__EXPORT param_t param_find(const char *name)
Look up a parameter by name.
Definition: parameters.cpp:370
int orb_check(int handle, bool *updated)
Definition: uORB.cpp:95
float temperature
Definition: sensor_gyro.h:63
float _max_start_temperature
maximum temperature above which the process does not start and an error is declared ...
Definition: common.h:97
float _min_start_temperature
minimum temperature before the process starts
Definition: common.h:96
#define TC_DEBUG(fmt,...)
Definition: common.h:40
int finish_sensor_instance(PerSensorData &data, int sensor_index)
Definition: gyro.cpp:172
__EXPORT hrt_abstime hrt_absolute_time(void)
Get absolute time in [us] (does not wrap).
PerSensorData _data[SENSOR_COUNT_MAX]
Definition: common.h:185