opensim-org / opensim-core

SimTK OpenSim C++ libraries and command-line applications, and Java/Python wrapping.
https://opensim.stanford.edu
Apache License 2.0
800 stars 323 forks source link

IMU (Xsens) Data Collection and Processing Improvements #3956

Open alexbeattie42 opened 3 weeks ago

alexbeattie42 commented 3 weeks ago

Background & Research

The XsensDataReader was introduced on March 7, 2019 (over 5 years ago) and is a great feature and part of many peoples workflow.

It is even a requested feature in an OpenSim Creator discussion. Unfortunately the feature does not appear to be very well known and understood which has lead to the proliferation of projects and code which duplicate it.

Duplicate Functionality

In a quick search, I have found at least 2 projects which have been recently developed with functionality to achieve exactly the same end result.

XsensDot2Mtw4OpenSense converts Xsens capture data to an OpenSim format.

C3dtools convert Xsens and APDM IMU data into an OpenSim format and includes a video tutorial. This article references that code.

Additionally the OpenSim wiki page Tools for Preparing Motion Data lists 12 different options for pre-processing data, some of which can be used to process IMU data.

I did find a project which consumes the python version of the OpenSense tooling for this task.

Additionally there are many more implementations which we will never know about that exist in the private domain or on various research servers.

Similar Problems

Many people struggle with converting raw IMU capture data to a format that is useable in an OpenSim simulation. It is my understanding that this is the problem that OpenSense was introduced to solve.

There is a related issue discussion Xsens quaternion discrepancies

Xsens MT Manager Software

Although this is not an OpenSim problem it is beneficial to understand the context in which the data comes from. This software is used to export the binary .mtb IMU collection data into a .txt file that can be used by the XsensDataReader.

MT Manager End of Life 💔

Movella purchased Xsens and has made an official notice that the 2022.2 version of MT manager will be the last.

Date: February, 2024

The MT Manager Software Suite 2022.2 is the current version that supports the DOT Pro/MTw2 Awinda, it contains many bug fixes and improvements compared to the previous stable version, MT Manager Software Suite 4.6. Given the excellent quality and stability of both the MT Manager Software Suite 2022.2 and DOT Pro/MTw2 Awinda hardware, the current versions are expected to remain the latest version in the foreseeable future. At this time there are no future releases planned for MT Manager Software Suite which supports the DOT Pro/MTw2 Awinda hardware.

MT Manager Software Releases

The following articles describe how to download and install this release.

Determining Sampling Frequency

The current version of the software introduces a bug (or maybe a feature in their eyes) where they have altogether removed the ability to determine the output frequency of the measurements. This is substantiated by the following movella forum post employee response:

Unfortunately, the sample frequency information is not available within the mtb file. however, if you open the mtb file in the MT manager software and play the file, in the right corner you find the duration of the file and the frames. by dividing the frames through the time you can calculate the sample frequency

In our research group we have tested the different versions of MT Manager: the current 2022.2.0 and the legacy version 4.6.0. Using the exact same .mtb file and the suggested method for calculating frequency on two different samples has yielded a +/- 5-10 Hz difference between the two software versions.

Using version 4.6.0 the sampling rate can be accurately calculated at 60 Hz and 100 Hz for the two files we tested (which matches the known sampling rate they were collected at). The new version of the software calculated 65 Hz and 107.8 Hz respectively. The legacy software also outputs the sampling rate in the header of the .txt files whereas the new one does not.

This means that with the current software release (which will not receive any more updates), it is not possible to accurately back calculate the measurement frequency from a data file if it was not recorded or known beforehand.

Additionally per the MT Manager User Manual

With Set current, the current time (in UTC format) is retrieved from the computer and written into the RAM of the MTi. When recording, the data will now include the time. Note that the time is discarded after a rescan, power off or revert.

The timing data which could have been used to back calculate the frequency by subtracting the starting clock time from the ending clock time is thrown away in the data file and not recoverable.

APDM users also seem to have related issues with sampling frequency.

Problems

There are many parsing assumptions made by the XsensDataReader which are not documented outside of source code or contained in walkthrough/wiki guides. The most important are described below

Insufficient documentation for the "Happy Path"

The OpenSense Workflow Documentation describes some of the intended "Happy Path" for OpenSense but does not specify how you must export the data from MT Manager into a format that OpenSense can understand. The documentation states:

We currently assume that sensor fusion and syncing have been performed using a vendor’s or third-party algorithm. Several open-source sensor fusion algorithms are also available on GitHub.

This is in contradiction with the functionality that is actually provided and even the previous sentence in the walkthrough.

Deep within this Confluence wiki page under "Import options for OpenSense", the following can be found.

A. OpenSense requires IMU orientations expressed as quaternions as input into the tools, so sensor fusion must be performed before importing data. We provide import tools for Xsens and APDM systems through our API (C++, MATLAB, and Python) to create an OpenSim storage file, and we have an OpenSense MATLAB example that shows this step with Xsens data. For other IMUs or if you want to use different sensor fusion algorithms, users can create custom import tools by matching the format in any example files provided with OpenSense.

This is a helpful clue but it does not provide concrete instructions on how to use the tool. This leads most people to infer that the functionality does not exist and they therefore create their own. These elements may explain the many duplicate implementations of the same parsing code.

Additionally there is not a plug-and-play full process example to use the entire OpenSense workflow in C++ (though I am hoping to put one together).

Parsing Assumption: File will be Tab Separated

On the SimTK forum this post describes a problem converting Xsens data to OpenSim caused by a mysterious "Table is missing a metaheader," error that is thrown here.

Unfortunately the error is not in the header, which makes it a misleading error message. I ran into this problem and it is caused by this line of code which expects that a "tab" is used when exporting from the MT Manager software. If a "comma" or any other separator is used instead of "tab" it creates this error.

Parsing Assumption: Rotation Matrix Exported

In this section of code, it is assumed that the Xsens data has a rotation matrix exported. It is trivial to change the export option if you have access to the original .mtb file of the data collection but this is often not the case. The MT Manager software can also export the rotation data as quaternions or euler angles.

Parsing Assumption: Default Data Rate (Sampling Frequency)

The Xsens parser initially tries to extract the sampling rate from the header (which isn't present with exports from the new software). If it cannot find the header, it silently sets the data rate to 40 Hz here.

Parsing Assumption: Path Separator Configuration Required

When using the data_folder configuration option it is required to handle the path separator in consuming code. This can be problematic due to path separation differences across platforms.

Solution Proposal

  1. Add a configuration option to XSensDataReaderSettings to specify a known data rate (sampling frequency). Given that the new Xsens software cannot accurately determine or report the sampling frequency, it is important that the user be able to specify the sampling frequency in the configuration. An alternative to this could be to add the expected header to every single IMU file but that would require a separate processing script. It would be much simpler to have a configuration option that implies: "Use this sampling frequency because I know it's correct". Additionally, if a sample frequency cannot be determined I would prefer the program to throw an exception instead of default to 40 Hz, or at least log a warning that it could not be determined and is using a default value. If the default behavior is to be kept it would be nice to have it living in the settings file instead of set within the consuming code.

  2. Add a configuration option to XSensDataReaderSettings to specify a custom separator. Maintain the default as "tab" if unspecified. This also requires defining what is accepted and what is not. For example tab should be specified as \t and not a tab literal. Defining what the separator for space should be also seems to not have a definitive answer but it seems most are saying to simply define it as ' '.

  3. Add the ability to read in either a Rotation Matrix or Quaternion values (also possibly Euler angles but it seems best to leave that alone for now because of the complexity it introduces) from Xsens files. This would need a configuration option to specify if both are provided which one to use.

  4. Update the parser to handle the path separator for data_folder. Ideally it would behave in a way that data_folder is known to be a directory and the trailing path separator is handled by the parser using something like std::filesystem::path. This was was introduced in C++17 and OpenSim is currently using C++14 so it wouldn't be possible to use this option without upgrading to C++17.

  5. Add an official simplest "happy path" example (with updated documentation) of an entire roundtrip of the OpenSense journey from raw data to calibration to inverse kinematics being done in C++. This ideally would make it incredibly apparent what the feature does, what problem it solves, and the minimal reproduction required to use it.

I am happy to create a pull request with some of the proposed changes if you would find it helpful.

Reproduction & Testing

This repository contains an example IMUXsense to test the IMU processing I'm discussing. There is also a screenshot which shows the settings required to export the Xsens data into a format that OpenSim can use in the XsensDataReader class as it currently stands. There are also unit tests within the OpenSim repository itself.