//Read values from driver through methods private void CheckTelescopeStatus() { //if device present at all and its ID is set if (Enabled && DRIVER_NAME != "" && objTelescope != null) { try { Connected_flag = this.Connect; curAzimuth = this.Azimuth; curAltitude = this.Altitude; curRightAscension = this.RightAscension; curDeclination = this.Declination; curSiderealTime = this.SiderealTime; curPierSideStatus = this.PierSideStatus; curAtPark = this.AtPark; curTracking = this.Tracking; curSlewing = this.Slewing; } catch (Exception ex) { Logging.AddLog("CheckTelescopeStatus error [" + ex.ToString() + "]", LogLevel.Important, Highlight.Error); } } else { //Print if somebody try to connect if device isn't presetn. Mostly for debug //Logging.AddLog("Telescope is not set. Couldn't set Park status", LogLevel.Debug, Highlight.Error); } }
public void DestinationSideOfPierTest() { Assert.IsTrue(_mgr.Connected); Vector currentPosition = GetTargetRaDec(); _svc.MockRaDec = currentPosition; _svc.MockSideOfPier = PierSide.pierWest; _svc.MockIsWeakDriver = false; PierSide currentSOP = _mgr.GetTargetSideOfPier(currentPosition.X, currentPosition.Y); Assert.AreEqual <PierSide>(PierSide.pierWest, currentSOP); Vector targetPosition = currentPosition - new Vector(7.0, 0.0); if (targetPosition.X < 0) { targetPosition.X += 24; } _svc.MockSideOfPier = PierSide.pierEast; PierSide targetSOP = _mgr.GetTargetSideOfPier(targetPosition.X, targetPosition.Y); Assert.IsTrue(targetSOP == PierSide.pierEast); _svc.MockIsWeakDriver = true; targetSOP = _mgr.GetTargetSideOfPier(targetPosition.X, targetPosition.Y); Assert.IsTrue(targetSOP == PierSide.pierEast); }
public SlewInProgressMessage(bool isSlewInProgress, double rightAscension = double.NaN, double declination = double.NaN , PierSide sideOfPier = PierSide.pierUnknown) { IsSlewInProgress = isSlewInProgress; RightAscension = rightAscension; Declination = declination; SideOfPier = sideOfPier; }
private AlignmentPoint[] GetNearestObservedPoints(AxisPosition axisPosition, PierSide pierSide, int numberOfPoints, out int checkSum) { AlignmentPoint[] points = AlignmentPoints .Where(p => p.PierSide == pierSide && p.ObservedAxes.IncludedAngleTo(axisPosition) <= NearbyLimit) .OrderBy(d => d.ObservedAxes.IncludedAngleTo(axisPosition)).Take(numberOfPoints).ToArray(); checkSum = GetChecksum(points.Select(p => p.Id).ToArray()); return(points); }
private IRestRequest BuildSetSideOfPierRequest(PierSide sideOfPier) { var parameters = new Dictionary <string, object> { { TelescopeCommandParameters.SideOfPier, ((int)sideOfPier).ToString() } }; return(RequestBuilder.BuildRestRequest(TelescopeCommand.SideOfPier, Method.PUT, parameters, GetClientTransactionId())); }
private AlignmentPoint GetNearestObservedPoint(AxisPosition axisPosition, PierSide pierSide, out int checkSum) { AlignmentPoint alignmentPoint = AlignmentPoints .Where(p => p.PierSide == pierSide) .OrderBy(d => d.ObservedAxes.IncludedAngleTo(axisPosition)).FirstOrDefault(); checkSum = alignmentPoint != null?GetChecksum(alignmentPoint.Id) : int.MinValue; return(alignmentPoint); }
public Form1() { XmlConfigurator.Configure(); test1 = new MountCheck(1, "Conectar y luego Park 3."); test1.TimeOutSeconds = 50; test2 = new MountCheck(2, "DEC ClockWise"); test2.TimeOutSeconds = 35; test3 = new MountCheck(3, "DEC CounterClockWise"); test3.TimeOutSeconds = 70; test4 = new MountCheck(4, "Alt 86, Az 270"); test4.TimeOutSeconds = 35; test5 = new MountCheck(5, "Check RA East Limit."); test5.TimeOutSeconds = 250; test6 = new MountCheck(6, "Alt 86, Az 90,Ra Home"); test6.TimeOutSeconds = 80; test7 = new MountCheck(7, "Check RA West Limit."); test7.TimeOutSeconds = 250; logger.Info("Constructor Start."); raLimit = false; raLimitLast = false; tiltLimit = false; tiltLimitLast = false; this.udpClient = new UdpClient(); this.arduinoTcp = new ArduinoTcp(settings.ipAddress, (int)settings.port); InitializeComponent(); stat = null; pierFlips = 0; pierSide = PierSide.pierUnknown; pierSideLast = PierSide.pierUnknown; this.arduinoLimits.Open(); this.timerReadSerial.Start(); this.radioButtonDecHome.Checked = false; this.radioButtonRA_East.Checked = false; this.radioButtonRA_Home.Checked = false; this.radioButtonRA_West.Checked = false; //try //{ // this.telescopio = new Telescope(settings.TelescopeProgId); //} //catch (Exception) //{ // this.telescopio = null; // logger.Error("Error al escoger telescopio ASCOM."); //} logger.Info("Constructor End."); }
public PierSide DestinationSideOfPier(double rightAscension, double declination) { RightAscensionConverter raConverter = new RightAscensionConverter((decimal)rightAscension); DeclinationConverter decConverter = new DeclinationConverter((decimal)declination); LogActivityStart(ActivityMessageTypes.Other, " Get DestinationSideOfPier \r\n RA {0}\r\n Dec {1}:", raConverter, decConverter); CheckDevice(); PierSide retval = Service.DestinationSideOfPier(rightAscension, declination); string name = GetPierSideName(retval); LogActivityEnd(ActivityMessageTypes.Other, "{0} {1}", name, Done); return(retval); }
public PierSide GetDecSideOfPier(double dec) { PierSide decSOP = PierSide.pierUnknown; dec = Math.Abs(dec - 180); if (dec <= 90.0) { decSOP = PierSide.pierEast; } else { decSOP = PierSide.pierWest; } return(decSOP); }
//public double RightAscensionRate //{ // get // { // double rightAscensionRate = 0.0; // tl.LogMessage("RightAscensionRate", "Get - " + rightAscensionRate.ToString()); // return rightAscensionRate; // } // set // { // tl.LogMessage("RightAscensionRate Set", "Not implemented"); // throw new ASCOM.PropertyNotImplementedException("RightAscensionRate", true); // } //} //public void SetPark() //{ // tl.LogMessage("SetPark", "Not implemented"); // throw new ASCOM.MethodNotImplementedException("SetPark"); //} private void UpdateSideOfPier() { if (Slewing || AtHome) { UpdatingSideOfPier = false; return; } double HourAngle = astroUtilities.ConditionHA(SiderealTime - RightAscension); bool NearMeridian = (HourAngle < -11 || HourAngle > 11) || (HourAngle > -1 && HourAngle < 1); if (!NearMeridian) // SideOfPier is constrained by mount design (no need to send :pS# command) { _SideOfPier = (HourAngle > 0) ? PierSide.pierEast : PierSide.pierWest; UpdatingSideOfPier = false; return; } //Command: “:pS#” //Response: “0” East, “1” West. var SideOfPierTransaction = new ZEQ25BooleanTransaction(":pS#") { Timeout = TimeSpan.FromSeconds(2) }; Task.Run(() => transactionProcessor.CommitTransaction(SideOfPierTransaction)); SideOfPierTransaction.WaitForCompletionOrTimeout(); String response = SideOfPierTransaction.Response.ToString(); log.Info("Update SideOfPier (Response): {0}", SideOfPierTransaction.Response); // pierEast is returned when the mount is observing at an hour angle between -12.0 and -6.0 // pierWest is returned when the mount is observing at an hour angle between -6.0 and 0.0 // pierEast is returned when the mount is observing at an hour angle between 0.0 and +6.0 // pierWest is returned when the mount is observing at an hour angle between +6.0 and +12.0 // "Through the pole" if (HourAngle < -6 || HourAngle > 6) // between -12.0 and -6.0 or between + 6.0 and + 12.0 { _SideOfPier = SideOfPierTransaction.Value ? PierSide.pierEast : PierSide.pierWest; } else // between -6.0 and 0.0 or between 0.0 and + 6.0 (Normal pointing state) - 1 = West, 0 = East { _SideOfPier = SideOfPierTransaction.Value ? PierSide.pierWest : PierSide.pierEast; } UpdatingSideOfPier = false; }
/// <summary> /// Wrapper to reset telescope driver /// Later system would reinitiate it itself /// </summary> public void Reset() { Connected_flag = false; curAzimuth = -1; curAltitude = -100; curRightAscension = -100; curDeclination = -100; curSiderealTime = -100; curPierSideStatus = PierSide.pierUnknown; curAtPark = false; curTracking = false; objTelescope = null; }
public void MeridianFlipTest() { // Unpark the scope and start tracking. _svc.MockAtPark = false; _svc.MockTracking = true; _svc.MockSideOfPier = PierSide.pierWest; _mgr.Status.SideOfPier = PierSide.pierWest; Thread.Sleep(5000); // Give the telescope manager time to do a status update. Assert.IsFalse(_mgr.AtPark); Assert.IsTrue(_mgr.Tracking); Assert.IsTrue(_mgr.Capabilities.CanSetPierSide); Assert.IsTrue(_mgr.Status.SideOfPier == PierSide.pierWest); // Verify that both the Manager and the Service have the same side-of-pier and that // it is not Unknown. PierSide sop = _mgr.SideOfPier; Assert.IsTrue(sop != PierSide.pierUnknown); Assert.IsTrue(sop == _svc.SideOfPier); // Do the flip. _mgr.StartMeridianFlip(); // Wait for the flip. Thread.Sleep(6000); while (_mgr.Slewing) { Thread.Sleep(500); } // Make sure that we are done and on the expected side of the mount. Assert.IsFalse(_mgr.Slewing); // Figure out which side we should end up on after the flip. PierSide targetSop = sop == PierSide.pierEast ? PierSide.pierWest : PierSide.pierEast; Assert.AreEqual(targetSop, _mgr.SideOfPier); }
/// <summary> /// Returns the pointing side of Pier as required by ASCOM /// </summary> public PierSide GetPointingSideOfPier(bool swapSideOfPier) { PierSide pointingSOP = PierSide.pierUnknown; if (ObservedAxes != null) { if (ObservedAxes[1] == 0.0) { // Impossible to tell so return unknown return(pointingSOP); } if (ObservedAxes[1] > 180.0) // (ObservedAxes[1] <= 90 || ObservedAxes[1] >= 270.0) { if (swapSideOfPier) { pointingSOP = PierSide.pierEast; } else { pointingSOP = PierSide.pierWest; } } else { if (swapSideOfPier) { pointingSOP = PierSide.pierWest; } else { pointingSOP = PierSide.pierEast; } } if (Hemisphere == HemisphereOption.Southern) { if (pointingSOP == PierSide.pierWest) { pointingSOP = PierSide.pierWest; } else { pointingSOP = PierSide.pierEast; } } } return(pointingSOP); }
public ActionResult <PierSideResponse> Get(int ClientID, int ClientTransactionID, double RightAscension, double Declination) { try { PierSide result = Program.Simulator.DestinationSideOfPier(RightAscension, RightAscension); Program.TraceLogger.LogMessage(methodName + " Get", result.ToString()); return(new PierSideResponse(ClientTransactionID, ClientID, result)); } catch (Exception ex) { Program.TraceLogger.LogMessage(methodName + " Get", string.Format("Exception: {0}", ex.ToString())); PierSideResponse response = new PierSideResponse(ClientTransactionID, ClientID, 0, 0); response.ErrorMessage = ex.Message; response.ErrorNumber = ex.HResult - Program.ASCOM_ERROR_NUMBER_OFFSET; return(response); } }
public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { try { PierSide pierSide = (PierSide)value; switch (pierSide) { case PierSide.pierEast: return(Locale.Loc.Instance["LblEast"]); case PierSide.pierWest: return(Locale.Loc.Instance["LblWest"]); default: return(string.Empty); } } catch (Exception ex) { Logger.Error(ex, $"Failed to convert {value} to PierSide"); return(string.Empty); } }
public bool GetSideOfPier(out PierSide pierSide) { bool success = false; pierSide = PierSide.pierUnknown; if (RequestReply(":pS#", out string pierSideReply)) { switch (pierSideReply) { case "East#": pierSide = PierSide.pierEast; success = true; break; case "West#": pierSide = PierSide.pierWest; success = true; break; } } return(success); }
private bool CalculateCounterWeightUp(PierSide pierSide, double hourAngle) { // The CW state is determined by looking at two things: pier side and hour angle (HA = LST – RA). // Pier Side = West; 0 > HA > -12 CW Down // Pier Side = East; 0 < HA < +12 CW Down // // Pier Side = East; 0 > HA > -12 CW UP // Pier Side = West; 0 < HA < +12 CW UP bool retval = false; if (pierSide == PierSide.pierEast && -12 < hourAngle && hourAngle < 0) { retval = true; } else if (pierSide == PierSide.pierWest && 0 < hourAngle && hourAngle < 12) { retval = true; } return(retval); }
public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { string retval = null; PierSide sop = (PierSide)value; switch (sop) { case PierSide.pierEast: retval = "East"; break; case PierSide.pierWest: retval = "West"; break; case PierSide.pierUnknown: retval = "Unknown"; break; } return(retval); }
/// <summary> /// Gets the mount axis positions for a given observed axis position. /// </summary> /// <param name="observedAxes">Observed Ra and Dec axis positions</param> /// <param name="pierSide">The pier side to use 0 = East, 1 = West, 2 = Unknown</param> /// <returns></returns> public double[] GetMountAxes(double[] observedAxes, int pierSide) { if (!IsAlignmentOn || !AlignmentPoints.Any()) { return(observedAxes); // Fast exit as alignment modeling is switched off or there are no points. } lock (_accessLock) { try { bool postLogMessages = false; AxisPosition sAxes = new AxisPosition(observedAxes); if (sAxes.IncludedAngleTo(_homePosition) < ProximityLimit) { return(observedAxes); // Fast exit if we are going home. } PierSide pSide = (PierSide)pierSide; WriteLastAccessTime(); Matrix offsets = Matrix.CreateInstance(1, 2); int checksum; if (AlignmentPoints.Count == 1) { checksum = GetChecksum(AlignmentPoints[0].Id); if (checksum == _currentChecksum) { // Checksum hasn't changed so use the last offsets offsets = _lastOffsets; } else { RaiseNotification(NotificationType.Information, MethodBase.GetCurrentMethod().Name, $"GetMountAxes for {observedAxes[0]}/{observedAxes[1]}"); ClearSelectedPoints(); offsets[0, 0] = AlignmentPoints[0].MountAxes[0] - AlignmentPoints[0].ObservedAxes[0]; offsets[0, 1] = AlignmentPoints[0].MountAxes[1] - AlignmentPoints[0].ObservedAxes[1]; AlignmentPoints[0].Selected = true; _selectedPoints.Add(AlignmentPoints[0]); // Cache the offsets and checksum _lastOffsets = offsets; _currentChecksum = checksum; RaiseNotification(NotificationType.Data, MethodBase.GetCurrentMethod().Name, $"Single alignment point selected {AlignmentPoints[0].Id:D3}, Mount axes: {AlignmentPoints[0].MountAxes.RaAxis}/{AlignmentPoints[0].MountAxes.RaAxis}, Observed axes: {AlignmentPoints[0].ObservedAxes.RaAxis}/{AlignmentPoints[0].ObservedAxes.RaAxis}"); postLogMessages = true; } } else { // Get the nearest points and their corresponding checksum value AlignmentPoint[] alignmentPoints = GetNearestObservedPoints(sAxes, pSide, SampleSize, out checksum); if (checksum == _currentChecksum) { // Checksum hasn't changed to use the last offsets offsets = _lastOffsets; } else { int rows = alignmentPoints.Length; if (rows > 2) { RaiseNotification(NotificationType.Information, MethodBase.GetCurrentMethod().Name, $"GetMountAxes for {observedAxes[0]}/{observedAxes[1]}"); ClearSelectedPoints(); // Build features and values from registered points Matrix features = Matrix.CreateInstance(rows, 3); Matrix values = Matrix.CreateInstance(rows, 2); _stringBuilder.Clear(); _stringBuilder.Append("Points chosen are"); for (int i = 0; i < rows; i++) { var pt = alignmentPoints[i]; _stringBuilder.Append($" ({pt.Id:D3})"); features[i, 0] = 1f; features[i, 1] = pt.ObservedAxes[0] * pt.ObservedAxes[0]; features[i, 2] = pt.ObservedAxes[1] * pt.ObservedAxes[1]; values[i, 0] = Range.RangePlusOrMinus180(pt.MountAxes[0] - pt.ObservedAxes[0]); values[i, 1] = Range.RangePlusOrMinus180(pt.MountAxes[1] - pt.ObservedAxes[1]); pt.Selected = true; _selectedPoints.Add(pt); } _stringBuilder.AppendLine("."); // Solve the normal equation to get theta Matrix theta = SolveNormalEquation(features, values); // Calculate the difference for the incoming points Matrix target = Matrix.CreateInstance(1, 3); target[0, 0] = 1f; target[0, 1] = sAxes[0] * sAxes[0]; target[0, 2] = sAxes[1] * sAxes[1]; offsets = target * theta; _stringBuilder.AppendLine("Features"); _stringBuilder.AppendLine(features.ToString()); _stringBuilder.AppendLine("Values"); _stringBuilder.AppendLine(values.ToString()); _stringBuilder.AppendLine("Theta"); _stringBuilder.AppendLine(theta.ToString()); _stringBuilder.AppendLine("Target"); _stringBuilder.AppendLine(target.ToString()); _stringBuilder.AppendLine("Offsets"); _stringBuilder.AppendLine(offsets.ToString()); RaiseNotification(NotificationType.Data, MethodBase.GetCurrentMethod().Name, _stringBuilder.ToString()); _stringBuilder.Clear(); // Cache the offsets and the checksum _lastOffsets = offsets; _currentChecksum = checksum; postLogMessages = true; } else if (rows > 0) { checksum = GetChecksum(AlignmentPoints[0].Id); if (checksum == _currentChecksum) { // Checksum hasn't changed so use the last offsets offsets = _lastOffsets; } else { RaiseNotification(NotificationType.Information, MethodBase.GetCurrentMethod().Name, $"GetMountAxes for {observedAxes[0]}/{observedAxes[1]}"); ClearSelectedPoints(); // Use the nearest point of the two. offsets[0, 0] = alignmentPoints[0].MountAxes[0] - alignmentPoints[0].ObservedAxes[0]; offsets[0, 1] = alignmentPoints[0].MountAxes[1] - alignmentPoints[0].ObservedAxes[1]; alignmentPoints[0].Selected = true; _selectedPoints.Add(alignmentPoints[0]); // Cache the offsets and checksum _lastOffsets = offsets; _currentChecksum = checksum; postLogMessages = true; RaiseNotification(NotificationType.Data, MethodBase.GetCurrentMethod().Name, $"Using nearest point of two {alignmentPoints[0].Id:D3}, Mount axes: {alignmentPoints[0].MountAxes.RaAxis}/{alignmentPoints[0].MountAxes.RaAxis}, Observed axes: {alignmentPoints[0].ObservedAxes.RaAxis}/{alignmentPoints[0].ObservedAxes.RaAxis}"); } } else { if (_currentChecksum != int.MinValue) { _currentChecksum = int.MinValue; RaiseNotification(NotificationType.Warning, MethodBase.GetCurrentMethod().Name, $"No alignment points selected, Mount axes: {alignmentPoints[0].MountAxes.RaAxis}/{alignmentPoints[0].MountAxes.RaAxis}, Observed axes: {alignmentPoints[0].ObservedAxes.RaAxis}/{alignmentPoints[0].ObservedAxes.RaAxis}"); } } } // Otherwise default to using zero offset } var mountAxes = new[] { observedAxes[0] + offsets[0, 0], observedAxes[1] + offsets[0, 1] }; if (postLogMessages) { RaiseNotification(NotificationType.Data, MethodBase.GetCurrentMethod().Name, $"Correction -> Mount = {offsets[0, 0]}/{offsets[0, 1]}"); RaiseNotification(NotificationType.Information, MethodBase.GetCurrentMethod().Name, $"Observed axes: {observedAxes[0]}/{observedAxes[1]} -> Mount axes: {mountAxes[0]}/{mountAxes[1]}"); } return(mountAxes); } catch (Exception ex) { LogException(ex); return(observedAxes); } } }
private AlignmentPoint[] GetNearestMountPoints(AxisPosition axisPosition, PierSide pierSide, int numberOfPoints) { return(AlignmentPoints .Where(p => p.PierSide == pierSide && p.MountAxes.IncludedAngleTo(axisPosition) <= NearbyLimit) .OrderBy(d => d.MountAxes.IncludedAngleTo(axisPosition)).Take(numberOfPoints).ToArray()); }
private void AddAlignmentPoint(double[] mountAltAz, double[] observedAltAz, AxisPosition mountAxes, AxisPosition observedAxes, PierSide pierSide, DateTime syncTime) { lock (_accessLock) { if (AlignmentPoints.Count > 2 && ProximityLimit > 0.0) { // Remove any existing alignment points that are too close to the new one. var nearPoints = AlignmentPoints .Where(p => p.MountAxes.IncludedAngleTo(mountAxes) <= ProximityLimit).ToList(); foreach (AlignmentPoint deletePt in nearPoints) { AlignmentPoints.Remove(deletePt); } } CarteseanCoordinate mountXy = AltAzToCartesean(mountAltAz); CarteseanCoordinate observedXy = AltAzToCartesean(observedAltAz); AlignmentPoints.Add(new AlignmentPoint(observedAltAz, mountAxes, observedAxes, mountXy, observedXy, pierSide, syncTime)); _currentChecksum = int.MinValue; // Reset checksum so that offsets are recalculated OneStarAdjustment[0] = observedAxes[0] - mountAxes[0]; OneStarAdjustment[1] = observedAxes[1] - mountAxes[1]; SaveAlignmentPoints(); } }
/// <summary> /// Refreshes the NCP and current positions if more than 500ms have elapsed since the last refresh. /// </summary> private void RefreshCurrentPosition() { DateTime now = DateTime.Now; bool axisHasMoved = false; double tolerance; AxisPosition axisPosition; //= _previousAxisPosition; lock (Controller) { _AxisState = Controller.MCGetAxesStates(); axisPosition = Controller.MCGetAxisPositions(); tolerance = Controller.AngularResolutionDegrees; } #if DEBUG //string raStatus = Convert.ToString(axesStatus[RA_AXIS], 2); //string decStatus = Convert.ToString(axesStatus[DEC_AXIS], 2); ; //System.Diagnostics.Debug.WriteLine($"\nAxis states - RA: {raStatus}, Dec : {decStatus}\n"); //AxisState raStatus = _AxisState[RA_AXIS]; //AxisState decStatus = _AxisState[DEC_AXIS]; //System.Diagnostics.Debug.WriteLine($"\nRA : Slewing-{raStatus.Slewing}, SlewingTo-{raStatus.SlewingTo}, Forward-{!raStatus.MeshedForReverse}, FullStop-{raStatus.FullStop}, Tracking-{raStatus.Tracking}"); //System.Diagnostics.Debug.WriteLine($"Dec: Slewing-{decStatus.Slewing}, SlewingTo-{decStatus.SlewingTo}, Forward-{!decStatus.MeshedForReverse}, FullStop-{decStatus.FullStop}, Tracking-{decStatus.Tracking}"); #endif if (!axisPosition.Equals(_previousAxisPosition, tolerance)) //if (!_AxisState[RA_AXIS].FullStop || !_AxisState[DEC_AXIS].FullStop) { // One or the other axis is moving axisHasMoved = true; if (_previousPointingSOP == PierSide.pierUnknown) { // First move away from home (NCP/SCP) position. if (_TargetPosition != null) { System.Diagnostics.Debug.WriteLine("Initialising SOP from goto target."); System.Diagnostics.Debug.WriteLine($"Target Axes: {_TargetPosition.ObservedAxes.RAAxis.Value}/{_TargetPosition.ObservedAxes.DecAxis.Value}\t{_TargetPosition.ObservedAxes.DecFlipped}\tRA/Dec: {_TargetPosition.Equatorial.RightAscension}/{_TargetPosition.Equatorial.Declination}\t{_TargetPosition.PointingSideOfPier}"); axisPosition.DecFlipped = _TargetPosition.ObservedAxes.DecFlipped; _previousPointingSOP = _TargetPosition.PointingSideOfPier; } } else { // Keep the axis position the same axisPosition.DecFlipped = _previousAxisPosition.DecFlipped; } } else { // Check if parking. if (Settings.ParkStatus == ParkStatus.Parking) { // Update the parked axis position decflipped setting if it isn't set. _ParkedAxisPosition.DecFlipped = _previousAxisPosition.DecFlipped; if (axisPosition.Equals(_ParkedAxisPosition, tolerance)) { LogMessage("Command", "Park - complete"); Settings.ParkStatus = ParkStatus.Parked; SaveSettings(); } else { //if (_NeedSlowToStopStep) //{ // Need to keep going Controller.MCAxisSlewTo(_ParkedAxisPosition, Hemisphere); // _NeedSlowToStopStep = false; //} } } axisPosition.DecFlipped = _previousAxisPosition.DecFlipped; } // Update current position _CurrentPosition.MoveRADec(axisPosition, _AscomToolsCurrentPosition, now); if (!_decFlippedConfirmed && _CurrentPosition.PointingSideOfPier != PierSide.pierUnknown) { double ha = AstroConvert.RangeHA(SiderealTime - _CurrentPosition.Equatorial.RightAscension.Value); if (_CurrentPosition.PointingSideOfPier == PierSide.pierWest) { if (ha >= 0) { // need to flip the DEC axis as it is reporting the wrong RA axisPosition.DecFlipped = !axisPosition.DecFlipped; _CurrentPosition.MoveRADec(axisPosition, _AscomToolsCurrentPosition, now); } } else { if (ha < 0) { // need to flip the DEC axis as it is reporting the wrong RA axisPosition.DecFlipped = !axisPosition.DecFlipped; _CurrentPosition.MoveRADec(axisPosition, _AscomToolsCurrentPosition, now); } } _decFlippedConfirmed = true; } //// Just check that we have the DecFlipped setting correct //if (!_decFlippedConfirmed && _IsSlewing) //{ // double deltaRa = _TargetPosition.Equatorial.RightAscension - _CurrentPosition.Equatorial.RightAscension; // if (_previousDeltaRa.HasValue) // { // if (deltaRa > _previousDeltaRa.Value) // { // // Going in the wrong direction so flip the Dec axis // axisPosition.DecFlipped = !axisPosition.DecFlipped; // _CurrentPosition.MoveRADec(axisPosition, _AscomToolsCurrentPosition, now); // } // _decFlippedConfirmed = true; // } // else { // // Get it on the next cycle // _previousDeltaRa = deltaRa; // } //} if (_previousPointingSOP != PierSide.pierUnknown) { // See if pointing has moved across the meridian if (_CurrentPosition.PointingSideOfPier != _previousPointingSOP) { System.Diagnostics.Debug.WriteLine("** Crossing the meridian **"); // Pointing has moved across the meridian so toggle the DecFlipped value; axisPosition.DecFlipped = !_previousAxisPosition.DecFlipped; _CurrentPosition.MoveRADec(axisPosition, _AscomToolsCurrentPosition, now); } } if (Settings.ParkStatus == ParkStatus.Parking) { System.Diagnostics.Debug.WriteLine($"Parking to: {_ParkedAxisPosition.RAAxis.Value}/{_ParkedAxisPosition.RAAxis.Value}\t{_ParkedAxisPosition.DecFlipped}"); } if (_TargetPosition != null) { System.Diagnostics.Debug.WriteLine($"Target Axes: {_TargetPosition.ObservedAxes.RAAxis.Value}/{_TargetPosition.ObservedAxes.DecAxis.Value}\t{_TargetPosition.ObservedAxes.DecFlipped}\tRA/Dec: {_TargetPosition.Equatorial.RightAscension}/{_TargetPosition.Equatorial.Declination}\t{_TargetPosition.PointingSideOfPier}"); } if (Settings.ParkStatus == ParkStatus.Parked) { System.Diagnostics.Debug.WriteLine("Parked"); } else { // System.Diagnostics.Debug.WriteLine($"Current Axes: {axisPosition.RAAxis.Value}/{axisPosition.DecAxis.Value}\t{axisPosition.DecFlipped}\tRA/Dec: {_CurrentPosition.Equatorial.RightAscension}/{_CurrentPosition.Equatorial.Declination}\t{_CurrentPosition.PointingSideOfPier}\n"); } _previousAxisPosition = axisPosition; // See if we can sort out the initial SideOfPier if (_previousPointingSOP == PierSide.pierUnknown) { // Only initialise the previous pointing SOP if we know for certain what it should be if (axisHasMoved && (_IsSlewing || _IsMoveAxisSlewing)) { // Remember the current pointing side of the pier. // Until the SOP has been determined from a SLEW or GOTO it should not be updated. _previousPointingSOP = _CurrentPosition.PointingSideOfPier; } } else { _previousPointingSOP = _CurrentPosition.PointingSideOfPier; } // If the axis has stopped moving there are some bit to clear up if (_wasMoving && !axisHasMoved) { // See if we need to refine a goto. if (_RefineGoto) { _RefineGoto = false; System.Diagnostics.Debug.WriteLine("Refining GOTO"); SlewToEquatorialCoordinate(TargetRightAscension, TargetDeclination); } else { if (Settings.ParkStatus == ParkStatus.Unparked) { // Check if slew finished if (_IsSlewing) { _IsSlewing = false; // Announce("Slew complete."); } if (_IsMoveAxisSlewing) { _IsMoveAxisSlewing = false; } if (!_IsMoveAxisSlewing && !_IsSlewing) { if (TrackingState != TrackingStatus.Off) { System.Diagnostics.Debug.WriteLine("Restarting tracking"); LogMessage("Command", "Restarting tracking {0}", TrackingState); StartTracking(); } } } } } _wasMoving = axisHasMoved; }
/// <summary> /// Gets the observed axis positions for a given mount axis position. /// </summary> /// <param name="mountAxes">Mount Ra and Dec axis positions</param> /// <param name="pierSide">The pier side to use 0 = East, 1 = West, 2 = Unknown</param> /// <returns></returns> public double[] GetObservedAxes(double[] mountAxes, int pierSide) { if (!IsAlignmentOn || !AlignmentPoints.Any()) { return(mountAxes); // Fast exit as alignment modeling is switched off or there are no points. } lock (_accessLock) { try { AxisPosition mAxes = new AxisPosition(mountAxes); if (mAxes.IncludedAngleTo(_homePosition) < ProximityLimit) { return(mountAxes); // Fast exist if we are going home. } RaiseNotification(NotificationType.Information, MethodBase.GetCurrentMethod().Name, $"GetObservedAxes for {mountAxes[0]}/{mountAxes[1]}"); PierSide pSide = (PierSide)pierSide; WriteLastAccessTime(); Matrix offsets = Matrix.CreateInstance(1, 2); if (AlignmentPoints.Count == 1) { offsets[0, 0] = AlignmentPoints[0].ObservedAxes[0] - AlignmentPoints[0].MountAxes[0]; offsets[0, 1] = AlignmentPoints[0].ObservedAxes[1] - AlignmentPoints[0].MountAxes[1]; RaiseNotification(NotificationType.Data, MethodBase.GetCurrentMethod().Name, $"Single alignment point selected {AlignmentPoints[0].Id:D3}, Mount axes: {AlignmentPoints[0].MountAxes.RaAxis}/{AlignmentPoints[0].MountAxes.RaAxis}, Observed axes: {AlignmentPoints[0].ObservedAxes.RaAxis}/{AlignmentPoints[0].ObservedAxes.RaAxis}"); } else { AlignmentPoint[] alignmentPoints = GetNearestMountPoints(mAxes, pSide, SampleSize); int rows = alignmentPoints.Length; if (rows > 2) { // Build features and values from registered points Matrix features = Matrix.CreateInstance(rows, 3); Matrix values = Matrix.CreateInstance(rows, 2); _stringBuilder.Clear(); _stringBuilder.Append("Points chosen are"); for (int i = 0; i < rows; i++) { var pt = alignmentPoints[i]; _stringBuilder.Append($" ({pt.Id:D3})"); features[i, 0] = 1f; features[i, 1] = pt.MountAxes[0] * pt.MountAxes[0]; features[i, 2] = pt.MountAxes[1] * pt.MountAxes[1]; values[i, 0] = Range.RangePlusOrMinus180(pt.ObservedAxes[0] - pt.MountAxes[0]); values[i, 1] = Range.RangePlusOrMinus180(pt.ObservedAxes[1] - pt.MountAxes[1]); } _stringBuilder.AppendLine("."); // Solve the normal equation to get theta Matrix theta = SolveNormalEquation(features, values); // Calculate the difference for the incoming points Matrix target = Matrix.CreateInstance(1, 3); target[0, 0] = 1f; target[0, 1] = mAxes[0] * mAxes[0]; target[0, 2] = mAxes[1] * mAxes[1]; offsets = target * theta; _stringBuilder.AppendLine("Features"); _stringBuilder.AppendLine(features.ToString()); _stringBuilder.AppendLine("Values"); _stringBuilder.AppendLine(values.ToString()); _stringBuilder.AppendLine("Theta"); _stringBuilder.AppendLine(theta.ToString()); _stringBuilder.AppendLine("Target"); _stringBuilder.AppendLine(target.ToString()); _stringBuilder.AppendLine("Offsets"); _stringBuilder.AppendLine(offsets.ToString()); RaiseNotification(NotificationType.Data, MethodBase.GetCurrentMethod().Name, _stringBuilder.ToString()); _stringBuilder.Clear(); } else if (rows > 0) { // Just use the nearest point of the two. offsets[0, 0] = alignmentPoints[0].ObservedAxes[0] - alignmentPoints[0].MountAxes[0]; offsets[0, 1] = alignmentPoints[0].ObservedAxes[1] - alignmentPoints[0].MountAxes[1]; RaiseNotification(NotificationType.Data, MethodBase.GetCurrentMethod().Name, $"Using nearest point of two {alignmentPoints[0].Id:D3}, Mount axes: {alignmentPoints[0].MountAxes.RaAxis}/{alignmentPoints[0].MountAxes.RaAxis}, Observed axes: {alignmentPoints[0].ObservedAxes.RaAxis}/{alignmentPoints[0].ObservedAxes.RaAxis}"); } // Otherwise default to using no correcting offset } var observedAxes = new[] { mountAxes[0] + offsets[0, 0], mountAxes[1] + offsets[0, 1] }; RaiseNotification(NotificationType.Data, MethodBase.GetCurrentMethod().Name, $"Correction -> Observer = {offsets[0, 0]}/{offsets[0, 1]}"); RaiseNotification(NotificationType.Information, MethodBase.GetCurrentMethod().Name, $"Mount axes: {mountAxes[0]}/{mountAxes[1]} -> Observed axes: {observedAxes[0]}/{observedAxes[1]}"); return(observedAxes); } catch (Exception ex) { LogException(ex, true); return(mountAxes); } } }
/// <summary> /// Lee el estado del telescopio desde los drivers de ASCOM. /// </summary> private void ProcesaTelescopio() { StringBuilder mensaje; mensaje = new StringBuilder(); Boolean conectado; conectado = false; try { if (this.telescopio != null) { try { conectado = telescopio.Connected; } catch (NullReferenceException nref) { logger.Debug(nref.Message); conectado = false; } } } catch (DriverAccessCOMException e) { conectado = false; logger.Debug(e.Message); } if (conectado) { mensaje.Append("Conectado,"); double ra, dec; try { ra = telescopio.RightAscension; dec = telescopio.Declination; } catch (DriverAccessCOMException e) { ra = dec = 0; logger.Debug(e.Message); } slewing = false; try { slewing = telescopio.Slewing; } catch (DriverAccessCOMException e) { slewing = false; logger.Debug(e.Message); } if ((this.checkBoxInfrared.Checked) && (slewing != lastSlewing)) { this.InfraredControl(slewing); } if (slewing) { mensaje.Append("Slewing,"); } else { mensaje.Append("Stationary,"); } #region PierSide mensaje.Append("PierSide="); this.pierSide = telescopio.SideOfPier; //if (pierFlips == 0) //{ // this.pierSideLast = pierSide; //} String strPierSide; strPierSide = "_undef"; switch (this.pierSide) { case (PierSide.pierEast): strPierSide = "East"; break; case PierSide.pierUnknown: strPierSide = "Unknown"; break; case PierSide.pierWest: strPierSide = "West"; break; } mensaje.Append(strPierSide); // SI: // 1) Si los ultimos dos estados estan bien determinados. // 2) Ambos estados son diferentes // ENtonces: // Se ha detectado un Trasito de la montura, o un GEM Flip. if ((pierSide != PierSide.pierUnknown) && //1) (pierSideLast != PierSide.pierUnknown) && //1) (pierSide != pierSideLast)) { pierFlips++; logger.Info("#Flips=" + pierFlips + ". Actual pierside=" + strPierSide); } mensaje.Append("#Flips="); mensaje.Append(pierFlips); pierSideLast = pierSide; #endregion //mensaje.Append(" RA="); //mensaje.Append(String.Format("{0:0.00}", ra)); //mensaje.Append(" DEC="); //mensaje.Append(String.Format("{0:0.00}", dec)); lastSlewing = slewing; } else { mensaje.Append("Telescope ProdID="); mensaje.Append(settings.TelescopeProgId); mensaje.Append(" ;; Desconectado"); } this.labelTelescope.Text = mensaje.ToString(); //this.timerTelescopio.Start(); }
private AlignmentPoint GetNearestMountPoint(AxisPosition axisPosition, PierSide pierSide) { return(AlignmentPoints .Where(p => p.PierSide == pierSide) .OrderBy(d => d.MountAxes.IncludedAngleTo(axisPosition)).FirstOrDefault()); }
/// <inheritdoc/> public async Task SetSideOfPierAsync(PierSide sideOfPier) => await ExecuteRequestAsync(BuildSetSideOfPierRequest, sideOfPier);
public void ShouldFlipTest(double timeToFlipMinutes, double exposureTimeMinutes, double minutesAfterMeridian, double pauseBeforeMeridian, bool useSideOfPier, bool shouldFlip, PierSide pierSide = PierSide.pierUnknown) { meridianFlipSettingsMock.SetupGet(m => m.Enabled).Returns(true); meridianFlipSettingsMock.SetupGet(m => m.MinutesAfterMeridian).Returns(minutesAfterMeridian); meridianFlipSettingsMock.SetupGet(m => m.PauseTimeBeforeMeridian).Returns(pauseBeforeMeridian); meridianFlipSettingsMock.SetupGet(m => m.Recenter).Returns(false); meridianFlipSettingsMock.SetupGet(m => m.SettleTime).Returns(0); meridianFlipSettingsMock.SetupGet(m => m.UseSideOfPier).Returns(useSideOfPier); var telescopeInfo = new TelescopeInfo() { TimeToMeridianFlip = TimeSpan.FromMinutes(timeToFlipMinutes).TotalHours, SideOfPier = pierSide, Connected = true }; var exposureTime = TimeSpan.FromMinutes(exposureTimeMinutes).TotalSeconds; var sut = MeridianFlipVM.ShouldFlip(profileServiceMock.Object, exposureTime, telescopeInfo); sut.Should().Be(shouldFlip); }
public PierSideResponse(int clientTransactionID, int transactionID, PierSide side) { base.ServerTransactionID = transactionID; base.ClientTransactionID = clientTransactionID; PierSide = side; }
/// <inheritdoc/> public void SetSideOfPier(PierSide sideOfPier) => ExecuteRequest(BuildSetSideOfPierRequest, sideOfPier);