Hello,
I have managed to isolate unexpected, to me, bahavior for DriveConstraintSettings.
If I use drive the constraint detecting contact everything is fine the first time. If I change the position of assemblycomponentoccurences and do the same again it stops at the same position as the previous run.
I suspect that this is due to internal caching of proxies or something.
See attached code and dataset to reproduce.
Please post suggestions and ideas for how to resolve this.
I installed this but to no use. http://usa.autodesk.com/adsk/servlet/ps/dl/item?siteID=123112&id=17804829&linkID=9242019
using System; using System.Management.Instrumentation; using System.Runtime.InteropServices; using Inventor; using Microsoft.VisualStudio.TestTools.UnitTesting; namespace SimulationInventorHandlerTest.Utilities.Assembly { [TestClass] public class DriveConstraintTest { [TestMethod] public void ProbeTest() { Application inventorAppliaction = GetInventorAppliaction(); AssemblyDocument assemblyDocument = GetActiveAssemblyDocument(inventorAppliaction); MateConstraint mateConstraintX = GetMateConstraintByName(assemblyDocument, "Axis X"); Inventor.MateConstraint mateConstraintZ = GetMateConstraintByName(assemblyDocument, "Axis Z"); assemblyDocument.ModelingSettings.InteractiveContactAnalysis = Inventor.InteractiveContactAnalysisEnum.kAllComponentsInteractiveContact; assemblyDocument.ModelingSettings.InteractiveContactSurfaces = Inventor.InteractiveContactSurfacesEnum.kAllSurfacesInteractiveContact; mateConstraintX.Offset.Expression = "0 mm"; mateConstraintZ.Offset.Expression = "20 mm"; assemblyDocument.Update(); Drive(0, 10, 0.1, mateConstraintX); double stopPosition = mateConstraintX.Offset.ModelValue; mateConstraintX.Offset.Expression = "0 mm"; mateConstraintZ.Offset.Expression = "0 mm"; assemblyDocument.Update(); Drive(0, 10, 0.1, mateConstraintX); if(Math.Abs(stopPosition - mateConstraintX.Offset.ModelValue) < 0.0001) throw new Exception("Stopped at same position as first run!"); } private void Drive(double startValue, double endValue, double incrementSize, MateConstraint mateConstraint ) { mateConstraint.DriveConstraintSettings.CollisionDetection = true; mateConstraint.DriveConstraintSettings.SetIncrement(Inventor.ConstraintIncrementTypeEnum.kIncrementAsAmountOfValue, incrementSize.ToString()); mateConstraint.DriveConstraintSettings.StartValue = startValue.ToString(); mateConstraint.DriveConstraintSettings.EndValue = endValue.ToString(); mateConstraint.DriveConstraintSettings.GoToStart(); mateConstraint.DriveConstraintSettings.PlayForward(); } private static MateConstraint GetMateConstraintByName(AssemblyDocument assemblyDocument, string constraintName) { MateConstraint mateConstraint; Inventor.AssemblyComponentDefinition assemblyComponentDefinition = assemblyDocument.ComponentDefinition; if (!(assemblyComponentDefinition.Constraints[constraintName] is Inventor.MateConstraint)) throw new InstanceNotFoundException("Not a MateConstraint"); mateConstraint = assemblyComponentDefinition.Constraints[constraintName] as Inventor.MateConstraint; if (mateConstraint == null) throw new InstanceNotFoundException("No constraint"); return mateConstraint; } private static AssemblyDocument GetActiveAssemblyDocument(Application inventorAppliaction) { AssemblyDocument assemblyDocument; if (!(inventorAppliaction.ActiveDocument is Inventor.AssemblyDocument)) { throw new InstanceNotFoundException("No active asseblydocument"); } assemblyDocument = inventorAppliaction.ActiveDocument as Inventor.AssemblyDocument; return assemblyDocument; } private static Application GetInventorAppliaction() { Application inventorAppliaction; inventorAppliaction = Marshal.GetActiveObject("Inventor.Application") as Inventor.Application; return inventorAppliaction; } } }
Corresponding VBA code
Public Sub StrangeBehavior() Dim assyDoc As AssemblyDocument Set assyDoc = ThisApplication.ActiveDocument assyDoc.ModelingSettings.InteractiveContactAnalysis = kAllComponentsInteractiveContact assyDoc.ModelingSettings.InteractiveContactSurfaces = kAllSurfacesInteractiveContact Dim xConstraint As MateConstraint Set xConstraint = assyDoc.ComponentDefinition.Constraints.Item("Axis X") Call xConstraint.DriveConstraintSettings.SetIncrement(kIncrementAsAmountOfValue, "0,1") Dim zConstraint As MateConstraint Set zConstraint = assyDoc.ComponentDefinition.Constraints.Item("Axis Z") xConstraint.Offset.Value = 0 zConstraint.Offset.Value = 0 assyDoc.Update With xConstraint.DriveConstraintSettings .CollisionDetection = True .StartValue = 0 .EndValue = 20 .GoToStart .PlayForward End With firstposition = xConstraint.Offset.Value xConstraint.Offset.Value = 0 zConstraint.Offset.Value = 2 assyDoc.Update With xConstraint.DriveConstraintSettings .CollisionDetection = True .StartValue = 0 .EndValue = 20 .GoToStart .PlayForward End With If (firstposition - xConstraint.Offset.Value) ^ 2 < 0.001 Then MsgBox ("Same position as first time, this is not corrrect!") End If End Sub
How can I call ?Clear@RDxCollisionDetector@@QEAAXXZ in rd.dll via pInvoke?
As described in this blog: http://through-the-interface.typepad.com/through_the_interface/2011/05/calling-unexposed-objectarx-m...
It seems the collision detector is not cleared between runs when drive constraint is invoked from .net.
An other option would be to make an API call that triggers a call to CollisionDetector.Clear, I have not found óne yet.
I think I found a really ugly solution to the problem.
I start a new process just to drive the constraint, the code is so ugly so atm so I am not posting. If anyone wants it I can post after cleaning it a bit.
Here is the pseudo code, its really ugly. i guess it shoul be a recursive call but I kept it this way. The key to repeated animation is the finally block. The code in the catch blocks handles the quite common case when Inventor fails to detect contact. I think you will be able to figure out the axismotion class.
private void DriveConstraintInNegativeDirection(AssemblyConstraint assemblyConstraint, AxisMotion axisMotion) { DriveConstraintSettings driveConstraintSettings = assemblyConstraint.DriveConstraintSettings; try { if (Math.Abs(axisMotion.CurrentUnitPosition - axisMotion.FromExpression.UnitValue) > double.Epsilon) throw new InvalidOperationException("Currentpostition got to be fromposition!"); driveConstraintSettings.StartValue = axisMotion.ToExpression.ExpressionString; driveConstraintSettings.PlayReverse(); SetIncrement(AxisMotion, AxisMotion.Axis.AxisSetting.Resolution); while (AxisMotion.Axis.IsInterference) { driveConstraintSettings.StepForward(); } } catch (Exception) { try { while (AxisMotion.Axis.IsInterference) { driveConstraintSettings.StepForward(); } SetIncrement(AxisMotion, 0.01); driveConstraintSettings.PlayReverse(); SetIncrement(AxisMotion, AxisMotion.Axis.AxisSetting.Resolution); while (AxisMotion.Axis.IsInterference) { driveConstraintSettings.StepForward(); } } catch (Exception) { try { while (AxisMotion.Axis.IsInterference) { driveConstraintSettings.StepForward(); } SetIncrement(AxisMotion, AxisMotion.Axis.AxisSetting.Resolution); driveConstraintSettings.PlayReverse(); while (AxisMotion.Axis.IsInterference) { driveConstraintSettings.StepForward(); } } catch (Exception) { while (AxisMotion.Axis.IsInterference) { driveConstraintSettings.StepForward(); } //throw; } } } finally { Marshal.FinalReleaseComObject(driveConstraintSettings); } }