예제 #1
0
        // This method is for when the system starts up fresh and hasn't
        // positioned the legs in any way.
        // 1 Enumerate the Distance holders into an array.
        // 2 Project thier position onto the ground plane/surface
        // 3 Use the projections to form a movement restriction region
        // 4 Apply paired anchor points to project positions.
        // 5 Calculate anchor position radii
        void startUpSequence()
        {
            // Collect distance holders
            if (distanceHolders == null)
            {
                distanceHolders = GetComponentsInChildren <BMod_DistanceHolder>();
            }
            // Proceed if there are distance holders defined
            updateRestrictionRegion(true);
            // Place anchor points at the projected ground positions for each anchor points parent distance holder
            int        layerMask = 1 << 8;
            RaycastHit strikePoint;
            Vector3    centerPoint      = new Vector3();
            bool       centerPointFound = false;

            // Project the attached vertex position down to the ground as a centre point.
            if (Physics.Raycast(controlVertex.transform.position, -Vector3.up, out strikePoint, 200.0f, layerMask))
            {
                centerPoint      = strikePoint.point;
                centerPointFound = true;
                biasCentreTrack  = centerPoint;                // Update the roving centre point.
            }
            List <BMod_AnchorPoint> anchorList = new List <BMod_AnchorPoint>();

            foreach (BMod_DistanceHolder distanceHolder in distanceHolders)
            {
                // Get the anchor point attached to this distance holder
                BMod_AnchorPoint anchorPoint = distanceHolder.transform.GetComponentInChildren <BMod_AnchorPoint>();
                if (anchorPoint != null)
                {
                    anchorList.Add(anchorPoint);
                    // Set down the anchor points to be scaled out slightly from the centre point
                    if (centerPointFound)
                    {
                        Vector3 anchorPosition = ((distanceHolder.projectedGroundPosition - centerPoint) * dropAreaRatio) + centerPoint;

                        anchorPoint.lockedPosition = anchorPosition;
                    }
                    else
                    {
                        anchorPoint.lockedPosition = distanceHolder.projectedGroundPosition;
                    }
                    anchorPoint.dropPosition     = anchorPoint.lockedPosition;
                    anchorPoint.unlockedPosition = distanceHolder.preferredUnlockPosition;
                    anchorPoint.currentAction    = BMod_AnchorPoint.AnchorCurrentActionEnum.movingToStartingLockPosition;
                }
            }
            if (anchorList.Count > 0)
            {
                anchorPoints = anchorList.ToArray();
            }
        }
예제 #2
0
 void updateRestrictionRegion(bool startUpSequence)
 {
     if (distanceHolders != null)
     {
         // Call their project routines
         // Collect each projected distance holder point into a array.
         List <Vector3> collectVectors = new List <Vector3>();
         Vector3        sumVector      = new Vector3();
         foreach (BMod_DistanceHolder distanceHolder in distanceHolders)
         {
             distanceHolder.updateProjectionValues();
             if (startUpSequence)
             {
                 collectVectors.Add(distanceHolder.projectedGroundPosition);
                 sumVector = sumVector + distanceHolder.projectedGroundPosition;
             }
             else
             {
                 // Use anchor point if locked.
                 BMod_AnchorPoint anchorPoint = distanceHolder.transform.GetComponentInChildren <BMod_AnchorPoint>();
                 if (anchorPoint != null)
                 {
                     if (anchorPoint.lockedInPosition && anchorPoint.currentAction != BMod_AnchorPoint.AnchorCurrentActionEnum.waitingForBalance)
                     {
                         collectVectors.Add(anchorPoint.lockedPosition);
                         sumVector = sumVector + anchorPoint.lockedPosition;
                     }
                 }
             }
         }
         // Form restriction region from collected ground positions.
         // Should an actual 3D object be created that's really tall?
         Vector3 centrePoint = sumVector / collectVectors.Count;
         biasMovementRestrictionArea = new List <Vector3>();
         // Shrink each vector towards the centre point.
         foreach (Vector3 workVector in collectVectors)
         {
             Vector3 scaledVector = ((workVector - centrePoint) * restrictionAreaShrinkRatio) + centrePoint;
             biasMovementRestrictionArea.Add(scaledVector);
         }
         // Build a line renderer
         LineRenderer debugLineDraw = GetComponent <LineRenderer>();
         if (debugLineDraw != null)
         {
             Vector3[] positions = biasMovementRestrictionArea.ToArray();
             debugLineDraw.positionCount = biasMovementRestrictionArea.Count;                     // Set position count first
             debugLineDraw.SetPositions(positions);
         }
     }
 }
예제 #3
0
        // Update is called once per frame
        void Update()
        {
            // TODO Balance position needs to be upgraded to use a centre of balance
            // system, where the body is tilted and shifted as needed.
            // Process each of the distance holder and anchor points attached to this
            // class.
            if (restrictedMovementAreaUpdateRequired)
            {
                updateRestrictionRegion(false);
                restrictedMovementAreaUpdateRequired = false;
            }

            // Control pad movement
            float hozAxis = Input.GetAxis("Horizontal") * maxSlideMovementSpeed;
            float verAxis = Input.GetAxis("Vertical") * maxSlideMovementSpeed;

            noncumulativeOffset.x = Input.GetAxis("Horizontal");
            noncumulativeOffset.z = Input.GetAxis("Vertical");
            float keyBiasOffset = 0.5f;             // This goes towards how far forward the anchor point

            // is positioned in the direction of movement for keyboard based control.
            // Collect bias from external controls
            if (Input.GetKey(KeyCode.UpArrow))
            {
                slideOffset.z         = slideOffset.z + (maxSlideMovementSpeed * Time.deltaTime);
                noncumulativeOffset.z = keyBiasOffset;
                noncumulativeOffset.x = 0.0f;
            }
            if (Input.GetKey(KeyCode.DownArrow))
            {
                slideOffset.z         = slideOffset.z - (maxSlideMovementSpeed * Time.deltaTime);
                noncumulativeOffset.z = -keyBiasOffset;
                noncumulativeOffset.x = 0.0f;
            }
            if (Input.GetKey(KeyCode.LeftArrow))
            {
                slideOffset.x         = slideOffset.x + (maxSlideMovementSpeed * Time.deltaTime);
                noncumulativeOffset.z = 0.0f;
                noncumulativeOffset.x = keyBiasOffset;
            }
            if (Input.GetKey(KeyCode.RightArrow))
            {
                slideOffset.x         = slideOffset.x - (maxSlideMovementSpeed * Time.deltaTime);
                noncumulativeOffset.z = 0.0f;
                noncumulativeOffset.x = -keyBiasOffset;
            }

            // Controls switches
            bool isLeaningSwitch      = Input.GetButton("Button_R");
            bool isNoLegLiftingSwitch = Input.GetButton("Button_L");

            // Manual leg lifting button presses
            int anchorLift = -1;

            if (Input.GetButtonDown("Button_A"))
            {
                anchorLift = 0;
            }
            if (Input.GetButtonDown("Button_B"))
            {
                anchorLift = 1;
            }
            if (Input.GetButtonDown("Button_X"))
            {
                anchorLift = 3;
            }
            if (Input.GetButtonDown("Button_Y"))
            {
                anchorLift = 2;
            }
            if (anchorLift != -1)
            {
                BMod_AnchorPoint anchorPoint = anchorPoints[anchorLift];
                anchorPoint.needsToLift = true;
            }


            //Debug.Log("Hoz " + hozAxis + ", Ver " + verAxis);
            // Only apply horizontal and vertical slide axis if bal pos is ready for work
            if (balPosWorkingStatus == balPolStatusEnum.readyForWork)
            {
                slideOffset.x = slideOffset.x + (hozAxis * Time.deltaTime);
                slideOffset.z = slideOffset.z + (verAxis * Time.deltaTime);
            }
            // Rotation around centre point slide calculations here
            float rotAxis = Input.GetAxis("Hoz Rotate") * rotationDegreeDelta;

            // Calculate the restriction centre and compare with the actual roving centre.
            Vector3 biasActualCentre = new Vector3();

            foreach (Vector3 biasVector in biasMovementRestrictionArea)
            {
                biasActualCentre = biasActualCentre + biasVector;
            }
            biasActualCentre = biasActualCentre / biasMovementRestrictionArea.Count;
            if (Vector3.Distance(biasCentreTrack, biasActualCentre) > 0.0f)
            {
                // If the centre if off then the robot is adjusting its balance
                balPosWorkingStatus = balPolStatusEnum.adjustingBalance;
                Vector3 biasMoved = Vector3.MoveTowards(biasCentreTrack, biasActualCentre, maxSlideMovementSpeed * Time.deltaTime);
                slideOffset = slideOffset + (biasCentreTrack - biasMoved) * 1.2f;                 // Boost the movement
                // Move the bias centre.
                biasCentreTrack = biasCentreTrack - (biasCentreTrack - biasMoved);
                if (biasCentreRepresentation != null)
                {
                    biasCentreRepresentation.transform.position = biasCentreTrack;
                }
            }
            else
            {
                // If the balance point has been reached then declare ready for work, unless still in the start up sequence.
                if (balPosWorkingStatus != balPolStatusEnum.startingUp)
                {
                    balPosWorkingStatus = balPolStatusEnum.readyForWork;
                }
            }

            // Roll through the anchor points and collect the limit reached offset vectices
            foreach (BMod_AnchorPoint anchorPoint in anchorPoints)
            {
                // Only pull from the ones locked in place
                if (anchorPoint.lockedInPosition)
                {
                    Vector3 limitCorrection = anchorPoint.limitReachCorrectionVector();
                    slideOffset.x = slideOffset.x + limitCorrection.x;
                    slideOffset.z = slideOffset.z + limitCorrection.z;
                }
            }

            // Update position sliders (Anchor points for now) with acceleration bias.
            // Only allow movement when balanced.
            if ((previousSlideOffset != slideOffset || rotAxis != 0.0f) && !isLeaningSwitch && anchorPoints != null)
            {
                // Apply the slide and rotation changes to the anchor points.
                float angleRad = rotAxis * rotationDegreeDelta * Mathf.Deg2Rad;             // Changed rotationDegreeDelta to movementSpeed
                foreach (BMod_AnchorPoint anchorPoint in anchorPoints)
                {
                    if (anchorPoint.lockedInPosition)
                    {
                        // Only apply offset as translation difference from previous offset if the anchor is locked.
                        Vector3 rotationOffset = Vector3.zero;
                        if (rotAxis != 0.0f)
                        {
                            // Rotation offset
                            Vector3 currentPosition = anchorPoint.anchorVertex.transform.position;
                            // The current position should be a vector from x = 0, z = 0. So be applying a rotation
                            // to the current position and keeping the offset, this should work as a way of creating rotation.
                            float xVal = currentPosition.x * Mathf.Cos(angleRad) - currentPosition.z * Mathf.Sin(angleRad);
                            float yVal = currentPosition.y;                             // We're not changing the height. Future versions may need to height check.
                            float zVal = currentPosition.x * Mathf.Sin(angleRad) + currentPosition.z * Mathf.Cos(angleRad);
                            rotationOffset = (new Vector3(xVal, yVal, zVal)) - currentPosition;
                        }
                        anchorPoint.anchorVertex.offset += (slideOffset - previousSlideOffset) + rotationOffset;                         // Apply the change in offset
                    }
                }
                previousSlideOffset = slideOffset;
            }

            // Check if any anchors have reached thier drop points.
            checkForCompletedAnchors();

            // If the counter bias has zero movement then any anchor points waiting for
            // release can be processed.
            // Check if prevent lift button is not pressed
            if (!isNoLegLiftingSwitch)
            {
                checkForReleaseableAnchors();
            }             //else {
                          //    Debug.Log("Button R pressed held");
                          // }

            // Adjust distance holder offsets
            float crouchAxis = Input.GetAxis("Crouch") * crouchRange;

            if (distanceHolders != null)
            {
                if (isLeaningSwitch)
                {
                    // This is to allow the rotational leaning of the robot.
                    Vector3 leanAxis = new Vector3(-Input.GetAxis("Hoz Rotate"), 0.0f, Input.GetAxis("Crouch"));
                    leanAxis = leanAxis * 1.5f;                     // Increase the movement range
                    foreach (BMod_DistanceHolder distanceHolder in distanceHolders)
                    {
                        Vector3 distHold      = distanceHolder.vertexPoint.transform.position;
                        Vector3 groundHolder  = new Vector3(distHold.x, 0.0f, distHold.z);
                        float   distToCentre  = Vector3.Distance(biasActualCentre, groundHolder);
                        float   distToTracked = Vector3.Distance(biasActualCentre + leanAxis, groundHolder);
                        float   ratioAlt      = distToTracked / distToCentre;
                        float   tiltOffset    = 0.0f;
                        if (ratioAlt != 1.0)
                        {
                            tiltOffset = distanceHolder.distanceToHold - (distanceHolder.distanceToHold * ratioAlt);
                        }
                        distanceHolder.distanceToHoldOffset = tiltOffset;
                    }
                }
                else
                {
                    // Alter the height of each distance holder by the crouch axis
                    foreach (BMod_DistanceHolder distanceHolder in distanceHolders)
                    {
                        distanceHolder.distanceToHoldOffset = crouchAxis;
                    }
                }
            }
        }
예제 #4
0
 void checkForReleaseableAnchors()
 {
     // Cycle through anchor points to check for any that need to be released.
     // Priority given to those furthest away from this balance position, which any tied then on priority value.
     if (anchorPoints != null)
     {
         BMod_AnchorPoint anchorToUnlock = null;
         int unlockedCount = 0;
         List <BMod_AnchorPoint> requestors = new List <BMod_AnchorPoint>();
         foreach (BMod_AnchorPoint anchor in anchorPoints)
         {
             if (anchor.needsToLift)
             {
                 requestors.Add(anchor);
             }
             if (anchor.lockedInPosition == false || anchor.currentAction == BMod_AnchorPoint.AnchorCurrentActionEnum.waitingForBalance)
             {
                 unlockedCount++;
             }
         }
         // Only proceed if there's less anchor points unlocked than the maximum allowed.
         if (unlockedCount < maxReleasable && requestors.Count > 0)
         {
             if (requestors.Count > maxReleasable)
             {
                 // Filter by distance and then by priority if needed.
                 // Distance is how far from original lock position
                 // Use a dictionary with the distance rounded to whole number. If a duplicat entry exists,
                 // it is overriden if the duplcate has a lower priority level.
                 // Dictionary is then sorted highest to lowest and first entry taken out.
                 Dictionary <int, BMod_AnchorPoint> distanceAnchors = new Dictionary <int, BMod_AnchorPoint>();
                 foreach (BMod_AnchorPoint anchorCheck in requestors)
                 {
                     // Only working with ground height of zero for the distances for now.
                     // Was used originally as part of the pushing through the ground test.
                     Vector3 nonHeightAnchor             = new Vector3(anchorCheck.anchorVertex.transform.position.x, 0.0f, anchorCheck.anchorVertex.transform.position.z);
                     int     distanceToOriginalLockPoint = Mathf.RoundToInt(Vector3.Distance(anchorCheck.lockedPosition, nonHeightAnchor) * 10.0f);
                     if (distanceAnchors.ContainsKey(distanceToOriginalLockPoint))
                     {
                         if (distanceAnchors[distanceToOriginalLockPoint].priorityIndex < anchorCheck.priorityIndex)
                         {
                             // Replace original anchor point
                             distanceAnchors[distanceToOriginalLockPoint] = anchorCheck;
                         }
                     }
                     else
                     {
                         distanceAnchors.Add(distanceToOriginalLockPoint, anchorCheck);
                     }
                 }
                 // Loop through keys and find the largest distance
                 int maxDistanceFound = -99;
                 foreach (int keyEntry in distanceAnchors.Keys)
                 {
                     if (keyEntry > maxDistanceFound)
                     {
                         maxDistanceFound = keyEntry;
                     }
                 }
                 // If a distance was found that wasn't the initialiser number then assign for unlocking.
                 if (maxDistanceFound != -99)
                 {
                     anchorToUnlock = distanceAnchors[maxDistanceFound];
                 }
             }
             else
             {
                 // Allow the anchor to be unlocked.
                 anchorToUnlock = requestors[0];
             }
         }
         // If an anchor point was found to release, then unlock it.
         // Safety check status will need to be implemented to allow centre point time to move
         // within restriction zone if restricted area shrinks past it.
         if (anchorToUnlock != null)
         {
             anchorToUnlock.currentAction = BMod_AnchorPoint.AnchorCurrentActionEnum.waitingForBalance;
             balPosWorkingStatus          = balPolStatusEnum.adjustingBalance;            // Make sure this is called.
             //anchorToUnlock.lockedInPosition = false;
             anchorToUnlock.needsToLift = false;
             Vector3 nonHeightAnchor = new Vector3(anchorToUnlock.anchorVertex.transform.position.x, 0.0f, anchorToUnlock.anchorVertex.transform.position.z);
             Vector3 currentPosition = nonHeightAnchor;
             // Update the unlock position to be slightly above the current position
             anchorToUnlock.unlockedPosition      = new Vector3(currentPosition.x, currentPosition.y + anchorLiftHeight, currentPosition.z);
             restrictedMovementAreaUpdateRequired = true;
         }
     }
 }
        /**
         * Test method for creating a Frame_Object from an OBJ file
         * 23 Jan 2019 - Updated to read from modified OBJ files.
         * @param objFile The filename of the OBJ file
         * @return A Frame_Object file
         * @throws FileNotFoundException
         */
        void createFromOBJ(TextAsset objFile)
        {
            //System.out.println("Loading OBJ file : " + objFile.toString());

            string[] inFile = objFile.text.Split('\n');

            List <GameObject> verticesBuild  = new List <GameObject>();
            List <GameObject> strutBuild     = new List <GameObject>();
            List <GameObject> angleViewBuild = new List <GameObject>();
            List <GameObject> compRepBuild   = new List <GameObject>();
            List <GameObject> balPosBuild    = new List <GameObject>();
            List <GameObject> disHolBuild    = new List <GameObject>();
            List <GameObject> ancPoiBuild    = new List <GameObject>();

            int vertexIndex = 0;

            foreach (string objLine in inFile)
            {
                //System.out.println(objLine); // Debug print to console the current line.
                // Reading in a vertex line
                if (objLine.StartsWith("v") && !objLine.StartsWith("vn") && !objLine.StartsWith("vt") && !objLine.StartsWith("vp"))
                {
                    // Split the string using space. e.g. v 3.00 2.00 -2.00
                    //System.out.println("Vertex : " + objLine);
                    string[] splits = objLine.Split(' ');
                    float    x      = float.Parse(splits[1]);
                    float    y      = float.Parse(splits[2]);
                    float    z      = float.Parse(splits[3]);

                    GameObject vertexGameObject = Instantiate(VertexInstantiator, this.transform);
                    vertexGameObject.name = vertexGameObject.name + "_" + vertexIndex;
                    vertexGameObject.transform.localPosition = new Vector3(x, y, z);
                    RFrame_Vertex vertexScript = vertexGameObject.GetComponent <RFrame_Vertex>();
                    vertexScript.x = x;
                    vertexScript.y = y;
                    vertexScript.z = z;
                    // Check for lock character
                    if (splits.Length > 4)
                    {
                        if (splits[4] == "l")
                        {
                            vertexScript.lockedInPlace = true;
                        }
                    }
                    verticesBuild.Add(vertexGameObject);
                    vertexIndex++;
                }
                else if (objLine.StartsWith("l"))
                {
                    // This is for any standalone lines, which will be turned into struts.
                    // Modified to only work with the first two vertice indexes

                    string[] splits = objLine.Split(' ');
                    // Remember that indexes start at 1 in the obj/txt file and need converting to zero-indexed.
                    int        v1 = int.Parse(splits[1]) - 1;
                    int        v2 = int.Parse(splits[2]) - 1;
                    GameObject strutGameObject = RFrame_Object.createStrutIfNotExisting(this, StrutInstantiator, strutBuild, v1, v2);
                    // Check if strut is displayed. This is determined by having more than three entries in splits.
                    // Basically any character entered after the 2 indexes will trigger this.
                    //if(strutGameObject!=null && splits.Length > 3) {
                    if (splits.Length == 5)
                    {
                        RFrame_Strut strutScript = strutGameObject.GetComponent <RFrame_Strut>();
                        strutScript.minLength = float.Parse(splits[3]);
                        strutScript.maxLength = float.Parse(splits[4]);
                    }
                    // All line renderers will be switched off.
                    LineRenderer lineRenderer = strutGameObject.GetComponent <LineRenderer>();
                    // Used when debugging the a fresh OBJ frame.
                    lineRenderer.enabled = transform.GetComponentInParent <RFrame_Bridge>().displayStrutsOnLoad;
                    //}
                }
                else if (objLine.StartsWith("anglink"))
                {
                    // Angle link entry.
                    // Requires 4 vertex indexes and a link channel number which will represent the angle measurer struts.
                    // and the actuator/motor/servo this is linked too.
                    // Centering and angle limits should be entered.
                    string[]         splits             = objLine.Split(' ');
                    int              centerVertex       = int.Parse(splits[1]);
                    int              upVertex           = int.Parse(splits[2]);
                    int              measure1           = int.Parse(splits[3]);
                    int              measure2           = int.Parse(splits[4]);
                    int              channel            = int.Parse(splits[5]);    // Channel number should already be zero-indexed.
                    bool             invertChannel      = bool.Parse(splits[6]);   // Should be 0, 1, true or false
                    float            minChannelAngle    = float.Parse(splits[7]);  // Channel won't be sent any number smaller than this.
                    float            maxChannelAngle    = float.Parse(splits[8]);  // Channel won't be sent any number larger than this.
                    float            biasAngle          = float.Parse(splits[9]);  // The bias to apply. Indicates that a servo may need recentering
                    int              angleMeasureType   = int.Parse(splits[10]);   // Quaternion or dot product angle
                    float            scaleChangedAngled = float.Parse(splits[11]); // How much to scale the change in angle from initial. Increases range of movement.
                    GameObject       angleViewerObj     = Instantiate(AngleViewerInstantiator, this.transform);
                    RFrame_AngleLink angleLinker        = angleViewerObj.GetComponent <RFrame_AngleLink>();
                    angleLinker.centerVertex       = centerVertex;
                    angleLinker.upVertex           = upVertex;
                    angleLinker.measure1           = measure1;
                    angleLinker.measure2           = measure2;
                    angleLinker.linkChannel        = channel;
                    angleLinker.invertedSendAngle  = invertChannel;
                    angleLinker.minimumAngle       = minChannelAngle;
                    angleLinker.maximumAngle       = maxChannelAngle;
                    angleLinker.biasAngle          = biasAngle;
                    angleLinker.angleChangeScaling = scaleChangedAngled;
                    switch (angleMeasureType)
                    {
                    case 0: {
                        angleLinker.angleMeasureType = RFrame_AngleLink.AngleMeasureTypeEnum.quaternionBased;
                        break;
                    }

                    case 1: {
                        angleLinker.angleMeasureType = RFrame_AngleLink.AngleMeasureTypeEnum.lineBased;
                        break;
                    }

                    default: {
                        angleLinker.angleMeasureType = RFrame_AngleLink.AngleMeasureTypeEnum.quaternionBased;
                        break;
                    }
                    }
                    angleViewBuild.Add(angleViewerObj);
                }
                else if (objLine.StartsWith("comprep") && transform.GetComponentInParent <RFrame_Bridge>().displayComponentRepsOnLoad)
                {
                    // Component representation
                    string[]         splits        = objLine.Split(' ');
                    int              centerVertex  = int.Parse(splits[1]);
                    int              upVertex      = int.Parse(splits[2]);
                    int              forwardVertex = int.Parse(splits[3]);
                    string           meshName      = splits[4];
                    float            xRot          = float.Parse(splits[5]);
                    float            yRot          = float.Parse(splits[6]);
                    float            zRot          = float.Parse(splits[7]);
                    float            xTran         = float.Parse(splits[8]);
                    float            yTran         = float.Parse(splits[9]);
                    float            zTran         = float.Parse(splits[10]);
                    GameObject       compRepObj    = Instantiate(ComponentRepresentorInstantiator, this.transform);
                    RFrame_Component componentRep  = compRepObj.GetComponent <RFrame_Component>();
                    componentRep.centerVertex  = centerVertex;
                    componentRep.forwardVertex = forwardVertex;
                    componentRep.upVertex      = upVertex;
                    GameObject meshObject = Instantiate(Resources.Load <GameObject>(meshName), compRepObj.transform);
                    meshObject.transform.localPosition = new Vector3(xTran, yTran, zTran);
                    meshObject.transform.localRotation = Quaternion.Euler(xRot, yRot, zRot);
                }
                else if (objLine.StartsWith("balpos"))
                {
                    // Balance position behaviour module building here
                    string[]             splits            = objLine.Split(' ');
                    int                  vertexAttachIndex = int.Parse(splits[1]);
                    float                reduceRatio       = float.Parse(splits[2]);
                    GameObject           balPolObj         = Instantiate(BalancePositionInstantiator, this.transform);
                    BMod_BalancePosition balPosMod         = balPolObj.GetComponent <BMod_BalancePosition>();
                    balPosMod.restrictionAreaShrinkRatio = reduceRatio;
                    balPosMod.controlVertex = verticesBuild[vertexAttachIndex].GetComponent <RFrame_Vertex>();
                    //balPosMod.controlVertex.lockedInPlace = true;
                    balPosBuild.Add(balPolObj);
                }
                else if (objLine.StartsWith("dishol"))
                {
                    // Distance holder behaviour module building here
                    string[]            splits            = objLine.Split(' ');
                    int                 balPosIndex       = int.Parse(splits[1]);
                    int                 vertexAttachIndex = int.Parse(splits[2]);
                    float               distanceToHold    = float.Parse(splits[3]);
                    int                 typeOfDisHol      = int.Parse(splits[4]);
                    GameObject          disHolObj         = Instantiate(DistanceHolderInstantiator, balPosBuild[balPosIndex].transform);
                    BMod_DistanceHolder disHolMod         = disHolObj.GetComponent <BMod_DistanceHolder>();
                    disHolMod.vertexPoint = verticesBuild[vertexAttachIndex].GetComponent <RFrame_Vertex>();
                    // Experimenting with not locking the vertex in place.
                    // Need to make sure frame doesn't move out of place.
                    disHolMod.vertexPoint.lockedInPlace = true;
                    disHolMod.distanceToHold            = distanceToHold;
                    switch (typeOfDisHol)
                    {
                    case 0: disHolMod.moduleType = BMod_DistanceHolder.DistanceModuleType.groundDistance; break;

                    case 1: disHolMod.moduleType = BMod_DistanceHolder.DistanceModuleType.allRoundDistance; break;

                    default: disHolMod.moduleType = BMod_DistanceHolder.DistanceModuleType.groundDistance; break;
                    }
                    disHolBuild.Add(disHolObj);
                }
                else if (objLine.StartsWith("ancpoi"))
                {
                    // Anchor Point behaviour module building here
                    string[]         splits            = objLine.Split(' ');
                    int              disHolIndex       = int.Parse(splits[1]);
                    int              vertexAttachIndex = int.Parse(splits[2]);
                    int              priorityValue     = int.Parse(splits[3]);
                    int              typeOfAnchor      = int.Parse(splits[4]);
                    GameObject       anchorObj         = Instantiate(AnchorPointInstantiator, disHolBuild[disHolIndex].transform);
                    BMod_AnchorPoint anchorMod         = anchorObj.GetComponent <BMod_AnchorPoint>();
                    anchorMod.anchorVertex = verticesBuild[vertexAttachIndex].GetComponent <RFrame_Vertex>();
                    anchorMod.anchorVertex.lockedInPlace = true;
                    anchorMod.priorityIndex = priorityValue;
                    switch (typeOfAnchor)
                    {
                    case 0: anchorMod.anchorType = BMod_AnchorPoint.AnchorTypeEnum.primaryAnchor; break;

                    case 1: anchorMod.anchorType = BMod_AnchorPoint.AnchorTypeEnum.secondaryAnchor; break;

                    case 2: anchorMod.anchorType = BMod_AnchorPoint.AnchorTypeEnum.tertiaryAnchor; break;

                    default: anchorMod.anchorType = BMod_AnchorPoint.AnchorTypeEnum.primaryAnchor; break;
                    }
                    ancPoiBuild.Add(anchorObj);
                }
            }
            // Set the parents of the objects instatiated to this object and
            // call the function for calculating all the distances between
            // struts.
            if (verticesBuild.Count != 0 && strutBuild.Count != 0)
            {
                // Apply the created vertices and struts to this object.
                // Set the parent of the vertices and struts to the transform of this frame object.
                // foreach (GameObject vertex in verticesBuild) {
                //  vertex.transform.SetParent(this.transform);
                // }
                // foreach (GameObject strut in strutBuild) {
                //  strut.transform.SetParent(this.transform);
                // }
                allVertices = verticesBuild;
                struts      = strutBuild;
                angleLinks  = angleViewBuild;
                compReps    = compRepBuild;
                this.calculateDistancesThenOrientate();
                // Get the initial measured angles for each angle link.
                foreach (GameObject angleLinkObj in angleViewBuild)
                {
                    angleLinkObj.GetComponent <RFrame_AngleLink>().measureAngle(true);
                }
                //frame.gatherBounds();
            }
        }