Difference between revisions of "Motive Batch Processor"

Line 49: Line 49:
 
The Motive Batch Processor can run C# and IronPython scripts. Below is an overview of the C# script format, as well as an example script.
 
The Motive Batch Processor can run C# and IronPython scripts. Below is an overview of the C# script format, as well as an example script.
  
{{Indent|
+
<div style="padding-left:3em;">
 
==C# Script Format==
 
==C# Script Format==
{{Indent|
+
<div style="padding-left:3em;">
 
A valid Batch Processor C# script file must contain a single class implementing the <code>ItakeProcessingScript</code> interface. This interface defines a single function:
 
A valid Batch Processor C# script file must contain a single class implementing the <code>ItakeProcessingScript</code> interface. This interface defines a single function:
  
Line 71: Line 71:
 
       }
 
       }
 
   }</nowiki>
 
   }</nowiki>
}}
+
</div>
  
 
==C# Example==
 
==C# Example==
{{Indent|
+
<div style="padding-left:3em;">
The following is an example of a C# Batch Processor script that exports a take to C3D format.
+
In the <code>[Motive Directory]\MotiveBatchProcessor\ExampleScripts\</code> folder, there are multiple C# (.cs) sample scripts that demonstrate the use of the NMotive for processing various different pipelines including tracking data export and other post-processing tools. Note that your C# script file must have a '.cs' extension.
<nowiki>
+
  using System;
+
  using NMotive;
+
  using System.IO;
+
  
  public class C3DExportScript : ItakeProcessingScript
 
  {
 
      public Result ProcessTake(Take t, ProgressIndicator progress)
 
      {
 
        // Create the name of the C3D file. The name will be the same as the
 
        // take file name, but with a .c3d extension.
 
        string c3dFileName = 
 
            Path.GetFullPath(Path.GetFileNameWithoutExtension(t.FileName) + ".c3d");
 
  
        // Create the C3D exporter object (from the NMotive class library)
+
<div class="mw-collapsible mw-collapsed" style="background-color:#f9ffe5; border-style: dotted; border-width: 1px; padding: 1em">
         // and ensure that the exported 3D data uses MotionBuilder
+
'''Batch Processor Script C# Sample (ExporterScript-C3D.cs): Exporting a take to C3D format.'''
         // compatible axes.
+
----
         C3DExporter exporter = new C3DExporter();
+
<div class="mw-collapsible-content">
         exporter.SetAxisMotionBuilderCompatible();
+
<nowiki>
 
+
using System;
        // Finally perform the export and return the result of the result of the
+
using System.IO;
         // export. The last argument to the Export function is a bool indicating
+
using NMotive;
         // whether or not we wish to overwrite any existing file. True means
+
         // overwrite it if it already exists.
+
/// <summary>
        Result exportResult = exporter.Export(t, c3dFileName, true);
+
/// Motive Batch Processor script for exporting a take file to C3D format.
        return exportResult;
+
/// </summary>
      }
+
public class C3DExportScript : ITakeProcessingScript
  }</nowiki>
+
{
Note that your C# script file must have a '.cs' extension.}}
+
    /// <summary>
}}
+
    /// The <c>ProcessTake</c> function is from the <c>ITakeProcessingScript</c> interface.
 +
    /// Exports the given take to C3D format. The exported file is in the same
 +
    /// directory as the take file, and has the same name, but with a '.c3d' file extension.
 +
    /// </summary>
 +
    /// <param name="take">The take to export.</param>
 +
    /// <param name="progress">Progress indicator object.</param>
 +
    /// <returns>The result of the export process.</returns>
 +
public Result ProcessTake(Take take, ProgressIndicator progress)
 +
{
 +
         // Construct an NMotive C3D exporter object with the desired
 +
         // options. We will write C3D data for markers and assets.
 +
         C3DExporter exporter = new C3DExporter
 +
         {
 +
//-== C3DExporter Class ==-
 +
          ColonNameSeparator = false,
 +
RenameUnlabeledMarkers = false,
 +
Units = LengthUnits.Units_Centimeters,
 +
UseTimeCode = true,
 +
UseZeroBasedFrameIndex = true,
 +
WriteFingerTipMarkers = false,
 +
WriteUnlabeledMarkers = false,
 +
XAxis = Axis.Axis_NegativeX, // Axis_PositiveX, Axis_NegativeX
 +
YAxis = Axis.Axis_PositiveZ, // Axis_PositiveY, Axis_NegativeY
 +
ZAxis = Axis.Axis_PositiveY // Axis_PositiveZ, Axis_NegativeZ
 +
 +
        };
 +
       
 +
         // Construct the output C3D file. The output file will be co-located with the
 +
         // take file and have the same name as the take file, but with a '.c3d' extension.
 +
string outputFileName = Path.GetFileNameWithoutExtension(take.FileName) + ".c3d";
 +
string outputDirectory = Path.GetDirectoryName(take.FileName);
 +
string outputFile = Path.Combine(outputDirectory, outputFileName);
 +
 +
         // Do the export and return the Export functions result object.
 +
progress.SetMessage("Writing to File");
 +
progress.SetProgress( (float)0.1 );
 +
return exporter.Export(take, outputFile, true);
 +
}
 +
}</nowiki>
 +
</div></div>
 +
</div>
 +
</div>
  
  
Line 114: Line 143:
 
[http://ironpython.net IronPython] is an implementation of the Python programming language that can use the .NET libraries and Python libraries. The batch processor can execute valid IronPython scripts in addition to C# scripts.
 
[http://ironpython.net IronPython] is an implementation of the Python programming language that can use the .NET libraries and Python libraries. The batch processor can execute valid IronPython scripts in addition to C# scripts.
  
{{Indent|
+
<div style="padding-left:3em;">
 
==IronPython Script Format==
 
==IronPython Script Format==
{{Indent|
+
<div style="padding-left:3em;">
 
Your IronPython script file must import the clr module and reference the NMotive assembly. In addition, it must contain the following function:
 
Your IronPython script file must import the clr module and reference the NMotive assembly. In addition, it must contain the following function:
  
Line 140: Line 169:
 
       .
 
       .
 
       .
 
       .
       # return result object</nowiki>}}
+
       # return result object</nowiki>
 +
</div>
  
 
==IronPython Script Example==
 
==IronPython Script Example==
{{Indent|
+
 
The following is an example IronPython Batch Processor script that first performs a trim tails operation followed by a filtering/smoothing operation. If both operations succeed, the resulting take is saved.
+
<div style="padding-left:3em;">
 +
<div class="mw-collapsible mw-collapsed" style="background-color:#f9ffe5; border-style: dotted; border-width: 1px; padding: 1em">
 +
'''Batch Processor Script IronPython Sample (TrimAndFilter.py): The following script performs a trim tails operation followed by a filtering/smoothing operation. If both operations succeed, the resulting take is saved.'''
 +
----
 +
<div class="mw-collapsible-content">
 
  <nowiki>
 
  <nowiki>
  import sys
+
import sys
  import clr
+
import clr
 +
 +
 +
# Add a reference to the NMotive assembly
 +
clr.AddReference("NMotive")
 +
 +
from System import *
 +
# Import everything from NMotive.
 +
from NMotive import *
 +
 +
 +
def ProcessTake(take, progress):
 +
    # Set the message to be displayed next to to the progress bar in the
 +
    # Motive Batch Processor UI.
 +
    progress.SetMessage('Triming tails...')
  
  # Add a reference to the NMotive assembly
+
    # Create an NMotive TrimTails object to perform the tail trimming operation.
  clr.AddReference("NMotive")
+
    tailTrimming = TrimTails()
  
  # Import everything from System and NMotive.
+
    # pass the progress object to the trim tails object. It will update
  from System import *
+
    # progress that will be rendered in the UI.
  from NMotive import *
+
    tailTrimming.Progress = progress
  
  # Define out ProcessTake function
+
    # Set trail trimming options.
  def ProcessTake(take, progress):
+
    tailTrimming.Automatic = True
      # Messages set with the ProgressIndicator SetMessage
+
    tailTrimming.LeadingTrimSize = 4
      # function appear on the batch processor UI below the
+
    tailTrimming.TrailingTrimSize = 4
      # status bar.
+
      progress.SetMessage('Triming tails...')
+
      # Create an NMotive TrimTails object, set desired
+
      # properties and apply the trimming operation by
+
      # invoking the Process function.
+
      tailTrimming = TrimTails()
+
      tailTrimming.Automatic = True
+
      tailTrimming.LeadingTrimSize = 4
+
      tailTrimming.TrailingTrimSize = 4
+
      trimResult = tailTrimming.Process(take)
+
      # If the trimming operation did not succeed we
+
      # do not continue with filtering and saving the
+
      # take file. We just exit the function by returning
+
      # the result of the trimming operation.
+
      if not trimResult.Success:
+
        return trimResult
+
   
+
      # Now apply the filter.
+
      progress.SetMessage('Filtering...')
+
      filtering = Filter()
+
      filtering.CutOffFrequency = 8 # Hz
+
      filteringResult = filtering.Process(take)
+
  
      # If filtering fails do not save the take. Just return.
+
    # And execute the trimming process.
      if not filteringResult.Success:
+
    trimResult = tailTrimming.Process(take)
        return filteringResult
+
  
      # trimming and filtering operations are successful. Save
+
    # If trimming failed for some reason the Success field of the returned
      # the take file and return the result of the file save.
+
    # NMotive Result object will be false and the Message field will contain
      fileSaveResult = take.Save()
+
    # information about the failure. The Message field of the returned Result
      if fileSaveResult != FileResult.ResultOK:
+
    # object will be displayed in the UI.  
        return Result(false, 'File save failed')
+
    if not trimResult.Success: # If trimming failed, return without saving the take.
 +
      return trimResult
 +
 
 +
    # Starting the filtering process...
 +
    progress.SetMessage('Filtering...')
  
      return Result(true, '')</nowiki>}}
+
    # Create the NMotive filter object.
}}
+
    filtering = Filter()
  
 +
    # We are going to use the progress bar to display the progress of each
 +
    # individual operation, so reset the progress bar to zero and pass the
 +
    # the progress object to the filtering object.
 +
    progress.SetProgress(0)
 +
    filtering.Progress = progress
 +
 +
    # Set the cutoff frequency and filter.
 +
    filtering.CutOffFrequency = 8 # Hz
 +
    filteringResult = filtering.Process(take)
 +
    if not filteringResult.Success: # If filtering failed, return without saving the take.
 +
    return filteringResult
 +
 +
    # If we get here trimming and filtering succeeded. Save the take file.
 +
    progress.SetMessage('Saving take...')
 +
    fileSaveResult = take.Save()
 +
    if fileSaveResult != FileResult.ResultOK:
 +
    return Result(False, 'File save failed')
 +
   
 +
    return Result(True, '')
 +
</nowiki>
 +
</div></div></div>
 +
</div>
 +
 +
 +
----
 
'''[[#top|Back to Top]]'''
 
'''[[#top|Back to Top]]'''

Revision as of 18:20, 21 November 2016

Back to the Main PageBack to Motive Documentation

Introduction



  • MotiveBatch.png
  • Motive Batch Processor

The Motive Batch Processor is a separate stand-alone Windows application, built on the new NMotive scripting and programming API, that can be utilized to process a set of Motive Take files via IronPython or C# scripts. While the Batch Processor includes some example script files, it is primarily designed to utilize user-authored scripts. Motive Batch Processor can also be launched from the Project pane toolbar.

Initial functionality includes scripting access to file I/O, trajectorization, high-level Take processing using many of Motive's existing editing tools, and data export. Upcoming versions will provide access to track, channel, and frame-level information, for creating cleanup and labeling tools based on individual marker reconstruction data.

Motive Batch Processor Scripts make use of the NMotive .NET class library, and you can also utilize the NMotive classes to write .NET programs and IronPython scripts that run outside of this application. The NMotive assembly is installed in the Global Assembly Cache and also located in the assemblies sub-directory of the Motive install directory. For example, the default location for the assembly included in the 64-bit Motive installer is:


C:\Program Files\OptiTrack\Motive\assemblies\x64

The full source code for the Motive Batch Processor is also installed with Motive, at:

C:\Program Files\OptiTrack\Motive\MotiveBatchProcessor\src


You are welcome to use the source code as a starting point to build your own applications on the NMotive framework.


Class Reference



Motive Batch Processor

A class reference in Microsoft compiled HTML (.chm) format can be found in the Help sub-directory of the Motive install directory. The default location for the help file (in the 64-bit Motive installer) is:

C:\Program Files\OptiTrack\Motive\Help\NMotiveAPI.chm



C# Scripts



The Motive Batch Processor can run C# and IronPython scripts. Below is an overview of the C# script format, as well as an example script.

C# Script Format

A valid Batch Processor C# script file must contain a single class implementing the ItakeProcessingScript interface. This interface defines a single function:

Result ProcessTake( Take t, ProgressIndicator progress ).

Result, Take, and ProgressIndicator are all classes defined in the NMotive namespace. The Take object t is an instance of the NMotive Take class. It is the take being processed. The progress object is an instance of the NMotive ProgressIndicator and allows the script to update the Batch Processor UI with progress and messages. The general format of a Batch Processor C# script is:

   using NMotive;
   // any other using statements
   public class MyCSharpScript : ITakeProcessingScript
   {
      public Result ProcessTake(Take t, ProgressIndicator progress)
      {
         Result scriptResult;
         // Script processing code here
         progress.SetMessage(“Done processing take “ + t.Name);
         progress.SetProgress( 100 );
         return scriptResult;
      }
   }

C# Example

In the [Motive Directory]\MotiveBatchProcessor\ExampleScripts\ folder, there are multiple C# (.cs) sample scripts that demonstrate the use of the NMotive for processing various different pipelines including tracking data export and other post-processing tools. Note that your C# script file must have a '.cs' extension.


Batch Processor Script C# Sample (ExporterScript-C3D.cs): Exporting a take to C3D format.


 using System;
 using System.IO;
 using NMotive;
 
 /// <summary>
 /// Motive Batch Processor script for exporting a take file to C3D format.
 /// </summary>
 public class C3DExportScript : ITakeProcessingScript
 {
     /// <summary>
     /// The <c>ProcessTake</c> function is from the <c>ITakeProcessingScript</c> interface.
     /// Exports the given take to C3D format. The exported file is in the same 
     /// directory as the take file, and has the same name, but with a '.c3d' file extension.
     /// </summary>
     /// <param name="take">The take to export.</param>
     /// <param name="progress">Progress indicator object.</param>
     /// <returns>The result of the export process.</returns>
 	public Result ProcessTake(Take take, ProgressIndicator progress)
 	{
         // Construct an NMotive C3D exporter object with the desired
         // options. We will write C3D data for markers and assets.
         C3DExporter exporter = new C3DExporter
         {
 			//-== C3DExporter Class ==-
          		ColonNameSeparator = false,
 			RenameUnlabeledMarkers = false,
 			Units = LengthUnits.Units_Centimeters,
 			UseTimeCode = true,
 			UseZeroBasedFrameIndex = true,
 			WriteFingerTipMarkers = false,
 			WriteUnlabeledMarkers = false,
 			XAxis = Axis.Axis_NegativeX,		// Axis_PositiveX, Axis_NegativeX
 			YAxis = Axis.Axis_PositiveZ,		// Axis_PositiveY, Axis_NegativeY
 			ZAxis = Axis.Axis_PositiveY		// Axis_PositiveZ, Axis_NegativeZ
 			
         };
         
         // Construct the output C3D file. The output file will be co-located with the
         // take file and have the same name as the take file, but with a '.c3d' extension.
 		string outputFileName = Path.GetFileNameWithoutExtension(take.FileName) + ".c3d";
 		string outputDirectory = Path.GetDirectoryName(take.FileName);
 		string outputFile = Path.Combine(outputDirectory, outputFileName);
 
         // Do the export and return the Export functions result object.
 		progress.SetMessage("Writing to File");
 		progress.SetProgress( (float)0.1 );
 		return exporter.Export(take, outputFile, true);
 	}
 }


IronPython Scripts



IronPython is an implementation of the Python programming language that can use the .NET libraries and Python libraries. The batch processor can execute valid IronPython scripts in addition to C# scripts.

IronPython Script Format

Your IronPython script file must import the clr module and reference the NMotive assembly. In addition, it must contain the following function:

def ProcessTake(Take t, ProgressIndicator progress)

The following illustrates a typical IronPython script format.

   #import sys and clr modules
   import sys
   import clr

   # Add a reference to the NMotive assembly
   clr.AddReference("NMotive")
   # Import everything from sys and NMotive.
   from System import *
   from NMotive import *

   # Define the ProcessTake function.
   def ProcessTake(take, progress):
      # Take processing code here
      .
      .
      .
      # return result object

IronPython Script Example

Batch Processor Script IronPython Sample (TrimAndFilter.py): The following script performs a trim tails operation followed by a filtering/smoothing operation. If both operations succeed, the resulting take is saved.


 import sys
 import clr
 
 
 # Add a reference to the NMotive assembly
 clr.AddReference("NMotive")
 
 from System import *
 # Import everything from NMotive.
 from NMotive import *
 
 
 def ProcessTake(take, progress):
    # Set the message to be displayed next to to the progress bar in the 
    # Motive Batch Processor UI. 
    progress.SetMessage('Triming tails...')

    # Create an NMotive TrimTails object to perform the tail trimming operation.
    tailTrimming = TrimTails()

    # pass the progress object to the trim tails object. It will update 
    # progress that will be rendered in the UI.
    tailTrimming.Progress = progress

    # Set trail trimming options.
    tailTrimming.Automatic = True
    tailTrimming.LeadingTrimSize = 4
    tailTrimming.TrailingTrimSize = 4

    # And execute the trimming process.
    trimResult = tailTrimming.Process(take)

    # If trimming failed for some reason the Success field of the returned
    # NMotive Result object will be false and the Message field will contain
    # information about the failure. The Message field of the returned Result
    # object will be displayed in the UI. 
    if not trimResult.Success: # If trimming failed, return without saving the take.
       return trimResult
   
    # Starting the filtering process...
    progress.SetMessage('Filtering...')

    # Create the NMotive filter object.
    filtering = Filter()

    # We are going to use the progress bar to display the progress of each 
    # individual operation, so reset the progress bar to zero and pass the
    # the progress object to the filtering object.
    progress.SetProgress(0)
    filtering.Progress = progress

    # Set the cutoff frequency and filter.
    filtering.CutOffFrequency = 8 # Hz
    filteringResult = filtering.Process(take)
    if not filteringResult.Success: # If filtering failed, return without saving the take.
    	return filteringResult
 
    # If we get here trimming and filtering succeeded. Save the take file.
    progress.SetMessage('Saving take...')
    fileSaveResult = take.Save()
    if fileSaveResult != FileResult.ResultOK:
    	return Result(False, 'File save failed')
    
    return Result(True, '')
 



Back to Top