v1.1.0
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Modules Pages
Public Member Functions | Static Public Attributes | List of all members
Sifteo::MotionBuffer< tSize > Struct Template Reference

A memory buffer which holds captured motion data. More...

#include <sifteo/motion.h>

Public Member Functions

void attach (_SYSCubeID id, unsigned hz=100)
 Initialize the MotionBuffer and attach it to a cube. More...
 
Int3 integrate (unsigned duration)
 Calculate a numerical integral over recent motion data. More...
 

Static Public Attributes

static const unsigned TICK_HZ = _SYS_MOTION_TIMESTAMP_HZ
 Reciprocal of the MotionBuffer's timestamp unit, in Hertz.
 
static const unsigned TICK_NS = _SYS_MOTION_TIMESTAMP_NS
 Duration of the MotionBuffer's timestamp unit, in nanoseconds.
 
static const unsigned TICK_US = _SYS_MOTION_TIMESTAMP_NS / 1000
 Duration of the MotionBuffer's timestamp unit, in microseconds.
 

Detailed Description

template<unsigned tSize = 32>
struct Sifteo::MotionBuffer< tSize >

A memory buffer which holds captured motion data.

This is a FIFO buffer which captures timestamped accelerometer samples. Samples are enqueued and timestamps are generated the moment a relevant packet arrives over the radio from a cube. Timestamps are collected using the system clock, and stored as 8-bit deltas.

Like a VideoBuffer, a MotionBuffer can be used with at most one CubeID at a time, but this association can change at runtime. The size of a MotionBuffer may also be modified, in order to trade off between capture duration and memory usage.

This captured accelerometer data may be directly read by signal processing code in userspace, or it may be processed with lower CPU overhead with the help of the provided higher-level methods.

MotionBuffers are templatized by buffer size. The default should be sufficient for most uses, but if you need to save a longer motion history the size can be adjusted to a maximum of 256 samples.

Warning
We don't recommend allocating MotionBuffers on the stack. Usually this wouldn't be a useful thing to do anyway, since MotionBuffers tend to be long-lived objects. But the specific reason we don't recommend this is that the system requires a MotionBuffer pointer to be at least 1kB away from the top of RAM. In other words, it needs to have enough physical memory for the entire size of a maximally-large (256-sample) buffer, even if you've defined the buffer with a smaller size.

Member Function Documentation

template<unsigned tSize = 32>
void Sifteo::MotionBuffer< tSize >::attach ( _SYSCubeID  id,
unsigned  hz = 100 
)
inline

Initialize the MotionBuffer and attach it to a cube.

When this cube is connected, this MotionBuffer will begin asynchronously receiving a sample every time we receive accelerometer data from the cube over the air.

We will store data as fast as it arrives, but due to power management the system will often try to reduce the rate at which we poll each cube's sensors. When a MotionBuffer is attached to a cube, we can request a particular rate of service, specified here in hertz. This is not a guranteed rate, just a suggestion for power management purposes.

The caller is responsible for ensuring that a MotionBuffer is only attached to one cube at a time.

Note that, regardless of the actual size of this motion buffer, the system requires a block of memoryw

template<unsigned tSize = 32>
Int3 Sifteo::MotionBuffer< tSize >::integrate ( unsigned  duration)
inline

Calculate a numerical integral over recent motion data.

The duration is specified in units as defined by TICK_NS, TICK_US, and TICK_HZ. Numerical integration is performed by the Trapezoid rule, using a non-uniform sampling grid. If the integral duration extends beyond the oldest buffered, sample, we act as if that sample lasted forever. If the integral ends in-between samples, we linearly interpolate.

The result will be scaled by (2 * duration), meaning you'll need to divide by this number to take an average. However, avoiding this division is both faster and preserves precision, so we recommend using the scaled values as-is if possible.

This integration can be used as a very simple "boxcar" or moving-average low pass filter, with a fixed temporal window size. This kind of filter will feel like it's "slowing" or "blurring" motions, but for short durations the filtered results can feel very natural.


The documentation for this struct was generated from the following file: