Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

The standard typical file format for Motion Capture and experimental motion capture data in the biomechanics community is C3D. C3D is a flexible format that can store marker, forcesforce plate, forceplate, EMG, and event data. Despite being very flexible, data on in C3D files are stored as in binary format and require specialized readers to access. To read more information on the C3D file format, we encourage you to visit the C3D.org to learn more. 

From Starting with OpenSim 4.0, C3D reading and conversion into OpenSim formats are is available. Currently, use of C3D reading is limited to C++ and scripting and we will be working to make GUI support direct C3D reading native in the GUI in future releases. The easiest way of using to use OpenSim to read your C3D data is through the Matlab interface. Once you have setup OpenSim use in Matlab, you can read C3D files and write marker and force data to .trc and .mot file formats, easily

Starting with OpenSim 4.2, OpenSim defaults to using ezc3d (https://github.com/pyomeca/ezc3d) to parse c3d files.


Note

Prior to OpenSim version 4.2, C3DFileAdapter only supported reading Type-2 Force plates (AMTI & Bertec) and not Type-3 (Kistler), however this limitation has been lifted with the use of ezC3D in version 4.2 and moving forward. Please contact the support of ezc3d project above if you run into issues using it. 

Table of Contents
maxLevel2

Reading C3D files through Matlab

osimC3D

We have included a utility in Matlab side class that can be used to perform some common operations, such as rotating data, converting data into Matlab data types, and writing marker and force data to OpenSim file formatformats. The Matlab file can be found in your resources directory /Code/Matlab/Utilities/osimC3D.m. An example of using the osimC3D function is (in the expandable ) section below. Here In this example, we

  • read a C3D file containing markers and forces, 
  • get some information about the data (rate, number of markers, and number of forces), 
  • rotate the data, and 
  • then write the markers to a .trc file, and the forces to a .mot file. 

    Expand

...

Reading C3D files through Python and C++

Some example code for using C3DFileAdapter through Python can be found below. This code is part of a test script that runs the C3D reader and writes data marker and force data to a storage (.sto) file. 

...


  • Code Block
    languagejava
    titleExport C3D Matlab
        %% Load OpenSim libs
        import org.opensim.modeling.*
        
        %% Get the path to a C3D file
        [filename, path] = uigetfile('*.c3d');
        c3dpath = fullfile(path,filename);
        
       

...

  •  %% Construct an opensimC3D object with input c3d path
       

...

  •  

...

  • % Constructor takes full path to c3d file and an integer for forceplate
        % representation in output forces file (0 = 

...

  • electrical 

...

  • center, 

...

  • 1 

...

  • = 

...

  • COP). 
        c3d = osimC3D(c3dpath,useCenterOfPressureAsMomentsPoint);
        
        %% Get some stats...
        % Get 

...

  • the number of marker trajectories
        

...

  • nTrajectories = 

...

  • c3d.

...

  • getNumTrajectories();
        % Get the marker data rate
        rMakers = c3d.getRate_marker();
        % Get the number of forces 
        

...

  • nForces = 

...

  • c3d.getNumForces();
        % Get the force data rate
        

...

  • rForces = 

...

  • c3d.getRate_force();
        
        % Get Start and end time
        

...

  • t0 = 

...

  • c3d.

...

  • getStartTime();
        tn = c3d.getEndTime();
        
        %% Rotate the data 
        c3d.rotateData('x',-90)
        
        %% Get the c3d in different forms
    

...

  •  

...

  •  

...

  •  

...

  •  

...

  • % 

...

  • Get OpenSim tables
        markerTable = c3d.getTable_markers();
        forceTable =

...

  •  c3d.getTable_forces();
        % Get as Matlab Structures
        [markerStruct forceStruct] = c3d.getAsStructs();
        
        %% Convert COP (mm to m) and Moments 

...

  • (Nmm to Nm)
        if convertLengthUnits
          

...

  •  

...

  •  

...

  • c3d.

...

  • convertMillimeters2Meters();
        end
        
        %% 

...

  • Write 

...

  • the 

...

  • marker 

...

  • and 

...

  • force data

...

  •  to file
        % Define output file names
        basename = strtok(filename,'.');
        markersFilename = strcat(basename,'_markers.

...

  • trc');
        
        switch useCenterOfPressureAsMomentsPoint
     

...

  •  

...

  •  

...

  •      case 0
      

...

  •  

...

  •          

...

  • forcesFilename = 

...

  • strcat(basename,'_forces_EC.mot');
            case 1
             

...

  •  

...

  •  

...

  •  

...

  • forcesFilename 

...

  • = strcat(basename,'_forces_COP.mot');
        end
        
     

...

  •   

...

  •  % Write marker data to trc file.
      

...

  •  

...

  •  

...

  • c3d.

...

  • writeTRC(

...

  • markersFilename);
        
       

...

  •  

...

  • % Write force data to mot file.
       

...

  •  

...

  • c3d.

...

  • writeMOT(

...

  • forcesFilename);
    
    



Reading C3D files through Python and C++

Some example code for using C3DFileAdapter through Python can be found below. This code is part of a test script that runs the C3D reader and writes data marker and force data to a storage (.sto) file. 

Expand


Code Block
tables = C3DFileAdapter.readFile(os.path.join(test_dir, 'walking2.c3d'), 1)
markers = tables['markers']
forces   = tables['forces']
 
# FlattenMarker forcesdata data.read from C3D.
markers = tables['markers']
   forcesFlat = forces.flatten() 
# Flatten marker data.
markersFlat = markers.flatten()
      
# Make sure flattenned forcesmarker data is writable/readable to/from file.
markersFilename = 'markers.sto'
stoAdapter = osim.STOFileAdapter()
stoAdapter.write(markersFlat, markersFilename)
markersDouble = stoAdapter.read(markersFilename)
      
# Forces data read from C3d.
forcesFilenameforces = tables['forces.sto']
fpCalMats = forces.getTableMetaDataVectorMatrix("CalibrationMatrices")
fpCorners = forces.getTableMetaDataVectorMatrix("Corners")
fpOrigins = stoAdapterforces.write(forcesFlat, forcesFilename)getTableMetaDataVectorMatrix("Origins")
      
# Flatten forces data.
forcesDoubleforcesFlat = stoAdapterforces.readflatten(forcesFilename)
      
# Make sure flattenned forces data is  # Clean upwritable/readable to/from file.
forcesFilename = 'forces.sto'
stoAdapter.write(forcesFlat, forcesFilename)
forcesDouble =  osstoAdapter.removeread(markersFilenameforcesFilename)
      
# Clean up.
os.remove(markersFilename)
os.remove(forcesFilename)


...

Example code for using the C3DFileAdapter in C++ is found below. This code is part of a test script that runs the C3D reader and checks for correct valueswrites the resulting tables to files

OpenSim 4.4

Expand


Code Block
languagecpp
titleUse C3DFileAdapter
    using namespace OpenSim;
    using namespace std;
    
    C3DFileAdapter c3dFileAdapter{};
    auto tables = c3dFileAdapter.read(filename);
    std::shared_ptr<TimeSeriesTableVec3> marker_table = c3dFileAdapter.getMarkersTable(tables);
    std::shared_ptr<TimeSeriesTableVec3> force_table = c3dFileAdapter.getForcesTable(tables);
    std::shared_ptr<TimeSeriesTable> analog_table = c3dFileAdapter.getAnalogDataTable(tables);
    const std::string marker_file = base + "_markers.trc";
    const std::string forces_file = base + "_grfs.sto";
    const std::string analogs_file = base + "_analog.sto";

    TRCFileAdapter trc_adapter{};
    trc_adapter.write(*marker_table, marker_file);
    force_table->updTableMetaData().setValueForKey("Units", 
                                                    std::string{"mm"});
    STOFileAdapter sto_adapter{};
    sto_adapter.write((force_table->flatten()), forces_file);
    sto_adapter.write(*analog_table, analogs_file);





Importing Force Data:  COP and NaNs

When you import your force data, you can use the origin of the force plate or center of pressure (COP) to express the forces. The C3DFileAdapter includes an input parameter (ForceLocation) that allows you to choose OriginOfForcePlate or CenterOfPressure. Using the COP is helpful for visualization, but can lead to NaN values. In particular, when the force values go to zero, the COP value is undefined (NaN). This is problematic during Inverse Dynamics analysis as you will get all NaN values for the output moments. This is because OpenSim splines the force and COP data before computing joint moments and the splines are undefined in the presence of NaNs for your input data. If you find that your mot files are containing NaNs for COPs after conversion, you can use the OriginOfForcePlate flag when you import your C3D data. 


Panel
borderColorgray
bgColorwhite
borderWidth5
borderStylesolid

Next: Tools for Preparing Motion Data 

Previous: Storage (.sto) Files

Home: Preparing Your Data

 

 

 

 

 

...