コード例 #1
0
    // Update is called once per frame
    void Update()
    {
        if (ammo > 0 && Input.GetMouseButtonDown(0))
        {
            Ray ray = cam.ScreenPointToRay(Input.mousePosition);

            BulletSharp.Math.Vector3 fromP    = ray.origin.ToBullet();
            BulletSharp.Math.Vector3 toP      = (ray.direction * 500).ToBullet();
            ClosestRayResultCallback callback = new ClosestRayResultCallback(ref fromP, ref toP);
            BPhysicsWorld            world    = BPhysicsWorld.Get();
            world.world.RayTest(fromP, toP, callback);
            if (callback.HasHit)
            {
                if (callback.CollisionObject.UserObject.GetType().Name == "BRigidBody")
                {
                    ((BRigidBody)callback.CollisionObject.UserObject).AddImpulse((new Vector3(callback.HitNormalWorld.X, callback.HitNormalWorld.Y, callback.HitNormalWorld.Z)) * -5);
                }
            }

            ammo--;
            UpdateAmmo();
        }
    }
コード例 #2
0
        /// <summary>
        /// Called when the script instance is being initialized.
        /// Initializes the bullet physics environment
        /// </summary>
        public override void Awake()
        {
            QualitySettings.SetQualityLevel(PlayerPrefs.GetInt("qualityLevel"));
            Screen.fullScreenMode = (FullScreenMode)PlayerPrefs.GetInt("fullscreen", 1);

            GameObject.Find("VersionNumber").GetComponent <Text>().text = "Version " + CurrentVersion;

            if (CheckConnection())
            {
                WebClient client = new WebClient();
                ServicePointManager.ServerCertificateValidationCallback = MyRemoteCertificateValidationCallback;
                var            json   = new WebClient().DownloadString("https://raw.githubusercontent.com/Autodesk/synthesis/master/VersionManager.json");
                VersionManager update = JsonConvert.DeserializeObject <VersionManager>(json);
                SimUI.updater = update.URL;

                var localVersion  = new Version(CurrentVersion);
                var globalVersion = new Version(update.Version);

                var check = localVersion.CompareTo(globalVersion);

                if (check < 0)
                {
                    Auxiliary.FindGameObject("UpdatePrompt").SetActive(true);
                }
            }

            robotDirectory = PlayerPrefs.GetString("RobotDirectory");
            Environment.SetEnvironmentVariable("MONO_REFLECTION_SERIALIZER", "yes");
            GImpactCollisionAlgorithm.RegisterAlgorithm((CollisionDispatcher)BPhysicsWorld.Get().world.Dispatcher);
            //BPhysicsWorld.Get().DebugDrawMode = DebugDrawModes.DrawWireframe | DebugDrawModes.DrawConstraints | DebugDrawModes.DrawConstraintLimits;
            BPhysicsWorld.Get().DebugDrawMode = DebugDrawModes.All;
            BPhysicsWorld.Get().DoDebugDraw   = false;
            ((DynamicsWorld)BPhysicsWorld.Get().world).SolverInfo.NumIterations = SolverIterations;

            CollisionTracker = new CollisionTracker(this);
            SpawnedRobots    = new List <SimulatorRobot>();
        }
コード例 #3
0
    public static CollisionObject ScreenPointToRay(Camera cam, Vector3 inputScreenCoords, CollisionFilterGroups rayFilterGroup, CollisionFilterGroups rayFilterMask)
    {
        /* Returns the first CollisionObject the ray hits.
         * Requires as Input:
         * - Camera cam, UnityCamera from which the ray should be cast, e.g. Camera.main
         * - Vector3 inputScreenCoords, the screenpoint through which the ray should be cast. E.g. mousepointer Input.mousePosition
         * - CollisionFilterGroups rayFilterGroup, of which FilterGroup the ray belongs to
         * - CollisionFilterGroups rayFilterMask, which FilterMask the ray has (to map to other Objects FilterGroups
         * Be aware the Bulletphysics probably needs Group/Mask to match in both ways, i.e. Ray needs to collide with otherObj, as otherObj needs to collide with Ray.
         * To get all Ray hits, see commented out Callback AllHitsRayResultCallback below.
         * First version. Adapt to your needs. Refer to Bulletphysics.org for info. Make Pull Request to Phong BulletUnity with improvements.*/

        CollisionWorld collisionWorld = BPhysicsWorld.Get().world;

        BulletSharp.Math.Vector3 rayFrom = cam.transform.position.ToBullet();
        BulletSharp.Math.Vector3 rayTo   = cam.ScreenToWorldPoint(new Vector3(inputScreenCoords.x, inputScreenCoords.y, cam.farClipPlane)).ToBullet();

        ClosestRayResultCallback rayCallBack = new ClosestRayResultCallback(ref rayFrom, ref rayTo);

        rayCallBack.CollisionFilterGroup = (short)rayFilterGroup;
        rayCallBack.CollisionFilterMask  = (short)rayFilterMask;
        //BulletSharp.AllHitsRayResultCallback rayCallBack = new BulletSharp.AllHitsRayResultCallback(rayFrom, rayTo);

        //Debug.Log("Casting ray from: " + rayFrom + " to: " + rayTo);
        collisionWorld.RayTest(rayFrom, rayTo, rayCallBack);

        closestRayResultReturnObj = null;
        if (rayCallBack.HasHit)
        {
            //Debug.Log("rayCallBack " + rayCallBack.GetType() + " had a hit: " + rayCallBack.CollisionObject.UserObject + " / of type: " + rayCallBack.CollisionObject.UserObject.GetType());
            closestRayResultReturnObj = rayCallBack.CollisionObject;
        }

        rayCallBack.Dispose();
        return(closestRayResultReturnObj);
    }
コード例 #4
0
ファイル: SensorManager.cs プロジェクト: Ronoman/synthesis
    /// <summary>
    /// When user click left mouse, use raycast to select a node for attachment
    /// </summary>
    public void SetNode()
    {
        if (Input.GetMouseButtonDown(0))
        {
            //Casts a ray from the camera in the direction the mouse is in and returns the closest object hit
            Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
            BulletSharp.Math.Vector3 start = ray.origin.ToBullet();
            BulletSharp.Math.Vector3 end   = ray.GetPoint(200).ToBullet();

            //Creates a callback result that will be updated if we do a ray test with it
            ClosestRayResultCallback rayResult = new ClosestRayResultCallback(ref start, ref end);

            //Retrieves the bullet physics world and does a ray test with the given coordinates and updates the callback object
            BPhysicsWorld world = BPhysicsWorld.Get();
            world.world.RayTest(start, end, rayResult);

            Debug.Log("Selected:" + rayResult.CollisionObject);
            //If there is a collision object and it is a robot part, set that to be new attachment point
            if (rayResult.CollisionObject != null)
            {
                GameObject selectedObject = ((BRigidBody)rayResult.CollisionObject.UserObject).gameObject;
                if (selectedObject.transform.parent != null && selectedObject.transform.parent.name == "Robot")
                {
                    string name = selectedObject.name;

                    SelectedNode = selectedObject;

                    UserMessageManager.Dispatch(name + " has been selected as the node for sensor attachment", 5);
                }
                else
                {
                    UserMessageManager.Dispatch("Please select a robot node", 3);
                }
            }
        }
    }
コード例 #5
0
ファイル: BRaycastRobot.cs プロジェクト: xiaodelea/synthesis
        /// <summary>
        /// Initializes the BRaycastVehicle.
        /// </summary>
        private void Awake()
        {
            rigidBody = GetComponent <BRigidBody>();

            if (rigidBody == null)
            {
                Destroy(this);
                return;
            }

            RaycastRobot = new RaycastRobot(defaultVehicleTuning = new VehicleTuning
            {
                MaxSuspensionForce    = 1000f,
                MaxSuspensionTravelCm = SuspensionToleranceCm,
                SuspensionDamping     = 10f,
                SuspensionCompression = SuspensionCompressionRatio,
                SuspensionStiffness   = CalculateStiffness(DefaultNumWheels),
                FrictionSlip          = 2f
            },
                                            (RigidBody)rigidBody.GetCollisionObject(),
                                            new BRobotRaycaster((DynamicsWorld)BPhysicsWorld.Get().world));

            BRobotManager.Instance.RegisterRaycastRobot(RaycastRobot);
        }
コード例 #6
0
 public override void BOnCollisionStay(CollisionObject other, PersistentManifoldList manifoldList)
 {
     Debug.Log("On Collision Stay " + BPhysicsWorld.Get().frameCount);
 }
コード例 #7
0
    //IMPORTANT Time.fixedTime must match the timestep being used here.
    public static List <UnityEngine.Vector3> SimulateBall(BRigidBody ballRb, UnityEngine.Vector3 ballThrowForce, int numberOfSimulationSteps, bool reverseOrder)
    {
        var ballPositions = new List <UnityEngine.Vector3>(numberOfSimulationSteps);

        //Create a World
        Debug.Log("Initialize physics");

        CollisionConfiguration CollisionConf;
        CollisionDispatcher    Dispatcher;
        BroadphaseInterface    Broadphase;
        CollisionWorld         cw;
        ConstraintSolver       Solver;

        BulletSharp.SoftBody.SoftBodyWorldInfo softBodyWorldInfo;

        //This should create a copy of the BPhysicsWorld with the same settings
        BPhysicsWorld bw = BPhysicsWorld.Get();

        bw.CreatePhysicsWorld(out cw, out CollisionConf, out Dispatcher, out Broadphase, out Solver, out softBodyWorldInfo);
        World = (DiscreteDynamicsWorld)cw;

        //Copy all existing rigidbodies in scene
        // IMPORTANT rigidbodies must be added to the offline world in the same order that they are in the source world
        // this is because collisions must be resolved in the same order for the sim to be deterministic
        DiscreteDynamicsWorld sourceWorld = (DiscreteDynamicsWorld)bw.world;

        BulletSharp.RigidBody   bulletBallRb = null;
        BulletSharp.Math.Matrix mm           = BulletSharp.Math.Matrix.Identity;
        for (int i = 0; i < sourceWorld.NumCollisionObjects; i++)
        {
            CollisionObject co = sourceWorld.CollisionObjectArray[i];
            if (co != null && co.UserObject is BRigidBody)
            {
                BRigidBody      rb            = (BRigidBody)co.UserObject;
                float           mass          = rb.isDynamic() ? rb.mass : 0f;
                BCollisionShape existingShape = rb.GetComponent <BCollisionShape>();
                CollisionShape  shape         = null;
                if (existingShape is BSphereShape)
                {
                    shape = ((BSphereShape)existingShape).CopyCollisionShape();
                }
                else if (existingShape is BBoxShape)
                {
                    shape = ((BBoxShape)existingShape).CopyCollisionShape();
                }

                RigidBody bulletRB = null;
                BulletSharp.Math.Vector3 localInertia = new BulletSharp.Math.Vector3();
                rb.CreateOrConfigureRigidBody(ref bulletRB, ref localInertia, shape, null);
                BulletSharp.Math.Vector3    pos = rb.GetCollisionObject().WorldTransform.Origin;
                BulletSharp.Math.Quaternion rot = rb.GetCollisionObject().WorldTransform.GetOrientation();
                BulletSharp.Math.Matrix.AffineTransformation(1f, ref rot, ref pos, out mm);
                bulletRB.WorldTransform = mm;
                World.AddRigidBody(bulletRB, rb.groupsIBelongTo, rb.collisionMask);
                if (rb == ballRb)
                {
                    bulletBallRb = bulletRB;
                    bulletRB.ApplyCentralImpulse(ballThrowForce.ToBullet());
                }
            }
        }

        //Step the simulation numberOfSimulationSteps times
        for (int i = 0; i < numberOfSimulationSteps; i++)
        {
            int numSteps = World.StepSimulation(1f / 60f, 10, 1f / 60f);
            ballPositions.Add(bulletBallRb.WorldTransform.Origin.ToUnity());
        }

        UnityEngine.Debug.Log("ExitPhysics");
        if (World != null)
        {
            //remove/dispose constraints
            int i;
            for (i = World.NumConstraints - 1; i >= 0; i--)
            {
                TypedConstraint constraint = World.GetConstraint(i);
                World.RemoveConstraint(constraint);
                constraint.Dispose();
            }

            //remove the rigidbodies from the dynamics world and delete them
            for (i = World.NumCollisionObjects - 1; i >= 0; i--)
            {
                CollisionObject obj  = World.CollisionObjectArray[i];
                RigidBody       body = obj as RigidBody;
                if (body != null && body.MotionState != null)
                {
                    body.MotionState.Dispose();
                }
                World.RemoveCollisionObject(obj);
                obj.Dispose();
            }

            World.Dispose();
            Broadphase.Dispose();
            Dispatcher.Dispose();
            CollisionConf.Dispose();
        }

        if (Broadphase != null)
        {
            Broadphase.Dispose();
        }
        if (Dispatcher != null)
        {
            Dispatcher.Dispose();
        }
        if (CollisionConf != null)
        {
            CollisionConf.Dispose();
        }

        return(ballPositions);
    }
コード例 #8
0
        // Update is called once per frame
        public override void Update()
        {
            Ray ray = UnityEngine.Camera.main.ScreenPointToRay(UnityEngine.Input.mousePosition);

            BulletSharp.Math.Vector3 start = ray.origin.ToBullet();
            BulletSharp.Math.Vector3 end   = ray.GetPoint(200).ToBullet();

            //Creates a callback result that will be updated if we do a ray test with it
            ClosestRayResultCallback rayResult = new ClosestRayResultCallback(ref start, ref end);

            //Retrieves the bullet physics world and does a ray test with the given coordinates and updates the callback object
            BPhysicsWorld world = BPhysicsWorld.Get();

            world.world.RayTest(start, end, rayResult);

            //If there is a collision object and it is dynamic and not a robot part, change the gamepiece to that
            if (rayResult.CollisionObject != null)
            {
                GameObject collisionObject = (rayResult.CollisionObject.UserObject as BRigidBody).gameObject;
                if (rayResult.CollisionObject.CollisionFlags == BulletSharp.CollisionFlags.StaticObject)
                {
                    RevertNodeColors(hoveredNode, hoveredColors);
                }
                else if (collisionObject == null)
                {
                    RevertNodeColors(hoveredNode, hoveredColors);
                }
                else if (collisionObject.transform.parent == StateMachine.SceneGlobal.FindState <MainState>().ActiveRobot.transform)
                {
                    if (hoveredNode != collisionObject)
                    {
                        RevertNodeColors(hoveredNode, hoveredColors);
                    }

                    hoveredNode = collisionObject;

                    ChangeNodeColors(hoveredNode, hoverColor, hoveredColors);
                    if (UnityEngine.Input.GetMouseButtonUp(0))
                    {
                        if (camera)
                        {
                            robotCameraManager.CurrentCamera.transform.parent = hoveredNode.transform;
                        }
                        else
                        {
                            currentSensor.gameObject.transform.parent = hoveredNode.transform;
                        }
                        ReturnToMainState();
                    }
                }
                else
                {
                    RevertNodeColors(hoveredNode, hoveredColors);
                }
            }
            if (UnityEngine.Input.GetKeyDown(KeyCode.Escape))
            {
                ReturnToMainState();
            }
            if (EventSystem.current.currentSelectedGameObject == highlightButton.gameObject && UnityEngine.Input.GetMouseButton(0))
            {
                HighlightNode();
            }
            else
            {
                RevertHighlight();
            }

            //if (highlightTimer > 0) highlightTimer--;
            //else if (highlightTimer == 0) RevertHighlight();
        }
コード例 #9
0
    /// <summary>
    /// Called after Awake() when the script instance is enabled.
    /// Initializes variables then loads the field and robot as well as setting up replay features.
    /// </summary>
    public override void Start()
    {
        AppModel.ClearError();

        //getting bullet physics information
        physicsWorld = BPhysicsWorld.Get();
        ((DynamicsWorld)physicsWorld.world).SetInternalTickCallback(BPhysicsTickListener.Instance.PhysicsTick);
        lastFrameCount = physicsWorld.frameCount;

        //setting up raycast robot tick callback
        BPhysicsTickListener.Instance.OnTick -= BRobotManager.Instance.UpdateRaycastRobots;
        BPhysicsTickListener.Instance.OnTick += BRobotManager.Instance.UpdateRaycastRobots;

        //setting up replay
        CollisionTracker = new CollisionTracker(this);

        //starts a new instance of unity packet which receives packets from the driver station
        unityPacket = new UnityPacket();
        unityPacket.Start();

        //loads all the controls
        Controls.Load();

        //If a replay has been selected, load the replay. Otherwise, load the field and robot.
        string selectedReplay = PlayerPrefs.GetString("simSelectedReplay");

        SpawnedRobots = new List <Robot>();

        if (string.IsNullOrEmpty(selectedReplay))
        {
            Tracking = true;

            if (!LoadField(PlayerPrefs.GetString("simSelectedField")))
            {
                AppModel.ErrorToMenu("Could not load field: " + PlayerPrefs.GetString("simSelectedField") + "\nHas it been moved or deleted?)");
                return;
            }

            if (!LoadRobot(PlayerPrefs.GetString("simSelectedRobot"), RobotTypeManager.IsMixAndMatch))
            {
                AppModel.ErrorToMenu("Could not load robot: " + PlayerPrefs.GetString("simSelectedRobot") + "\nHas it been moved or deleted?)");
                return;
            }

            if (RobotTypeManager.IsMixAndMatch && RobotTypeManager.HasManipulator)
            {
                Debug.Log(LoadManipulator(RobotTypeManager.ManipulatorPath) ? "Load manipulator success" : "Load manipulator failed");
            }
        }
        else
        {
            awaitingReplay = true;
            LoadReplay(selectedReplay);
        }

        //initializes the dynamic camera
        DynamicCameraObject         = GameObject.Find("Main Camera");
        dynamicCamera               = DynamicCameraObject.AddComponent <DynamicCamera>();
        DynamicCamera.MovingEnabled = true;

        sensorManager    = GameObject.Find("SensorManager").GetComponent <SensorManager>();
        sensorManagerGUI = GameObject.Find("StateMachine").GetComponent <SensorManagerGUI>();

        robotCameraManager = GameObject.Find("RobotCameraList").GetComponent <RobotCameraManager>();

        IsMetric = PlayerPrefs.GetString("Measure").Equals("Metric") ? true : false;

        StateMachine.Instance.Link <MainState>(GameObject.Find("Main Camera").transform.GetChild(0).gameObject);
        StateMachine.Instance.Link <ReplayState>(Resources.FindObjectsOfTypeAll <GameObject>().First(x => x.name.Equals("ReplayUI")));
        StateMachine.Instance.Link <SaveReplayState>(Resources.FindObjectsOfTypeAll <GameObject>().First(x => x.name.Equals("SaveReplayUI")));
    }
コード例 #10
0
        internal override bool _BuildConstraint()
        {
            BPhysicsWorld world = BPhysicsWorld.Get();

            if (m_constraintPtr != null && m_isInWorld && world != null)
            {
                m_isInWorld = false;
                world.RemoveConstraint(m_constraintPtr);
            }

            BRigidBody targetRigidBodyA = GetComponent <BRigidBody>();

            if (targetRigidBodyA == null)
            {
                Debug.LogError("Fixed Constraint needs to be added to a component with a BRigidBody.");
                return(false);
            }

            if (!targetRigidBodyA.isInWorld)
            {
                world.AddRigidBody(targetRigidBodyA);
            }

            RigidBody rba = (RigidBody)targetRigidBodyA.GetCollisionObject();

            if (rba == null)
            {
                Debug.LogError("Constraint could not get bullet RigidBody from target rigid body");
                return(false);
            }

            if (m_otherRigidBody == null)
            {
                Debug.LogError("Other rigid body is not set");
                return(false);
            }

            if (!m_otherRigidBody.isInWorld)
            {
                world.AddRigidBody(m_otherRigidBody);
            }

            RigidBody rbb = (RigidBody)m_otherRigidBody.GetCollisionObject();

            if (rbb == null)
            {
                Debug.LogError("Constraint could not get bullet RigidBody from target rigid body");
                return(false);
            }

            initialTransform = BM.Matrix.AffineTransformation(1f, localRotationOffset.ToBullet(), m_localConstraintPoint.ToBullet());

            m_constraintPtr = new FixedConstraint(rba, rbb, BM.Matrix.Identity, initialTransform)
            {
                Userobject                  = this,
                DebugDrawSize               = m_debugDrawSize,
                BreakingImpulseThreshold    = m_breakingImpulseThreshold,
                OverrideNumSolverIterations = m_overrideNumSolverIterations
            };

            return(true);
        }
コード例 #11
0
ファイル: MainState.cs プロジェクト: ezhangle/synthesis
        /// <summary>
        /// Called after Awake() when the script instance is enabled.
        /// Initializes variables then loads the field and robot as well as setting up replay features.
        /// </summary>
        public override void Start()
        {
            AppModel.ClearError();

            //getting bullet physics information
            physicsWorld = BPhysicsWorld.Get();
            ((DynamicsWorld)physicsWorld.world).SetInternalTickCallback(BPhysicsTickListener.Instance.PhysicsTick);
            lastFrameCount = physicsWorld.frameCount;

            //setting up raycast robot tick callback
            BPhysicsTickListener.Instance.OnTick -= BRobotManager.Instance.UpdateRaycastRobots;
            BPhysicsTickListener.Instance.OnTick += BRobotManager.Instance.UpdateRaycastRobots;

            //starts a new instance of unity packet which receives packets from the driver station
            unityPacket.Start();

            //If a replay has been selected, load the replay. Otherwise, load the field and robot.
            string selectedReplay = PlayerPrefs.GetString("simSelectedReplay");

            if (string.IsNullOrEmpty(selectedReplay))
            {
                Tracking = true;

                if (!LoadField(PlayerPrefs.GetString("simSelectedField")))
                {
                    AppModel.ErrorToMenu("Could not load field: " + PlayerPrefs.GetString("simSelectedField") + "\nHas it been moved or deleted?)");
                    return;
                }

                if (!LoadRobot(PlayerPrefs.GetString("simSelectedRobot"), RobotTypeManager.IsMixAndMatch))
                {
                    AppModel.ErrorToMenu("Could not load robot: " + PlayerPrefs.GetString("simSelectedRobot") + "\nHas it been moved or deleted?)");
                    return;
                }

                reset = FieldDataHandler.robotSpawn == new Vector3(99999, 99999, 99999);

                if (RobotTypeManager.IsMixAndMatch && RobotTypeManager.HasManipulator)
                {
                    Debug.Log(LoadManipulator(RobotTypeManager.ManipulatorPath) ? "Load manipulator success" : "Load manipulator failed");
                }
            }
            else
            {
                awaitingReplay = true;
                LoadReplay(selectedReplay);
            }

            //initializes the dynamic camera
            DynamicCameraObject          = GameObject.Find("Main Camera");
            dynamicCamera                = DynamicCameraObject.AddComponent <DynamicCamera>();
            DynamicCamera.ControlEnabled = true;

            sensorManager    = GameObject.Find("SensorManager").GetComponent <SensorManager>();
            sensorManagerGUI = StateMachine.gameObject.GetComponent <SensorManagerGUI>();

            simUI = StateMachine.SceneGlobal.GetComponent <SimUI>();

            robotCameraManager = GameObject.Find("RobotCameraList").GetComponent <RobotCameraManager>();

            IsMetric = PlayerPrefs.GetString("Measure").Equals("Metric") ? true : false;

            StateMachine.Link <MainState>(GameObject.Find("Main Camera").transform.GetChild(0).gameObject);
            StateMachine.Link <MainState>(GameObject.Find("Main Camera").transform.GetChild(1).gameObject, false);
            StateMachine.Link <ReplayState>(Auxiliary.FindGameObject("ReplayUI"));
            StateMachine.Link <SaveReplayState>(Auxiliary.FindGameObject("SaveReplayUI"));
            StateMachine.Link <GamepieceSpawnState>(Auxiliary.FindGameObject("ResetGamepieceSpawnpointUI"));
            StateMachine.Link <DefineNodeState>(Auxiliary.FindGameObject("DefineNodeUI"));
            StateMachine.Link <GoalState>(Auxiliary.FindGameObject("GoalStateUI"));
            StateMachine.Link <SensorSpawnState>(Auxiliary.FindGameObject("ResetSensorSpawnpointUI"));
            StateMachine.Link <DefineSensorAttachmentState>(Auxiliary.FindGameObject("DefineSensorAttachmentUI"));

            string defaultDirectory = (Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + @"Autodesk\Synthesis\Emulator");
            string directoryPath    = "";

            if (Directory.Exists(defaultDirectory))
            {
                directoryPath         = defaultDirectory;
                isEmulationDownloaded = true;
            }
        }
コード例 #12
0
 public override void BOnCollisionExit(CollisionObject other)
 {
     Debug.Log("On Collision Exit " + BPhysicsWorld.Get().frameCount);
 }
コード例 #13
0
ファイル: MainState.cs プロジェクト: solomondg/synthesis
    /// <summary>
    /// Called after Awake() when the script instance is enabled.
    /// Initializes variables then loads the field and robot as well as setting up replay features.
    /// </summary>
    public override void Start()
    {
        AppModel.ClearError();

        //getting bullet physics information
        physicsWorld = BPhysicsWorld.Get();
        ((DynamicsWorld)physicsWorld.world).SetInternalTickCallback(BPhysicsTickListener.Instance.PhysicsTick);
        lastFrameCount = physicsWorld.frameCount;

        //setting up raycast robot tick callback
        BPhysicsTickListener.Instance.OnTick += BRobotManager.Instance.UpdateRaycastRobots;

        //setting up replay
        CollisionTracker = new CollisionTracker(this);

        //starts a new instance of unity packet which receives packets from the driver station
        unityPacket = new UnityPacket();
        unityPacket.Start();

        //loads all the controls
        Controls.Load();

        //If a replay has been selected, load the replay. Otherwise, load the field and robot.
        string selectedReplay = PlayerPrefs.GetString("simSelectedReplay");

        SpawnedRobots = new List <Robot>();

        if (string.IsNullOrEmpty(selectedReplay))
        {
            Tracking  = true;
            fieldPath = PlayerPrefs.GetString("simSelectedField");
            robotPath = PlayerPrefs.GetString("simSelectedRobot");
            Debug.Log(RobotFieldLoader.LoadField(fieldPath) ? "Load field success!" : "Load field failed.");
            Debug.Log(LoadRobot(robotPath) ? "Load robot success!" : "Load robot failed.");

            if (!LoadRobot(PlayerPrefs.GetString("simSelectedRobot")))
            {
                AppModel.ErrorToMenu("Could not load robot: " + PlayerPrefs.GetString("simSelectedRobot") + "\nHas it been moved or deleted?)");
                return;
            }

            int isMixAndMatch  = PlayerPrefs.GetInt("mixAndMatch", 0); // 0 is false, 1 is true
            int hasManipulator = PlayerPrefs.GetInt("hasManipulator");
            if (isMixAndMatch == 1 && hasManipulator == 1)
            {
                Debug.Log(LoadManipulator(PlayerPrefs.GetString("simSelectedManipulator")) ? "Load manipulator success" : "Load manipulator failed");
            }
        }
        else
        {
            awaitingReplay = true;
            LoadReplay(selectedReplay);
        }

        //initializes the dynamic camera
        dynamicCameraObject         = GameObject.Find("Main Camera");
        dynamicCamera               = dynamicCameraObject.AddComponent <DynamicCamera>();
        DynamicCamera.MovingEnabled = true;

        sensorManager    = GameObject.Find("SensorManager").GetComponent <SensorManager>();
        sensorManagerGUI = GameObject.Find("StateMachine").GetComponent <SensorManagerGUI>();

        robotCameraManager = GameObject.Find("RobotCameraList").GetComponent <RobotCameraManager>();

        ScoreZoneSimSceneManager scoreZoneSimSceneManager = GameObject.Find("StateMachine").GetComponent <ScoreZoneSimSceneManager>();

        scoreZoneSimSceneManager.LoadScoreZones();
    }
コード例 #14
0
 public override void BOnTriggerEnter(CollisionObject other, AlignedManifoldArray details)
 {
     Debug.Log("Enter with " + other.UserObject + " fixedFrame " + BPhysicsWorld.Get().frameCount);
 }
コード例 #15
0
 public override void BOnTriggerExit(CollisionObject other)
 {
     Debug.Log("Exit with " + other.UserObject + " fixedFrame " + BPhysicsWorld.Get().frameCount);
 }
コード例 #16
0
        // Update is called once per frame
        public override void Update()
        {
            Ray ray = UnityEngine.Camera.main.ScreenPointToRay(UnityEngine.Input.mousePosition);

            BulletSharp.Math.Vector3 start = ray.origin.ToBullet();
            BulletSharp.Math.Vector3 end   = ray.GetPoint(200).ToBullet();

            //Creates a callback result that will be updated if we do a ray test with it
            ClosestRayResultCallback rayResult = new ClosestRayResultCallback(ref start, ref end);

            //Retrieves the bullet physics world and does a ray test with the given coordinates and updates the callback object
            BPhysicsWorld world = BPhysicsWorld.Get();

            world.world.RayTest(start, end, rayResult);

            //If there is a collision object and it is dynamic and not a robot part, change the gamepiece to that
            if (rayResult.CollisionObject != null)
            {
                GameObject collisionObject = (rayResult.CollisionObject.UserObject as BRigidBody).gameObject;
                if (rayResult.CollisionObject.CollisionFlags == BulletSharp.CollisionFlags.StaticObject)
                {
                    RevertNodeColors(hoveredNode, hoveredColors);
                }
                else if (collisionObject == null)
                {
                    RevertNodeColors(hoveredNode, hoveredColors);
                }
                else if (collisionObject.transform.parent == t)
                {
                    if (hoveredNode != collisionObject)
                    {
                        RevertNodeColors(hoveredNode, hoveredColors);
                    }

                    hoveredNode = collisionObject;

                    ChangeNodeColors(hoveredNode, hoverColor, hoveredColors);
                    if (UnityEngine.Input.GetMouseButtonUp(0))
                    {
                        if (intake)
                        {
                            DPMDataHandler.dpmodes.Find(d => d.Equals(dp)).intakeNode = hoveredNode.name;
                        }
                        else
                        {
                            DPMDataHandler.dpmodes.Find(d => d.Equals(dp)).releaseNode = hoveredNode.name;
                        }
                        DPMDataHandler.WriteRobot();
                        dpr.SetAllInteractors();
                        ReturnToMainState();
                    }
                }
                else
                {
                    RevertNodeColors(hoveredNode, hoveredColors);
                }
            }
            if (UnityEngine.Input.GetKeyDown(KeyCode.Escape))
            {
                ReturnToMainState();
            }
            if (EventSystem.current.currentSelectedGameObject == highlightButton.gameObject && UnityEngine.Input.GetMouseButton(0))
            {
                HighlightNode();
            }
            else
            {
                RevertHighlight();
            }
        }
コード例 #17
0
ファイル: Main.cs プロジェクト: aaroncohen73/synthesis
 void Awake()
 {
     GImpactCollisionAlgorithm.RegisterAlgorithm((CollisionDispatcher)BPhysicsWorld.Get().world.Dispatcher);
     BPhysicsWorld.Get().DebugDrawMode = DebugDrawModes.DrawWireframe | DebugDrawModes.DrawConstraints | DebugDrawModes.DrawConstraintLimits;
     BPhysicsWorld.Get().DoDebugDraw   = true;
 }
コード例 #18
0
    public int AddLinkToMultiBody(BMultiBody mb, int currentLinkIndex, int parentIndex, Transform parent)
    {
        if (isLinked)
        {
            Debug.LogErrorFormat("Cannot add link {0} to multibody {1} bacause it is already linked", name, mb.name);
            return(0);
        }

        BCollisionShape collisionShape = GetComponent <BCollisionShape>();

        if (collisionShape == null)
        {
            throw new MissingComponentException("Could not find " + typeof(BCollisionShape).Name + " component on BodyLink " + name);
        }

        multiBody       = mb;
        linkId          = currentLinkIndex;
        parentLinkId    = parentIndex;
        parentTransform = parent;

        CollisionShape shape = collisionShape.GetCollisionShape();

        if (shape == null)
        {
            throw new MissingComponentException("Could not get collision shape from " + collisionShape.GetType().Name + " shape component on BodyLink " + name);
        }
        BulletSharp.Math.Vector3 linkInertia;
        shape.CalculateLocalInertia(Mass, out linkInertia);

        if (BPhysicsWorld.Get().debugType >= BulletUnity.Debugging.BDebug.DebugType.Debug)
        {
            Debug.LogFormat(this, "Adding link {0} : {1} to parent {2} of multibody {3}", currentLinkIndex, name, parentIndex, mb.name);
        }


        SetupLink(linkInertia);

        linkCollider = new MultiBodyLinkCollider(mb.MultiBody, currentLinkIndex);
        linkCollider.CollisionShape  = shape;
        linkCollider.WorldTransform  = transform.localToWorldMatrix.ToBullet();
        linkCollider.CollisionFlags  = collisionFlags;
        linkCollider.Friction        = Friction;
        linkCollider.RollingFriction = RollingFriction;
        linkCollider.Restitution     = Restitution;
        linkCollider.UserObject      = this;
        BPhysicsWorld.Get().world.AddCollisionObject(linkCollider, groupsIBelongTo, collisionMask);
        m_collisionObject = linkCollider;

        BulletMultiBodyLinkColliderProxy proxy = gameObject.GetComponent <BulletMultiBodyLinkColliderProxy>();

        if (proxy == null)
        {
            proxy = gameObject.AddComponent <BulletMultiBodyLinkColliderProxy>();
        }

        mb.MultiBody.GetLink(currentLinkIndex).Collider = linkCollider;
        proxy.target = linkCollider;

        isLinked = true;

        foreach (BMultiBodyConstraint mbc in Constraints)
        {
            mbc.AddConstraintToMultiBody(MultiBody, LinkId);
        }

        int addedLinks = 1;

        for (int i = 0; i < Links.Count; ++i)
        {
            addedLinks += Links[i].AddLinkToMultiBody(mb, i + currentLinkIndex + 1, currentLinkIndex, transform);
        }
        return(addedLinks);
    }
コード例 #19
0
        /// <summary>
        /// Called after Awake() when the script instance is enabled.
        /// Initializes variables then loads the field and robot as well as setting up replay features.
        /// </summary>
        public override void Start()
        {
            AppModel.ClearError();

            //getting bullet physics information
            physicsWorld = BPhysicsWorld.Get();
            ((DynamicsWorld)physicsWorld.world).SetInternalTickCallback(BPhysicsTickListener.Instance.PhysicsTick);
            lastFrameCount = physicsWorld.frameCount;

            //setting up raycast robot tick callback
            BPhysicsTickListener.Instance.OnTick -= BRobotManager.Instance.UpdateRaycastRobots;
            BPhysicsTickListener.Instance.OnTick += BRobotManager.Instance.UpdateRaycastRobots;

            //If a replay has been selected, load the replay. Otherwise, load the field and robot.
            string selectedReplay = PlayerPrefs.GetString("simSelectedReplay");

            if (PlayerPrefs.GetString("simSelectedRobot", "").Equals(""))
            {
                AppModel.ErrorToMenu("ROBOT_SELECT|FIRST");
                return;
            }

            if (string.IsNullOrEmpty(selectedReplay))
            {
                Tracking = true;

                if (!LoadField(PlayerPrefs.GetString("simSelectedField")))
                {
                    //AppModel.ErrorToMenu("FIELD_SELECT|FIRST");
                    AppModel.ErrorToMenu("FIELD_SELECT|Could not load field: " + PlayerPrefs.GetString("simSelectedField") + "\nHas it been moved or deleted?)");
                    return;
                }
                else
                {
                    MovePlane();
                }

                bool result = false;

                try
                {
                    result = LoadRobot(PlayerPrefs.GetString("simSelectedRobot"), false);
                }
                catch (Exception e)
                {
                    MonoBehaviour.Destroy(GameObject.Find("Robot"));
                }

                if (!result)
                {
                    AppModel.ErrorToMenu("ROBOT_SELECT|Could not find the selected robot");
                    return;
                }

                reset = FieldDataHandler.robotSpawn == new Vector3(99999, 99999, 99999);

                if (RobotTypeManager.IsMixAndMatch && RobotTypeManager.HasManipulator)
                {
                    Debug.Log(LoadManipulator(RobotTypeManager.ManipulatorPath) ? "Load manipulator success" : "Load manipulator failed");
                }
            }
            else
            {
                awaitingReplay = true;
                PlayerPrefs.SetString("simSelectedReplay", "");
                LoadReplay(selectedReplay);
            }

            //initializes the dynamic camera
            DynamicCameraObject          = GameObject.Find("Main Camera");
            dynamicCamera                = DynamicCameraObject.AddComponent <DynamicCamera>();
            DynamicCamera.ControlEnabled = true;

            sensorManager    = GameObject.Find("SensorManager").GetComponent <SensorManager>();
            sensorManagerGUI = StateMachine.gameObject.GetComponent <SensorManagerGUI>();

            simUI = StateMachine.SceneGlobal.GetComponent <SimUI>();

            robotCameraManager = GameObject.Find("RobotCameraList").GetComponent <RobotCameraManager>();

            IsMetric = PlayerPrefs.GetString("Measure").Equals("Metric");

            StateMachine.Link <MainState>(GameObject.Find("Main Camera").transform.GetChild(0).gameObject);
            StateMachine.Link <MainState>(GameObject.Find("Main Camera").transform.GetChild(1).gameObject, false);
            StateMachine.Link <ReplayState>(Auxiliary.FindGameObject("ReplayUI"));
            StateMachine.Link <SaveReplayState>(Auxiliary.FindGameObject("SaveReplayUI"));
            StateMachine.Link <GamepieceSpawnState>(Auxiliary.FindGameObject("ResetGamepieceSpawnpointUI"));
            StateMachine.Link <DefineNodeState>(Auxiliary.FindGameObject("DefineNodeUI"));
            StateMachine.Link <GoalState>(Auxiliary.FindGameObject("GoalStateUI"));
            StateMachine.Link <SensorSpawnState>(Auxiliary.FindGameObject("ResetSensorSpawnpointUI"));
            StateMachine.Link <DefineSensorAttachmentState>(Auxiliary.FindGameObject("DefineSensorAttachmentUI"));

            MediaManager.getInstance();

            Controls.Load();
            Controls.UpdateFieldControls();
            Controls.Save(true);
        }
コード例 #20
0
        /// <summary>
        /// Builds the constraint.
        /// </summary>
        /// <returns></returns>
        internal override bool _BuildConstraint()
        {
            BPhysicsWorld world = BPhysicsWorld.Get();

            if (m_constraintPtr != null)
            {
                if (m_isInWorld && world != null)
                {
                    m_isInWorld = false;
                    world.RemoveConstraint(m_constraintPtr);
                }
            }
            BRigidBody targetRigidBodyA = GetComponent <BRigidBody>();

            if (targetRigidBodyA == null)
            {
                Debug.LogError("BHingedConstraint needs to be added to a component with a BRigidBody.");
                return(false);
            }
            if (!targetRigidBodyA.isInWorld)
            {
                world.AddRigidBody(targetRigidBodyA);
            }
            if (m_localConstraintAxisX == Vector3.zero)
            {
                Debug.LogError("Constaint axis cannot be zero vector");
                return(false);
            }
            RigidBody rba = (RigidBody)targetRigidBodyA.GetCollisionObject();

            if (rba == null)
            {
                Debug.LogError("Constraint could not get bullet RigidBody from target rigid body");
                return(false);
            }
            if (m_constraintType == ConstraintType.constrainToAnotherBody)
            {
                if (m_otherRigidBody == null)
                {
                    Debug.LogError("Other rigid body must not be null");
                    return(false);
                }
                if (!m_otherRigidBody.isInWorld)
                {
                    world.AddRigidBody(m_otherRigidBody);
                }
                RigidBody rbb = (RigidBody)m_otherRigidBody.GetCollisionObject();
                if (rbb == null)
                {
                    Debug.LogError("Constraint could not get bullet RigidBody from target rigid body");
                    return(false);
                }

                m_constraintPtr = new HingeConstraint(rba, rbb, m_localConstraintPoint.ToBullet(),
                                                      m_otherRigidBody.transform.InverseTransformPoint(transform.TransformPoint(m_localConstraintPoint)).ToBullet(),
                                                      m_axisInA.ToBullet(), m_axisInB.ToBullet());
            }
            else
            {
                m_constraintPtr = new HingeConstraint(rba, m_localConstraintPoint.ToBullet(), m_axisInA.ToBullet(), false);
            }
            if (m_enableMotor)
            {
                ((HingeConstraint)m_constraintPtr).EnableAngularMotor(true, m_targetMotorAngularVelocity, m_maxMotorImpulse);
            }
            if (m_setLimit)
            {
                ((HingeConstraint)m_constraintPtr).SetLimit(m_lowLimitAngleRadians, m_highLimitAngleRadians, m_limitSoftness, m_limitBiasFactor);
            }
            m_constraintPtr.Userobject                  = this;
            m_constraintPtr.DebugDrawSize               = m_debugDrawSize;
            m_constraintPtr.BreakingImpulseThreshold    = m_breakingImpulseThreshold;
            m_constraintPtr.OverrideNumSolverIterations = m_overrideNumSolverIterations;
            return(true);
        }
コード例 #21
0
    /// <summary>
    /// Allows the user to select a robot node with their mouse and change the intake/release node
    /// </summary>
    /// <param name="index">configuring index</param>
    public void SetMechanism(int index)
    {
        //Casts a ray from the camera in the direction the mouse is in and returns the closest object hit
        Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);

        BulletSharp.Math.Vector3 start = ray.origin.ToBullet();
        BulletSharp.Math.Vector3 end   = ray.GetPoint(200).ToBullet();

        //Creates a callback result that will be updated if we do a ray test with it
        ClosestRayResultCallback rayResult = new ClosestRayResultCallback(ref start, ref end);

        //Retrieves the bullet physics world and does a ray test with the given coordinates and updates the callback object
        BPhysicsWorld world = BPhysicsWorld.Get();

        world.world.RayTest(start, end, rayResult);

        //If there is a collision object and it is dynamic and not a robot part, change the gamepiece to that
        if (rayResult.CollisionObject != null)
        {
            string name = (rayResult.CollisionObject.UserObject.ToString().Replace(" (BulletUnity.BRigidBody)", ""));
            Debug.Log(name);
            if (rayResult.CollisionObject.CollisionFlags == BulletSharp.CollisionFlags.StaticObject)
            {
                UserMessageManager.Dispatch("Please click on a robot part", 3);
            }
            else if (GameObject.Find(name) == null)
            {
                Debug.Log("DPM: Game object not found");
            }
            else if (GameObject.Find(name).transform.parent == transform)
            {
                if (definingIntake)
                {
                    intakeNode[index] = GameObject.Find(name);
                    SetInteractor(intakeNode[index], index);

                    UserMessageManager.Dispatch(name + " has been selected as intake node", 5);

                    definingIntake = false;
                }
                else
                {
                    releaseNode[index] = GameObject.Find(name);
                    SetInteractor(releaseNode[index], index);

                    UserMessageManager.Dispatch(name + " has been selected as release node", 5);

                    definingRelease = false;
                }

                RevertNodeColors(hoveredNode, hoveredColors);
            }
            else
            {
                UserMessageManager.Dispatch("A gamepiece is NOT a robot part!", 3);
            }
        }
        else
        {
        }
    }
コード例 #22
0
    /// <summary>
    /// Handles the ruler animation and display values
    /// </summary>
    private void ClickRuler()
    {
        //Casts a ray from the camera in the direction the mouse is in and returns the closest object hit
        Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);

        BulletSharp.Math.Vector3 start = ray.origin.ToBullet();
        BulletSharp.Math.Vector3 end   = ray.GetPoint(200).ToBullet();

        //Creates a callback result that will be updated if we do a ray test with it
        ClosestRayResultCallback rayResult = new ClosestRayResultCallback(ref start, ref end);

        //Retrieves the bullet physics world and does a ray test with the given coordinates and updates the callback object
        BPhysicsWorld world = BPhysicsWorld.Get();

        world.world.RayTest(start, end, rayResult);

        if (rayResult.CollisionObject != null)
        {
            if (Input.GetMouseButtonDown(0))
            {
                if (firstPoint == BulletSharp.Math.Vector3.Zero)
                {
                    rulerStartPoint.GetComponent <LineRenderer>().enabled = true;
                    rulerStartPoint.GetComponent <LineRenderer>().SetPosition(0, rulerStartPoint.transform.position);
                    rulerEndPoint.SetActive(true);
                    firstPoint = rayResult.HitPointWorld;
                }
                else
                {
                    DisableRuler();
                }
            }

            if (firstPoint != null)
            {
                Debug.DrawRay(firstPoint.ToUnity(), Vector3.up);
            }
            if (firstPoint == BulletSharp.Math.Vector3.Zero)
            {
                rulerStartPoint.transform.position = rayResult.HitPointWorld.ToUnity();
            }
            //Display different values based on the measure system it's currently using
            else if (!mainState.IsMetric)
            {
                rulerText.text  = Mathf.Round(BulletSharp.Math.Vector3.Distance(firstPoint, rayResult.HitPointWorld) * 328.084f) / 100 + "ft";
                rulerXText.text = Mathf.Round(Mathf.Abs(firstPoint.X - rayResult.HitPointWorld.X) * 328.084f) / 100 + "ft";
                rulerYText.text = Mathf.Round(Mathf.Abs(firstPoint.Y - rayResult.HitPointWorld.Y) * 328.084f) / 100 + "ft";
                rulerZText.text = Mathf.Round(Mathf.Abs(firstPoint.Z - rayResult.HitPointWorld.Z) * 328.084f) / 100 + "ft";
                rulerEndPoint.transform.position = rayResult.HitPointWorld.ToUnity();
                rulerStartPoint.GetComponent <LineRenderer>().SetPosition(1, rulerEndPoint.transform.position);
            }
            else
            {
                rulerText.text  = Mathf.Round(BulletSharp.Math.Vector3.Distance(firstPoint, rayResult.HitPointWorld) * 100f) / 100 + "m";
                rulerXText.text = Mathf.Round(Mathf.Abs(firstPoint.X - rayResult.HitPointWorld.X) * 1000f) / 1000 + "m";
                rulerYText.text = Mathf.Round(Mathf.Abs(firstPoint.X - rayResult.HitPointWorld.X) * 1000f) / 1000 + "m";
                rulerZText.text = Mathf.Round(Mathf.Abs(firstPoint.X - rayResult.HitPointWorld.X) * 1000f) / 1000 + "m";
                rulerEndPoint.transform.position = rayResult.HitPointWorld.ToUnity();
                rulerStartPoint.GetComponent <LineRenderer>().SetPosition(1, rulerEndPoint.transform.position);
            }
        }
    }
コード例 #23
0
    /// <summary>
    /// Set the node where the camera will be attached to
    /// </summary>
    public void SetNode()
    {
        //Casts a ray from the camera in the direction the mouse is in and returns the closest object hit
        Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);

        BulletSharp.Math.Vector3 start = ray.origin.ToBullet();
        BulletSharp.Math.Vector3 end   = ray.GetPoint(200).ToBullet();

        //Creates a callback result that will be updated if we do a ray test with it
        ClosestRayResultCallback rayResult = new ClosestRayResultCallback(ref start, ref end);

        //Retrieves the bullet physics world and does a ray test with the given coordinates and updates the callback object
        BPhysicsWorld world = BPhysicsWorld.Get();

        world.world.RayTest(start, end, rayResult);

        //Debug.Log("Selected:" + rayResult.CollisionObject);
        //If there is a collision object and it is a robot part, set that to be new attachment point
        if (rayResult.CollisionObject != null)
        {
            GameObject selectedObject = ((BRigidBody)rayResult.CollisionObject.UserObject).gameObject;
            if (selectedObject.transform.parent != null && selectedObject.transform.parent.name == "Robot")
            {
                //Change highlight target when the mouse point to a different object
                if (lastNode != null && !selectedObject.Equals(lastNode))
                {
                    RevertNodeColors(lastNode, hoveredColors);
                    lastNode = null;
                }
                //Highlight the node which mouse is pointing to to yellow
                else
                {
                    ChangeNodeColors(selectedObject, hoverColor, hoveredColors);
                    lastNode = selectedObject;
                }
                //Change the color to selected color when user click and choose the node
                if (Input.GetMouseButtonDown(0))
                {
                    string name = selectedObject.name;

                    //Revert the current selection back to its original so selectedColors can store the new selection properly
                    RevertNodeColors(lastNode, hoveredColors);

                    RevertNodeColors(SelectedNode, selectedColors);

                    SelectedNode = selectedObject;
                    ChangeNodeColors(SelectedNode, selectedColor, selectedColors);
                    Debug.Log(selectedColors.Count);
                    UserMessageManager.Dispatch(name + " has been selected as the node for camera attachment", 5);
                }
            }
            else
            {
                //When mouse is not pointing to any robot node, set the last hovered node back to its original color
                if (lastNode != null)
                {
                    RevertNodeColors(lastNode, hoveredColors);
                    lastNode = null;
                }
                //When users try to select a non-robotNode object
                if (Input.GetMouseButtonDown(0))
                {
                    UserMessageManager.Dispatch("Please select a robot node!", 3);
                }
            }
        }
    }