Re: Sensor API Helper Functions

2017-01-04 Thread Kevin Townsend

Hi Sterling,
All of the above can probably be fit into a package based on sensor 
'orientation', which might be a natural organizational unit?


I think this belongs in the core sensor package itself, or as a 
sub-directory of hw/sensor (i.e. hw/sensor/orientation). Orientation 
is a very common transformation and having a unified API for it makes 
sense to me, unless you think that the various factors that go into 
orientation (e.g. accuracy) vary greatly based upon the type of sensor 
that you’re looking at, and therefore the algorithms themselves will 
vary greatly.
The orientation code is quite generic and I think should apply to almost 
any accel/mag/gyro as is. It gets slightly more complicated with full 
9DOF sensor fusion (adding gyro support in) since there are certain 
assumptions about gyro unit types that get fed into the algorithm (rad/s 
or dps from the gyro, for example), but if these are clearly defined 
it's up to the user to make sure you feed the filter what it expects in 
terms of units and scale.

FILTERS

A second very important helper unit is something that implements 
basic DSP algorithms to filter raw sensor data. This is critical in 
my opinion, but often neglected in open source systems.


My biggest question comes in: what are the standard types that we 
allow to be passed to these filters?  Is it just floats, or do we 
allow you to, for example, pass accelerometer directly.
If there is one standard type for DSP, I think it should be 
single-precision float, but having an int32_t, fixed-point and maybe 
even double option might be nice. I generally write float and int32_t 
based versions of any DSP filters as a minimum. Part of the reason I 
want to discuss this on the dev list, though, is because you need to 
design things like variable types in from the start, and it isn't always 
obvious how to do it well.


This is easier once you start dealing with concrete examples, though, so 
maybe adding orientation in can be done now since that code is very 
independent, and then we can start looking at how you can add an IIR 
filter between the raw data and the orientation transform to get cleaner 
data (simple moving average implementation, etc.). You will quickly run 
into issues of type, and dealing with filter parameters then.

BONUS POINTS: PEDOMETER

Yeah, I think this is useful.  I’m not sure this belongs in the core, 
but perhaps a package that uses Mynewt?  I could be convinced 
otherwise, if folks think it should be OS level.

This is a separate package to me, yes, since it's very application specific.

K.


Re: Sensor API Helper Functions

2017-01-04 Thread Sterling Hughes

Hi Kevin,

On 23 Dec 2016, at 15:26, Kevin Townsend wrote:

I'm probably getting ahead of myself diving into this before the 
sensor API is nailed down, but if we wanted to add some generic helper 
functions that make use of the sensor API, what would be a good 
location or what to organize them as a package? It isn't always easy 
to organize things like this by sensor type since there is a lot of 
overlap.




Well, certainly ahead of me.  I’m just looking at this stuff now, 
sorry about that.


Comments inline, as I think some of it belongs in the sensor interface, 
some is probably better a separate package.


I can think of two helper packages we might want to add as a core test 
case, that are useful for testing and getting actionable, useful 
output from the sensor API:


ORIENTATION

Using only an accelerometer you can get rough roll/pitch values: 
https://github.com/microbuilder/LPC11U_LPC13U_CodeBase/blob/development/src/drivers/sensors/accelerometers/accelerometers.c#L81


If you add a magnetometer you can get rough roll/pitch/heading values: 
https://github.com/microbuilder/LPC11U_LPC13U_CodeBase/blob/development/src/drivers/sensors/sensorfusion.c#L78


If you add a gyroscope, you can do proper 9DOF sensor fusion using a 
variety of algorithms and get better quality roll/pitch heading 
(madgwick, mahoney, etc.).


All of this will require at a minimum magnetometer calibration to 
compensate for hard and soft iron errors, and probably gyroscope 
calibration to remove the zero drift error. Accel calibration helps, 
but isn't as critical as the mag and gyro.


All of the above can probably be fit into a package based on sensor 
'orientation', which might be a natural organizational unit?




I think this belongs in the core sensor package itself, or as a 
sub-directory of hw/sensor (i.e. hw/sensor/orientation).  Orientation is 
a very common transformation and having a unified API for it makes sense 
to me, unless you think that the various factors that go into 
orientation (e.g. accuracy) vary greatly based upon the type of sensor 
that you’re looking at, and therefore the algorithms themselves will 
vary greatly.



FILTERS

A second very important helper unit is something that implements basic 
DSP algorithms to filter raw sensor data. This is critical in my 
opinion, but often neglected in open source systems.


This should contain things like a simple moving average filter, a 
basic FIR and IIR filter (that can take coefficients from 
Octave/Matlab), and a other very common but useful filters that will 
help remove noise from less expensive sensors like the lsm303dlhc.


For example, see:

 * *iir.c* here:
   
https://github.com/microbuilder/LPC11U_LPC13U_CodeBase/tree/development/src/drivers/filters/iir
 * Simple and weighted moving average filters here:
   
https://github.com/microbuilder/LPC11U_LPC13U_CodeBase/tree/development/src/drivers/filters/ma

The iir.c example above has some notes on calculating the coefficients 
for a 2 pole butterworth filter, or determining the coefficients 
internally. It's a limited example, but I think the right direction to 
move things:


 * Octave Butterworth Example:
   
https://github.com/microbuilder/LPC11U_LPC13U_CodeBase/blob/development/src/drivers/filters/iir/iir.c#L57
 * Calculating Butterworth Directly:
   
https://github.com/microbuilder/LPC11U_LPC13U_CodeBase/blob/development/src/drivers/filters/iir/iir.c#L269



To me, this is a separate package in core, but very useful.. Also, being 
able to apply simulated data through a filter and get reliable results 
(and standard scripts to graph those results.)


My biggest question comes in: what are the standard types that we allow 
to be passed to these filters?  Is it just floats, or do we allow you 
to, for example, pass accelerometer directly.



BONUS POINTS: PEDOMETER

A third package that could be implemented that would be a useful 
example for BLE is taking accelerometer data and turning it into a 
pedometer, which can be done with some reasonably straight forward 
code. I have some code I can recycle for this, but it isn't publicly 
available on Github.


I think this is interesting for BLE and I can help here, but the two 
above are more critical.




Yeah, I think this is useful.  I’m not sure this belongs in the core, 
but perhaps a package that uses Mynewt?  I could be convinced otherwise, 
if folks think it should be OS level.



Kevin

PS: Some of the code above is quite old and I'm not terribly proud of 
it and would do things differently today and I've reimplemented these 
elsewhere differently, but I think the examples are at least valid as 
an illustration or where things need to move to be useful in the real 
world.


:-)

Very useful.

Sterling


Sensor API Helper Functions

2016-12-23 Thread Kevin Townsend
I'm probably getting ahead of myself diving into this before the sensor 
API is nailed down, but if we wanted to add some generic helper 
functions that make use of the sensor API, what would be a good location 
or what to organize them as a package? It isn't always easy to organize 
things like this by sensor type since there is a lot of overlap.


I can think of two helper packages we might want to add as a core test 
case, that are useful for testing and getting actionable, useful output 
from the sensor API:


ORIENTATION

Using only an accelerometer you can get rough roll/pitch values: 
https://github.com/microbuilder/LPC11U_LPC13U_CodeBase/blob/development/src/drivers/sensors/accelerometers/accelerometers.c#L81


If you add a magnetometer you can get rough roll/pitch/heading values: 
https://github.com/microbuilder/LPC11U_LPC13U_CodeBase/blob/development/src/drivers/sensors/sensorfusion.c#L78


If you add a gyroscope, you can do proper 9DOF sensor fusion using a 
variety of algorithms and get better quality roll/pitch heading 
(madgwick, mahoney, etc.).


All of this will require at a minimum magnetometer calibration to 
compensate for hard and soft iron errors, and probably gyroscope 
calibration to remove the zero drift error. Accel calibration helps, but 
isn't as critical as the mag and gyro.


All of the above can probably be fit into a package based on sensor 
'orientation', which might be a natural organizational unit?


FILTERS

A second very important helper unit is something that implements basic 
DSP algorithms to filter raw sensor data. This is critical in my 
opinion, but often neglected in open source systems.


This should contain things like a simple moving average filter, a basic 
FIR and IIR filter (that can take coefficients from Octave/Matlab), and 
a other very common but useful filters that will help remove noise from 
less expensive sensors like the lsm303dlhc.


For example, see:

 * *iir.c* here:
   
https://github.com/microbuilder/LPC11U_LPC13U_CodeBase/tree/development/src/drivers/filters/iir
 * Simple and weighted moving average filters here:
   
https://github.com/microbuilder/LPC11U_LPC13U_CodeBase/tree/development/src/drivers/filters/ma

The iir.c example above has some notes on calculating the coefficients 
for a 2 pole butterworth filter, or determining the coefficients 
internally. It's a limited example, but I think the right direction to 
move things:


 * Octave Butterworth Example:
   
https://github.com/microbuilder/LPC11U_LPC13U_CodeBase/blob/development/src/drivers/filters/iir/iir.c#L57
 * Calculating Butterworth Directly:
   
https://github.com/microbuilder/LPC11U_LPC13U_CodeBase/blob/development/src/drivers/filters/iir/iir.c#L269

BONUS POINTS: PEDOMETER

A third package that could be implemented that would be a useful example 
for BLE is taking accelerometer data and turning it into a pedometer, 
which can be done with some reasonably straight forward code. I have 
some code I can recycle for this, but it isn't publicly available on 
Github.


I think this is interesting for BLE and I can help here, but the two 
above are more critical.


Kevin

PS: Some of the code above is quite old and I'm not terribly proud of it 
and would do things differently today and I've reimplemented these 
elsewhere differently, but I think the examples are at least valid as an 
illustration or where things need to move to be useful in the real world.