/// <summary>
        /// Internal rotate degrees handler
        /// </summary>
        /// <param name="rotateDegrees"></param>
        /// <returns></returns>
        public virtual IEnumerator <ITask> InternalRotateDegreesHandler(drive.RotateDegrees rotateDegrees)
        {
            switch (rotateDegrees.Body.RotateDegreesStage)
            {
            case drive.DriveStage.InitialRequest:
                _state.InternalPendingDriveOperation = drive.DriveRequestOperation.RotateDegrees;
                SpawnIterator <double, double>(rotateDegrees.Body.Degrees, rotateDegrees.Body.Power, RotateUntilDegrees);
                break;

            case drive.DriveStage.Started:
                SendNotification <drive.RotateDegrees>(_subMgrPort, rotateDegrees.Body);
                break;

            case drive.DriveStage.Completed:
                _state.InternalPendingDriveOperation = drive.DriveRequestOperation.NotSpecified;
                SendNotification <drive.RotateDegrees>(_subMgrPort, rotateDegrees.Body);
                break;

            case drive.DriveStage.Canceled:
                _state.InternalPendingDriveOperation = drive.DriveRequestOperation.NotSpecified;
                SendNotification <drive.RotateDegrees>(_subMgrPort, rotateDegrees.Body);
                break;
            }

            yield break;
        }
 /// <summary>
 /// RotateDegreesUpdateHandler - Posts a message on Canceled or Completed
 /// </summary>
 /// <param name="rotate"></param>
 /// <returns></returns>
 IEnumerator <ITask> RotateDegreesUpdateHandler(drive.RotateDegrees rotate)
 {
     if (rotate.Body.RotateDegreesStage == drive.DriveStage.Canceled)
     {
         completionPort.Post(rotate.Body.RotateDegreesStage);
     }
     if (rotate.Body.RotateDegreesStage == drive.DriveStage.Completed)
     {
         completionPort.Post(rotate.Body.RotateDegreesStage);
     }
     yield break;
 }
        public IEnumerator <ITask> RotateHandler(diffdrive.RotateDegrees rotate)
        {
            if (_entity == null)
            {
                throw new InvalidOperationException("Simulation entity not registered with service");
            }

            if (!_state.IsEnabled)
            {
                rotate.ResponsePort.Post(Fault.FromException(new Exception("Drive is not enabled.")));
                LogError("RotateDegrees request to disabled drive.");
                yield break;
            }

            _state.RotateDegreesStage = rotate.Body.RotateDegreesStage;
            if (rotate.Body.RotateDegreesStage == diffdrive.DriveStage.InitialRequest)
            {
                Port <simengine.OperationResult> entityResponse = new Port <simengine.OperationResult>();
                Activate(Arbiter.Receive <simengine.OperationResult>(false, entityResponse, delegate(simengine.OperationResult result)
                {
                    // post a message to ourselves indicating that the drive distance has completed
                    diffdrive.RotateDegreesRequest req = new diffdrive.RotateDegreesRequest(0, 0);
                    switch (result)
                    {
                    case simengine.OperationResult.Error:
                        req.RotateDegreesStage = diffdrive.DriveStage.Canceled;
                        break;

                    case simengine.OperationResult.Canceled:
                        req.RotateDegreesStage = diffdrive.DriveStage.Canceled;
                        break;

                    case simengine.OperationResult.Completed:
                        req.RotateDegreesStage = diffdrive.DriveStage.Completed;
                        break;
                    }
                    _mainPort.Post(new diffdrive.RotateDegrees(req));
                }));

                _entity.RotateDegrees((float)rotate.Body.Degrees, (float)rotate.Body.Power, entityResponse);

                diffdrive.RotateDegreesRequest req2 = new diffdrive.RotateDegreesRequest(0, 0);
                req2.RotateDegreesStage = diffdrive.DriveStage.Started;
                _mainPort.Post(new diffdrive.RotateDegrees(req2));
            }
            else
            {
                base.SendNotification(_subMgrPort, rotate);
            }
            rotate.ResponsePort.Post(DefaultUpdateResponseType.Instance);
            yield break;
        }
 /// <summary>
 /// RotateDegreesUpdateHandler - Posts a message on Canceled or Complete
 /// </summary>
 /// <param name="rotate"></param>
 /// <returns></returns>
 IEnumerator <ITask> RotateDegreesUpdateHandler(drive.RotateDegrees rotate)
 {
     if (rotate.Body.RotateDegreesStage == drive.DriveStage.Canceled)
     {
         LogInfo(LogGroups.Console, "Rotate Canceled");
         completionPort.Post(rotate.Body.RotateDegreesStage);
     }
     if (rotate.Body.RotateDegreesStage == drive.DriveStage.Completed)
     {
         LogInfo(LogGroups.Console, "Rotate Complete");
         completionPort.Post(rotate.Body.RotateDegreesStage);
     }
     yield break;
 }
        public IEnumerator <ITask> RotateDegreesHandler(drive.RotateDegrees rotateDegrees)
        {
            ValidateDriveConfiguration(true);
            if (_state.DistanceBetweenWheels <= 0)
            {
                rotateDegrees.ResponsePort.Post(new Fault());
                throw new InvalidOperationException("The wheel encoders are not properly configured");
            }
            else
            {
                _state.TimeStamp = DateTime.Now;

                // send immediate response
                rotateDegrees.ResponsePort.Post(DefaultUpdateResponseType.Instance);


                // send immediate response
                rotateDegrees.ResponsePort.Post(DefaultUpdateResponseType.Instance);

                // post request to internal port.
                _internalDriveOperationsPort.Post(rotateDegrees);
            }
            yield break;
        }
        /// <summary>
        /// Rotate the the drive (positive degrees turn counterclockwise)
        /// </summary>
        /// <param name="degrees">(positive degrees turn counterclockwise)</param>
        /// <param name="power">(-1.0 to 1.0)</param>
        IEnumerator <ITask> RotateUntilDegrees(double degrees, double power)
        {
            LogInfo("^^^^^^^^^^^^^^^^^^^^^ TrackRoamerDriveService:: RotateUntilDegrees(degrees=" + degrees + ",  power=" + power + ")");

            _leftEncoderTickEnabled  = false;
            _rightEncoderTickEnabled = false;

            //reset encoders
            encoder.Reset Lreset = new encoder.Reset();
            _leftEncoderCmdPort.Post(Lreset);
            yield return(Arbiter.Choice(Lreset.ResponsePort,
                                        delegate(DefaultUpdateResponseType response) { },
                                        delegate(Fault fault) { LogError(fault); }
                                        ));

            encoder.Reset Rreset = new encoder.Reset();
            _rightEncoderCmdPort.Post(Rreset);
            yield return(Arbiter.Choice(Rreset.ResponsePort,
                                        delegate(DefaultUpdateResponseType response) { },
                                        delegate(Fault fault) { LogError(fault); }
                                        ));

            double arcDistance = Math.Abs(degrees) * _state.DistanceBetweenWheels * Math.PI / 360.0d;

            //compute tick to stop at
            stopLeftWheelAt  = (int)Math.Round(arcDistance / (2.0d * Math.PI * _state.LeftWheel.Radius / _state.LeftWheel.EncoderState.TicksPerRevolution));
            stopRightWheelAt = (int)Math.Round(arcDistance / (2.0d * Math.PI * _state.RightWheel.Radius / _state.RightWheel.EncoderState.TicksPerRevolution));

            _leftEncoderTickEnabled  = true;
            _rightEncoderTickEnabled = true;

            //start moving

            // start rotate operation
            _state.RotateDegreesStage = drive.DriveStage.Started;

            drive.RotateDegrees rotateUpdate = new drive.RotateDegrees();
            rotateUpdate.Body.RotateDegreesStage = drive.DriveStage.Started;
            _internalDriveOperationsPort.Post(rotateUpdate);

            PortSet <DefaultUpdateResponseType, Fault> responsePort = new PortSet <DefaultUpdateResponseType, Fault>();

            double rightPow;
            double leftPow;

            if (degrees > 0)
            {
                rightPow = power;
                leftPow  = -power;
            }
            else
            {
                rightPow = -power;
                leftPow  = power;
            }

            motor.SetMotorPower leftPower = new motor.SetMotorPower(new motor.SetMotorPowerRequest()
            {
                TargetPower = leftPow
            });
            leftPower.ResponsePort = responsePort;
            _leftMotorPort.Post(leftPower);

            motor.SetMotorPower rightPower = new motor.SetMotorPower(new motor.SetMotorPowerRequest()
            {
                TargetPower = rightPow
            });
            rightPower.ResponsePort = responsePort;
            _rightMotorPort.Post(rightPower);

            LogInfo("=============== TrackRoamerDriveService:: RotateUntilDegrees() start moving: degrees=" + degrees);
            LogInfo("=============== TrackRoamerDriveService:: RotateUntilDegrees() will stop wheels at:  Left=" + stopLeftWheelAt + " Right=" + stopRightWheelAt);

            Activate(Arbiter.MultipleItemReceive <DefaultUpdateResponseType, Fault>(responsePort, 2,
                                                                                    delegate(ICollection <DefaultUpdateResponseType> successList, ICollection <Fault> failureList)
            {
                foreach (Fault fault in failureList)
                {
                    LogError(fault);
                }
            }
                                                                                    ));

            LogInfo("=============== TrackRoamerDriveService:: RotateUntilDegrees() calling WaitForCompletion() - waiting for the first side to complete...");

            yield return(WaitForCompletion());

            LogInfo("=============== TrackRoamerDriveService:: RotateUntilDegrees() calling WaitForCompletion() - other side should complete too...");

            yield return(WaitForCompletion());

            LogInfo("=============== TrackRoamerDriveService:: RotateUntilDegrees() - both sides completed, send notification of RotateDegrees complete to subscription manager");

            // send notification of RotateDegrees complete to subscription manager
            rotateUpdate.Body.RotateDegreesStage = drive.DriveStage.Completed;
            _internalDriveOperationsPort.Post(rotateUpdate);

            _state.RotateDegreesStage = drive.DriveStage.Completed;
        }
Example #7
0
 public IEnumerator <ITask> RotateDegreesHandler(drive.RotateDegrees rotateDegrees)
 {
     LogError("Rotate degrees is not implemented");
     yield break;
 }
Example #8
0
 public virtual IEnumerator <ITask> RotateDegreesHandler(drive.RotateDegrees update)
 {
     // TODO: Implement RotateDegrees operation here.
     throw new NotImplementedException("RotateDegrees is not Implemented.");
 }
        private void cancelCurrentOperation()
        {
            switch (_internalPendingDriveOperation)
            {
                case drive.DriveRequestOperation.DriveDistance:
                    {
            #if TRACELOG
                        Tracer.Trace("cancelCurrentOperation() - DriveDistance - completionPort.ItemCount=" + completionPort.ItemCount);
            #endif

                        if (pendingDriveDistance != null)
                        {
                            EncoderTicksEnabled = false;
                            // send notification to subscription manager
                            pendingDriveDistance.Body.DriveDistanceStage = drive.DriveStage.Canceled;
                            double distanceTraveled = pendingDriveDistance.Body.Distance / 2.0d;        // TODO: need to compute real distance traveled
                            pendingDriveDistance.Body.Distance = distanceTraveled;
                            SendNotification<drive.DriveDistance>(_subMgrPort, pendingDriveDistance);
                            pendingDriveDistance = null;
                        }
                    }
                    break;

                case drive.DriveRequestOperation.RotateDegrees:
                    {
            #if TRACELOG
                        Tracer.Trace("cancelCurrentOperation() - RotateDegrees - completionPort.ItemCount=" + completionPort.ItemCount);
            #endif

                        if (pendingRotateDegrees != null)
                        {
                            EncoderTicksEnabled = false;
                            // send notification to subscription manager
                            pendingRotateDegrees.Body.RotateDegreesStage = drive.DriveStage.Canceled;
                            double angleRotated = pendingRotateDegrees.Body.Degrees / 2.0d;             // TODO: need to compute real angle rotated
                            pendingRotateDegrees.Body.Degrees = angleRotated;
                            SendNotification<drive.RotateDegrees>(_subMgrPort, pendingRotateDegrees);
                            pendingRotateDegrees = null;
                        }
                    }
                    break;

                case drive.DriveRequestOperation.NotSpecified:
                    break;

                default:
                    Tracer.Trace("Warning: cancelCurrentOperation() - no pending wait-type operation to cancel - current operation = " + _internalPendingDriveOperation);
                    break;
            }
            _internalPendingDriveOperation = drive.DriveRequestOperation.NotSpecified;
        }
        /// <summary>
        /// Internal rotate degrees handler
        /// </summary>
        /// <param name="rotateDegrees"></param>
        /// <returns></returns>
        public virtual IEnumerator<ITask> InternalRotateDegreesHandler(drive.RotateDegrees rotateDegrees)
        {
            #if TRACELOG
            Tracer.Trace("InternalRotateDegreesHandler() - DriveStage." + rotateDegrees.Body.RotateDegreesStage);
            #endif

            switch (rotateDegrees.Body.RotateDegreesStage)
            {
                case drive.DriveStage.InitialRequest:
                    cancelCurrentOperation();
                    pendingRotateDegrees = rotateDegrees;
                    // _state.InternalPendingDriveOperation = drive.DriveRequestOperation.RotateDegrees; - not available in Proxy
                    _internalPendingDriveOperation = drive.DriveRequestOperation.RotateDegrees;
                    SpawnIterator<double, double>(rotateDegrees.Body.Degrees, rotateDegrees.Body.Power, RotateUntilDegrees);
                    break;

                case drive.DriveStage.Started:
                    SendNotification<drive.RotateDegrees>(_subMgrPort, rotateDegrees.Body);
                    break;

                case drive.DriveStage.Completed:
                    pendingRotateDegrees = null;
                    // _state.InternalPendingDriveOperation = drive.DriveRequestOperation.NotSpecified; - not available in Proxy
                    _internalPendingDriveOperation = drive.DriveRequestOperation.NotSpecified;
                    SendNotification<drive.RotateDegrees>(_subMgrPort, rotateDegrees.Body);
                    break;

                case drive.DriveStage.Canceled:
                    pendingRotateDegrees = null;
                    // _state.InternalPendingDriveOperation = drive.DriveRequestOperation.NotSpecified; - not available in Proxy
                    _internalPendingDriveOperation = drive.DriveRequestOperation.NotSpecified;
                    SendNotification<drive.RotateDegrees>(_subMgrPort, rotateDegrees.Body);
                    break;
            }

            yield break;
        }
        /// <summary>
        /// Rotate the the drive (positive degrees turn counterclockwise)
        /// </summary>
        /// <param name="degrees">(positive degrees turn counterclockwise)</param>
        /// <param name="power">(-1.0 to 1.0)</param>
        IEnumerator<ITask> RotateUntilDegrees(double degrees, double power)
        {
            #if TRACELOG
            Tracer.Trace("^^^^^^^^^^^^^^^^^^^^^ TrackRoamerDriveService:: RotateUntilDegrees(degrees=" + degrees + ",  power=" + power + ")");
            #endif

            EncoderTicksEnabled = false;

            //reset encoders
            encoder.Reset Lreset = new encoder.Reset();
            _leftEncoderPort.Post(Lreset);
            yield return (Arbiter.Choice(Lreset.ResponsePort,
                delegate(DefaultUpdateResponseType response) { },
                delegate(Fault fault) { LogError(fault); }
            ));

            encoder.Reset Rreset = new encoder.Reset();
            _rightEncoderPort.Post(Rreset);
            yield return (Arbiter.Choice(Rreset.ResponsePort,
                delegate(DefaultUpdateResponseType response) { },
                delegate(Fault fault) { LogError(fault); }
            ));

            double arcDistance = Math.Abs(degrees) * _state.DistanceBetweenWheels * Math.PI / 360.0d;

            //compute tick to stop at
            stopLeftWheelAt = (int)Math.Round(arcDistance / (2.0d * Math.PI * _state.LeftWheel.Radius / _state.LeftWheel.EncoderState.TicksPerRevolution));
            stopRightWheelAt = (int)Math.Round(arcDistance / (2.0d * Math.PI * _state.RightWheel.Radius / _state.RightWheel.EncoderState.TicksPerRevolution));

            EncoderTicksEnabled = true;

            pollEncoderState();     // get starting encoder state

            //start moving

            // start rotate operation
            _state.RotateDegreesStage = drive.DriveStage.Started;

            drive.RotateDegrees rotateUpdate = new drive.RotateDegrees();
            rotateUpdate.Body.RotateDegreesStage = drive.DriveStage.Started;
            #if TRACELOG
            Tracer.Trace("++++++++++++++++++ DRIVE: RotateUntilDegrees() DriveStage.Started");
            #endif
            _internalDriveOperationsPort.Post(rotateUpdate);

            PortSet<DefaultUpdateResponseType, Fault> responsePort = new PortSet<DefaultUpdateResponseType, Fault>();

            double rightPow;
            double leftPow;

            if (degrees > 0)
            {
                rightPow = power;
                leftPow = -power;
            }
            else
            {
                rightPow = -power;
                leftPow = power;
            }

            motor.SetMotorPower leftPower = new motor.SetMotorPower(new motor.SetMotorPowerRequest() { TargetPower = leftPow });
            leftPower.ResponsePort = responsePort;
            _leftMotorPort.Post(leftPower);

            motor.SetMotorPower rightPower = new motor.SetMotorPower(new motor.SetMotorPowerRequest() { TargetPower = rightPow });
            rightPower.ResponsePort = responsePort;
            _rightMotorPort.Post(rightPower);

            #if TRACELOG
            Tracer.Trace("=============== TrackRoamerDriveService:: RotateUntilDegrees() start moving: degrees=" + degrees);
            Tracer.Trace("=============== TrackRoamerDriveService:: RotateUntilDegrees() will stop wheels at:  Left=" + stopLeftWheelAt + " Right=" + stopRightWheelAt);
            #endif

            Activate(Arbiter.MultipleItemReceive<DefaultUpdateResponseType, Fault>(responsePort, 2,
                delegate(ICollection<DefaultUpdateResponseType> successList, ICollection<Fault> failureList)
                {
                    foreach (Fault fault in failureList)
                    {
                        LogError(fault);
                    }
                }
            ));

            #if TRACELOG
            Tracer.Trace("=============== TrackRoamerDriveService:: RotateUntilDegrees() calling DriveWaitForCompletionDual() - waiting for both sides to complete...");
            #endif

            yield return DriveWaitForCompletionDual();

            #if TRACELOG
            Tracer.Trace("=============== TrackRoamerDriveService:: RotateUntilDegrees() - both sides completed, send notification of RotateDegrees complete to subscription manager");
            #endif

            // send notification of RotateDegrees complete to subscription manager
            rotateUpdate.Body.RotateDegreesStage = drive.DriveStage.Completed;
            #if TRACELOG
            Tracer.Trace("++++++++++++++++++ DRIVE: RotateUntilDegrees() DriveStage.Completed");
            #endif
            _internalDriveOperationsPort.Post(rotateUpdate);

            _state.RotateDegreesStage = drive.DriveStage.Completed;
        }
        /// <summary>
        /// Notified subscribers a success or fault to completed Drive request.
        /// </summary>
        /// <param name="driveDistance"></param>
        /// <param name="success"></param>
        /// <param name="fault"></param>
        public void HandleDriveResponseForGenericOperationsNotifications(DriveDistance driveDistance, bool success, Fault fault)
        {
            if (fault == null)
            {
                if (driveDistance.Body.isGenericOperation == true)
                {
                    //notify subscribers of generic drive distance -- complete

                    switch (driveDistance.Body.DriveRequestOperation)
                    {
                        case pxdrive.DriveRequestOperation.DriveDistance:
                            pxdrive.DriveDistanceRequest driveDistanceRequest = new pxdrive.DriveDistanceRequest();
                            driveDistanceRequest.DriveDistanceStage = pxdrive.DriveStage.Completed;

                            pxdrive.DriveDistance driveDistanceUpdate = new pxdrive.DriveDistance(driveDistanceRequest);
                            SendNotification<pxdrive.DriveDistance>(_genericSubMgrPort, driveDistanceUpdate);
                            break;

                        case pxdrive.DriveRequestOperation.RotateDegrees:
                            pxdrive.RotateDegreesRequest rotateDegreesRequest = new pxdrive.RotateDegreesRequest();
                            rotateDegreesRequest.RotateDegreesStage = pxdrive.DriveStage.Completed;

                            pxdrive.RotateDegrees rotateDegreesUpdate = new pxdrive.RotateDegrees(rotateDegreesRequest);
                            SendNotification<pxdrive.RotateDegrees>(_genericSubMgrPort, rotateDegreesUpdate);
                            break;
                    }
                }
                else
                {
                    // Operation canceled.
                    driveDistance.Body.DriveDistanceStage = pxdrive.DriveStage.Canceled;
                    SendNotification<pxdrive.SetDrivePower>(_genericSubMgrPort, driveDistance.Body);
                }
                _internalPendingDriveOperation = pxdrive.DriveRequestOperation.NotSpecified;
            }
        }
        public virtual IEnumerator<ITask> GenericRotateDegreesHandler(pxdrive.RotateDegrees rotateDegrees)
        {
            if (_state.DistanceBetweenWheels <= 0)
            {
                rotateDegrees.ResponsePort.Post(Fault.FromException(new ArgumentOutOfRangeException("DistanceBetweenWheels must be specified in the Drive Configuration.")));
                yield break;
            }

            // set back response immediately or fault if drive is not enabled.
            ValidateDriveEnabledAndRespondHelper(rotateDegrees.ResponsePort);

            // distance = circumference / 360 * degreesToTurn
            double distance = Math.PI * _state.DistanceBetweenWheels * rotateDegrees.Body.Degrees / 360.0;

            // axleRotationDegrees = distance (meters) / wheelCircumference (pi * diameter) * 360
            long axleRotationDegrees = (long)Math.Round(Math.Abs(distance) / (Math.PI * _state.LeftWheel.WheelDiameter) * 360.0);

            LogVerbose(LogGroups.Console, "RotateDegrees: Wheel Distance: " + distance.ToString() + "  Axle Rotation Degrees: " + axleRotationDegrees.ToString());

            double leftDirection = 1.0, rightDirection = 1.0;
            if (rotateDegrees.Body.Degrees > 0)
                leftDirection = -1.0;
            else
                rightDirection = -1.0;

            DriveDistance drive = new DriveDistance(new SetDriveRequest());
            drive.Body.LeftStopAtRotationDegrees = axleRotationDegrees;
            drive.Body.RightStopAtRotationDegrees = axleRotationDegrees;
            drive.Body.StopState = MotorStopState.Brake;
            drive.Body.isGenericOperation = true;
            drive.Body.DriveRequestOperation = pxdrive.DriveRequestOperation.RotateDegrees;
            _internalPendingDriveOperation = pxdrive.DriveRequestOperation.RotateDegrees;
            bool synchronized = false;

            if (synchronized)
            {
                drive.Body.LeftPower = Math.Abs(rotateDegrees.Body.Power);
                drive.Body.RightPower = Math.Abs(rotateDegrees.Body.Power);
            }
            else
            {
                drive.Body.LeftPower = rotateDegrees.Body.Power * leftDirection;
                drive.Body.RightPower = rotateDegrees.Body.Power * rightDirection;
            }
            drive.ResponsePort = rotateDegrees.ResponsePort;

            // notify subscribers of rotate degrees start
            rotateDegrees.Body.RotateDegreesStage = pxdrive.DriveStage.Started;
            pxdrive.RotateDegrees rotateDegreesUpdate = new pxdrive.RotateDegrees(rotateDegrees.Body);
            SendNotification<pxdrive.RotateDegrees>(_genericSubMgrPort, rotateDegreesUpdate);

            _internalDrivePowerPort.Post(drive);
            yield break;
        }