High-frequency measures with the Yocto-3D-V2

High-frequency measures with the Yocto-3D-V2

We regularly receive questions on how to obtain high frequency measures with the Yocto-3D and the Yocto-3D-V2. We already discussed the principle in a previous post, but to make your life easier, we prepared a concrete example.




Principle

The only truly efficient way to retrieve measures at a high frequency consists in configuring the module so that it spontaneously sends measures as soon as they are available through the callback function mechanism. No other method allows you to acquire measures at frequencies up to 100Hz with Yoctopuce modules.

Reading the orientation at 100Hz

The best understood manner to express orientation is in the shape of Tait-Bryan angles, coming from aeronautics, describing the orientation with regards to the North (yaw or head), the elevation (pitch), and the balance (roll) with three angles. These are the angles that you can obtain at lower frequencies respectively through the compass, tilt2, and tilt1 functions of the Yocto-3D and Yocto-3D-V2 modules.

To obtain them at a high frequency, you must process as follows:

  1. define 3 variables to store the current value of the angles:

    static double _roll;
    static double _pitch;
    static double _head;


  2. define the callback function called by the library as soon as necessary and which stores the received values into variables, so that they are available at any time:

    static void anglesCback(YGyro yGyro, double roll, double pitch, double head)
    {
        _roll = roll;
        _pitch = pitch;
        _head = head;
    }


  3. in the initialization code, when detecting the module, enable the callback:

    YGyro gyro = YGyro.FindGyro(deviceSerialNumber + ".gyro");
    gyro.registerAnglesCallback(anglesCback);


  4. in the application code, add a timer at the desired frequency (for example 100Hz) which calls the YAPI.HandleEvents() method, or a thread which calls YAPI.Sleep() in a loop. It's one of these calls which allows the triggering of the callbacks. For example, a graphical application could include the following code:

    private void RefreshTimer_Tick(object sender, EventArgs e)
    {
        string errmsg = "";
        YAPI.HandleEvents(ref errmsg);
        refreshUI();
    }


Reading the orientation as a quaternion at 100Hz

Although the expression of the orientation as angles is more intuitive, it has the disadvantage of presenting singularities toward both poles (when the module is vertical). To avoid these singularities, you must instead use a representation of the orientation as a quaternion. You can also configure a callback working on the quaternion rather than on the angles:

static void quaternionCback(YGyro yGyro, double w, double x, double y, double z)
{
    _w = w;
    _x = x;
    _y = y;
    _z = z;
}


And in the initialization code:

YGyro gyro = YGyro.FindGyro(deviceSerialNumber + ".gyro");
gyro.registerQuaternionCallback(quaternionCback);


Don't ask us to explain to you how to use quaternions, there are many sites on the Internet which will explain this much better than we could!

Reading 3D acceleration at 100Hz

For some applications, you might want to receive the coordinates of the acceleration vector at 100Hz. It's not possible with the Yocto-3D, but you can do it with the Yocto-3D-V2 if you agree to renounce to an estimate of the orientation.

To do so, you must perform some additional operations when configuring the module. First, you must assign the qt2, qt3, and qt4 functions to acceleration rather than to the representation of the quaternion. For obscure technical reasons, this is done through a change of logical name:

YQt qt2 = YQt.FindQt(deviceSerialNumber + ".qt2");
YQt qt3 = YQt.FindQt(deviceSerialNumber + ".qt3");
YQt qt4 = YQt.FindQt(deviceSerialNumber + ".qt4");
qt2.set_logicalName("ax");
qt3.set_logicalName("ay");
qt4.set_logicalName("az");


Then, you must configure the module to remove filtering on the accelerometer so that it returns the maximum of measures, even if they are somewhat noisy:

accelerometer = YAccelerometer.FindAccelerometer(deviceSerialNumber + ".accelerometer");
accelerometer.set_bandwidth(100);


You define a callback which receives the coordinates of the acceleration vector:

static void accelCback(YGyro yGyro, double w, double x, double y, double z)
{
    _ax = x;
    _ay = y;
    _az = z;
}


Finally, you enable this acceleration vector callback as if it were a quaternion, as it is through the Qt functions that the values are coming:

YGyro gyro = YGyro.FindGyro(deviceSerialNumber + ".gyro");
gyro.registerQuaternionCallback(accelCback);


A complete sample program

If you want to see what this looks like in real life, you can open the new example called Prog-3D-Callback in the C# library. It's a small graphical application which allows you to see the fluidity obtained by high-frequency callbacks, and to measure the number of different values received per second.

Sample program interface
Sample program interface



As a conclusion, let's remember that even if you can obtain these acceleration vector coordinates at 100Hz, the values are rather noisy and it is an illusion to think that you could integrate this vector to then estimate the speed: the cumulative noise won't converge. Therefore, it would be totally naive to imagine integrating this bad speed estimate to then compute a position estimate: it won't work!.

Add a comment No comment yet Back to blog












Yoctopuce, get your stuff connected.