コード例 #1
0
    def test300_010ShouldReturnSumOfAngles(self):
        # Arrange
        # Act
        angle1 = Angle.stringToAngle("100d4.8")
        angle2 = Angle.stringToAngle("-1d0.0")

        # Assert
        result = Angle.add(angle1, angle2)
        self.assertEqual(result.str, "99d4.8")
コード例 #2
0
    def getPrimeMeridian(cls, year):

        referenceRotation = Angle.stringToAngle("100d42.6")
        yearlyGHADecrement = Angle.stringToAngle("-0d14.32")
        deltaYear = year - 2001
        cumulativeProgression = Angle.multiply(yearlyGHADecrement, deltaYear)

        dailyRotation = Angle.stringToAngle("0d59.0")
        leapYears = math.floor((year - 2001) / 4)
        leapProgression = Angle.multiply(dailyRotation, leapYears)

        totalProgression = Angle.add(referenceRotation, cumulativeProgression)
        totalProgression = Angle.add(totalProgression, leapProgression)

        return totalProgression
コード例 #3
0
    def test400_010ShouldReturnProductOfAngles(self):
        # Arrange
        # Act
        angle = Angle.stringToAngle("0d59.0")
        result = Angle.multiply(angle, 3)

        # Assert
        self.assertEqual(result.str, "2d56.9")
コード例 #4
0
    def test100_010ShouldReturnStringConvertedToAngle(self):
        # Arrange
        # Act
        angle = Angle.stringToAngle("164d54.5")

        # Assert
        self.assertEqual(angle.hourDegree, 164)
        self.assertEqual(angle.minuteDegree, 54.5)
        self.assertAlmostEqual(angle.decimal, 0.458, places=3)
コード例 #5
0
def locate(values=None):

    # ----- Validation -----
    if values is None or not isinstance(values, dict):
        return {'error': 'values is not provided'}

    if (not ('assumedLat' in values)):
        return {'error': 'mandatory information missing'}

    if (not ('assumedLong' in values)):
        return {'error': 'mandatory information missing'}

    if (not ('corrections' in values)):
        return {'error': 'mandatory information missing'}

    # validate assumedLat
    assumedLat = values['assumedLat']
    x, y = assumedLat.split("d")

    if int(x) < -89 or int(x) > 89:
        return {'error': 'assumedLat is invalid'}
    y = y.lstrip("0")
    if float(y) < 0.0 or not float(y) < 60:
        return {'error': 'assumedLat is invalid'}

    # validate assumed longitude
    assumedLong = values['assumedLong']
    x, y = assumedLong.split("d")
    if int(x) < 0 or int(x) > 359:
        return {'error': 'assumedLong is invalid'}
    y = y.lstrip("0")
    if float(y) < 0.0 or not float(y) < 60:
        return {'error': 'assumedLong is invalid'}

    # validate corrections
    corrections = values['corrections']
    corrections = corrections.split(', ')
    for correction in corrections:
        correctedDistance, correctedAzmuth = correction.split(",")

        # remove brackets
        correctedAzmuth = correctedAzmuth.replace(']', "")
        correctedAzmuth = correctedAzmuth.replace(']', "")
        correctedDistance = correctedDistance.replace('[', "")
        correctedDistance = correctedDistance.replace('[', "")

        # validate corrected distance
        correctedDistance = float(correctedDistance)
        if correctedDistance < 0:
            return {'error': 'correctedDistance is invalid'}

    # ----- Initialization ------
    result = values

    assumedLat = values['assumedLat']
    assumedLong = values['assumedLong']
    corrections = values['corrections']

    # ----- Calculation -----

    # add corrections to dict
    corrections = corrections.split(', ')

    # Calculate the present position as the vector sum of the corrections for each sighting:
    nsCorrection = 0
    ewCorrection = 0
    n = len(corrections)

    for correction in corrections:
        correctedDistance, correctedAzmuth = correction.split(",")

        # remove brackets
        correctedAzmuth = correctedAzmuth.replace(']', "")
        correctedAzmuth = correctedAzmuth.replace(']', "")
        correctedDistance = correctedDistance.replace('[', "")
        correctedDistance = correctedDistance.replace('[', "")

        correctedAzmuth = Angle.stringToAngle(correctedAzmuth)
        correctedAzmuth.decimal = correctedAzmuth.hourDegree + (
            correctedAzmuth.minuteDegree / 60)
        correctedDistance = float(correctedDistance)

        nsCorrection += correctedDistance * math.cos(
            math.radians(correctedAzmuth.decimal))
        ewCorrection += correctedDistance * math.sin(
            math.radians(correctedAzmuth.decimal))

    nsCorrection = nsCorrection / n
    ewCorrection = ewCorrection / n

    assumedLat = Angle.stringToAngle(assumedLat)
    assumedLat.decimal = assumedLat.hourDegree + (assumedLat.minuteDegree / 60)
    assumedLat.decimal = assumedLat.decimal + (nsCorrection / 60)
    left, right = str(assumedLat.decimal).split(".")
    right = "0." + right
    right = float(right)
    right = right * 60
    right = round(right, 1)

    result['presentLat'] = str(int(left)) + "d" + str(right)

    assumedLong = Angle.stringToAngle(assumedLong)
    assumedLong.decimal = assumedLong.hourDegree + (assumedLong.minuteDegree /
                                                    60)
    assumedLong.decimal = assumedLong.decimal + (ewCorrection / 60)
    left, right = str(assumedLong.decimal).split(".")
    right = "0." + right
    right = float(right)
    right = right * 60
    right = round(right, 1)

    result['presentLong'] = str(int(left)) + "d" + str(right)

    # Estimate the precision of the present position by measuring the uniformity of the input corrected distance/corrected azimuth pairs:
    precision = 0

    for correction in corrections:
        correctedDistance, correctedAzmuth = correction.split(",")

        # remove brackets
        correctedAzmuth = correctedAzmuth.replace(']', "")
        correctedAzmuth = correctedAzmuth.replace(']', "")
        correctedDistance = correctedDistance.replace('[', "")
        correctedDistance = correctedDistance.replace('[', "")

        correctedAzmuth = Angle.stringToAngle(correctedAzmuth)
        correctedAzmuth.decimal = correctedAzmuth.hourDegree + (
            correctedAzmuth.minuteDegree / 60)
        correctedDistance = float(correctedDistance)

        a = math.pow(
            ((correctedDistance *
              math.cos(math.radians(correctedAzmuth.decimal))) - nsCorrection),
            2)

        b = math.pow(
            ((correctedDistance *
              math.sin(math.radians(correctedAzmuth.decimal))) - ewCorrection),
            2)

        precision += math.sqrt(a + b)

    precision = (1.0 / n) * precision
    left, right = str(precision).split(".")
    result['precision'] = left
    result['accuracy'] = 'NA'

    return result
コード例 #6
0
def predict(values=None):

    # ------ Validation ------
    if values is None or not isinstance(values, dict):
        return {'error': 'values is not provided'}

    if (not ('body' in values)):
        return {'error': 'no body provided'}

    starName = values['body']
    if starName not in STARS:
        return {'error': 'unknown star'}

    if "date" in values:
        date = values['date']
        (year, month, day) = date.split('-')
        year = int(year)
        month = int(month)
        day = int(day)

        if year < 2001:
            return {'error': 'invalid date'}

    if "time" in values:
        time = values['time']
        (hour, minute, second) = time.split(':')
        hour = int(hour)
        minute = int(minute)
        second = int(second)

        if hour > 23 or minute > 59 or second > 59:
            return {'error': 'invalid time'}

    # ------ Initialization ------
    result = values

    body = values['body']

    if 'date' in values:
        date = values['date']
    else:
        date = '2001-01-01'

    if 'time' in values:
        time = values['time']
    else:
        time = "00:00:00"

    sidereal = STARS[body]['sidereal']

    declination = STARS[body]['declination']

    # ------ Calculation ------
    latitude = Angle.stringToAngle(declination)
    (year, month, day) = date.split("-")
    (hour, minute, second) = time.split(":")
    year = int(year)
    month = int(month)
    day = int(day)
    hour = int(hour)
    minute = int(minute)
    second = int(second)

    gha = Aries.getGreenwichHourAngle(year, month, day, hour, minute, second)
    sha = Angle.stringToAngle(sidereal)

    longitude = Angle.add(gha, sha)
    fullAngle = Angle.stringToAngle("-360d0.0")

    if longitude.hourDegree > 360:
        longitude = Angle.add(longitude, fullAngle)

    if longitude.hourDegree == 360 and longitude.minuteDegree > 0:
        longitude = Angle.add(longitude, fullAngle)

    result['lat'] = latitude.str
    result['long'] = longitude.str

    return result
コード例 #7
0
def correct(values=None):

    # ----- Validation -----
    if values is None or not isinstance(values, dict):
        return {'error': 'values is not provided'}

    if (not ('lat' in values)):
        return {'error': 'mandatory information missing'}
    if (not ('long' in values)):
        return {'error': 'mandatory information missing'}
    if (not ('altitude' in values)):
        return {'error': 'mandatory information missing'}
    if (not ('assumedLat' in values)):
        return {'error': 'mandatory information missing'}
    if (not ('assumedLong' in values)):
        return {'error': 'mandatory information missing'}

    # validate lat
    lat = values['lat']
    x, y = lat.split("d")

    if int(x) < -89 or int(x) > 89:
        return {'error': 'lat is invalid'}
    y = y.lstrip("0")
    if float(y) < 0.0 or not float(y) < 60:
        return {'error': 'lat is invalid'}

    # validate assumedLat
    assumedLat = values['assumedLat']
    x, y = assumedLat.split("d")

    if int(x) < -89 or int(x) > 89:
        return {'error': 'assumedLat is invalid'}
    y = y.lstrip("0")
    if float(y) < 0.0 or not float(y) < 60:
        return {'error': 'assumedLat is invalid'}

    # validate longitude
    longitude = values['long']
    x, y = longitude.split("d")

    if int(x) < 0 or int(x) > 359:
        return {'error': 'long is invalid'}
    y = y.lstrip("0")
    if float(y) < 0.0 or not float(y) < 60:
        return {'error': 'long is invalid'}

    # validate assumed longitude
    assumedLong = values['assumedLong']
    x, y = assumedLong.split("d")
    if int(x) < 0 or int(x) > 359:
        return {'error': 'assumedLong is invalid'}
    y = y.lstrip("0")
    if float(y) < 0.0 or not float(y) < 60:
        return {'error': 'assumedLong is invalid'}

    # validate altitude
    altitude = values['altitude']
    x, y = altitude.split("d")
    if int(x) < 0 or int(x) > 89:
        return {'error': 'altitude is invalid'}
    y = y.lstrip("0")
    if float(y) < 0.0 or not float(y) < 60:
        return {'error': 'altitude is invalid'}
    if int(x) == 0 and float(y) < 0.1:
        return {'error': 'altitude is invalid'}

    # ----- Initialization -----
    result = values

    lat = values['lat']
    longitude = values['long']
    altitude = values['altitude']
    assumedLat = values['assumedLat']
    assumedLong = values['assumedLong']

    # ----- Calculation -----
    lat = Angle.stringToAngle(lat)
    longitude = Angle.stringToAngle(longitude)
    assumedLat = Angle.stringToAngle(assumedLat)
    assumedLong = Angle.stringToAngle(assumedLong)
    altitude = Angle.stringToAngle(altitude)

    # calculate the local hour angle of the navigator
    lha = Angle.add(longitude, assumedLong)

    # calculate the angle to adjust the observed altitude to match
    # the star observed from the assumed position
    sin_lat = math.sin(math.radians(lat.decimal * 360))
    cos_lat = math.cos(math.radians(lat.decimal * 360))

    sin_assumedLat = math.sin(math.radians(assumedLat.decimal * 360))
    cos_assumedLat = math.cos(math.radians(assumedLat.decimal * 360))
    cos_lha = math.cos(math.radians(lha.decimal * 360))

    intermediateDistance = sin_lat * sin_assumedLat + cos_lat * cos_assumedLat * cos_lha

    correctedAltitude = math.asin(intermediateDistance) / math.pi * 180 / 360
    correctedAltitude = Angle.decimalToAngle(-correctedAltitude)

    # Calculate the distance the navigator needs to move to make the
    # observed and calculated star positions match
    correctedDistance = Angle.add(altitude, correctedAltitude)
    correctedDistance = int(correctedDistance.decimal * 60 * 360)

    # Determine the compass direction in which to make the distance adjustment
    compassDirection = math.cos(math.radians(correctedAltitude.decimal * 360))

    numerator = (sin_lat - (sin_assumedLat * intermediateDistance))
    denomonator = cos_assumedLat * compassDirection

    correctedAz = math.acos(numerator / denomonator)
    correctedAzDegree = math.degrees(correctedAz)
    correctedAzimuth = Angle.decimalToAngle(correctedAzDegree / 360)

    # If the correctedDistance < 0, then normalize  by 1) obtaining the absolute value of the
    # correctedDistance and 2) adjusting the correctedAzimuth by 180 degrees
    if (correctedDistance < 0):
        correctedDistance = abs(correctedDistance) + 1
        correctedAzimuth.str = str(correctedAzimuth.hourDegree +
                                   180) + "d" + str(
                                       correctedAzimuth.minuteDegree)

    result['correctedDistance'] = correctedDistance
    result['correctedAzimuth'] = correctedAzimuth.str

    return result