public override void TraverseTestBench(CyPhy.TestBenchType testBenchBase)
        {
            CyPhy.KinematicTestBench testBench = testBenchBase as CyPhy.KinematicTestBench;
            if (testBench == null)
                testBench = CyPhyClasses.KinematicTestBench.Cast(testBenchBase.Impl);

            base.TraverseTestBench(testBenchBase);

            //STLDataExchangeFormats.Add("Parasolid");

            Name = testBench.Name;
            SimulationStep = testBench.Attributes.SimulationResolution;
            SimulationTime = testBench.Attributes.Duration;

            if (testBench.Children.GravityLoadCollection.Any())
            {
                CyPhy.GravityLoad load = testBench.Children.GravityLoadCollection.First();
                double x = 0;
                double y = 0;
                double z = 0;

                GetGravityLoadParam(load, "X", out x);
                GetGravityLoadParam(load, "Y", out y);
                GetGravityLoadParam(load, "Z", out z);
                Gravity = new KinematicGravity(x, y, z, load.Attributes.Active);

            }

            var terrain = testBench.Children.ComponentRefCollection.Where(c => ((MgaFCO)c.Impl).MetaRole.Name == "Terrain");

            if (terrain.Any())
            {
                CyPhy.Component terraincomp = terrain.First().AllReferred as CyPhy.Component;
                if (terraincomp == null)
                {
                    Logger.Instance.AddLogMessage("Terrain component reference must refer to a cyphy component.", Severity.Error);
                    return;
                }
                if (!terraincomp.Children.CADModelCollection.Any())
                {
                    Logger.Instance.AddLogMessage("Terrain component must contain a CAD model.", Severity.Error);
                    return;
                }
                TerrainFileName = terraincomp.Children.ResourceCollection.First().Attributes.Path;
                try
                {
                    File.Copy(Path.Combine(terraincomp.GetDirectoryPath(), TerrainFileName), Path.Combine(OutputDirectory, Path.GetFileName(TerrainFileName)));
                }
                catch (Exception e)
                {
                    Logger.Instance.AddLogMessage("Unable to copy terrain file: " + e.Message, Severity.Warning);
                }
                TerrainFileName = Path.GetFileNameWithoutExtension(TerrainFileName);
            }
            else
            {
                if (testBench.Children.AnchorCollection.Any())
                {
                    CyPhy.Anchor anchor = testBench.Children.AnchorCollection.First();
                    var pointList = anchor
                        .DstConnections
                        .SetAnchorCollection
                        .Select(x => x.DstEnds.Point)
                       .Concat(anchor
                       .SrcConnections
                       .SetAnchorCollection
                       .Select(x => x.SrcEnds.Point));

                    if (!pointList.Any())
                    {
                        Logger.Instance.AddLogMessage("Anchor is not connected to a point. Anchor should be connected to a datum point on one of the components.", Severity.Error);
                        return;
                    }

                    var point = pointList.First();
                    PointMetricTraversal traverser = new PointMetricTraversal(point);
                    foreach (var pointFound in traverser.portsFound)
                    {
                        string name = (pointFound as CyPhy.Point).Attributes.DatumName;
                        string componentID = CyPhyClasses.Component.Cast((pointFound as CyPhy.Point).ParentContainer.ParentContainer.Impl).Attributes.InstanceGUID;
                        Computations.Add(new TBComputationType() { ComponentID = componentID, FeatureDatumName = name, MetricID = "Anchor", ComputationType = "PointCoordinates", RequestedValueType = "Vector" });
                        GroundCyphyID = componentID;
                    }
                }
                else
                {
                    Logger.Instance.AddLogMessage("Anchor not found. There should be exactly one anchor in the testbench, to specify which body is fixed to the ground in the kinematic simnulation.", Severity.Error);
                    return;
                }
            }

            foreach (var motion in testBench.Children.MotionLoadCollection)
            {
                var connectorList = motion
                                .SrcConnections
                                .ApplyMotionToJointCollection
                                .Select(x => x.SrcEnds.Connector)
                                .Concat(motion
                                .DstConnections
                                .ApplyMotionToJointCollection
                                .Select(x => x.DstEnds.Connector)
                                );

                var toplevelSUT = testBench.Children.ComponentAssemblyCollection.FirstOrDefault();

                foreach (var connector in connectorList)
                {
                    OriginatingConnectorTraversal traverser = new OriginatingConnectorTraversal(connector);

                    if (traverser.result != null)
                    {
                        CyPhy.KinematicJoint joint = GetJoint(traverser.result);
                        if (joint != null)
                        {
                            Multibody.ModelLoadsMotion mbdMotion = new Multibody.ModelLoadsMotion();
                            mbdMotion.Active = (motion.Attributes.Active) ? Multibody.ModelLoadsMotionActive.on : Multibody.ModelLoadsMotionActive.off;
                            mbdMotion.FreedomType = (Multibody.ModelLoadsMotionFreedomType)((int)motion.Attributes.JointFreedomType);
                            mbdMotion.Function = motion.Attributes.CustomFunction;
                            mbdMotion.JointID = cadDataContainer.GetJointIDFromGMEID(joint.ID);
                            mbdMotion.MotionID = motion.Name;
                            mbdMotion.TimeDerivative = (Multibody.ModelLoadsMotionTimeDerivative)((int)motion.Attributes.TimeDerivative);
                            mbdMotion.Type = "JointMotion";

                            MotionList.Add(mbdMotion);
                        }
                        else
                        {
                            Logger.Instance.AddLogMessage("Kinematic motion is connected to a connector without joint information: " + connector.ToHyperLink(), Severity.Error);
                        }
                    }
                }
            }

            if (testBench.Children.AdamsScriptCollection.Any())
            {
                Scripts = new List<Multibody.ModelScript>();
                foreach (var script in testBench.Children.AdamsScriptCollection)
                {
                    Scripts.Add(new Multibody.ModelScript() { Path = script.Attributes.Path });
                }
            }

            ProcessContacts(testBench);
        }