How do I Perform mathematical operations on gyroscope data sequentially

Hi Everyone,

I am trying to program the below algorithm using the gyroscope on the metatracker. To do so, i would need to
do the following sequentially, although i'm not sure how to really do it. Currently i am using multicast, although i understand that this is not sequential. with the to() functionality. I am able to print each of the below values in their corresponding apply method, although i want to use all of the values at once. I have attempted to create an object to store all the values when they are populated, but is there a better way.

X-dc = lowpass((byte) 10)
Y-dc = lowpass((byte)10)
Z-dc = lowpass((byte) 10)

X = X-RAW - X-dc
Y = Y-RAW - Y-dc
Z = Z-RAW - Z-dc

YZ = Y * Z

X-delayed = delay(X, 10)

YZ-filtered = average(YZ, 8)

Output = X-delayed * YZ-filtered

to attempt the above, i have done the following:
Using source.multicast

[to address #1 above]

[to address #2 above] Note: Does this work?
to.split.index(0).map(Function2.Subtract, "x_lowpass").stream
to.split.index(0).map(Function2.Subtract, "x_lowpass").stream
to.split.index(0).map(Function2.Subtract, "x_lowpass").stream

[to address #3 above]
Not sure how to do this, since it includes using the lowpass value, and the current raw value

[to address #4 above]

[to address #5 above]
Not sure how to do this, since it is using the average of the y-axis and z-axis angular velocity

[to address #6 above]
Not sure how to do this since its a combination of raw, and lowpassed data, along with delayed data, and performing math on that.

Thank you


  • For step 2), which raw value are you using when computing "raw - lpf"? The lowpass processor delays the stream until it has collected enough samples so in your case, it won't provide a value until the 10th data sample.

  • edited March 2018
    @Eric, thank you for your response.

    I assumed that with the multicast functionality, it allows for the same raw gyroscope data, to then be used and perform different actions on them, so for step 1 it would use the low pass data, and for step 2 it would use the original angular velocity in the x y and z axis.

    Is this the true use of the multicast functionality

    Or would I have to use multicast with values of the same data, and anything using different angular veloxities whether raw or low passed need to go in separate multicast functions as different routes as well? Ie a multicast for all lowpass values, and a multicast for all raw values? How do I operate on things in sequence?
  • multicast is simply an API feature to let you reuse the same data producer for different chains; it does not affect data flow.

    Each data processing component is executed in the order it is added.

    Since you are looking to compute "x0 - lpf(x0...x9)", you can attach a delay component to the x-axis data to similarly hold its data until until the lpf data is available. See if this example code works for x-axis data:

            .to().lowpass((byte) 10).name("x-lpf")
            .to().delay((byte) 10).map(Function2.SUBTRACT, "x-lpf")
  • source.split()
            .to().lowpass((byte) 10).name("x-lpf")
            .to().delay((byte)10).map(Function2.SUBTRACT, "x-lpf").name("raw-x-lpf")
            .stream(new Subscriber() {
            public void apply(Data data, Object... env) {
                Log.i("raw-x-lpf", data.value(Float.class).toString());
           .to().delay((byte)10).map(Function2.SUBTRACT, "y-lpf").name("raw-y-lpf")
           .stream(new Subscriber() {
           public void apply(Data data, Object... env) {
               Log.i("raw-y-lpf", data.value(Float.class).toString());
          .to().delay((byte)10).map(Function2.SUBTRACT, "z-lpf").name("raw-z-lpf")
          .map(Function2.MULTIPLY, "raw-y-lpf")
          .stream(new Subscriber() {
          public void apply(Data data, Object... env) {
              Log.i("raw-z-lpf X raw-y-lpf", data.value(Float.class).toString());

    in each of the .to() lines, are all of these tasks run parallel or sequentially? i am assuming parallel, since you said above that the delay should have a value of 10, to ensure that the previous lowpass step has returned?

    for example for index(0).
    Assuming the following sample values below:

    [2,2,2,2,2,2,2,2,2,2] (first set of 10 samples)
    [3,3,3,3,3,3,3,3,3,3] (second set of 10 samples)
    [4,4,4,4,4,4,4,4,4,4] (third set of 10 samples)

    is it lowpass 10 samples of data, followed by a delay of another 10 samples and then subtracting the two values?

    lowpass of first 10 samples = 2
    delay of another 10 samples (after the lowpass) [will skip the second set of samples, and take me to the third set of samples] = giving me 4
    then subtract 4-2 = 2?


    is it lowpass 10 samples of data while also delaying 10 samples, to then subtract the two values?

    lowpass of first 10 samples = 2
    delay of 10 samples starting at same starting point as the lowpass step = 3
    then subtract 3-2 = 1

    Likewise with the above code, when using the split().index() command for all three axis', will the values be retrieved in the individual split().index commands be done in parallel, similar to how it would be if retrieving the values all at once without splitting?

    is the values received from each

    .index(0).lowpass((byte)10) //[lets call this 3]
    .index(1).lowpass((byte)10) //[lets call this 4]
    .index(2).lowpass((byte)10) //[lets call this 5]

    the same as //[3,4,5]

    With regard to my above step #3
    how do i just multiple two results together to then be used, for instance i want to multiply the values "raw-z-lpf times raw-y-lpf", and then save it to be used later, can i add a name(""raw-z-lpf X raw-y-lpf") for it to be used later?

    With regard to my above step #4
    How do i perform a delay on the [x0 - lpf(x0...x9)] over 4 samples.
    i.e the value received from the above:

    .to().lowpass((byte) 10).name("x-lpf")
            .to().delay((byte)10).map(Function2.SUBTRACT, "x-lpf").name("raw-x-lpf")

    but now delayed over 4 samples

    Thank you so much

  • Rather than crunch numbers with your example, run the x-axis code yourself while streaming the raw, lpf, and raw-lpf values. You'll understand how things work faster than trying to think everything through on paper. Same thing for your other question, stream the values from each data route.

    You can simply chain another map element either chain raw-z-lpf or raw-y-lpf.

    You do the same thing with delaying the x-axis difference.

This discussion has been closed.