2 * Copyright (c) 2016-2017 Samsung Electronics Co., Ltd.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 #include "step_detection.h"
20 #include <sensor_log.h>
22 /* Size of average filter. */
23 #define AV_FILTER_SIZE 7
25 #define AV_GFILTER_SIZE 500
27 #define FAST_PEAK_THRESHOLD 0.77
29 #define SLOW_PEAK_THRESHOLD 0.3
31 #define PEAK_THRESHOLD_FOR_MEAN 2.0
35 #define SLOPE_PARAM -0.75
37 step_detection::step_detection()
38 : m_average_filter(AV_FILTER_SIZE)
39 , m_average_gfilter(AV_GFILTER_SIZE)
40 , m_zero_crossing_up(true)
41 , m_zero_crossing_down(false)
43 , m_peak_threshold(FAST_PEAK_THRESHOLD)
44 , m_use_savitzky(false)
45 , m_last_step_timestamp(UNKNOWN_TIMESTAMP)
46 , m_zero_crossing_up_detected(false)
47 , m_zero_crossing_down_detected(false)
48 , m_minimum_acceleration(0)
49 , m_maximum_acceleration(0)
50 , m_is_slow_step_detected(false)
54 step_detection::~step_detection()
58 /************************************************************************
60 void step_detection::reset(void)
62 m_average_filter.reset();
63 m_average_gfilter.reset();
64 m_zero_crossing_up.reset();
65 m_zero_crossing_down.reset();
67 m_average_gfilter.filter(9.81);
70 m_zero_crossing_up_detected = false;
71 m_zero_crossing_down_detected = false;
72 m_minimum_acceleration = 0;
73 m_maximum_acceleration = 0;
74 m_is_slow_step_detected = false;
77 /************************************************************************
79 void step_detection::set_peak_threshold(double threshold)
81 m_peak_threshold = threshold;
84 /************************************************************************
86 void step_detection::set_use_savitzky(bool use_savitzky)
88 m_use_savitzky = use_savitzky;
91 /************************************************************************
93 bool step_detection::is_slow_step(void)
95 return m_is_slow_step_detected;
98 /************************************************************************
100 static double cal_step_length(double time, double sqrt4peak_valley_diff)
102 double step_length = 0;
103 if (time <= 0 || time > 1.00) {
104 step_length = 0.50 * sqrt4peak_valley_diff;
105 } else if (time < 0.3) {
108 step_length = B_COEF + SLOPE_PARAM * time;
111 if (step_length > 1.5)
117 /************************************************************************
119 bool step_detection::add_acc_sensor_values_average(
120 timestamp_t timestamp, double acc, step_event* step)
122 double acceleration = m_average_filter.filter(acc - 9.8066f);
124 bool n_zero_up = m_zero_crossing_up.detect_step(timestamp, acceleration);
125 bool n_zero_down = m_zero_crossing_down.detect_step(timestamp, acceleration);
127 double sqrt4peak_valley_diff = 0;
128 bool is_step_detected = false;
131 m_zero_crossing_up_detected = true;
132 m_zero_crossing_down_detected = false;
135 m_zero_crossing_up_detected = false;
136 m_zero_crossing_down_detected = true;
138 if (m_zero_crossing_up_detected) {
139 if (m_maximum_acceleration < acceleration) {
140 m_maximum_acceleration = acceleration;
143 if (m_zero_crossing_down_detected) {
144 if (m_minimum_acceleration > acceleration) {
145 m_minimum_acceleration = acceleration;
149 double peak_threshold;
150 if (m_zero_crossing_up.m_time_sum / 1E9 < 1.2) {
151 peak_threshold = m_peak_threshold;
152 m_is_slow_step_detected = false;
154 peak_threshold = SLOW_PEAK_THRESHOLD;
155 m_is_slow_step_detected = true;
159 if (m_maximum_acceleration > peak_threshold
160 || (m_maximum_acceleration - m_minimum_acceleration > PEAK_THRESHOLD_FOR_MEAN)) {
161 sqrt4peak_valley_diff = pow(m_maximum_acceleration - m_minimum_acceleration, 0.25);
162 m_minimum_acceleration = 0;
163 m_maximum_acceleration = 0;
164 is_step_detected = true;
168 if (m_zero_crossing_up.m_time_sum / 1E9 < 0.3)
169 is_step_detected = false;
171 if (is_step_detected) {
172 if (m_last_step_timestamp == UNKNOWN_TIMESTAMP)
173 m_last_step_timestamp = timestamp;
175 double time = (timestamp - m_last_step_timestamp) / 1E9;
176 m_last_step_timestamp = timestamp;
177 m_zero_crossing_up.m_time_sum = 0;
178 step->m_timestamp = timestamp;
179 step->m_step_length = cal_step_length(time, sqrt4peak_valley_diff);
186 /************************************************************************
188 bool step_detection::add_acc_sensor_values_savitzky(
189 timestamp_t timestamp, double acc, step_event* step)
191 double acceleration = m_zc_filter.filter(acc - m_average_gfilter.filter(acc));
192 bool n_zero_up = m_zero_crossing_up.detect_step(timestamp, acceleration);
193 bool n_zero_down = m_zero_crossing_down.detect_step(timestamp, acceleration);
195 double sqrt4peak_valley_diff = 0;
196 bool is_step_detected = false;
199 m_zero_crossing_up_detected = true;
200 m_zero_crossing_down_detected = false;
203 m_zero_crossing_up_detected = false;
204 m_zero_crossing_down_detected = true;
206 if (m_zero_crossing_up_detected) {
207 if (m_maximum_acceleration < acceleration) {
208 m_maximum_acceleration = acceleration;
211 if (m_zero_crossing_down_detected) {
212 if (m_minimum_acceleration > acceleration) {
213 m_minimum_acceleration = acceleration;
217 bool zup = m_zero_crossing_up.m_time_sum / 1E9 > 1.2;
219 is_step_detected = false;
221 if ((m_maximum_acceleration > 0.6 &&
222 m_minimum_acceleration < -0.852)
223 || (m_maximum_acceleration > 0.714
224 && m_minimum_acceleration < -0.455)) {
225 is_step_detected = true;
226 m_is_slow_step_detected = false;
228 if (m_maximum_acceleration - m_minimum_acceleration > 3.32) {
229 is_step_detected = true;
230 m_is_slow_step_detected = false;
232 if (zup && m_maximum_acceleration > 0.764 && m_minimum_acceleration < -0.0235) {// slow steps
233 is_step_detected = true;
234 m_is_slow_step_detected = true;
237 if (is_step_detected) {
238 sqrt4peak_valley_diff = pow(m_maximum_acceleration - m_minimum_acceleration, 0.25);
239 m_minimum_acceleration = 0.0;
240 m_maximum_acceleration = 0.0;
244 if (m_zero_crossing_up.m_time_sum / 1E9 < 0.3)
245 is_step_detected = false;
247 if (is_step_detected) {
248 if (m_last_step_timestamp == UNKNOWN_TIMESTAMP)
249 m_last_step_timestamp = timestamp;
251 double time = (timestamp - m_last_step_timestamp) / 1E9;
253 m_last_step_timestamp = timestamp;
254 m_zero_crossing_up.m_time_sum = 0;
255 step->m_timestamp = timestamp;
256 step->m_step_length = cal_step_length(time, sqrt4peak_valley_diff);
264 /************************************************************************
266 bool step_detection::get_step(timestamp_t timestamp, double acc, step_event* step)
268 return m_use_savitzky
269 ? add_acc_sensor_values_savitzky(timestamp, acc, step)
270 : add_acc_sensor_values_average(timestamp, acc, step);