Filter: ported to AP_HAL

This commit is contained in:
Pat Hickey 2012-10-09 17:07:25 -07:00 committed by Andrew Tridgell
parent 30deb76ea3
commit 84e0dd406e
17 changed files with 122 additions and 165 deletions

View File

@ -9,12 +9,11 @@
/// @file AverageFilter.h
/// @brief A class to provide the average of a number of samples
#ifndef AverageFilter_h
#define AverageFilter_h
#ifndef __AVERAGE_FILTER_H__
#define __AVERAGE_FILTER_H__
#include <inttypes.h>
#include <Filter.h>
#include <FilterWithBuffer.h>
#include "FilterClass.h"
#include "FilterWithBuffer.h"
// 1st parameter <T> is the type of data being filtered.
// 2nd parameter <U> is a larger data type used during summation to prevent overflows
@ -100,4 +99,4 @@ void AverageFilter<T,U,FILTER_SIZE>:: reset()
_num_samples = 0;
}
#endif
#endif // __AVERAGE_FILTER_H__

View File

@ -9,12 +9,13 @@
/// @file Derivative.cpp
/// @brief A class to implement a derivative (slope) filter
/// See http://www.holoborodko.com/pavel/numerical-methods/numerical-derivative/smooth-low-noise-differentiators/
#include <FastSerial.h>
//
#include <inttypes.h>
#include <math.h>
#include <Filter.h>
#include <DerivativeFilter.h>
template <class T, uint8_t FILTER_SIZE>
void DerivativeFilter<T,FILTER_SIZE>::update(T sample, uint32_t timestamp)
{

View File

@ -10,12 +10,11 @@
/// @brief A class to implement a derivative (slope) filter
/// See http://www.holoborodko.com/pavel/numerical-methods/numerical-derivative/smooth-low-noise-differentiators/
#ifndef Derivative_h
#define Derivative_h
#ifndef __DERIVATIVE_FILTER_H__
#define __DERIVATIVE_FILTER_H__
#include <inttypes.h>
#include <Filter.h>
#include <FilterWithBuffer.h>
#include "FilterClass.h"
#include "FilterWithBuffer.h"
// 1st parameter <T> is the type of data being filtered.
// 2nd parameter <FILTER_SIZE> is the number of elements in the filter
@ -50,5 +49,5 @@ typedef DerivativeFilter<float,7> DerivativeFilterFloat_Size7;
typedef DerivativeFilter<float,9> DerivativeFilterFloat_Size9;
#endif // Derivative_h
#endif // __DERIVATIVE_FILTER_H__

View File

@ -1,49 +1,16 @@
// -*- tab-width: 4; Mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*-
//
// This is free software; you can redistribute it and/or modify it under
// the terms of the GNU Lesser General Public License as published by the
// Free Software Foundation; either version 2.1 of the License, or (at
// your option) any later version.
//
/// @file Filter.h
/// @brief A base class from which various filters classes should inherit
///
#ifndef __FILTER_H__
#define __FILTER_H__
#ifndef Filter_h
#define Filter_h
#include <inttypes.h>
#include <AP_Common.h>
template <class T>
class Filter
{
public:
// constructor
Filter() {
};
// apply - Add a new raw value to the filter, retrieve the filtered result
virtual T apply(T sample) {
return sample;
};
// reset - clear the filter
virtual void reset() {
};
};
// Typedef for convenience
typedef Filter<int8_t> FilterInt8;
typedef Filter<uint8_t> FilterUInt8;
typedef Filter<int16_t> FilterInt16;
typedef Filter<uint16_t> FilterUInt16;
typedef Filter<int32_t> FilterInt32;
typedef Filter<uint32_t> FilterUInt32;
#endif
/* Umbrella header for the Filter library */
#include "FilterClass.h"
#include "AverageFilter.h"
#include "DerivativeFilter.h"
#include "FilterWithBuffer.h"
#include "LowPassFilter.h"
#include "ModeFilter.h"
#include "ThirdOrderCompFilter.h"
#endif //__FILTER_H__

View File

@ -0,0 +1,39 @@
// -*- tab-width: 4; Mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*-
//
// This is free software; you can redistribute it and/or modify it under
// the terms of the GNU Lesser General Public License as published by the
// Free Software Foundation; either version 2.1 of the License, or (at
// your option) any later version.
//
/// @file FilterClass.h
/// @brief A pure virtual interface class
///
#ifndef __FILTER_CLASS_H__
#define __FILTER_CLASS_H__
#include <inttypes.h>
template <class T>
class Filter
{
public:
// apply - Add a new raw value to the filter, retrieve the filtered result
virtual T apply(T sample) = 0;
// reset - clear the filter
virtual void reset() = 0;
};
// Typedef for convenience
typedef Filter<int8_t> FilterInt8;
typedef Filter<uint8_t> FilterUInt8;
typedef Filter<int16_t> FilterInt16;
typedef Filter<uint16_t> FilterUInt16;
typedef Filter<int32_t> FilterInt32;
typedef Filter<uint32_t> FilterUInt32;
#endif // __FILTER_CLASS_H__

View File

@ -12,12 +12,10 @@
/// restrictions caused by the use of templates which makes different sizes essentially
/// completely different classes
#ifndef FilterWithBuffer_h
#define FilterWithBuffer_h
#ifndef __FILTER_WITH_BUFFER_H__
#define __FILTER_WITH_BUFFER_H__
#include <inttypes.h>
#include <AP_Common.h>
#include <Filter.h>
#include "FilterClass.h"
template <class T, uint8_t FILTER_SIZE>
class FilterWithBuffer : public Filter<T>
@ -27,13 +25,13 @@ public:
FilterWithBuffer();
// apply - Add a new raw value to the filter, retrieve the filtered result
virtual T apply(T sample);
T apply(T sample);
// reset - clear the filter
virtual void reset();
void reset();
// get filter size
virtual uint8_t get_filter_size() {
uint8_t get_filter_size() {
return FILTER_SIZE;
};
@ -76,7 +74,6 @@ typedef FilterWithBuffer<uint32_t,7> FilterWithBufferUInt32_Size7;
// Constructor
template <class T, uint8_t FILTER_SIZE>
FilterWithBuffer<T,FILTER_SIZE>::FilterWithBuffer() :
Filter<T>(),
sample_index(0)
{
// clear sample buffer
@ -85,11 +82,8 @@ FilterWithBuffer<T,FILTER_SIZE>::FilterWithBuffer() :
// reset - clear all samples from the buffer
template <class T, uint8_t FILTER_SIZE>
void FilterWithBuffer<T,FILTER_SIZE>:: reset()
void FilterWithBuffer<T,FILTER_SIZE>::reset()
{
// call base class reset
Filter<T>::reset();
// clear samples buffer
for( int8_t i=0; i<FILTER_SIZE; i++ ) {
samples[i] = 0;

View File

@ -11,11 +11,11 @@
/// the downside being that it's a little slower as it internally uses a float
/// and it consumes an extra 4 bytes of memory to hold the constant gain
#ifndef LowPassFilter_h
#define LowPassFilter_h
#ifndef __LOW_PASS_FILTER_H__
#define __LOW_PASS_FILTER_H__
#include <inttypes.h>
#include <Filter.h>
#include <AP_Math.h>
#include "FilterClass.h"
// 1st parameter <T> is the type of data being filtered.
template <class T>
@ -106,4 +106,4 @@ T LowPassFilter<T>::apply(T sample)
return (T)_base_value;
}
#endif
#endif // __LOW_PASS_FILTER_H__

View File

@ -10,12 +10,12 @@
/// @brief A class to apply a mode filter which is basically picking the median value from the last x samples
/// the filter size (i.e buffer size) should always be an odd number
#ifndef ModeFilter_h
#define ModeFilter_h
#ifndef __MODE_FILTER_H__
#define __MODE_FILTER_H__
#include <inttypes.h>
#include <Filter.h>
#include <FilterWithBuffer.h>
#include "FilterClass.h"
#include "FilterWithBuffer.h"
template <class T, uint8_t FILTER_SIZE>
class ModeFilter : public FilterWithBuffer<T,FILTER_SIZE>
@ -135,4 +135,4 @@ void ModeFilter<T,FILTER_SIZE>:: isort(T new_sample, bool drop_high)
}
}
#endif
#endif // __MODE_FILTER_H__

View File

@ -2,38 +2,22 @@
* Example sketch to demonstrate use of DerivativeFilter library.
*/
#include <FastSerial.h>
#include <stdlib.h>
#include <AP_Common.h>
#include <AP_HAL.h>
#include <AP_HAL_AVR.h>
#include <AP_Param.h>
#include <AP_Math.h>
#include <Filter.h>
#include <DerivativeFilter.h>
#include <AP_Buffer.h>
const AP_HAL::HAL& hal = AP_HAL_AVR_APM2;
#ifdef DESKTOP_BUILD
// all of this is needed to build with SITL
#include <DataFlash.h>
#include <APM_RC.h>
#include <GCS_MAVLink.h>
#include <Arduino_Mega_ISR_Registry.h>
#include <AP_PeriodicProcess.h>
#include <AP_ADC.h>
#include <AP_Baro.h>
#include <AP_Compass.h>
#include <AP_GPS.h>
#include <Filter.h>
#include <SITL.h>
#include <I2C.h>
#include <SPI.h>
#include <AP_Declination.h>
#include <AP_Semaphore.h>
Arduino_Mega_ISR_Registry isr_registry;
AP_Baro_BMP085_HIL barometer;
AP_Compass_HIL compass;
SITL sitl;
#error Desktop build not supported with AP_HAL
#endif
FastSerialPort0(Serial); // FTDI/console
DerivativeFilter<float,11> derivative;
@ -41,7 +25,7 @@ DerivativeFilter<float,11> derivative;
void setup()
{
// Open up a serial connection
Serial.begin(115200);
hal.uart0->begin(115200);
}
static float noise(void)
@ -52,13 +36,15 @@ static float noise(void)
//Main loop where the action takes place
void loop()
{
delay(50);
float t = millis()*1.0e-3;
hal.scheduler->delay(50);
float t = hal.scheduler->millis()*1.0e-3;
float s = sin(t);
//s += noise();
uint32_t t1 = micros();
uint32_t t1 = hal.scheduler->micros();
derivative.update(s, t1);
float output = derivative.slope() * 1.0e6;
uint32_t t2 = micros();
Serial.printf("%f %f %f %f\n", t, output, s, cos(t));
uint32_t t2 = hal.scheduler->micros();
hal.console->printf("%f %f %f %f\n", t, output, s, cos(t));
}
AP_HAL_MAIN();

View File

@ -3,8 +3,10 @@
* Code by Randy Mackay and Jason Short. DIYDrones.com
*/
#include <FastSerial.h>
#include <AP_Common.h>
#include <AP_HAL.h>
#include <AP_HAL_AVR.h>
#include <AP_Param.h>
#include <AP_Math.h> // ArduPilot Mega Vector/Matrix math Library
#include <Filter.h> // Filter library
@ -12,10 +14,7 @@
#include <AverageFilter.h> // AverageFilter class (inherits from Filter class)
#include <AP_Buffer.h>
////////////////////////////////////////////////////////////////////////////////
// Serial ports
////////////////////////////////////////////////////////////////////////////////
FastSerialPort0(Serial); // FTDI/console
const AP_HAL::HAL& hal = AP_HAL_AVR_APM2;
int16_t rangevalue[] = {31000, 31000, 50, 55, 60, 55, 10, 0, 31000};
@ -25,34 +24,23 @@ ModeFilterInt16_Size5 mfilter(2); // buffer of 5 values, result will be from bu
AverageFilterUInt16_Size4 _temp_filter;
// Function to print contents of a filter
// we need to ues FilterWithBuffer class because we want to access the individual elements
void printFilter(FilterWithBufferInt16_Size5& filter)
{
for(uint8_t i=0; i < filter.get_filter_size(); i++)
{
Serial.printf("%d ",(int)filter.get_sample(i));
}
Serial.println();
}
void setup()
{
// Open up a serial connection
Serial.begin(115200);
hal.uart0->begin(115200);
// introduction
Serial.printf("ArduPilot ModeFilter library test ver 1.0\n\n");
hal.console->printf("ArduPilot ModeFilter library test ver 1.0\n\n");
// Wait for the serial connection
delay(500);
hal.scheduler->delay(500);
}
// Read Raw Temperature values
void ReadTemp()
void readTemp()
{
static uint8_t next_num = 0;
static int32_t RawTemp = 0;
static int32_t raw_temp = 0;
uint8_t buf[2];
uint16_t _temp_sensor;
@ -63,9 +51,9 @@ void ReadTemp()
_temp_sensor = buf[0];
_temp_sensor = (_temp_sensor << 8) | buf[1];
RawTemp = _temp_filter.apply(_temp_sensor);
raw_temp = _temp_filter.apply(_temp_sensor);
Serial.printf("RT: %ld\n",RawTemp);
hal.console->printf("RT: %ld\n", raw_temp);
}
//Main loop where the action takes place
@ -77,28 +65,10 @@ void loop()
int16_t j;
for(j=0; j<0xFF; j++ ) {
ReadTemp();
readTemp();
hal.scheduler->delay(100);
}
/*while( i < 9 ) {
*
* // output to user
* Serial.printf("applying: %d\n",(int)rangevalue[i]);
*
* // display original
* Serial.printf("before: ");
* printFilter(mfilter);
*
* // apply new value and retrieved filtered result
* filtered_value = mfilter.apply(rangevalue[i]);
*
* // display results
* Serial.printf("after: ");
* printFilter(mfilter);
* Serial.printf("The filtered value is: %d\n\n",(int)filtered_value);
*
* i++;
* }*/
delay(10000);
hal.scheduler->delay(10000);
}
AP_HAL_MAIN();

View File

@ -3,18 +3,16 @@
* Code by Randy Mackay. DIYDrones.com
*/
#include <FastSerial.h>
#include <AP_Common.h>
#include <AP_HAL.h>
#include <AP_HAL_AVR.h>
#include <AP_Param.h>
#include <AP_Math.h> // ArduPilot Mega Vector/Matrix math Library
#include <Filter.h> // Filter library
#include <LowPassFilter.h> // LowPassFilter class (inherits from Filter class)
#include <AP_Buffer.h>
////////////////////////////////////////////////////////////////////////////////
// Serial ports
////////////////////////////////////////////////////////////////////////////////
FastSerialPort0(Serial); // FTDI/console
const AP_HAL::HAL& hal = AP_HAL_AVR_APM2;
// create a global instance of the class
LowPassFilterFloat low_pass_filter;
@ -23,17 +21,17 @@ LowPassFilterFloat low_pass_filter;
void setup()
{
// Open up a serial connection
Serial.begin(115200);
hal.uart0->begin(115200);
// introduction
Serial.printf("ArduPilot LowPassFilter test ver 1.0\n\n");
hal.console->printf("ArduPilot LowPassFilter test ver 1.0\n\n");
// set-up filter
low_pass_filter.set_time_constant(0.02, 0.015);
//low_pass_filter.set_cutoff_frequency(0.02, 1.0);
// Wait for the serial connection
delay(500);
hal.scheduler->delay(500);
}
//Main loop where the action takes place
@ -52,13 +50,17 @@ void loop()
new_value = sin((float)i*2*M_PI*5/50.0); // 5hz
// output to user
Serial.printf("applying: %6.4f",(float)new_value);
hal.console->printf("applying: %6.4f", new_value);
// apply new value and retrieved filtered result
filtered_value = low_pass_filter.apply(new_value);
// display results
Serial.printf("\toutput: %6.4f\n",(float)filtered_value);
hal.console->printf("\toutput: %6.4f\n", filtered_value);
hal.scheduler->delay(10);
}
delay(10000);
hal.scheduler->delay(10000);
}
AP_HAL_MAIN();