Skip to content

Commit

Permalink
Apply a simple moving average to incoming transmitter commands
Browse files Browse the repository at this point in the history
  • Loading branch information
stevendaniluk committed Jul 1, 2019
1 parent 094bb52 commit c9267f3
Show file tree
Hide file tree
Showing 3 changed files with 76 additions and 4 deletions.
1 change: 1 addition & 0 deletions arduino/CMakeLists.txt
Expand Up @@ -7,6 +7,7 @@ generate_arduino_firmware(car_interface
HDRS interrupt_pwm_signal.h
HDRS PinChangeInt.h
HDRS signal_map.h
HDRS simple_moving_average.h
BOARD nano328
PORT /dev/ttyUSB0
)
18 changes: 14 additions & 4 deletions arduino/car_interface.cpp
Expand Up @@ -18,6 +18,7 @@ the controller commands (from the incoming topic) are issued.
#include "Arduino.h"
#include "interrupt_pwm_signal.h"
#include "signal_map.h"
#include "simple_moving_average.h"

// Use PinChangeInt library to detect rising/falling/change on any pin
// Declare which ports will not be used to save memory
Expand All @@ -43,8 +44,8 @@ the controller commands (from the incoming topic) are issued.
// positions for the servo positions and incoming PWM signals Argument order is: min, center, max.
const SignalMap steering_servo_map(63, 100, 137);
const SignalMap throttle_servo_map(58, 87, 132);
const SignalMap steering_pwm_map(1020, 1475, 1970);
const SignalMap throttle_pwm_map(1020, 1392, 1970);
const SignalMap steering_pwm_map(1020, 1485, 1965);
const SignalMap throttle_pwm_map(1020, 1392, 1965);

// Threshold PWM value for 3rd channel switch to trigger override mode
const uint16_t override_pwm_thresh = 1500;
Expand All @@ -63,6 +64,11 @@ const int16_t cmd_timout = 500;
bool override_active = false;
bool prev_override_active = false;

// Helpers to compute a moving average of the incoming controls from the transmitter, since the
// signals can be noisy
SimpleMovingAverage<uint16_t, 5> steering_sma(steering_pwm_map.center);
SimpleMovingAverage<uint16_t, 5> throttle_sma(throttle_pwm_map.center);

// Arduino servo objects for controlling the steering servo and ESC
Servo steering;
Servo throttle;
Expand Down Expand Up @@ -156,9 +162,13 @@ void loop() {
throttle_input.processNewSignals();
interrupts();

// Apply the moving average to smooth the signals
steering_sma.addDataPoint(steering_input.pwm_local);
throttle_sma.addDataPoint(throttle_input.pwm_local);

// Map the pwm inputs to the [-1, 1] range for controls
cmd_execute.steering = -steering_pwm_map.mapToUnitOutput(steering_input.pwm_local);
cmd_execute.throttle = throttle_pwm_map.mapToUnitOutput(throttle_input.pwm_local);
cmd_execute.steering = -steering_pwm_map.mapToUnitOutput(steering_sma.getAverage());
cmd_execute.throttle = throttle_pwm_map.mapToUnitOutput(throttle_sma.getAverage());
} else {
// Check controller timeout
if ((millis() - cmd_receive_time) > cmd_timout) {
Expand Down
61 changes: 61 additions & 0 deletions arduino/simple_moving_average.h
@@ -0,0 +1,61 @@
#pragma once

/* SimpleMovingAverage
*
* Computes and stores a simple moving average over a fixed window size.
*
* The template parameter N is the window size.
*/
template <typename DataT, uint8_t N>
class SimpleMovingAverage {
public:
/* SimpleMovingAverage
*
* @param init_value: Value to initialize the moving average to
*/
SimpleMovingAverage(const DataT& init_value = 0) { reset(init_value); }

/* reset
*
* @param new_value: Value to assign to the current average and all values in the window
*/
void reset(const DataT& new_value = 0) {
average_ = new_value;

index_ = 0;
for (uint8_t i = 0; i < N; ++i) {
data_[i] = new_value;
}
}

/* addDataPoint
*
* @param new_point: New data value to add to the moving average
*/
void addDataPoint(const DataT& new_point) {
// Get the oldest data point in the history, replace it with the newest, and update the
// index for out position in the window
const DataT oldest = data_[index_];
data_[index_] = new_point;
index_++;
if (index_ == N) {
index_ = 0;
}

// Can perform an incremental update based on the new and oldest points in the window
average_ += (static_cast<float>(new_point) - static_cast<float>(oldest)) / N;
}

/* getAverage
*
* @return: Current value of the moving average
*/
DataT getAverage() const { return static_cast<DataT>(average_); }

private:
// All data in the window
DataT data_[N];
uint8_t index_;
// Current average value
float average_;
}; // end SimpleMovingAverage

0 comments on commit c9267f3

Please sign in to comment.