Stream Filtered Accelerometer Data

edited April 2017 in Android
Hi,

I am trying to filter and stream filtered accelerometer data. Eventually I'd like to program the board to only store data from when the board is moving.

I very new to Java and Metawear, but from what I can tell I need to map or split the data before filtering. Can the full set of data (x, y and z) be streamed after satisfying filter conditions?

Here is the code I've got (adapted from the freefall tutorial which was super helpful!). Outputting "data.value(Acceleration.class)"in any form doesn't seem to work but doesn't give an error in the log

return accelerometer.acceleration().addRouteAsync(new RouteBuilder() {
@Override
public void configure(RouteComponent source) {
source.map(Function1.RSS).average((byte) 4).filter(ThresholdOutput.ABSOLUTE,1f,0.01f)
.multicast()
.to()
.stream(new Subscriber() {
@Override
public void apply(Data data, Object... env) {
Log.i("freefall", "move");
Log.i("freefall", String.valueOf(data.value(Acceleration.class).x()));
CONTENT = CONTENT + "\n" + data.formattedTimestamp() + "," + data.value(Acceleration.class).toString();

}
})
.end();
}
});
I'm using a metawear C with the latest firmware on a samsung galaxy s 6 edge.
Thanks!
-Tom

Comments

  • RSS returns a scalar value so you can't map its output to an Acceleration type.  You can check valid types using the types method.  In this specific case, rss returns a float value.
    https://mbientlab.com/androiddocs/3/data_route.html#handling-data

    For your filter chain, you'll want to use a passthrough limiter in conditional mode to control when to allow acceleration data though.  The rss->threshold chain sets the passthrough value and the raw acceleration data feeds into the passthrough limiter.  You'll need to use the DataProcessor module to edit the passthrough state.


    acc -> rss -> threshold [set passthrough value to 1 or 0]
            |
            | -> passthrough -> log
  • Hi Eric,

    Thanks for the response! 

    I think I'm following but would you mind representing what you said, in code? Perhaps with reference to my snippet above? I learn a lot better from code snippets :).

    Thanks!

    -Tom
  • Checkout this unit test using the passthrough limiter.  It's in count mode but it demonstrates the idea of using the DataProcessor module to modify the passthrough state.

  • Thanks Eric,

    I'm still struggling! This is what I have. I'm not sure how to combine the passthrough modifier with the threshold filter?

    Can you suggest changes to the code below?

    Thanks!!

    return accelerometer.acceleration().addRouteAsync(new RouteBuilder() {
    @Override
    public void configure(RouteComponent source) {
    source.limit(Passthrough.CONDITIONAL, (short) 0).name("Passthrough Acceleration").stream(new Subscriber() {
    @Override
    public void apply(Data data, Object... env) {
    Log.i("freefall", "move");
    Log.i("freefall", data.toString());
    }
    });
    }
    });


  • edited April 2017
    You need attach the "rss -> threshold" chain to the acceleration source as drawn out in my ASCII art; the threshold processor will edit the passthrough's state with a reaction.  This setup is demonstrated in the unit test I linked in my previous post.


  • This is my first Java project as well as my first Metawear project so I'm still learning the syntax. This is why I've been asking for code snippets, and why the terminology and illustrations you're using aren't 100% clear to me.

    The code below is still giving in the form of: {timestamp: 2017-04-25T21:03:55.494, data: [0xda, 0x0e]}

    Is the dataprocessor module in the right place? Again, if you can illustrate with code, that would be super helpful!

    Thanks for your continued help!!

    public void configure(RouteComponent source) {
    source.map(Function1.RSS).average((byte) 4).filter(ThresholdOutput.ABSOLUTE,0.1f,0.01f)
    .limit(Passthrough.CONDITIONAL, (short) 1).name("filteredAC").stream(new Subscriber()
    {
    public void apply(Data data, Object... env) {
    Log.i("freefall", "move");
    dataprocessor.edit("filteredAC", DataProcessor.PassthroughEditor.class).modify(Passthrough.ALL,(short) 1);
    Log.i("freefall",data.toString());
    }
    });
    }

  • edited April 2017
    The data processor editing goes in a reaction; it should mirror how the unit test I linked edits the passthrough limiter.

    On the bigger picture, your route should resemble the route that is constructed in the free fall tutorial.  Using that as a starting point, you only need to make 2 modifications:
    1. Use a multicast component to add another branch that directs the data source to the "passthrough (conditional) -> log" chain
      • Make sure you name the limiter
    2. Replace the log subscribers with reactions that set the conditional passthrough state to 1 or 0 
      • See the unit test I linked above for code example

    If things are still not clear for you, please point out specifically which sample code, terminology, etc. is not making sense.
  • Brilliant, thanks Eric, I've finally cracked it! 

    It took me a while to release that the passthrough editor effectively sets a variable which can then be used by the passthrough limiter in a separate branch. Thanks for staying with me!

    My app is all working now. except I can't work out how to access the downloaded log. I'm using the code below and the log seems to be downlaoded properly but I've not no idea how to find the data. Is it saved in a variable or similar which I can export via email or the android "share" function?

    Thanks!

    -Tom
  • What code are you using?
  • Sorry, here it is.It's called by the stop button


    private void download() {
    final TextView infoText = (TextView)findViewById(R.id.info);
    Log.i("freefall", "Downloading..");

    logging.downloadAsync(100, new Logging.LogDownloadUpdateHandler() {
    @Override
    public void receivedUpdate(long nEntriesLeft, long totalEntries) {
    Log.i("freefall", "Progress Update = " + nEntriesLeft + "/" + totalEntries);
    }
    }).continueWithTask(new Continuation<Void, Task<Void>>() {
    @Override
    public Task<Void> then(Task<Void> task) throws Exception {
    Log.i("freefall", "Download completed");
    logging.clearEntries();
    return null;
    }
    });
  • edited May 2017
    Add a log component to the passthrough limiter, which you do in the last step of the Free Fall tutorial.


    limit(...).name("acc_passthrough").log(new Subscriber() {
        @Override
        public void apply(Data data, Object... env) {
            // Save to file or memory here
        }
    })
  • Thanks Eric,

    I'm saving the data to an array inside the log component, then writing the array to a file after the download has completed. 

    I wasn't sure if the "download" function actually downloaded the log to the device. But i guess it doesn't

    Thanks!

    -Tom
  • It does download the data to the device, you just didn't tell the API what to do with the downloaded data in your data route.
This discussion has been closed.