Exemplo n.º 1
0
        private void ChargerPoseMessage(IChargerPoseEvent eventResponse)
        {
            // Using averaged value of charger pose.
            if (_poseLock)
            {
                return;
            }

            _poseLock = true;

            try
            {
                if (_previousChargerPose.Count > 5)
                {
                    _previousChargerPose.Dequeue();
                }

                var latestPose = new ChargerPosition()
                {
                    X = eventResponse.Pose.HomogeneousMatrix[12],
                    Y = eventResponse.Pose.HomogeneousMatrix[13],
                    Z = eventResponse.Pose.HomogeneousMatrix[14],
                    //EulerYaw = (float)(180.0 * Math.Atan2(eventResponse.Pose.HomogeneousMatrix[6], eventResponse.Pose.HomogeneousMatrix[2]) / Math.PI)
                    EulerYaw = (float)(-180.0 * Math.Asin(eventResponse.Pose.HomogeneousMatrix[2]) / Math.PI)
                };
                _previousChargerPose.Enqueue(latestPose);

                var meanPose = new ChargerPosition();
                foreach (var pose in _previousChargerPose)
                {
                    meanPose.X        += pose.X;
                    meanPose.Y        += pose.Y;
                    meanPose.Z        += pose.Z;
                    meanPose.EulerYaw += pose.EulerYaw;
                }

                meanPose.X        /= _previousChargerPose.Count;
                meanPose.Y        /= _previousChargerPose.Count;
                meanPose.Z        /= _previousChargerPose.Count;
                meanPose.EulerYaw /= _previousChargerPose.Count;

                //_skillHelper.LogMessage($"{latestPose.X} {meanPose.X}");

                // Apply offset so that we can treat charger position as relative to the center
                // of the Occipital sensor.
                meanPose.X += CENTER_OFFSET;

                //_skillHelper.LogMessage($"Charger pose: X {meanPose.X} Y {meanPose.Y} Z {meanPose.Z} EY {meanPose.EulerYaw}");

                _chargerPose = meanPose;
            }
            finally
            {
                _poseLock = false;
            }
        }
Exemplo n.º 2
0
        private async Task <bool> FindChargerAsync()
        {
            try
            {
                _skillHelper.LogMessage("Initiating search for charger.");

                // Clear pose and pause to see if we can already see the charger.
                _chargerPose = null;
                await Task.Delay(3000);

                if (_abort)
                {
                    return(false);
                }
                if (_chargerPose != null)
                {
                    _skillHelper.LogMessage($"Charger at [{_chargerPose.X:f3}, {_chargerPose.Y:f3}, {_chargerPose.Z:f3}] meters. Euler yaw is {_chargerPose.EulerYaw:f3} degrees.");
                }
                else
                {
                    // Perform a sweep to look for the charger.
                    // This is based upon the assumption that we just drove back to the charger and are roughly facing it.
                    await _skillHelper.TurnAsync(INITIAL_ROTATION_BEFORE_SWEEP);

                    _chargerPose = null;
                    if (_abort)
                    {
                        return(false);
                    }

                    if (!await SweepForCharger())
                    {
                        // Did not find charger after a full spin. Check our TOF distance assuming that charger is against a wall.
                        await _skillHelper.TurnAsync(AxisRotation(_skillHelper.ImuYaw, _initialYaw));

                        if (_abort)
                        {
                            return(false);
                        }

                        TofValues tofValues = _skillHelper.GetTofValues();
                        if (_abort)
                        {
                            return(false);
                        }
                        double?distance = tofValues.FrontCenter.HasValue ? tofValues.FrontCenter.Value : tofValues.FrontLeft.HasValue ? tofValues.FrontLeft.Value : tofValues.FrontRight.Value;
                        if (distance.HasValue)
                        {
                            // Drive to about 1 meter from wall
                            await _skillHelper.DriveAsync(distance.Value - 1.0);

                            // Sweep again.
                            await _skillHelper.TurnAsync(INITIAL_ROTATION_BEFORE_SWEEP);

                            if (_abort)
                            {
                                return(false);
                            }
                            if (!await SweepForCharger())
                            {
                                _skillHelper.LogMessage("Never found the charger.");
                                return(false);
                            }
                        }
                    }
                }
                _skillHelper.LogMessage($"Charger at [{_chargerPose.X:f3}, {_chargerPose.Y:f3}, {_chargerPose.Z:f3}] meters. Euler yaw is {_chargerPose.EulerYaw:f3} degrees.");
            }
            catch (Exception ex)
            {
                _skillHelper.LogMessage("An exception occurred within ChargerDock.FindChargerAsync: " + ex.Message);
            }

            return(true);
        }
Exemplo n.º 3
0
        private async Task <bool> ExecuteDockAsync()
        {
            _charging = false;

            // Set head position.
            await _skillHelper.MoveHeadAsync(_headPitchOffset, _headRollOffset, _headYawOffset);

            if (_abort)
            {
                return(false);
            }

            // Find the charger.
            if (!await FindChargerAsync())
            {
                return(false);
            }

            // Get Misty aligned with charger based upon charger pose X and Euler angle.
            int retries = 0;

            while (Math.Abs(_chargerPose.X) > ALIGNED_X || Math.Abs(_chargerPose.EulerYaw) > ALIGNED_EULER_YAW)
            {
                if (retries++ > ALIGN_MAX_RETRIES)
                {
                    _skillHelper.LogMessage("Failed to align with charger.");
                    return(false);
                }

                _skillHelper.LogMessage($"Charger position is [{_chargerPose.X:f3}, {_chargerPose.Y:f3}, {_chargerPose.Z:f3}] meters. Euler yaw is {_chargerPose.EulerYaw:f3} degrees.");
                await FaceChargerAsync(ALIGNED_X);

                if (_abort)
                {
                    return(false);
                }

                if (Math.Abs(_chargerPose.X) > ALIGNED_X || Math.Abs(_chargerPose.EulerYaw) > ALIGNED_EULER_YAW)
                {
                    await AlignWithChargerAsync();

                    if (Math.Abs(_chargerPose.Z - IDEAL_ALIGNMENT_DISTANCE) > .1)
                    {
                        await _skillHelper.DriveAsync(_chargerPose.Z - IDEAL_ALIGNMENT_DISTANCE);
                    }
                }
            }

            _skillHelper.LogMessage($"Charger position is [{_chargerPose.X:f3}, {_chargerPose.Y:f3}, {_chargerPose.Z:f3}] meters. Euler yaw is {_chargerPose.EulerYaw:f3} degrees.");

            // Backup and drive straight forward to check alignment.
            double chargerDistance = _chargerPose.Z;
            var    offsets         = new List <double>();
            await _skillHelper.DriveAsync(-1.0, true);

            await Task.Delay(1000);

            offsets.Add(_chargerPose.X);
            for (int i = 0; i < 6; i++)
            {
                await _skillHelper.DriveAsync(.25, true);

                await Task.Delay(1000);

                offsets.Add(_chargerPose.X);
            }
            foreach (var o in offsets)
            {
                _skillHelper.LogMessage(o.ToString("f3"));
            }
            double slope = (offsets[0] - offsets.Last()) / 1.5;
            double estimateFinalOffset = offsets.Last() - slope * 0.5;
            double offsetAngle         = -Math.Asin(estimateFinalOffset / 0.4) * 180.0 / Math.PI;

            _skillHelper.LogMessage($"Estimate final offset {estimateFinalOffset:f3} meters and {offsetAngle} degrees.");

            if (Math.Abs(offsetAngle) > FINAL_OFFSET_ANGLE_MAX)
            {
                _skillHelper.LogMessage("Offset angle is too large. Backing up and retrying dock process.");
                await _skillHelper.DriveAsync(-IDEAL_ALIGNMENT_DISTANCE + 0.25);

                return(false);
            }
            await _skillHelper.TurnAsync(offsetAngle);

            // Turn around.
            _skillHelper.LogMessage("Turning 180 degrees to face away from charger.");
            await _skillHelper.TurnAsync(-180);

            if (_abort)
            {
                return(false);
            }

            // Back on to charger.
            _skillHelper.LogMessage($"Driving {chargerDistance - 0.5 + CHARGER_DOCK_OVERSHOOT:f3} meters to back on to charger.");
            await _skillHelper.DriveAsync(-chargerDistance + 0.5 - CHARGER_DOCK_OVERSHOOT, true);

            if (_abort)
            {
                return(false);
            }

            // Check if we've ended up on top of the wedge.
            await Task.Delay(1000);

            _skillHelper.LogMessage($"Roll = {_skillHelper.ImuRoll:f3}. Pitch = {_skillHelper.ImuPitch:f3}.");
            if (Math.Abs(_skillHelper.ImuRoll) > MISTY_ON_WEDGE_ROLL || Math.Abs(AxisRotation(_initialPitch, _skillHelper.ImuPitch)) > MISTY_ON_WEDGE_PITCH)
            {
                // We're on the wedge. Drive away from the charger and try again.
                _skillHelper.LogMessage($"We appear to have driven on top of the alignment wedge. IMU roll is {_skillHelper.ImuRoll:f3}. IMU pitch is {_skillHelper.ImuPitch:f3}.");
                await _skillHelper.DriveAsync(IDEAL_ALIGNMENT_DISTANCE - 0.1);

                if (_abort)
                {
                    return(false);
                }
                await _skillHelper.TurnAsync(180);

                _chargerPose = null;
                return(false);
            }

            // Check that we're fully docked: back up a little bit to get more aligned.
            _misty.DriveHeading(0, 0.2, 500, true, OnResponse);

            // It can take several seconds for the charging indicator to update...
            await Task.Delay(7000);

            // Check that we're charging.
            if (!_charging)
            {
                _misty.PlayAudio("s_Anger3.wav", 100, OnResponse);
                await _skillHelper.DriveAsync(IDEAL_ALIGNMENT_DISTANCE - 0.1);

                if (_abort)
                {
                    return(false);
                }
                await _skillHelper.TurnAsync(180);

                _chargerPose = null;
                return(false);
            }

            _misty.PlayAudio("s_Ecstacy.wav", 100, OnResponse);

            return(true);
        }