8 Replies Latest reply on Nov 25, 2018 1:31 PM by Amen Allah Jlili

    How to retrieve data from Motion Studies

    Taus Moller

      I am attempting to use the api to run and retrieve data from motion studies with very little success. I have tried retrieving data both through sensors and through plots set up in the study. The sensor seems to be non functioning and always return 0 through the API even though it updates fine in Solidworks. When attempting to retrieve data from the plots i have very mixed success with retrieving x-valuess and RuntimeBinderExceptions when running trying to retrieve y-values 


      To demonstrate what i tried and what is happening i created a small example. Since Macro support for C# is apparently in pretty bad shape in 2017 i have created a small Add-in that basically just contains two buttons that can run a piece of C# code


      In the attached zip file is a visual studio project and a Solidworks assembly to test with. In order to recreate the issues:


      1. Open the solution in Visual studio 2015.

      2. in the project references, make sure that all references to solidworks.interop dll resolves correctly to 2017 dll files.

      3. Right click the MinimalExampleAddIn and go to properties.

      4. In the debug tab, make sure "Start external program" is selected and points to the sldworks.exe for Solidworks 2017

      5. Find the method "Macro1()" in SwAddin.cs and set a break point at the beginning.

      6. Build and run the solution in debug mode

      7. Open Valve_cam.sldasm located in the "support file" directory

      8. Make sure to enable both SOLIDWORKS Motion and SOLIDWORKS Simulation as well as the "Minimal Example" Addin

      9. In the "Minimal Example Command Manager click the "Run Macro 1" button.


      You should now hit the break point set in the Macro1 method. Here is my attempts at retrieving data from a motion analysis. Both through the sensor and the Plots. Neither

      Method has been succesful.


      The sensor simply returns 0 even though its return value indicated that the retrieval was succesful.


      I am a bit unsure whether my approach for getting data out of the plots is correct. The documentation is a bit confusing, and the only example available seem to create the axes right before they are used. There seems to be no example on how to get data from an existing plot. On these lines:


      double[] xs = output.GetXAxis();


      double[] ys = output.GetYAxis(yaxis);


      xs becomes null and output.GetYAxis(yaxis); throws a RuntimeBinderException with the message: "Additional information: Cannot implicitly convert type 'System.DBNull' to 'double[]'"


      For the second macro i tried using DispatchWrapper since one of the examples in the documentation uses this. However, this did not help.


      Any information on how to retrieve data from a motion study will be greatly appreciated!

        • Re: How to retrieve data from Motion Studies
          Amen Allah Jlili

          Have you thought about taking a look at the API example?

          This example shows how to get a COSMOSMotion motion study's properties and results.
          ' Preconditions: Model is open that has a COSMOSMotion motion study
          '                named PhysSim and at least one COSMOSMotion motion study plot.
          ' Postconditions: None
          Option Explicit
          Dim swApp As SldWorks.SldWorks
          Dim swModel As SldWorks.ModelDoc2
          Dim swModelDocExt As SldWorks.ModelDocExtension
          Dim swMotionMgr As SwMotionStudy.MotionStudyManager
          Dim swMotionStudy1 As SwMotionStudy.MotionStudy
          Dim swResults As SwMotionStudy.MotionStudyResults
          Dim swMotionStudyProps As SwMotionStudy.MotionStudyProperties
          Dim swCosmosMotionStudyProps As SwMotionStudy.CosmosMotionStudyProperties
          Dim swCosmosMotionStudyResults As SwMotionStudy.CosmosMotionStudyResults
          Sub main()
              Set swApp = Application.SldWorks
              Set swModel = swApp.ActiveDoc
              Set swModelDocExt = swModel.Extension
              ' Get the MotionManager.
              Set swMotionMgr = swModelDocExt.GetMotionStudyManager()
              If (swMotionMgr Is Nothing) Then
              End If
              ' Get motion study named PhysSim.
              Set swMotionStudy1 = swMotionMgr.GetMotionStudy("PhysSim")
              If (swMotionStudy1 Is Nothing) Then
                  MsgBox "PhysSim is not available."
              End If
              swMotionStudy1.StudyType = swMotionStudyType_e.swMotionStudyTypePhysicalSimulation
              'Is the motion study active?  If not, activate it.
              If Not swMotionStudy1.IsActive Then swMotionStudy1.Activate
              Debug.Print "Duration of motion study: " & swMotionStudy1.GetDuration
              Debug.Print "Timebar position on timeline: " & swMotionStudy1.GetTime
              Debug.Print "Number of motion features: " & swMotionStudy1.GetMotionFeaturesCount
              'Get COSMOSMotion study properties.
              Set swMotionStudyProps = swMotionStudy1.GetProperties(4)
              Set swCosmosMotionStudyProps = swMotionStudyProps
              Debug.Print ""
              Debug.Print "COSMOSMotion study properties: "
              Debug.Print "    Animate during simulation: " & swCosmosMotionStudyProps.AnimateDuringSimulation
              Debug.Print "    Make all mates flexible: " & swCosmosMotionStudyProps.MakeAllMatesFlexible
              Debug.Print "    Display results graphics as wireframe: " & swCosmosMotionStudyProps.WireframeGraphics
              ' Get COSMOSMotion study results.
              Set swResults = swMotionStudy1.GetResults(4)
              Set swCosmosMotionStudyResults = swResults
              Debug.Print "    Number of plots: " & swCosmosMotionStudyResults.GetPlotCount
              Debug.Print ""
              Debug.Print "Are the motion study results out of date? " & swResults.IsOutOfDate
            • Re: How to retrieve data from Motion Studies
              Taus Moller

              The only examples i have been able to find are the ones listed under the IMotionStudy documentation here: 2017 SOLIDWORKS API Help - IMotionStudy Interface . These examples are creating the plots right before retrieving data from them. What i am having problems with is retrieving data from existing plots. If you have run the minimal example i posted, the issue should (hopefully) be pretty clear.


              I had not seen to example you posted before, but unfortunately it doesn't really answer the question since it does not actually retrieve any of the simulation data. It just prints the number of plots in the results.

            • Re: How to retrieve data from Motion Studies
              Taus Moller

              For quick reference here is the "macro" i am attempting to retrieve the data with.


              public void Macro1()
                          ModelDoc2 doc = SwApp.ActiveDoc;
                          FeatureManager featMgr = doc.FeatureManager;
                          object[] features = featMgr.GetFeatures(false);
                          foreach (Feature feature in features)
                              Sensor sensor = feature.GetSpecificFeature2() as Sensor;
                              if (sensor != null)
                                  int sensortype = sensor.SensorType;
                                  double val = 1111;
                                  string unit;
                                  bool success = sensor.GetSensorValue(out val, out unit);
                          IMotionStudyManager motionstudyman = doc.Extension.GetMotionStudyManager();
                          string[] names = motionstudyman.GetMotionStudyNames();
                          if (names.Length > 0)
                              Debug.Print("activating motion study: " + names[0]);
                              IMotionStudy motionstudy = motionstudyman.GetMotionStudy(names[0]);
                              swMotionStudyType_e studytype = (swMotionStudyType_e)motionstudy.StudyType;
                              IMotionStudyResults res = motionstudy.GetResults((int)studytype);
                              if (studytype == swMotionStudyType_e.swMotionStudyTypeCosmosMotion)
                                  ICosmosMotionStudyResults cosres = (ICosmosMotionStudyResults)res;
                                  object[] plotfeatures = cosres.GetPlotFeatures();
                                  foreach (Feature feature in plotfeatures)
                                      string typename = feature.GetTypeName2();
                                      IMotionPlotFeatureData mpfd = feature.GetDefinition();
                                      IMotionPlotAxisFeatureData xaxis = mpfd.GetXAxis().GetDefinition();
                                      object[] yaxes = mpfd.GetYAxis();
                                      IMotionPlotFeatureOutput output = cosres.GetValues(mpfd, xaxis, yaxes);
                                      foreach (Feature yaxisf in yaxes)
                                          string name = yaxisf.Name;
                                          MotionPlotAxisFeatureData yaxis = yaxisf.GetDefinition();
                                          swMotionPlotAxisType_e axistype = (swMotionPlotAxisType_e)yaxis.Type;
                                          double[] xs = output.GetXAxis();
                                          double[] ys = output.GetYAxis(yaxis);
              • Re: How to retrieve data from Motion Studies
                Taus Moller

                I just wanted to give an update about this. I contacted support and after a lot of back and forth, it seems that the motion plot API is pretty broken. Here is what it amounted to in the end:


                "I spent the last few days trying to find a workaround to the issue we've been discussing, however I could not find one unfortunately. The issue seems to be the Feature::GetDefinition method. This method is dynamic, and returns a different object depending on the type of feature. I think in this case this function is either not recognizing the plot feature type (GetTypeName2 seems to report correctly though) or more likely is not setting up the feature data correctly so that the subsequent calls to GetValues and GetYAxis will fail."


                There have been opened 2 SPR's in relation to this issue. Hopefully it will not take too long before it is resolved. In the mean time i am using ICosmosMotionStudyResults::ExportCSV and reading the back in the file. This seems to work for now, but it will obviously not work for motion studies not using Cosmos.


                The SPR's are:

                SPR 1046641: IMotionPlotAxisFeaturedata::Type property returns -1 for reaction force plots

                SPR 1046642: Unable to obtain plot results using motion APIs and IMotionPlotFeatureOutput/IMotionPlotAxisFeatureData

                • Re: How to retrieve data from Motion Studies
                  Taus Moller

                  I took another stab at this and i am happy to report that i have defeated the MotionApi and succesfully wrestle some data from its hands. And it only took me a year!

                  I created a method that will load the results of a single plot into a array of lists. with each list being a dataset. The first list is the x-axis and each of the following lists are data for a given. The Columns array contains the names of the datasets



                  protected bool LoadPlotDataFromAPI(CosmosMotionStudyResults cosres, Feature plot)
                              MotionPlotFeatureData mpfd = (MotionPlotFeatureData)plot.GetDefinition();
                              Feature fx = mpfd.GetXAxis();
                              MotionPlotAxisFeatureData xmpafd = (MotionPlotAxisFeatureData)fx.GetDefinition();
                              object[] yfeatures = (object[])mpfd.GetYAxis();
                              MotionPlotAxisFeatureData[] ympafdarray = new MotionPlotAxisFeatureData[yfeatures.Length];
                              string[] columns = new string[yfeatures.Length + 1];
                              string[] units = new string[columns.Length];
                              columns[0] = fx.Name;
                              for (int i = 0; i < yfeatures.Length; ++i)
                                  Feature yfeat = (Feature)yfeatures[i];
                                  columns[i + 1] = yfeat.Name;
                                  ympafdarray[i] = (MotionPlotAxisFeatureData)yfeat.GetDefinition();
                              IMotionPlotFeatureOutput output = (IMotionPlotFeatureOutput)cosres.GetValues(mpfd, xmpafd, ympafdarray);
                              List<double>[] data = new List<Double>[columns.Length];
                              double[] xval = (double[])output.GetXAxis();
                              data[0] = xval.ToList();
                              for (int i = 0; i< ympafdarray.Length; ++i)  
                                      double[] yval = (double[])output.GetYAxis(ympafdarray[i]);
                                      data[i +1] = yval.ToList();


                  The critical piece of code is the for loop that type creates the "ympafdarray". Previously i took the feature array and feeded it directly to the GetValues method. It seems seems however that is not enough and the values in the array has to be of the type MotionPlotAxisFeatureData

                  • Re: How to retrieve data from Motion Studies
                    Amen Allah Jlili

                    This is great! Good job man, let's celebrate if you are coming to SWW this year!