Beispiel #1
0
bool ScopeASCOM::SlewToCoordinates(double ra, double dec)
{
    bool bError = false;

    try
    {
        if (!IsConnected())
        {
            throw ERROR_INFO("ASCOM Scope: cannot slew when not connected");
        }

        if (!m_bCanSlew)
        {
            throw THROW_INFO("ASCOM Scope: not capable of slewing");
        }

        GITObjRef scope(m_gitEntry);

        Variant vRes;

        if (!scope.InvokeMethod(&vRes, dispid_slewtocoordinates, ra, dec))
        {
            throw ERROR_INFO("ASCOM Scope: slew to coordinates failed");
        }
    }
    catch (wxString Msg)
    {
        POSSIBLY_UNUSED(Msg);
        bError = true;
    }

    return bError;
}
Mount::MOVE_RESULT StepGuider::CalibrationMove(GUIDE_DIRECTION direction, int steps)
{
    MOVE_RESULT result = MOVE_OK;

    Debug.AddLine(wxString::Format("stepguider calibration move dir= %d steps= %d", direction, steps));

    try
    {
        MoveResultInfo move;
        result = Move(direction, steps, false, &move);

        if (move.amountMoved != steps)
        {
            throw THROW_INFO("stepsTaken != m_calibrationStepsPerIteration");
        }
    }
    catch (wxString Msg)
    {
        POSSIBLY_UNUSED(Msg);
        if (result == MOVE_OK)
           result = MOVE_ERROR;
    }

    return result;
}
Beispiel #3
0
bool ScopeASCOM::GetCoordinates(double *ra, double *dec, double *siderealTime)
{
    bool bError = false;

    try
    {
        if (!IsConnected())
        {
            throw ERROR_INFO("ASCOM Scope: cannot get coordinates when not connected");
        }

        if (!m_bCanGetCoordinates)
        {
            throw THROW_INFO("ASCOM Scope: not capable of getting coordinates");
        }

        GITObjRef scope(m_gitEntry);

        Variant vRA;

        if (!scope.GetProp(&vRA, dispid_rightascension))
        {
            throw ERROR_INFO("ASCOM Scope: get right ascension failed: " + ExcepMsg(scope.Excep()));
        }

        Variant vDec;

        if (!scope.GetProp(&vDec, dispid_declination))
        {
            throw ERROR_INFO("ASCOM Scope: get declination failed: " + ExcepMsg(scope.Excep()));
        }

        Variant vST;

        if (!scope.GetProp(&vST, dispid_siderealtime))
        {
            throw ERROR_INFO("ASCOM Scope: get sidereal time failed: " + ExcepMsg(scope.Excep()));
        }

        *ra = vRA.dblVal;
        *dec = vDec.dblVal;
        *siderealTime = vST.dblVal;
    }
    catch (wxString Msg)
    {
        bError = true;
        POSSIBLY_UNUSED(Msg);
    }

    return bError;
}
Beispiel #4
0
// Return RA and Dec guide rates in native ASCOM units, degrees/sec.
// Convention is to return true on an error
bool ScopeASCOM::GetGuideRates(double *pRAGuideRate, double *pDecGuideRate)
{
    bool bError = false;

    try
    {
        if (!IsConnected())
        {
            throw ERROR_INFO("ASCOM Scope: cannot get guide rates when not connected");
        }

        if (!m_bCanGetGuideRates)
        {
            throw THROW_INFO("ASCOM Scope: not capable of getting guide rates");
        }

        GITObjRef scope(m_gitEntry);

        Variant vRes;

        if (!scope.GetProp(&vRes, dispid_decguiderate))
        {
            throw ERROR_INFO("ASCOM Scope: GuideRateDec() failed: " + ExcepMsg(scope.Excep()));
        }

        *pDecGuideRate = vRes.dblVal;

        if (!scope.GetProp(&vRes, dispid_raguiderate))
        {
            throw ERROR_INFO("ASCOM Scope: GuideRateRA() failed: " + ExcepMsg(scope.Excep()));
        }

        *pRAGuideRate = vRes.dblVal;
    }
    catch (wxString Msg)
    {
        bError = true;
        POSSIBLY_UNUSED(Msg);
    }

    Debug.AddLine("ScopeASCOM::GetGuideRates() returns %u %.4f %.4f", bError,
        bError ? 0.0 : *pDecGuideRate, bError ? 0.0 : *pRAGuideRate);

    return bError;
}
Beispiel #5
0
PierSide ScopeASCOM::SideOfPier(void)
{
    PierSide pierSide = PIER_SIDE_UNKNOWN;

    try
    {
        if (!IsConnected())
        {
            throw ERROR_INFO("ASCOM Scope: cannot get side of pier when not connected");
        }

        if (dispid_sideofpier == DISPID_UNKNOWN)
        {
            throw THROW_INFO("ASCOM Scope: not capable of getting side of pier");
        }

        GITObjRef scope(m_gitEntry);

        Variant vRes;

        if (!scope.GetProp(&vRes, dispid_sideofpier))
        {
            throw ERROR_INFO("ASCOM Scope: SideOfPier failed: " + ExcepMsg(scope.Excep()));
        }

        switch (vRes.intVal) {
        case 0: pierSide = PIER_SIDE_EAST; break;
        case 1: pierSide = PIER_SIDE_WEST; break;
        }
    }
    catch (wxString Msg)
    {
        POSSIBLY_UNUSED(Msg);
    }

    Debug.AddLine("ScopeASCOM::SideOfPier() returns %d", pierSide);

    return pierSide;
}
Beispiel #6
0
PierSide ScopeINDI::SideOfPier(void)
{
    PierSide pierSide = PIER_SIDE_UNKNOWN;
    
    try
    {
        if (!IsConnected())
        {
            throw ERROR_INFO("INDI Scope: cannot get side of pier when not connected");
        }
        
        if (pierside_prop == NULL)
        {
            throw THROW_INFO("INDI Scope: not capable of getting side of pier");
        }
        else
        {
            if (piersideEast_prop->s == ISS_ON) {
                pierSide = PIER_SIDE_EAST;
                
            }
            if (piersideWest_prop->s == ISS_ON) {
                pierSide = PIER_SIDE_WEST;
                
            }
        }
    }
    
    catch (const wxString& Msg)
    {
        POSSIBLY_UNUSED(Msg);
    }
    
    Debug.Write(wxString::Format("ScopeINDI::SideOfPier() returns %d\n", pierSide));
    
    return pierSide;
}
Beispiel #7
0
// Special purpose function to return the guiding declination (radians) - either the actual scope position or the
// default values defined in mount.cpp.  Doesn't throw exceptions to callers.
double ScopeASCOM::GetGuidingDeclination(void)
{
    double dReturn = Scope::GetDefGuidingDeclination();

    try
    {
        if (!IsConnected())
        {
            throw ERROR_INFO("ASCOM Scope: cannot get Declination when not connected to mount");
        }

        if (!m_bCanGetCoordinates)
        {
            throw THROW_INFO("!m_bCanGetCoordinates");
        }

        GITObjRef scope(m_gitEntry);

        Variant vRes;
        if (!scope.GetProp(&vRes, dispid_declination))
        {
            throw ERROR_INFO("GetDeclination() fails: " + ExcepMsg(scope.Excep()));
        }

        dReturn = radians(vRes.dblVal);
    }
    catch (wxString Msg)
    {
        POSSIBLY_UNUSED(Msg);
        m_bCanGetCoordinates = false;
    }

    Debug.AddLine("ScopeASCOM::GetDeclination() returns %.1f", degrees(dReturn));

    return dReturn;
}
Mount::MOVE_RESULT StepGuider::Move(const PHD_Point& cameraVectorEndpoint, bool normalMove)
{
    MOVE_RESULT result = MOVE_OK;

    try
    {
        MOVE_RESULT mountResult = Mount::Move(cameraVectorEndpoint, normalMove);
        if (mountResult != MOVE_OK)
            Debug.AddLine("StepGuider::Move: Mount::Move failed!");

        if (!m_guidingEnabled)
        {
            throw THROW_INFO("Guiding disabled");
        }

        // keep a moving average of the AO position
        if (m_avgOffset.IsValid())
        {
            static double const alpha = .33; // moderately high weighting for latest sample
            m_avgOffset.X += alpha * (m_xOffset - m_avgOffset.X);
            m_avgOffset.Y += alpha * (m_yOffset - m_avgOffset.Y);
        }
        else
        {
            m_avgOffset.SetXY((double) m_xOffset, (double) m_yOffset);
        }

        pFrame->pStepGuiderGraph->AppendData(m_xOffset, m_yOffset, m_avgOffset);

        // consider bumping the secondary mount if this is a normal move
        if (normalMove && pSecondaryMount && pSecondaryMount->IsConnected())
        {
            int absX = abs(CurrentPosition(RIGHT));
            int absY = abs(CurrentPosition(UP));
            bool isOutside = absX > m_xBumpPos1 || absY > m_yBumpPos1;
            bool forceStartBump = false;
            if (m_forceStartBump)
            {
                Debug.Write("stepguider::Move: will start forced bump\n");
                forceStartBump = true;
                m_forceStartBump = false;
            }

            // if the current bump has not brought us in, increase the bump size
            if (isOutside && m_bumpInProgress)
            {
                if (absX > m_xBumpPos2 || absY > m_yBumpPos2)
                {
                    Debug.AddLine("FAR outside bump range, increase bump weight %.2f => %.2f", m_bumpStepWeight, m_bumpStepWeight + 1.0);
                    m_bumpStepWeight += 1.0;
                }
                else
                {
                    Debug.AddLine("outside bump range, increase bump weight %.2f => %.2f", m_bumpStepWeight, m_bumpStepWeight + 1./6.);
                    m_bumpStepWeight += 1./6.;
                }
            }

            // if we are back inside, decrease the bump weight
            if (!isOutside && m_bumpStepWeight > 1.0)
            {
                double prior = m_bumpStepWeight;
                m_bumpStepWeight *= 0.5;
                if (m_bumpStepWeight < 1.0)
                    m_bumpStepWeight = 1.0;
                Debug.AddLine("back inside bump range: decrease bump weight %.2f => %.2f", prior, m_bumpStepWeight);
            }

            if (m_bumpInProgress && !m_bumpTimeoutAlertSent)
            {
                long now = ::wxGetUTCTime();
                if (now - m_bumpStartTime > BumpWarnTime)
                {
                    pFrame->Alert(_("A mount \"bump\" was needed to bring the AO back to its center position,\n"
                        "but the bump did not complete in a reasonable amount of time.\n"
                        "You probably need to increase the AO Bump Step setting."), wxICON_INFORMATION);
                    m_bumpTimeoutAlertSent = true;
                }
            }

            if ((isOutside || forceStartBump) && !m_bumpInProgress)
            {
                // start a new bump
                m_bumpInProgress = true;
                m_bumpStartTime = ::wxGetUTCTime();
                m_bumpTimeoutAlertSent = false;

                Debug.AddLine("starting a new bump");
            }

            // stop the bump if we are "close enough" to the center position
            if ((!isOutside || forceStartBump) && m_bumpInProgress)
            {
                int minDist = m_bumpCenterTolerance;
                if (m_avgOffset.X * m_avgOffset.X + m_avgOffset.Y * m_avgOffset.Y <= minDist * minDist)
                {
                    Debug.AddLine("Stop bumping, close enough to center -- clearing m_bumpInProgress");
                    m_bumpInProgress = false;
                    pFrame->pStepGuiderGraph->ShowBump(PHD_Point());
                }
            }
        }

        if (m_bumpInProgress && pSecondaryMount->IsBusy())
            Debug.AddLine("secondary mount is busy, cannot bump");

        // if we have a bump in progress and the secondary mount is not moving,
        // schedule another move
        if (m_bumpInProgress && !pSecondaryMount->IsBusy())
        {
            // compute incremental bump based on average position
            PHD_Point vectorEndpoint(xRate() * -m_avgOffset.X, yRate() * -m_avgOffset.Y);

            // we have to transform our notion of where we are (which is in "AO Coordinates")
            // into "Camera Coordinates" so we can bump the secondary mount to put us closer
            // to the center of the AO

            PHD_Point bumpVec;

            if (TransformMountCoordinatesToCameraCoordinates(vectorEndpoint, bumpVec))
            {
                throw ERROR_INFO("MountToCamera failed");
            }

            Debug.AddLine("incremental bump (%.3f, %.3f) isValid = %d", bumpVec.X, bumpVec.Y, bumpVec.IsValid());

            double maxBumpPixelsX = m_calibration.xRate * m_bumpMaxStepsPerCycle * m_bumpStepWeight;
            double maxBumpPixelsY = m_calibration.yRate * m_bumpMaxStepsPerCycle * m_bumpStepWeight;
            double len = bumpVec.Distance();
            double xBumpSize = bumpVec.X * maxBumpPixelsX / len;
            double yBumpSize = bumpVec.Y * maxBumpPixelsY / len;

            PHD_Point thisBump(xBumpSize, yBumpSize);

            // display the current bump vector on the stepguider graph
            {
                PHD_Point tcur;
                TransformCameraCoordinatesToMountCoordinates(thisBump, tcur);
                tcur.X /= xRate();
                tcur.Y /= yRate();
                pFrame->pStepGuiderGraph->ShowBump(tcur);
            }

            Debug.AddLine("Scheduling Mount bump of (%.3f, %.3f)", thisBump.X, thisBump.Y);

            pFrame->ScheduleSecondaryMove(pSecondaryMount, thisBump, false);
        }
    }
    catch (wxString Msg)
    {
        POSSIBLY_UNUSED(Msg);
        result = MOVE_ERROR;
    }

    return result;
}
Mount::MOVE_RESULT StepGuider::Move(GUIDE_DIRECTION direction, int steps, bool normalMove, MoveResultInfo *moveResult)
{
    MOVE_RESULT result = MOVE_OK;
    bool limitReached = false;

    try
    {
        Debug.AddLine(wxString::Format("Move(%d, %d, %d)", direction, steps, normalMove));

        // Compute the required guide steps
        if (!m_guidingEnabled)
        {
            throw THROW_INFO("Guiding disabled");
        }

        // Acutally do the guide
        assert(steps >= 0);

        if (steps > 0)
        {
            int yDirection = 0;
            int xDirection = 0;

            switch (direction)
            {
                case UP:
                    yDirection = 1;
                    break;
                case DOWN:
                    yDirection = -1;
                    break;
                case RIGHT:
                    xDirection = 1;
                    break;
                case LEFT:
                    xDirection = -1;
                    break;
                default:
                    throw ERROR_INFO("StepGuider::Move(): invalid direction");
                    break;
            }

            assert(yDirection == 0 || xDirection == 0);
            assert(yDirection != 0 || xDirection != 0);

            Debug.AddLine(wxString::Format("stepping direction=%d steps=%d xDirection=%d yDirection=%d", direction, steps, xDirection, yDirection));

            if (WouldHitLimit(direction, steps))
            {
                int new_steps = MaxPosition(direction) - 1 - CurrentPosition(direction);
                Debug.AddLine(wxString::Format("StepGuider step would hit limit: truncate move direction=%d steps=%d => %d", direction, steps, new_steps));
                steps = new_steps;
                limitReached = true;
            }

            if (steps > 0)
            {
                if (Step(direction, steps))
                {
                    throw ERROR_INFO("step failed");
                }

                m_xOffset += xDirection * steps;
                m_yOffset += yDirection * steps;

                Debug.AddLine(wxString::Format("stepped: xOffset=%d yOffset=%d", m_xOffset, m_yOffset));
            }
        }
    }
    catch (const wxString& Msg)
    {
        POSSIBLY_UNUSED(Msg);
        steps = 0;
        result = MOVE_ERROR;
    }

    if (moveResult)
    {
        moveResult->amountMoved = steps;
        moveResult->limited = limitReached;
    }

    return result;
}
void GuiderOneStar::OnLClick(wxMouseEvent &mevent)
{
    try
    {
        if (mevent.GetModifiers() == wxMOD_CONTROL)
        {
            double const scaleFactor = ScaleFactor();
            wxRealPoint pt((double) mevent.m_x / scaleFactor,
                           (double) mevent.m_y / scaleFactor);
            ToggleBookmark(pt);
            m_showBookmarks = true;
            pFrame->bookmarks_menu->Check(MENU_BOOKMARKS_SHOW, GetBookmarksShown());
            Refresh();
            Update();
            return;
        }

        if (GetState() > STATE_SELECTED)
        {
            mevent.Skip();
            throw THROW_INFO("Skipping event because state > STATE_SELECTED");
        }

        if (mevent.GetModifiers() == wxMOD_SHIFT)
        {
            // Deselect guide star
            InvalidateCurrentPosition(true);
        }
        else
        {
            if ((mevent.m_x <= m_searchRegion) || (mevent.m_x + m_searchRegion >= XWinSize) || (mevent.m_y <= m_searchRegion) || (mevent.m_y + m_searchRegion >= YWinSize))
            {
                mevent.Skip();
                throw THROW_INFO("Skipping event because click outside of search region");
            }

            usImage *pImage = CurrentImage();

            if (pImage->NPixels == 0)
            {
                mevent.Skip();
                throw ERROR_INFO("Skipping event m_pCurrentImage->NPixels == 0");
            }

            double scaleFactor = ScaleFactor();
            double StarX = (double) mevent.m_x / scaleFactor;
            double StarY = (double) mevent.m_y / scaleFactor;

            SetCurrentPosition(pImage, PHD_Point(StarX, StarY));

            if (!m_star.IsValid())
            {
                pFrame->SetStatusText(wxString::Format(_("No star found")));
            }
            else
            {
                SetLockPosition(m_star);
                pFrame->SetStatusText(wxString::Format(_("Selected star at (%.1f, %.1f)"), m_star.X, m_star.Y), 1);
                pFrame->SetStatusText(wxString::Format(_T("m=%.0f SNR=%.1f"), m_star.Mass, m_star.SNR));
                EvtServer.NotifyStarSelected(CurrentPosition());
                SetState(STATE_SELECTED);
                pFrame->UpdateButtonsStatus();
                pFrame->pProfile->UpdateData(pImage, m_star.X, m_star.Y);
            }

            Refresh();
            Update();
        }
    }
    catch (wxString Msg)
    {
        POSSIBLY_UNUSED(Msg);
    }
}
bool GuiderOneStar::UpdateCurrentPosition(usImage *pImage, FrameDroppedInfo *errorInfo)
{
    if (!m_star.IsValid() && m_star.X == 0.0 && m_star.Y == 0.0)
    {
        Debug.AddLine("UpdateCurrentPosition: no star selected");
        errorInfo->starError = Star::STAR_ERROR;
        errorInfo->starMass = 0.0;
        errorInfo->starSNR = 0.0;
        errorInfo->status = _("No star selected");
        return true;
    }

    bool bError = false;

    try
    {
        Star newStar(m_star);

        if (!newStar.Find(pImage, m_searchRegion, pFrame->GetStarFindMode()))
        {
            errorInfo->starError = newStar.GetError();
            errorInfo->starMass = 0.0;
            errorInfo->starSNR = 0.0;
            errorInfo->status = StarStatusStr(newStar);
            m_star.SetError(newStar.GetError());
            throw ERROR_INFO("UpdateCurrentPosition():newStar not found");
        }

        // check to see if it seems like the star we just found was the
        // same as the original star.  We do this by comparing the
        // mass
        m_massChecker->SetExposure(pFrame->RequestedExposureDuration());
        double limits[3];
        if (m_massChangeThresholdEnabled &&
            m_massChecker->CheckMass(newStar.Mass, m_massChangeThreshold, limits))
        {
            m_star.SetError(Star::STAR_MASSCHANGE);
            errorInfo->starError = Star::STAR_MASSCHANGE;
            errorInfo->starMass = newStar.Mass;
            errorInfo->starSNR = newStar.SNR;
            errorInfo->status = StarStatusStr(m_star);
            pFrame->SetStatusText(wxString::Format(_("Mass: %.0f vs %.0f"), newStar.Mass, limits[1]), 1);
            Debug.Write(wxString::Format("UpdateGuideState(): star mass new=%.1f exp=%.1f thresh=%.0f%% range=(%.1f, %.1f)\n", newStar.Mass, limits[1], m_massChangeThreshold * 100, limits[0], limits[2]));
            m_massChecker->AppendData(newStar.Mass);
            throw THROW_INFO("massChangeThreshold error");
        }

        // update the star position, mass, etc.
        m_star = newStar;
        m_massChecker->AppendData(newStar.Mass);

        const PHD_Point& lockPos = LockPosition();
        if (lockPos.IsValid())
        {
            double distance = newStar.Distance(lockPos);
            UpdateCurrentDistance(distance);
        }

        pFrame->pProfile->UpdateData(pImage, m_star.X, m_star.Y);

        pFrame->AdjustAutoExposure(m_star.SNR);

        errorInfo->status.Printf(_T("m=%.0f SNR=%.1f"), m_star.Mass, m_star.SNR);
    }
    catch (wxString Msg)
    {
        POSSIBLY_UNUSED(Msg);
        bError = true;
        pFrame->ResetAutoExposure(); // use max exposure duration
    }

    return bError;
}
double GuideAlgorithmResistSwitch::result(double input)
{
    double dReturn = input;

    m_history.Add(input);
    m_history.RemoveAt(0);

    try
    {
        if (fabs(input) < m_minMove)
        {
            throw THROW_INFO("input < m_minMove");
        }

        if (m_fastSwitchEnabled)
        {
            double thresh = 3.0 * m_minMove;
            if (sign(input) != m_currentSide && fabs(input) > thresh)
            {
                Debug.Write(wxString::Format("resist switch: large excursion: input %.2f thresh %.2f direction from %d to %d\n", input, thresh, m_currentSide, sign(input)));
                // force switch
                m_currentSide = 0;
                unsigned int i;
                for (i = 0; i < HISTORY_SIZE - 3; i++)
                    m_history[i] = 0.0;
                for (; i < HISTORY_SIZE; i++)
                    m_history[i] = input;
            }
        }

        int decHistory = 0;

        for (unsigned int i = 0; i < m_history.GetCount(); i++)
        {
            if (fabs(m_history[i]) > m_minMove)
            {
                decHistory += sign(m_history[i]);
            }
        }

        if (m_currentSide == 0 || sign(m_currentSide) == -sign(decHistory))
        {
            if (abs(decHistory) < 3)
            {
                throw THROW_INFO("not compelling enough");
            }

            double oldest = 0.0;
            double newest = 0.0;

            for (int i = 0; i < 3; i++)
            {
                oldest += m_history[i];
                newest += m_history[m_history.GetCount() - (i + 1)];
            }

            if (fabs(newest) <= fabs(oldest))
            {
                throw THROW_INFO("Not getting worse");
            }

            Debug.Write(wxString::Format("switching direction from %d to %d - decHistory=%d oldest=%.2f newest=%.2f\n", m_currentSide, sign(decHistory), decHistory, oldest, newest));

            m_currentSide = sign(decHistory);
        }

        if (m_currentSide != sign(input))
        {
            throw THROW_INFO("must have overshot -- vetoing move");
        }
    }
    catch (const wxString& Msg)
    {
        POSSIBLY_UNUSED(Msg);
        dReturn = 0.0;
    }

    Debug.Write(wxString::Format("GuideAlgorithmResistSwitch::Result() returns %.2f from input %.2f\n", dReturn, input));

    return dReturn * m_aggression;
}