def cfunc(x, params): """ this function returns the constraint violation of the 3seg leg. it must be zeroed! Parameters ---------- x configuration of the leg: Fy, h1, h2, tau1, tau2 params parameter of the system: l, l1, l2, l3, c1, c2 Returns ------- eq : *array* (1x5) the non-fulfilment of the constraints (subject to root finding) """ l, l1, l2, l3, c1, c2 = params # print l, l1, l2, l3, c1, c2 Fy, h1, h2, tau1, tau2 = array(x).squeeze() # print Fy, h1, h2, tau1, tau2 if h1 > l1: print "warning: invalid h1" h1 = l1 return [ 5000, ] * 5 if h2 > l3: print "warning: invalid h2" h2 = l2 return [ 5000, ] * 5 if h1 + h2 > l2: print "warning: invalid h1 + h2" return [ 5000, ] * 5 while h1 + h2 > l2: h1 = .8 * h1 h2 = .8 * h2 eq1 = Fy * h1 - tau1 eq2 = tau1 - Fy * h1 - Fy * h2 + tau2 eq3 = Fy * h2 - tau2 eq4 = -1. * c1 * (arccos(h1 / l1) + arccos( (h1 + h2) / l2) - .9 * pi) - tau1 eq5 = -1. * c2 * (arccos(h2 / l3) + arccos( (h1 + h2) / l2) - .9 * pi) - tau2 eq6 = sqrt(l1**2 - h1**2) + sqrt(l2**2 - (h1 + h2)**2) + sqrt(l3**2 - h2**2) - l # note: eq2 is omitted because of equality to - (eq1 + eq3)! return array([eq1, eq3, eq4, eq5, eq6])
def FreezeDuration_calculator(pointing_altitude1, pointing_altitude2, TLE2): """Function that calculates the angle between two tangential altitudes and then calculates the time it takes for orbital position angle of a satellite in a circular orbit to change by the same amount. Used to estimate the duration of an attitude freeze for which the pointing altitude reorients itself to the standard pointing altitude. Arguments: pointing_altitude1 (int): First tangential pointing altitude in m pointing_altitude2 (int): Second tangential pointing altitude in m TLE2 (str): Second row of a TLE. Returns: (int): FreezeDuration, Time [s] it takes for the satellites orbital position angle to change by the same amount as the angle between the two tangential pointing altitudes as seen from the satellite. """ U = 398600.4418 # Earth gravitational parameter MATS_P = 24 * 3600 / float(TLE2[52:63]) # Orbital Period of MATS [s] MATS_p = ((MATS_P / 2 / pi)**2 * U)**( 1 / 3) # Semi-major axis of MATS assuming circular orbit [km] R_mean = 6371 # Mean Earth radius [km] pitch1 = arccos((R_mean + pointing_altitude1 / 1000) / (MATS_p)) / pi * 180 pitch2 = arccos((R_mean + pointing_altitude2 / 1000) / (MATS_p)) / pi * 180 pitch_angle_difference = abs(pitch1 - pitch2) "#The time it takes for the orbital position angle to change by the same amount as" "#the angle between the pointing axes" FreezeDuration = int(round(MATS_P * (pitch_angle_difference) / 360, 0)) return FreezeDuration
def match_SIFT(desc1, desc2): '''For each descriptor in the first image, select its match in the second image. input: desc1 (descriptors for the first image), desc2 (same for the second image).''' desc1 = np.array([d / plt.linalg.norm(d) for d in desc1]) desc2 = np.array([d / plt.linalg.norm(d) for d in desc2]) dist_ratio = 0.6 desc1_size = desc1.shape matchscores = np.zeros((desc1_size[0], 1), 'int') desc2t = desc2.T #precompute matrix transpose for i in range(desc1_size[0]): dotprods = np.dot(desc1[i, :], desc2t) #vector of dot products dotprods = 0.9999 * dotprods # inverse cosine and sort, return index for features in second Image indx = np.argsort(plt.arccos(dotprods)) # check if nearest neighbor has angle less than dist_ratio times 2nd if plt.arccos(dotprods)[ indx[0]] < dist_ratio * plt.arccos(dotprods)[indx[1]]: matchscores[i] = np.int(indx[0]) return matchscores
def cartesian2polar(xyz): """cartesian2polar(x, y, z) converts coordinate from xyz to r\theta\phi""" x, y, z = xyz ## if z == 0: ## raise exceptions.ValueError("cartesian " + str(xyz) + " z must be nonzero.") r = pylab.sqrt(sum(map(lambda x: x**2, [x, y, z]))) theta = pylab.arccos(z / r) phi = pylab.arccos(x / pylab.sqrt(sum(map(lambda x: x**2, [x, y])))) if y < 0: phi *= -1 return (r, theta, phi)
def cartesian2polar(xyz): """cartesian2polar(x, y, z) converts coordinate from xyz to r\theta\phi""" x, y, z = xyz ## if z == 0: ## raise exceptions.ValueError("cartesian " + str(xyz) + " z must be nonzero.") r = pylab.sqrt(sum(map(lambda x: x**2, [x, y, z]))) theta = pylab.arccos(z/r) phi = pylab.arccos(x / pylab.sqrt(sum(map(lambda x: x**2, [x, y])))) if y < 0: phi *= -1 return (r, theta, phi)
def vectors_to_Angle(self, aV1, aV2): mVect1 = pylab.matrix(aV1) mVect2 = pylab.matrix(aV2) nNorms = (pylab.norm(mVect1) * pylab.norm(mVect2)) if nNorms == 0: return "-" nAngle = pylab.arccos(mVect1 * mVect2.T / nNorms) return float(nAngle)
def vectors_to_Angle(self, aV1, aV2): mVect1 = pylab.matrix(aV1); mVect2 = pylab.matrix(aV2); nNorms = (pylab.norm(mVect1)*pylab.norm(mVect2)); if nNorms==0: return float('nan'); nAngle = pylab.arccos(mVect1*mVect2.T/nNorms); return float(nAngle);
def getMohoEvePA(t): moho = tk.Moho.eph(t)[0][:2] eve = tk.Eve.eph(t)[0][:2] moho = moho / norm(moho) eve = eve / norm(eve) return degrees(arccos(moho.dot(eve)))
def getMohoKerbinPA(t): moho = tk.Moho.eph(t)[0][:2] kerbin = tk.Kerbin.eph(t)[0][:2] moho = moho / norm(moho) kerbin = kerbin / norm(kerbin) return degrees(arccos(moho.dot(kerbin)))
def sine_single(mini, maxi): """ generator function for psudo random numbers from a single seed under pdf = 0.5*pl.sin(x) to be used in rejection method """ f = lambda x: pl.arccos(1 - 2 * x) while True: yield f(random.uniform(mini, maxi))
def my_hor_to_eq(az, el, lat, lsts): dec = arcsin(sin(el) * sin(lat) + cos(el) * cos(lat) * cos(az)) argument = (sin(el) - sin(lat) * sin(dec)) / (cos(lat) * cos(dec)) argument = clip(argument, -1.0, 1.0) H = arccos(argument) flag = sin(az) > 0 H[flag] = 2.0*pi - H[flag] ra = lsts - H ra %= 2*pi return ra,dec
def eq_to_hor(ra, dec, lat, lst): H = lst - ra el = arcsin(sin(dec) * sin(lat) + cos(dec) * cos(lat) * cos(H)) az = arccos((sin(dec) - sin(lat) * sin(el)) / (cos(lat) * cos(el))) flag = sin(H) > 0 if type(flag) is ndarray: az[flag] = 2.0 * pi - az[flag] elif flag: az = 2.0 * pi - az return az, el
def draw_rand_sphere_pos(self): azimuth = (pl.rand(self.n) - 0.5) * 2 * pl.pi zenith = pl.arccos(2 * pl.rand(self.n) - 1) r = pl.rand(self.n)**(2. / 3.) * self.radius x = r * pl.sin(zenith) * pl.cos(azimuth) y = r * pl.sin(zenith) * pl.sin(azimuth) z = r * pl.cos(zenith) soma_pos = {'xpos': x, 'ypos': y, 'zpos': z, 'r': r} return soma_pos
def transformation(N, mini, maxi, bins): start_time = time.time() a = uniform(N, mini, maxi, bins)[0] f = lambda x: pl.arccos(1 - 2 * x) #implements calculated cdf l = [f(i) for i in a] print("Time for transformation method with %s points: %s" % (N, time.time() - start_time)) transformation.time = time.time() - start_time return l
def hor_to_eq(az, el, lat, lst): dec = arcsin(sin(el) * sin(lat) + cos(el) * cos(lat) * cos(az)) argument = (sin(el) - sin(lat) * sin(dec)) / (cos(lat) * cos(dec)) argument = pylab.clip(argument, -1.0, 1.0) H = arccos(argument) flag = sin(az) > 0 if type(flag) is ndarray: H[flag] = 2.0 * pi - H[flag] elif flag: H = 2.0 * pi - H ra = lst - H ra %= 2 * pi return ra, dec
def fitOscillations(self, harmonics=None): """""" t = self.variableArray dt = t[1] - t[0] data = self.orders[0] amp_guess = (data.max() - data.min()) / 2 weights = abs(py.fft(data))**2 index = weights.argmax() if harmonics is None else harmonics f_guess = py.fftfreq(t[-1] - t[0], dt)[index] offset_guess = data.mean() phi_guess = py.arccos(data[0] - offset_guess) guesses = [amp_guess, f_guess, phi_guess, offset_guess] self.guesses = guesses coeffs, matcov = curve_fit(self.func, t, data, self.guesses) self.coeffs = coeffs self.matcov = matcov
def branch_angle(G, parent, child1, child2): parent_coord = pylab.array(G.node[parent]['coord']) child1_coord = pylab.array(G.node[child1]['coord']) child2_coord = pylab.array(G.node[child2]['coord']) v1 = child1_coord - parent_coord v2 = child2_coord - parent_coord m1 = ((v1**2).sum())**0.5 m2 = ((v2**2).sum())**0.5 dp = pylab.dot(v1, v2) cos = dp / (m1 * m2) if cos < -1: cos = 1 elif cos > 1: cos = 1 theta = pylab.arccos(cos) return theta
def SunAngle(PositionVector, SimulationTime): """Calculates angle between a position vector and the position vector of the Sun. Simulates a single point in time for the Sun observed from Earth using Skyfield and then calculates the angle between the position vector of the Sun and the given input position vector. Used to determine the eclipse angle of the Sun angle of the position. Arguments: PositionVector (array): Position vector. SimulationTime (:obj:`ephem.Date`): The time of the simulation. Returns: (float): The sun angle [degrees]. """ current_time_datetime = ephem.Date(SimulationTime).datetime() year = current_time_datetime.year month = current_time_datetime.month day = current_time_datetime.day hour = current_time_datetime.hour minute = current_time_datetime.minute second = current_time_datetime.second + current_time_datetime.microsecond / 1000000 current_time_skyfield = timescale_skyfield.utc( year, month, day, hour, minute, second ) Sun = database_skyfield["Sun"] Earth = database_skyfield["Earth"] SunFromEarth = Earth.at(current_time_skyfield).observe(Sun) r_SunFromEarth_km = SunFromEarth.position.km SunAngle = arccos( dot(PositionVector, r_SunFromEarth_km) / (norm(r_SunFromEarth_km) * norm(PositionVector)) ) SunAngle = SunAngle / pi * 180 return SunAngle
def generate_datafile(name,departures,depart_planet,arrive_planet,errors=0): f = open(name,'w') last = departures[-1] lasty = int(last[0] / 60.0 / 60.0 / 24.0 / 365.0) inacc = 0.0 for departure in departures: if departure[1]: inacc += 1.0 f.write("// Phase angles for the next %i years for %s - %s Hohmann transfers\n"%(lasty,depart_planet.name,arrive_planet.name)) f.write("// Calculated using the KSP Mission Control toolkit\n") f.write("// Angles are valid for Kerbal Space Program 0.19\n") f.write("// Total windows: %i\n"%len(departures)) f.write("// Inaccuracies during calculation: %i (%i%%)\n\n"%(inacc,inacc / len(departures) * 100)) f.write("UT Departure\tPhase angle\tDate time\tAccurate (Error in seconds)\n") for departure in departures: accurate = departure[1] if accurate == 0: accurate = "Yes" else: accurate = str(accurate) departure = departure[0] e1 = depart_planet.eph(departure)[0] e2 = arrive_planet.eph(departure)[0] e1 /= norm(e1) e2 /= norm(e2) PA = degrees(arccos(e1.dot(e2))) * sign(cross(e1,e2)[2]) years = floor(departure/60.0/60.0/24.0/365.0)+1 days = floor((departure/60.0/60.0/24.0)%365.0)+1 f.write("%f\t%f\tYear %i, Day %i\t%s\n"%(departure,PA,years,days,accurate)) f.close()
def __init__(self,celestialFrom,celestialTo,timeRange,multiplier=86400.0): self.figure = figure(figsize=(8,8)) self.axis = self.figure.gca(projection="rectilinear")#,aspect='equal') X = [] Y = [] for t in timeRange: t *= multiplier ephFrom = celestialFrom.eph(t) ephTo= celestialTo.eph(t) pFrom = ephFrom[0] / norm(ephFrom[0]) pTo = ephTo[0] / norm(ephTo[0]) print pFrom print pTo print "ye",t angle = degrees(arccos(pFrom.dot(pTo))) X.append(t/multiplier) Y.append(angle) self.axis.plot(X,Y)
A = ma * mb * Ta B = mB + mb C = (mB + mb) / mb D = C * 2. * mb * Tb E = 2. * ma * Ta F0 = 2. * mB * (Q0 + Ta) F1 = 2. * mB * (Q1 + Ta) F2 = 2. * mB * (Q2 + Ta) G = 2. * py.sqrt(2. * ma * Ta) * py.sqrt(2. * mb * Tb) primer = (py.sqrt(A)) / (B) segundo0 = (B) * (mB * Q0 + (mB - ma) * Ta) segundo1 = (B) * (mB * Q1 + (mB - ma) * Ta) segundo2 = (B) * (mB * Q2 + (mB - ma) * Ta) thetamin0 = py.arccos(py.sqrt(-segundo0 / A)) thetamin1 = py.arccos(py.sqrt(-segundo1 / A)) thetamin2 = py.arccos(py.sqrt(-segundo2 / A)) print('thetamin0=', thetamin0) print('thetamin1=', thetamin1) print('thetamin2=', thetamin2) print('') x = py.arange(0, thetamin0, 0.000005) y1 = (py.cos(x) * primer + (py.sqrt(A * (py.cos(x)**2) + segundo0) / B))**2 y2 = (py.cos(x) * primer - (py.sqrt(A * (py.cos(x)**2) + segundo0) / B))**2 y3 = (py.cos(x) * primer + (py.sqrt(A * (py.cos(x)**2) + segundo1) / B))**2 y4 = (py.cos(x) * primer - (py.sqrt(A * (py.cos(x)**2) + segundo1) / B))**2 y5 = (py.cos(x) * primer + (py.sqrt(A * (py.cos(x)**2) + segundo2) / B))**2 y6 = (py.cos(x) * primer - (py.sqrt(A * (py.cos(x)**2) + segundo2) / B))**2
def lambert(r1vec,r2vec,tf,m,muC): # original documentation: # ············································· # # This routine implements a new algorithm that solves Lambert's problem. The # algorithm has two major characteristics that makes it favorable to other # existing ones. # # 1) It describes the generic orbit solution of the boundary condition # problem through the variable X=log(1+cos(alpha/2)). By doing so the # graph of the time of flight become defined in the entire real axis and # resembles a straight line. Convergence is granted within few iterations # for all the possible geometries (except, of course, when the transfer # angle is zero). When multiple revolutions are considered the variable is # X=tan(cos(alpha/2)*pi/2). # # 2) Once the orbit has been determined in the plane, this routine # evaluates the velocity vectors at the two points in a way that is not # singular for the transfer angle approaching to pi (Lagrange coefficient # based methods are numerically not well suited for this purpose). # # As a result Lambert's problem is solved (with multiple revolutions # being accounted for) with the same computational effort for all # possible geometries. The case of near 180 transfers is also solved # efficiently. # # We note here that even when the transfer angle is exactly equal to pi # the algorithm does solve the problem in the plane (it finds X), but it # is not able to evaluate the plane in which the orbit lies. A solution # to this would be to provide the direction of the plane containing the # transfer orbit from outside. This has not been implemented in this # routine since such a direction would depend on which application the # transfer is going to be used in. # # please report bugs to [email protected] # # adjusted documentation: # ······················· # # By default, the short-way solution is computed. The long way solution # may be requested by giving a negative value to the corresponding # time-of-flight [tf]. # # For problems with |m| > 0, there are generally two solutions. By # default, the right branch solution will be returned. The left branch # may be requested by giving a negative value to the corresponding # number of complete revolutions [m]. # Authors # .·`·.·`·.·`·.·`·.·`·.·`·.·`·.·`·.·`·.·`·.·`·.·`·.·`·.·`·.·`·. # Name : Dr. Dario Izzo # E-mail : [email protected] # Affiliation: ESA / Advanced Concepts Team (ACT) # Made readible and optimized for speed by Rody P.S. Oldenhuis # Code available in MGA.M on http://www.esa.int/gsp/ACT/inf/op/globopt.htm # last edited 12/Dec/2009 # ADJUSTED FOR EML-COMPILATION 24/Dec/2009 # initial values tol = 1e-12 bad = False days = 1 # work with non-dimensional units r1 = norm(r1vec) #sqrt(r1vec*r1vec.'); r1vec = r1vec/r1; r1vec = r1vec / r1 r2vec = r2vec / r1 V = sqrt(muC/r1) T = r1/V tf= tf*days/T # also transform to seconds # relevant geometry parameters (non dimensional) mr2vec = norm(r2vec) # make 100# sure it's in (-1 <= dth <= +1) dth = arccos( max(-1, min(1, (r1vec.dot(r2vec)/mr2vec)))) # decide whether to use the left or right branch (for multi-revolution # problems), and the long- or short way leftbranch = sign(m) longway = sign(tf) m = abs(m) tf = abs(tf) if (longway < 0): dth = 2*pi - dth # derived quantities c = sqrt(1.0 + mr2vec**2 - 2*mr2vec*cos(dth)) # non-dimensional chord s = (1.0 + mr2vec + c)/2.0 # non-dimensional semi-perimeter a_min = s/2.0 # minimum energy ellipse semi major axis Lambda = sqrt(mr2vec)*cos(dth/2.0)/s # lambda parameter (from BATTIN's book) crossprd = cross(r1vec,r2vec) mcr = norm(crossprd) # magnitues thereof nrmunit = crossprd/mcr # unit vector thereof # Initial values # ························································· # ELMEX requires this variable to be declared OUTSIDE the IF-statement logt = log(tf); # avoid re-computing the same value # single revolution (1 solution) if (m == 0): # initial values inn1 = -0.5233 # first initial guess inn2 = +0.5233 # second initial guess x1 = log(1 + inn1)# transformed first initial guess x2 = log(1 + inn2)# transformed first second guess # multiple revolutions (0, 1 or 2 solutions) # the returned soltuion depends on the sign of [m] else: # select initial values if (leftbranch < 0): inn1 = -0.5234 # first initial guess, left branch inn2 = -0.2234 # second initial guess, left branch else: inn1 = +0.7234 # first initial guess, right branch inn2 = +0.5234 # second initial guess, right branch x1 = tan(inn1*pi/2)# transformed first initial guess x2 = tan(inn2*pi/2)# transformed first second guess # since (inn1, inn2) < 0, initial estimate is always ellipse xx = array([inn1, inn2]) aa = a_min/(1 - xx**2) bbeta = longway * 2*arcsin(sqrt((s-c)/2./aa)) # make 100.4% sure it's in (-1 <= xx <= +1) if xx[0] > 1: xx[0] = 1 if xx[0] < -1: xx[0] = -1 if xx[1] > 1: xx[1] = 1 if xx[1] < -1: xx[1] = -1 aalfa = 2*arccos( xx ) # evaluate the time of flight via Lagrange expression y12 = aa*sqrt(aa)*((aalfa - sin(aalfa)) - (bbeta-sin(bbeta)) + 2*pi*m) # initial estimates for y if m == 0: y1 = log(y12[0]) - logt y2 = log(y12[1]) - logt else: y1 = y12[0] - tf y2 = y12[1] - tf # Solve for x # ························································· # Newton-Raphson iterations # NOTE - the number of iterations will go to infinity in case # m > 0 and there is no solution. Start the other routine in # that case err = 1e99 iterations = 0 xnew = 0 while (err > tol): # increment number of iterations iterations += 1 # new x xnew = (x1*y2 - y1*x2) / (y2-y1); # copy-pasted code (for performance) if m == 0: x = exp(xnew) - 1 else: x = arctan(xnew)*2/pi a = a_min/(1 - x**2); if (x < 1): # ellipse beta = longway * 2*arcsin(sqrt((s-c)/2/a)) # make 100.4% sure it's in (-1 <= xx <= +1) alfa = 2*arccos( max(-1, min(1, x)) ) else: # hyperbola alfa = 2*arccosh(x); beta = longway * 2*arcsinh(sqrt((s-c)/(-2*a))) # evaluate the time of flight via Lagrange expression if (a > 0): tof = a*sqrt(a)*((alfa - sin(alfa)) - (beta-sin(beta)) + 2*pi*m) else: tof = -a*sqrt(-a)*((sinh(alfa) - alfa) - (sinh(beta) - beta)) # new value of y if m ==0: ynew = log(tof) - logt else: ynew = tof - tf # save previous and current values for the next iterarion # (prevents getting stuck between two values) x1 = x2; x2 = xnew; y1 = y2; y2 = ynew; # update error err = abs(x1 - xnew); # escape clause if (iterations > 15): bad = True break # If the Newton-Raphson scheme failed, try to solve the problem # with the other Lambert targeter. if bad: # NOTE: use the original, UN-normalized quantities #[V1, V2, extremal_distances, exitflag] = ... # lambert_high_LancasterBlanchard(r1vec*r1, r2vec*r1, longway*tf*T, leftbranch*m, muC); print "FAILZ0r" return # convert converged value of x if m==0: x = exp(xnew) - 1 else: x = arctan(xnew)*2/pi #{ # The solution has been evaluated in terms of log(x+1) or tan(x*pi/2), we # now need the conic. As for transfer angles near to pi the Lagrange- # coefficients technique goes singular (dg approaches a zero/zero that is # numerically bad) we here use a different technique for those cases. When # the transfer angle is exactly equal to pi, then the ih unit vector is not # determined. The remaining equations, though, are still valid. #} # Solution for the semi-major axis a = a_min/(1-x**2); # Calculate psi if (x < 1): # ellipse beta = longway * 2*arcsin(sqrt((s-c)/2/a)) # make 100.4# sure it's in (-1 <= xx <= +1) alfa = 2*arccos( max(-1, min(1, x)) ) psi = (alfa-beta)/2 eta2 = 2*a*sin(psi)**2/s eta = sqrt(eta2); else: # hyperbola beta = longway * 2*arcsinh(sqrt((c-s)/2/a)) alfa = 2*arccosh(x) psi = (alfa-beta)/2 eta2 = -2*a*sinh(psi)**2/s eta = sqrt(eta2) # unit of the normalized normal vector ih = longway * nrmunit; # unit vector for normalized [r2vec] r2n = r2vec/mr2vec; # cross-products # don't use cross() (emlmex() would try to compile it, and this way it # also does not create any additional overhead) #crsprd1 = [ih(2)*r1vec(3)-ih(3)*r1vec(2),... # ih(3)*r1vec(1)-ih(1)*r1vec(3),... # ih(1)*r1vec(2)-ih(2)*r1vec(1)]; crsprd1 = cross(ih,r1vec) #crsprd2 = [ih(2)*r2n(3)-ih(3)*r2n(2),... # ih(3)*r2n(1)-ih(1)*r2n(3),... # ih(1)*r2n(2)-ih(2)*r2n(1)]; crsprd2 = cross(ih,r2n) # radial and tangential directions for departure velocity Vr1 = 1/eta/sqrt(a_min) * (2*Lambda*a_min - Lambda - x*eta) Vt1 = sqrt(mr2vec/a_min/eta2 * sin(dth/2)**2) # radial and tangential directions for arrival velocity Vt2 = Vt1/mr2vec Vr2 = (Vt1 - Vt2)/tan(dth/2) - Vr1 # terminal velocities V1 = (Vr1*r1vec + Vt1*crsprd1)*V V2 = (Vr2*r2n + Vt2*crsprd2)*V # exitflag #exitflag = 1 # (success) #print "V1:",V1 #print "V2:",V2 return V1,V2
def XML_generator_Mode2(root, date, duration, relativeTime, params=Mode2_default()): "Generates parameters and calls for macros, which will generate commands in the XML-file" from MATS_TIMELINE_macros import IR_night, IR_day "Load parameters from config function" params_default = Mode2_default() "Check if optional params were given" if (params != params_default): params_new = params_default "Loop through parameters given and exchange them for the default ones" for key in params.keys(): params_new[key] = params[key] params = params_new Sun = ephem.Sun(date) MATS = ephem.readtle('MATS', getTLE()[0], getTLE()[1]) "Pre-allocate space" sun_angle = zeros((duration, 1)) R_mean = 6371 pointing_altitude = str(params['pointing_altitude']) #Estimation of the angle between the sun and the FOV position when it enters eclipse MATS_nadir_eclipse_angle = arccos(R_mean / (R_mean + 90)) / pi * 180 + 90 "Loop and calculate the relevant angle of each star to each direction of MATS's FOV" for t in range(duration): current_time = ephem.Date(date + ephem.second * t) MATS.compute(current_time) Sun.compute(current_time) sun_angle[t] = ephem.separation(Sun, MATS) / pi * 180 ############# Initial Mode setup ########################################## if (t == 0): "Check if night or day" if (sun_angle[t] > MATS_nadir_eclipse_angle): current_state = "IR_night" IR_night(root, str(t + relativeTime), pointing_altitude) elif (sun_angle[t] < MATS_nadir_eclipse_angle): current_state = "IR_day" IR_day(root, str(t + relativeTime), pointing_altitude) ############# End of Initial Mode setup ################################### if (t != 0): ####################### SCI-mode Operation planner ################ #Check if night or day if (sun_angle[t] > MATS_nadir_eclipse_angle and current_state != "IR_night"): #Check dusk/dawn boundaries and if NLC is active if ((sun_angle[t] > MATS_nadir_eclipse_angle and sun_angle[t - 1] < MATS_nadir_eclipse_angle) or current_state == "NLC_night"): IR_night(root, str(t + relativeTime), pointing_altitude) current_state = "IR_night" #Check if night or day if (sun_angle[t] < MATS_nadir_eclipse_angle and current_state != "IR_day"): #Check dusk/dawn boundaries and if NLC is active if ((sun_angle[t] < MATS_nadir_eclipse_angle and sun_angle[t - 1] > MATS_nadir_eclipse_angle) or current_state != "NLC_day"): IR_day(root, str(t + relativeTime), pointing_altitude) current_state = "IR_day"
def Limb_functional_test( root, date, duration, relativeTime, Timeline_settings, configFile, Test_settings={'ExpTimes': [1000, 2000, 4000, 8000, 16000]}): """Limb_functional_test. Schedules Limb_functional_test with defined parameters and simulates MATS propagation from TLE. Scheduling of all daylight and nighttime commands are separated timewise and all commands for one of the two is scheduled first. """ Logger.info('') Logger.info('Start of Limb_functional_test') Logger.debug('Test_settings from Science Mode List: ' + str(Test_settings)) log_timestep = 500 Logger.debug('log_timestep [s]: ' + str(log_timestep)) TLE = configFile.getTLE() CCD_settings = configFile.CCD_macro_settings('FullReadout') duration_flag = 0 JPEGQs = [100, 95] WDWs = [7, 128] altitudes = [50000, 70000, 90000, 110000, 130000, 160000, 200000] ExpTimes = Test_settings['ExpTimes'] SnapshotSpacing = 5 R_mean = 6371 # km Altitude_defining_night = 45 # km Altitude_defining_day = 25 # km #lat = Test_settings['lat']/180*pi lat = 30 Mode_name = sys._getframe(0).f_code.co_name "Estimation of the angle [degrees] between the sun and the LP when it enters eclipse" #NightDayAngle = arccos(R_mean/(R_mean+Altitude_defining_night))/pi*180 + 90 NightAngle = arccos(R_mean / (R_mean + Altitude_defining_night)) / pi * 180 + 90 DayAngle = arccos(R_mean / (R_mean + Altitude_defining_day)) / pi * 180 + 90 Logger.debug('') Logger.debug('NightAngle : ' + str(NightAngle)) Logger.debug('DayAngle : ' + str(DayAngle)) timestep = 4 t = 0 initial_relativeTime = relativeTime "Consecutively schedule all Macros for day, and then night" for mode in ['Day', 'Night']: "Altitudes that defines the LP" for altitude in altitudes: "Start looping the CCD settings and call for macros" for JPEGQ, WDW in zip(JPEGQs, WDWs): for key in CCD_settings.keys(): CCD_settings[key]['JPEGQ'] = JPEGQ CCD_settings[key]['WDW'] = WDW for ExpTime in ExpTimes: for key in CCD_settings.keys(): CCD_settings[key]['TEXPMS'] = ExpTime ############################################################################ ########################## Orbit simulator ################################# ############################################################################ MATS_skyfield = skyfield.api.EarthSatellite(TLE[0], TLE[1]) "Calculate the current angle between MATS and the Sun and the latitude of the LP" "and Loop until it is either day or night and the right latitude" while (True): mode_relativeTime = relativeTime - initial_relativeTime current_time = ephem.Date(date + ephem.second * mode_relativeTime) current_time_datetime = current_time.datetime() if (mode_relativeTime > duration and duration_flag == 0): Logger.warning( 'Warning!! The scheduled time for the Test has ran out.' ) #input('Enter anything to continue:\n') duration_flag = 1 if (t * timestep % log_timestep == 0): LogFlag = True else: LogFlag = False Satellite_dict = Library.Satellite_Simulator( MATS_skyfield, current_time, Timeline_settings, altitude / 1000, LogFlag, Logger) r_MATS = Satellite_dict['Position [km]'] lat_MATS = Satellite_dict['Latitude [degrees]'] lat_LP = Satellite_dict[ 'EstimatedLatitude_LP [degrees]'] sun_angle = Library.SunAngle(r_MATS, current_time) if (LogFlag == True): Logger.debug('sun_angle: ' + str(sun_angle)) if ((sun_angle < DayAngle and abs(lat_LP) <= lat and mode == 'Day') or (sun_angle > NightAngle and abs(lat_LP) <= lat and mode == 'Night')): Logger.debug('!!Break of Loop!!') Logger.debug('Loop Counter (t): ' + str(t)) Logger.debug('current_time: ' + str(current_time)) Logger.debug('lat_MATS [degrees]: ' + str(lat_MATS)) Logger.debug('lat_LP [degrees]: ' + str(lat_LP)) Logger.debug('sun_angle [degrees]: ' + str(sun_angle)) Logger.debug('mode: ' + str(mode)) Logger.debug('') break "Increase Loop counter" t = t + 1 "Timestep for propagation of MATS" relativeTime = round(relativeTime + timestep, 2) ############################################################################ ########################## End of Orbit simulator ########################## ############################################################################ comment = (Mode_name + ', ' + str(date) + ', ' + str(mode) + ', pointing_altitude = ' + str(altitude) + ', ExpTime = ' + str(ExpTime) + ', JPEGQ = ' + str(JPEGQ)) Logger.debug(comment) relativeTime = Macros.Snapshot_Limb_Pointing_macro( root, round(relativeTime, 2), CCD_settings, pointing_altitude=altitude, SnapshotSpacing=SnapshotSpacing, Timeline_settings=Timeline_settings, configFile=configFile, comment=comment) # relativeTime = Macros.Limb_functional_test_macro(root = root, relativeTime = str(relativeTime), # pointing_altitude = str(altitude), ExpTime = str(ExpTime), # JPEGQ = JPEGQ, comment=comment) #"Postpone next command until at least the end of ExpTime" #relativeTime = round(relativeTime + ExpTime/1000,2) mode_relativeTime = relativeTime - initial_relativeTime current_time = ephem.Date(date + ephem.second * mode_relativeTime) Logger.info('End of Limb_functional_test') return relativeTime, current_time
def ChAngle(n, m, v, w): """Returns Cherenkov angle as function of refraction coefficient, mass, velocity, and frequency.""" return py.arccos(CosCh(n, m, v, w)) # Angle is always positive
def MinAlpha(n, m, v, w): """Returns polarization basis parameter, a, which minimizes left-handed polarization amplitude at chi=MinChi.""" A = 0.5 * (v * SinCh(n, m, v, w))**2 B = 0.5 * w / (Gamma(v) * m) den = A + (n**2 - 1) * B**2 return 0.5 * py.arccos(A / den) # alpha always positive, <= pi/2
def Mode120_date_calculator(): """Subfunction, Simulates MATS FOV and stars. Determines when stars are entering the FOV at an vertical offset-angle equal to *#V-offset*, and also being located at a horizontal off-set angle equal to less than *#H-offset*, when pointing at the LP located at an altitude equal to *#pointing_altitude*. \n (# as defined in the *Configuration File*). \n Saves the date and parameters regarding the spotting of a star. Also saves relevant data to an .csv file located in Output/. Arguments: Returns: SpottedStarList ((:obj:`list` of :obj:`dict`)) or (str): A list containing dictionaries containing parameters for each time a star is spotted. """ Timeline_settings = OPT_Config_File.Timeline_settings() Mode120_settings = OPT_Config_File.Mode120_settings() ###################################################### "Check how many times Mode120 have been scheduled" Mode120Iteration = _Globals.Mode120Iteration "Make the V_offset_Index go from 0 to len(Mode120_settings['V_offset'] for each time Mode120 is scheduled" V_offset_Index = (Mode120Iteration-1) % (len(Mode120_settings['V_offset'])) "Constants" V_offset = Mode120_settings['V_offset'][V_offset_Index] H_offset = Mode120_settings['H_offset'] pointing_altitude = Mode120_settings['pointing_altitude']/1000 yaw_correction = Timeline_settings['yaw_correction'] Logger.debug('H_offset set to [degrees]: '+str(H_offset)) Logger.debug('V_offset set to [degrees]: '+str(V_offset)) Logger.debug('yaw_correction set to: '+str(yaw_correction)) TLE = OPT_Config_File.getTLE() Logger.debug('TLE used: '+TLE[0]+TLE[1]) TimeSkips = 0 Timeskip = Mode120_settings['TimeSkip'] #################################################### "Simulation length and timestep" log_timestep = Mode120_settings['log_timestep'] Logger.debug('log_timestep: '+str(log_timestep)) timestep = Mode120_settings['timestep'] #In seconds Logger.info('timestep set to: '+str(timestep)+' s') if( Mode120_settings['TimeToConsider'] <= Timeline_settings['duration']): duration = Mode120_settings['TimeToConsider'] else: duration = Timeline_settings['duration'] Logger.info('Duration set to: '+str(duration)+' s') timesteps = int(ceil(duration / timestep)) + 2 Logger.info('Maximum number of timesteps set to: '+str(timesteps)) timeline_start = ephem.Date(Timeline_settings['start_date']) initial_time = ephem.Date( timeline_start + ephem.second*Mode120_settings['freeze_start'] ) current_time = initial_time Logger.info('Initial simulation date set to: '+str(initial_time)) "Get relevant stars" result = Vizier(columns=['all'], row_limit=3000).query_constraints(catalog='I/239/hip_main',Vmag=Mode120_settings['Vmag']) star_cat = result[0] ROWS = star_cat[0][:].count() stars = [] stars_dec = zeros((ROWS,1)) stars_ra = zeros((ROWS,1)) "Insert stars into Pyephem" for t in range(ROWS): s = "{},f|M|F7,{},{},{},2000/01/01 11:58:55.816" s = s.format(star_cat[t]['HIP'], deg2HMS(ra=star_cat[t]['_RA.icrs']), deg2HMS(dec=star_cat[t]['_DE.icrs']), star_cat[t]['Vmag']) stars.append(ephem.readdb(s)) stars[t].compute(epoch='2000/01/01 11:58:55.816') stars_dec[t] = stars[t].dec stars_ra[t] = stars[t].ra Logger.debug('') Logger.debug('List of stars used: '+str(star_cat)) Logger.debug('') "Calculate unit-vectors of stars" stars_x = cos(stars_dec)* cos(stars_ra) stars_y = cos(stars_dec)* sin(stars_ra) stars_z = sin(stars_dec) stars_r = array([stars_x,stars_y,stars_z]) stars_r = stars_r.transpose() "Prepare the .csv file output" star_list_excel = [] star_list_excel.append(['Name']) star_list_excel.append(['t1']) star_list_excel.append(['long']) star_list_excel.append(['lat']) star_list_excel.append(['mag']) star_list_excel.append(['H_offset']) star_list_excel.append(['V_offset']) star_list_excel.append(['e_Hpmag']) star_list_excel.append(['Hpscat']) star_list_excel.append(['o_Hpmag']) star_list_excel.append(['Classification']) star_list_excel.append(['Optical Axis Dec (ICRS J2000, eq)']) star_list_excel.append(['Optical Axis RA (ICRS J2000, eq)']) star_list_excel.append(['Star Dec (ICRS J2000, eq)']) star_list_excel.append(['Star RA (ICRS J2000, eq)']) "Prepare the output" SpottedStarList = [] "Pre-allocate space" lat_MATS = zeros((timesteps,1)) long_MATS = zeros((timesteps,1)) optical_axis = zeros((timesteps,3)) stars_r_V_offset_plane = zeros((ROWS,3)) stars_r_H_offset_plane = zeros((ROWS,3)) stars_vert_offset = zeros((timesteps,ROWS)) stars_hori_offset = zeros((timesteps,ROWS)) stars_offset = zeros((timesteps,ROWS)) r_V_offset_normal = zeros((timesteps,3)) r_H_offset_normal = zeros((timesteps,3)) star_counter = 0 spotted_star_name = [] spotted_star_timestamp = [] spotted_star_timecounter = [] skip_star_list = [] MATS_P = zeros((timesteps,1)) Dec_optical_axis = zeros((timesteps,1)) RA_optical_axis = zeros((timesteps,1)) angle_between_orbital_plane_and_star = zeros((timesteps,ROWS)) MATS_skyfield = api.EarthSatellite(TLE[0], TLE[1]) t = 0 Logger.info('') Logger.info('Start of simulation of MATS for Mode120') ################## Start of Simulation ######################################## "Loop and calculate the relevant angle of each star to each direction of MATS's FOV" while( current_time-initial_time < ephem.second*duration): #current_time = ephem.Date(date+ephem.second*timestep*t) if( t*timestep % log_timestep == 0): LogFlag = True else: LogFlag = False Satellite_dict = Satellite_Simulator( MATS_skyfield, current_time, Timeline_settings, pointing_altitude, LogFlag, Logger ) MATS_P[t] = Satellite_dict['OrbitalPeriod [s]'] lat_MATS[t] = Satellite_dict['Latitude [degrees]'] long_MATS[t] = Satellite_dict['Longitude [degrees]'] optical_axis[t] = Satellite_dict['OpticalAxis'] Dec_optical_axis[t] = Satellite_dict['Dec_OpticalAxis [degrees]'] RA_optical_axis[t] = Satellite_dict['RA_OpticalAxis [degrees]'] r_H_offset_normal[t] = Satellite_dict['Normal2H_offset'] r_V_offset_normal[t] = Satellite_dict['Normal2V_offset'] OrbitalAngularVelocity = 360 / MATS_P[t] AngularChangePerTimestep = OrbitalAngularVelocity * timestep ###################### Star-mapper #################################### if(t != 0): "Check position of stars relevant to pointing direction" for x in range(ROWS): "Skip star if it is not visible during this epoch" if(stars[x].name in skip_star_list): continue "Check if a star has already been spotted during this orbit." if( stars[x].name in spotted_star_name ): time_until_far_outside_of_FOV = ephem.second*(180*MATS_P[t]/360) "If enough time has passed (half an orbit), the star can be removed from the exception list" if((current_time - spotted_star_timestamp[spotted_star_name.index(stars[x].name)]) >= time_until_far_outside_of_FOV): spotted_star_timestamp.pop(spotted_star_name.index(stars[x].name)) spotted_star_timecounter.pop(spotted_star_name.index(stars[x].name)) spotted_star_name.remove(stars[x].name) continue "Total angle offset of the star compared to MATS's FOV" stars_offset[t][x] = arccos(dot(optical_axis[t],stars_r[0][x]) / (norm(optical_axis[t]) * norm(stars_r[0][x]))) /pi*180 "Project 'star vectors' ontop pointing H-offset and V-offset plane" stars_r_V_offset_plane[x] = stars_r[0][x] - (dot(stars_r[0][x],r_V_offset_normal[t,0:3]) * r_V_offset_normal[t,0:3]) stars_r_H_offset_plane[x] = stars_r[0][x] - (dot(stars_r[0][x],r_H_offset_normal[t]) * r_H_offset_normal[t]) "Dot product to get the Vertical and Horizontal angle offset of the star in the FOV" stars_vert_offset[t][x] = arccos(dot(optical_axis[t],stars_r_V_offset_plane[x]) / (norm(optical_axis[t]) * norm(stars_r_V_offset_plane[x]))) /pi*180 stars_hori_offset[t][x] = arccos(dot(optical_axis[t],stars_r_H_offset_plane[x]) / (norm(optical_axis[t]) * norm(stars_r_H_offset_plane[x]))) /pi*180 "Determine sign of off-set angle where positive V-offset angle is when looking at higher altitude" if( dot(cross(optical_axis[t],stars_r_V_offset_plane[x]),r_V_offset_normal[t,0:3]) > 0 ): stars_vert_offset[t][x] = -stars_vert_offset[t][x] if( dot(cross(optical_axis[t],stars_r_H_offset_plane[x]),r_H_offset_normal[t]) > 0 ): stars_hori_offset[t][x] = -stars_hori_offset[t][x] "To be able to skip stars far outside the orbital plane of MATS" if( t == 1 ): "For first loop of stars, calculate angle between stars and orbital plane" angle_between_orbital_plane_and_star[t][x] = arccos( dot(stars_r[0][x], stars_r_V_offset_plane[x]) / norm(stars_r_V_offset_plane[x])) /pi*180 "Make exception list for stars not visible during this epoch (relativiely far outside of orbital plane)" if( ( abs(angle_between_orbital_plane_and_star[t][x]) > H_offset+(duration)/(365*24*3600)*360 and yaw_correction == False ) or ( abs(angle_between_orbital_plane_and_star[t][x]) > H_offset + abs(Timeline_settings['yaw_amplitude']) + (duration)/(365*24*3600)*360 and yaw_correction == True )): Logger.debug('Skip star: '+stars[x].name+', with angle_between_orbital_plane_and_star of: '+str(angle_between_orbital_plane_and_star[t][x])+' degrees') skip_star_list.append(stars[x].name) continue "Check that the star is entering at V-offset degrees with a standard timestep and within the H-offset angle" if( V_offset - AngularChangePerTimestep <= stars_vert_offset[t][x] <= V_offset and stars_vert_offset[t-1][x] > V_offset and abs(stars_hori_offset[t][x]) < H_offset): if( t % log_timestep == 0): Logger.debug('Star: '+stars[x].name+', with H-offset: '+str(stars_hori_offset[t][x])+' V-offset: '+str(stars_vert_offset[t][x])+' in degrees is available') "Add the spotted star to the exception list and timestamp it" spotted_star_name.append(stars[x].name) spotted_star_timestamp.append(current_time) spotted_star_timecounter.append(t) "Append all relevent data for the star" star_list_excel[0].append(stars[x].name) star_list_excel[1].append(str(current_time)) star_list_excel[2].append(str(float(long_MATS[t]))) star_list_excel[3].append(str(float(lat_MATS[t]))) star_list_excel[4].append(str(stars[x].mag)) star_list_excel[5].append(str(stars_hori_offset[t][x])) star_list_excel[6].append(str(stars_vert_offset[t][x])) star_list_excel[7].append(str(star_cat[x]['e_Hpmag'])) star_list_excel[8].append(str(star_cat[x]['Hpscat'])) star_list_excel[9].append(str(star_cat[x]['o_Hpmag'])) star_list_excel[10].append(str(star_cat[x]['SpType'])) star_list_excel[11].append(str(Dec_optical_axis[t])) star_list_excel[12].append(str(RA_optical_axis[t])) star_list_excel[13].append(str(stars_dec[x]/pi*180)) star_list_excel[14].append(str(stars_ra[x]/pi*180)) "Log data of star relevant to filtering process" SpottedStarList.append({ 'Date': str(current_time), 'V-offset': stars_vert_offset[t][x], 'H-offset': stars_hori_offset[t][x], 'long_MATS': float(long_MATS[t]), 'lat_MATS': float(lat_MATS[t]), 'Dec_optical_axis': Dec_optical_axis[t], 'RA_optical_axis': RA_optical_axis[t], 'Vmag': stars[x].mag, 'Name': stars[x].name, 'Dec': stars_dec[x]/pi*180, 'RA': stars_ra[x]/pi*180 }) star_counter = star_counter + 1 ######################### End of star_mapper ############################# "Increase Simulation Time with a timestep, or skip ahead if 1 orbit is completed" t += 1 if( t*timestep > MATS_P[t-1]*(TimeSkips+1) ): current_time = ephem.Date(current_time+ephem.second*Timeskip) TimeSkips += 1 else: current_time = ephem.Date(current_time+ephem.second*timestep) ########################## END OF SIMULATION ############################ Logger.info('') Logger.info('End of simulation for Mode120') Logger.info('') "Write spotted stars to file" try: os.mkdir('Output') except: pass while(True): try: file_directory = os.path.join('Output',sys._getframe(1).f_code.co_name+'_Visible_Stars__'+_Globals.Config_File+'__V_offset'+str(V_offset)+'.csv') with open(file_directory, 'w', newline='') as write_file: writer = csv.writer(write_file, dialect='excel-tab') writer.writerows(star_list_excel) Logger.info('Available Stars data saved to: '+file_directory) #print('Available Stars data saved to: '+file_directory) break except PermissionError: Logger.error(file_directory+' cannot be overwritten. Please close it') data = input('Enter anything to try again or 1 to exit') if( data == '1'): sys.exit() Logger.debug('Visible star list to be filtered:') for x in range(len(SpottedStarList)): Logger.debug(str(SpottedStarList[x])) Logger.debug('') Logger.debug('Exit '+str(__name__)) Logger.debug('') return(SpottedStarList)
def Mode200_date_calculator(): #if(True): Logger = logging.getLogger(Logger_name()) log_timestep = 2000 "Simulation length and timestep" duration = Timeline_params()['duration'] Logger.info('Duration set to [s]: '+str(duration)) timestep = Mode200_calculator_defaults()['timestep'] #In seconds Logger.info('Timestep set to [s]: '+str(timestep)) date = Timeline_params()['start_time'] Logger.info('date set to: '+str(date)) MATS = ephem.readtle('MATS',getTLE()[0],getTLE()[1]) Moon = ephem.Moon() "Pre-allocate space" lat_MATS = zeros((duration,1)) long_MATS = zeros((duration,1)) altitude_MATS = zeros((duration,1)) g_ra_MATS = zeros((duration,1)) g_dec_MATS = zeros((duration,1)) x_MATS = zeros((duration,1)) y_MATS = zeros((duration,1)) z_MATS = zeros((duration,1)) r_MATS = zeros((duration,3)) r_MATS_unit_vector = zeros((duration,3)) r_FOV = zeros((duration,3)) normal_orbit = zeros((duration,3)) normal_H_offset = zeros((duration,3)) normal_H_offset_unit_vector = zeros((duration,3)) pitch_array = zeros((duration,1)) MATS_p = zeros((duration,1)) MATS_P = zeros((duration,1)) g_ra_Moon = zeros((duration,1)) g_dec_Moon = zeros((duration,1)) distance_Moon = zeros((duration,1)) x_Moon = zeros((duration,1)) y_Moon = zeros((duration,1)) z_Moon = zeros((duration,1)) r_Moon = zeros((duration,3)) r_MATS_2_Moon = zeros((duration,3)) r_MATS_2_Moon_norm = zeros((duration,3)) Moon_r_orbital_plane = zeros((duration,3)) Moon_r_H_offset_plane = zeros((duration,3)) Moon_vert_offset = zeros((duration,1)) Moon_hori_offset = zeros((duration,1)) angle_between_orbital_plane_and_moon = zeros((duration,1)) Moon_list = [] r_Moon_unit_vector = zeros((duration,3)) "Constants" AU = 149597871 #km R_mean = 6371 #Earth radius U = 398600.4418 #Earth gravitational parameter FOV_altitude = Mode200_calculator_defaults()['default_pointing_altitude']/1000 #Altitude at which MATS center of FOV is looking Logger.info('FOV_altitude set to [km]: '+str(FOV_altitude)) pointing_adjustment = 3 #Angle in degrees that the pointing can be adjusted V_FOV = Mode200_calculator_defaults()['V_FOV'] #0.91 is actual V_FOV H_FOV = Mode200_calculator_defaults()['H_FOV'] #5.67 is actual H_FOV Logger.info('V_FOV set to [degrees]: '+str(V_FOV)) Logger.info('H_FOV set to [degrees]: '+str(H_FOV)) V_offset = 0 H_offset = 0 Moon_orbital_period = 3600*24*27.32 t=0 current_time = date Logger.info('') Logger.info('Start of simulation for Mode200') while(current_time < date+ephem.second*duration): MATS.compute(current_time) Moon.compute(current_time) (lat_MATS[t],long_MATS[t],altitude_MATS[t],g_ra_MATS[t],g_dec_MATS[t])= ( MATS.sublat,MATS.sublong,MATS.elevation/1000,MATS.g_ra,MATS.g_dec) R = lat_2_R(lat_MATS[t]) z_MATS[t] = sin(g_dec_MATS[t])*(altitude_MATS[t]+R) x_MATS[t] = cos(g_dec_MATS[t])*(altitude_MATS[t]+R)* cos(g_ra_MATS[t]) y_MATS[t] = cos(g_dec_MATS[t])*(altitude_MATS[t]+R)* sin(g_ra_MATS[t]) r_MATS[t,0:3] = [x_MATS[t], y_MATS[t], z_MATS[t]] r_MATS_unit_vector[t] = r_MATS[t]/norm(r_MATS[t]) #Semi-Major axis of MATS, assuming circular orbit MATS_p[t] = norm(r_MATS[t,0:3]) #Orbital Period of MATS MATS_P[t] = 2*pi*sqrt(MATS_p[t]**3/U) #Estimated pitch angle for MATS pointing pitch_array[t]= array(arccos((R_mean+FOV_altitude)/(R+altitude_MATS[t]))/pi*180) pitch = pitch_array[t][0] (g_ra_Moon[t],g_dec_Moon[t],distance_Moon[t])= (Moon.g_ra,Moon.g_dec,Moon.earth_distance*AU) z_Moon[t] = sin(g_dec_Moon[t]) * distance_Moon[t] x_Moon[t] = cos(g_dec_Moon[t])*cos(g_ra_Moon[t]) * distance_Moon[t] y_Moon[t] = cos(g_dec_Moon[t])*sin(g_ra_Moon[t]) * distance_Moon[t] r_Moon[t,0:3] = [x_Moon[t], y_Moon[t], z_Moon[t]] r_Moon_unit_vector[t,0:3] = r_Moon[t,0:3]/norm(r_Moon[t,0:3]) r_MATS_2_Moon[t] = r_Moon[t]-r_MATS[t] r_MATS_2_Moon_norm[t] = r_MATS_2_Moon[t]/norm(r_MATS_2_Moon[t]) if( t*timestep % log_timestep == 0 ): Logger.debug('') Logger.debug('log_timestep: '+str(log_timestep)) Logger.debug('timestep: '+str(timestep)) Logger.debug('t (loop iteration number): '+str(t)) Logger.debug('Current time: '+str(current_time)) Logger.debug('Semimajor axis in km: '+str(MATS_p[t])) Logger.debug('Orbital Period in s: '+str(MATS_P[t])) Logger.debug('Vector to MATS [km]: '+str(r_MATS[t,0:3])) Logger.debug('Latitude in radians: '+str(lat_MATS[t])) Logger.debug('Longitude in radians: '+str(long_MATS[t])) Logger.debug('Altitude in km: '+str(altitude_MATS[t])) Logger.debug('FOV pitch in degrees: '+str(pitch)) if(t != 0): ############# Calculations of orbital and pointing vectors ############ "Vector normal to the orbital plane of MATS" normal_orbit[t,0:3] = cross(r_MATS[t],r_MATS[t-1]) normal_orbit[t,0:3] = normal_orbit[t,0:3] / norm(normal_orbit[t,0:3]) "Rotate 'vector to MATS', to represent pointing direction, includes vertical offset change" rot_mat = rot_arbit(-pi/2+(-pitch+V_offset)/180*pi, normal_orbit[t,0:3]) r_FOV[t,0:3] = (r_MATS[t] @ rot_mat) "Rotate 'vector to MATS', to represent a vector normal to the H-offset pointing plane, includes vertical offset change (Parallax is negligable)" rot_mat = rot_arbit((-pitch+V_offset)/180*pi, normal_orbit[t,0:3]) normal_H_offset[t,0:3] = (r_MATS[t] @ rot_mat) /2 normal_H_offset_unit_vector[t,0:3] = normal_H_offset[t,0:3] / norm(normal_H_offset[t,0:3]) ############# End of Calculations of orbital and pointing vectors ##### "Project 'r_MATS_2_Moon' ontop pointing H-offset and orbital plane" Moon_r_orbital_plane[t] = r_MATS_2_Moon_norm[t] - dot(r_MATS_2_Moon_norm[t],normal_orbit[t]) * normal_orbit[t] Moon_r_H_offset_plane[t] = r_MATS_2_Moon_norm[t] - dot(r_MATS_2_Moon_norm[t],normal_H_offset_unit_vector[t]) * normal_H_offset_unit_vector[t] "Dot product to get the Vertical and Horizontal angle offset of the Moon" Moon_vert_offset[t] = arccos(dot(r_FOV[t],Moon_r_orbital_plane[t]) / (norm(r_FOV[t])*norm(Moon_r_orbital_plane[t]))) /pi*180 Moon_hori_offset[t] = arccos(dot(r_FOV[t],Moon_r_H_offset_plane[t]) / (norm(r_FOV[t])*norm(Moon_r_H_offset_plane[t]))) /pi*180 "Get the offset angle sign correct" if( dot(cross(r_FOV[t],Moon_r_orbital_plane[t]),normal_orbit[t,0:3]) > 0 ): Moon_vert_offset[t] = -Moon_vert_offset[t] if( dot(cross(r_FOV[t],Moon_r_H_offset_plane[t]),normal_H_offset[t]) > 0 ): Moon_hori_offset[t] = -Moon_hori_offset[t] "Angle between orbital plane and moon" angle_between_orbital_plane_and_moon[t] = arccos( dot(r_MATS_2_Moon_norm[t], Moon_r_orbital_plane[t]) / norm(Moon_r_orbital_plane[t])) /pi*180 if( t*timestep % log_timestep == 0 ): Logger.debug('angle_between_orbital_plane_and_moon [degrees]: '+str(angle_between_orbital_plane_and_moon[t])) Logger.debug('Moon_vert_offset [degrees]: '+str(Moon_vert_offset[t])) Logger.debug('Moon_hori_offset [degrees]: '+str(Moon_hori_offset[t])) Logger.debug('normal_orbit: '+str(normal_orbit[t,0:3])) Logger.debug('normal_H_offset: '+str(normal_H_offset[t,0:3])) Logger.debug('r_FOV [km]: '+str(r_FOV[t,0:3])) #print('angle_between_orbital_plane_and_moon = ' + str(angle_between_orbital_plane_and_moon[t])) "Save data when Moon is visible in specified FOV. " #if(abs(Moon_vert_offset[t]) <= timestep/MATS_P[t]*360 and abs(Moon_hori_offset[t]) < H_FOV/2): if(abs(Moon_vert_offset[t]) <= V_FOV/2 and abs(Moon_hori_offset[t]) < H_FOV/4): Logger.debug('') Logger.debug('!!!!!!!!Moon visible!!!!!!!!!!') Logger.debug('angle_between_orbital_plane_and_moon [degrees]: '+str(angle_between_orbital_plane_and_moon[t])) Logger.debug('Moon_vert_offset [degrees]: '+str(Moon_vert_offset[t])) Logger.debug('Moon_hori_offset [degrees]: '+str(Moon_hori_offset[t])) Logger.debug('normal_orbit: '+str(normal_orbit[t,0:3])) Logger.debug('normal_H_offset: '+str(normal_H_offset[t,0:3])) Logger.debug('r_FOV: '+str(r_FOV[t,0:3])) Logger.debug('') Moon_list.append({ 'Date': str(current_time), 'V-offset': Moon_vert_offset[t], 'H-offset': Moon_hori_offset[t], 'long_MATS': float(long_MATS[t]/pi*180), 'lat_MATS': float(lat_MATS[t]/pi*180)}) current_time = ephem.Date(current_time+ephem.second*MATS_P[t]/2) "To be able to make time skips when the moon is far outside the orbital plane of MATS" if( angle_between_orbital_plane_and_moon[t] > H_FOV/2): t= t + 1 current_time = ephem.Date(current_time+ephem.second * H_FOV/4 / 360 * Moon_orbital_period) #if( t*timestep % floor(log_timestep/400) == 0 ): Logger.info('Moon currently not visible -> jump ahead') Logger.info('current_time is: '+str(current_time)) else: t= t + 1 current_time = ephem.Date(current_time+ephem.second*timestep) Logger.info('End of simulation for Mode200') Logger.info('Moon_list: '+str(Moon_list)) ########################## Optional plotter ########################################### from mpl_toolkits.mplot3d import axes3d from pylab import figure "Orbital points to plot" points_2_plot_start = 0#0*24*120 points_2_plot = points_2_plot_start+1000 "Plotting of orbit and FOV" fig = figure(1) ax = fig.add_subplot(111,projection='3d') ax.set_xlim3d(-1, 1) ax.set_ylim3d(-1, 1) ax.set_zlim3d(-1, 1) ax.scatter(r_MATS_unit_vector[points_2_plot_start:points_2_plot,0],r_MATS_unit_vector[points_2_plot_start:points_2_plot,1],r_MATS_unit_vector[points_2_plot_start:points_2_plot,2]) ax.scatter(r_Moon_unit_vector[points_2_plot_start:points_2_plot,0],r_Moon_unit_vector[points_2_plot_start:points_2_plot,1],r_Moon_unit_vector[points_2_plot_start:points_2_plot,2]) ########################### END of Optional plotter ######################################## return Moon_list
def eph2D(self,epoch): if self.ref == None: return ([0,0,0],[0,0,0]) dt = epoch-self.epoch #print "dT",dt # Step 1 - Determine mean anomaly at epoch if self.e == 0: M = self.M0 + dt * sqrt(self.ref.mu / self.a**3) M %= PI2 E = M ta = E r3 = (self.h**2/self.ref.mu) rv = r3 * array([cos(ta),sin(ta),0]) v3 = self.ref.mu / self.h vv = v3 * array([-sin(ta),self.e+cos(ta),0]) return (rv,vv) if self.e < 1: if epoch == self.epoch: M = self.M0 else: M = self.M0 + dt * sqrt(self.ref.mu / self.a**3) M %= PI2 # Step 2a - Eccentric anomaly try: E = so.newton(lambda x: x-self.e * sin(x) - M,M) except RuntimeError: # Debugging a bug here, disregard print "Eccentric anomaly failed for",self.obj.name print "On epoch",epoch print "Made error available at self.ERROR" self.ERROR = [lambda x: x-self.e * sin(x) - M,M] raise # Step 3a - True anomaly, method 1 ta = 2 * arctan2(sqrt(1+self.e)*sin(E/2.0), sqrt(1-self.e)*cos(E/2.0)) #print "Ta:",ta # Method b is faster cosE = cos(E) ta2 = arccos((cosE - self.e) / (1-self.e*cosE)) #print "e",self.e #print "M",M #print "E",E #print "TA:",ta #print "T2:",ta2 # Step 4a - distance to central body (eccentric anomaly). r = self.a*(1-self.e * cos(E)) # Alternative (true anomaly) r2 = (self.a*(1-self.e**2) / (1.0 + self.e * cos(ta))) # Things get crazy #h = sqrt(self.a*self.ref.mu*(1-self.e**2)) r3 = (self.h**2/self.ref.mu)*(1.0/(1.0+self.e*cos(ta))) #print "R1:",r #print "R2:",r2 #print "R3:",r3 rv = r3 * array([cos(ta),sin(ta),0]) #v1 = sqrt(self.ref.mu * (2.0/r - 1.0/self.a)) #v2 = sqrt(self.ref.mu * self.a) / r v3 = self.ref.mu / self.h #meanmotion = sqrt(self.ref.mu / self.a**3) #v2 = sqrt(self.ref.mu * self.a)/r #print "v1",v1 #print "v2",v2 #print "v3",v3 #print "mm",meanmotion # Velocity can be calculated from the eccentric anomaly #vv = v1 * array([-sin(E),sqrt(1-self.e**2) * cos(E),0]) # Or from the true anomaly (this one has an error..) #vv = sqrt(self.ref.mu * self.a)/r * array([-sin(ta),self.e+cos(ta),0]) vv = v3 * array([-sin(ta),self.e+cos(ta),0]) #print "rv",rv #print "vv",vv #print "check",E,-sin(E),v1*-sin(E) #print "V1:",vv #print "V2:",vv2 return (rv,vv) elif self.e > 1: # Hyperbolic orbits # Reference: Stephen Kemble: Interplanetary Mission Analysis and Design, Pg 220-221 M = self.M0 + dt * sqrt(-(self.ref.mu / self.a**3)) #print "M0",self.M0 #print "M",M #print "M",M #print "M0",self.M0 # Step 2b - Hyperbolic eccentric anomaly #print "Hyperbolic mean anomaly:",M F = so.newton(lambda x: self.e * sinh(x) - x - M,M,maxiter=1000) #F = -F H = M / (self.e-1) #print "AAAA"*10 #print "F:",F #print "H:",H #F=H #print "Hyperbolic eccentric anomaly:",F # Step 3b - Hyperbolic true anomaly? # This is wrong prooobably #hta = arccos((cosh(F) - self.e) / (1-self.e*cosh(F))) #hta = arccos((self.e-cosh(F)) / (self.e*cosh(F) - 1)) # TÄSSÄ ON BUGI hta = arccos((cosh(F) - self.e) / (1 - self.e*cosh(F))) hta2 = 2 * arctan2(sqrt(self.e+1)*sinh(F/2.0),sqrt(self.e-1)*cosh(F/2.0)) hta3 = 2 * arctan2(sqrt(1+self.e)*sinh(F/2.0),sqrt(self.e-1)*cosh(F/2.0)) hta4 = 2 * arctan2(sqrt(self.e-1)*cosh(F/2.0),sqrt(1+self.e)*sinh(F/2.0)) #print "Hyperbolic true anomaly:",degrees(hta) # This is wrong too #hta2 = 2 * arctan2(sqrt(1+self.e)*sin(F/2.0), sqrt(1-self.e)*cos(F/2.0)) if M == self.M0: print "HTA1:",degrees(hta) print "HTA2:",degrees(hta2) print "HTA3:",degrees(hta3) print "HTA4:",degrees(hta4) # According to http://mmae.iit.edu/~mpeet/Classes/MMAE441/Spacecraft/441Lecture17.pdf # this is right.. hta = hta2 #print cos(hta) #print cosh(hta) #####hta = arctan(sqrt((self.e-1.0)/self.e+1.0) * tanh(F/2.0)) / 2.0 #print "Mean anomaly:",M #print "Hyperbolic eccentric anomaly:",F #print "HTA:",hta #raise # Step 4b - Distance from central body? # Can calculate it from hyperbolic true anomaly.. #p = self.a*(1-self.e**2) #r = p / (1+self.e * cos(hta)) r3 = (self.h**2/self.ref.mu)*(1.0/(1.0+self.e*cos(hta))) v3 = self.ref.mu / self.h # But it's faster to calculate from eccentric anomaly #r = self.a*(1-self.e * cos(F)) #print "Hyper r1:",r #print "Hyper r2:",r2 rv = r3 * array([cos(hta),sin(hta),0]) #http://en.wikipedia.org/wiki/Hyperbola #rv = array([ r * sin(hta),-self.a*self.e + r * cos(hta), 0]) #sinhta = sin(hta) #coshta = cos(hta) #print self.ref.mu,r,self.a,hta #vv = sqrt(self.ref.mu *(2.0/r - 1.0/self.a)) * array([-sin(hta),self.e+cos(hta),0]) vv = v3 * array([-sin(hta),self.e+cos(hta),0]) return (rv,vv)
def initFromStateVectors(self,epoch,pV,vV): self.epoch = epoch # 1) Calculate auxilary vector h hV = cross(pV,vV) # 2) Normalize position,velocity, specific angular momentum, calculate radial velocity p = linalg.norm(pV) v = linalg.norm(vV) h = linalg.norm(hV) print "H:",h radv = pV.dot(vV) / p hVu = hV / h pVu = pV / p nV = cross(array([0,0,1]),hV) n = linalg.norm(nV) if n == 0: nVu = array([0,0,0]) else: nVu = nV/n # 3) Calculate inclination #self.i = arccos(hV[2]/h) self.i = arcsin(linalg.norm(cross(array([0,0,1]),hVu))) print "i1",self.i print "RADVEL",radv self.i = arccos(array([0,0,1]).dot(hV)/h) #if radv < 0: # self.i = PI2 - self.i print "i2",self.i # 4) Calculate node line # 5) Calculate longitude of ascending node = right ascension of ascending node ''' if self.i == 0: self.lan=0 elif nV[1] >= 0: self.lan = arccos(nV[0] / n) else: self.lan = PI2 - arccos(nV[0] / n) ''' if self.i == 0: self.lan = 0 else: self.lan = arcsin(cross(array([1,0,0]),nVu).dot(array([0,0,1]))) print "lan1",self.lan self.lan = arccos(array([1,0,0]).dot(nV)/n) if nV[1] < 0: self.lan = PI2-self.lan print "lan2",self.lan # 6) Eccentricity vector #eV = (1.0 / self.ref.mu)*((v**2 - (self.ref.mu / p))*pV - radv*vV) #eV2 = (1.0 / self.ref.mu) * ( hV - self.ref.mu * (pV/p)) #eV3 = hV/self.ref.mu - (pV/p) # Source: cdeagle eV = cross(vV,hV)/self.ref.mu - pVu #print "eV1:",eV,linalg.norm(eV) #print "eV2:",eV2,linalg.norm(eV2) #print "eV3:",eV3,linalg.norm(eV3) print "eV3:",eV,linalg.norm(eV) self._e = linalg.norm(eV) #eVu = eV / self.e print "h",h print "u",self.ref.mu print "v",v print "r",p print "alte:",sqrt(1+(h**2/self.ref.mu**2)*(v**2-(2*self.ref.mu)/p)**2) # 7) Argument of perigree ''' if self.e == 0: self.aop = 0 elif self.i == 0: self.aop = arccos(eV[0] / self.e) elif eV[2] >= 0: print "AOP AOP AOP" #self.aop = arccos(nV.dot(eV) / (n*self.e)) print cross(nV,eV).dot(hV) self.aop = arcsin(cross(nVu,eVu).dot(hVu)) #self.aop = arccos(n*self.e) else: self.aop = PI2 - arccos(nV.dot(eV) / (n*self.e)) ''' #CDEagle method # TODO CHECK how KSP handles this. if self.e == 0: self.aop = 0 elif self.i == 0 and self.e != 0: #self.aop = arccos(eV[0] / self.e) #self.aop = arctan2(eV[1],eV[0]) self.aop = arccos(array([1,0,0]).dot(eV) / self.e) print eV if eV[2] < 0: #self.aop = -self.aop self.aop = PI2-self.aop #print "BOOM",eV #if eV[2] < 0: # print "BAM N***A" # self.aop = PI2 - self.aop elif self.i == 0 and self.e == 0: #raise AttributeError("Perfectly circular orbits are not supported atm") self.aop = 0 else: #self.aop = arcsin(cross(nVu,eVu).dot(hVu)) self.aop = arccos(nV.dot(eV)/(n*self.e)) if eV[2] < 0: self.aop = PI2-self.aop # 8) Semi major axis aE = v**2/2.0 - self.ref.mu / p self._a = -self.ref.mu / (2*aE) print "Old method for semi-major",self.a self._a = h**2 / (self.ref.mu * (1-self.e**2)) print "New method for semi-major",self.a #if self.e > 1: # self._a = h**2 / (self.ref.mu * (self.e**2 - 1)) if self.e == 0: if self.i == 0: #TODO update document to this print "JEA JEA JEA JEA"*10 ta = arccos(array([1,0,0]).dot(pV) / p) if pV[1] < 0: # Vallado pg. 111 ta = PI2 - ta else: #TODO VERIFY THIS CASE ta = arccos((nV.dot(pV))/(n*p)) if pV[2] < 0: # Vallado pg. 110 ta = PI2 - ta E = ta self.M0 = E elif self.e < 1: # 9) True anomaly, eccentric anomaly and mean anomaly if radv >= 0: ta = arccos((eV / self.e).dot(pV/p)) else: ta = PI2 - arccos((eV / self.e).dot(pV/p)) E = arccos((self.e+cos(ta))/(1+ self.e*cos(ta))) if radv < 0: E = PI2 - E self.M0 = E - self.e * sin(E) elif self.e > 1: # 9) Hyperbolic True anomaly, eccentric anomaly and mean anomaly # http://scienceworld.wolfram.com/physics/HyperbolicOrbit.html V = arccos((abs(self.a)*(self.e**2 - 1)) /(self.e * p) - 1/self.e) ta = arccos((eV / self.e).dot(pV/p)) if radv < 0: #TODO: Should affect F too? # Negative = heading towards periapsis print "PI2" V = PI2 - V ta = PI2-ta print "V",V print "TA",ta # http://www.bogan.ca/orbits/kepler/orbteqtn.html In you I trust # Hyperbolic eccentric anomaly cosV = cos(V) F = arccosh((self.e+cosV)/(1+self.e*cosV)) if radv < 0: F = -F F2 = arcsinh((sqrt(self.e-1)*sin(V))/(1+self.e*cos(V))) ##F1 = F2 print "F1:",F print "F2:",F2 self.M0 = self.e * sinh(F) - F self.h = h print "Semi-major:",self.a print "Eccentricity:",self.e print "Inclination:",degrees(self.i),"deg" print "LAN:",degrees(self.lan),"deg" print "AoP:",degrees(self.aop),"deg" print "Mean anomaly:",self.M0 print "Specific angular momentum:",self.h if self.e < 1: print "Eccentric anomaly",E print "True anomaly",ta else: print "Hyperbolic eccentric anomaly",F print "Hyperbolic true anomaly",degrees(V) print "Distance from object:",p print "Velocity:",v
# Plot a bunch of randomly distributed points on the earth. # set up stereographic map centered on N. Pole. m = Basemap(lon_0=-105,boundinglat=30., resolution='l',area_thresh=10000.,projection='npstere') # number of points to plot. npts = 750 # generate random points on a sphere, # so that every small area on the sphere is expected # to have the same number of points. # http://mathworld.wolfram.com/SpherePointPicking.html u = uniform(0.,1.,size=npts) v = uniform(0.,1.,size=npts) z = uniform(0,100,size=npts) lons = 360.*u lats = (180./pi)*arccos(2*v-1) - 90. # transform lons and lats to map coordinates. x,y = m(lons,lats) # plot them as filled circles on the map. # first, create a figure. fig=figure() # background color will be used for 'wet' areas. fig.add_axes([0.1,0.1,0.8,0.8],axisbg='aqua') # draw colored markers. # use zorder=10 to make sure markers are drawn last. # (otherwise they are covered up when continents are filled) #m.scatter(x,y,25,z,cmap=cm.jet,marker='o',faceted=False,zorder=10) # create a list of strings containing z values # or, plot actual numbers as color-coded text strings. zn = [ '%2i' % zz for zz in z ] # plot numbers on map, colored by value.
def angle(a,b): return arccos(dot(a,b) / (l2norm(a) * l2norm(b)))
def get_angle_between_3_points(pc, p1, p2): """ pc=point center, p1,p2 """ vl = vector_length return arccos( ( vl(pc, p1) ** 2 + vl(pc, p2) ** 2 - vl(p1, p2) ** 2 ) / ( 2 * vl(pc, p1) * vl(pc, p2)))
def arcdistance(d, R): return R * pl.arccos(1 - 0.5 * d * d / (R * R))
def ChAngleCl(n, v): """Returns classical Cherenkov angle as function of refraction coefficient, mass, velocity, and frequency.""" return py.arccos(CosChCl(n, v)) # Angle is always positive
m = Basemap(lon_0=-105, boundinglat=30., resolution='l', area_thresh=10000., projection='npstere') # number of points to plot. npts = 750 # generate random points on a sphere, # so that every small area on the sphere is expected # to have the same number of points. # http://mathworld.wolfram.com/SpherePointPicking.html u = uniform(0., 1., size=npts) v = uniform(0., 1., size=npts) z = uniform(0, 100, size=npts) lons = 360. * u lats = (180. / pi) * arccos(2 * v - 1) - 90. # transform lons and lats to map coordinates. x, y = m(lons, lats) # plot them as filled circles on the map. # first, create a figure. fig = figure() # background color will be used for 'wet' areas. fig.add_axes([0.1, 0.1, 0.8, 0.8], axisbg='aqua') # draw colored markers. # use zorder=10 to make sure markers are drawn last. # (otherwise they are covered up when continents are filled) #m.scatter(x,y,25,z,cmap=cm.jet,marker='o',faceted=False,zorder=10) # create a list of strings containing z values # or, plot actual numbers as color-coded text strings. zn = ['%2i' % zz for zz in z] # plot numbers on map, colored by value.
def arcdistance(d,R): return R * pl.arccos(1 - 0.5*d*d / (R*R))
import pylab import numpy from scipy.optimize import curve_fit t,T,Tr=pylab.loadtxt('pendulum.txt',unpack='True') lmax=118. # sigma 0.1cm lcm=113.26#sigma 0.1cm dl=0.1 g=980 s=2.09 #sigma 0.005cm ds=0.005 v=(s/Tr)*(lcm/lmax) Theta=pylab.arccos(1.-(v**2)/(2*980.*lcm)) def vel(x,v0,tau): return v0*pylab.exp(-x/tau) def theta(x,p1,p2): return 2*pylab.pi*pylab.sqrt(lcm/980.)*(1+p1*(x**2)+p2*(x**4)) popt,pcov=curve_fit(vel,t,v,sigma=s/t) v0_fit,tau_fit=popt dv0_fit, dtau_fit=pylab.sqrt(pcov.diagonal()) print(f"v0={v0_fit} +- {dv0_fit}") print(f"tau={tau_fit} +- {dtau_fit}") def errorel(vi): return (vi**2)/(2*g*(lcm**2)*numpy.sqrt(1-(1-((vi**2)/(2*g*lcm)))**2)) def errores(ti): return (s)/(g*lcm*numpy.sqrt(1-((1-((s**2)/(2*g*lcm*(ti**2))))**2))*(ti**2)) errs=(errores(Tr)*ds) errl=errorel(v)*dl errtheta=numpy.sqrt(errs**2+errl**2) def erroret(x): return 2*numpy.sqrt(lcm/980.)*numpy.pi*(x/8+(11/768)*x**3) erry=erroret(Theta)*errtheta
def Nadir_functional_test( root, date, duration, relativeTime, Timeline_settings, configFile, Test_settings={'ExpTimes': [1000, 2000, 4000, 8000, 16000]}): """Nadir_functional_test Schedules Nadir_functional_test with defined parameters and simulates MATS propagation from TLE. Scheduling of all daylight and nighttime commands are separated timewise and all commands for one of the two is scheduled first. """ Logger.info('') Logger.info('Start of Nadir_functional_test') Logger.debug('Test_settings from Science Mode List: ' + str(Test_settings)) CCD_settings = configFile.CCD_macro_settings('FullReadout') altitude = Timeline_settings['StandardPointingAltitude'] ExpTimes = Test_settings['ExpTimes'] log_timestep = 500 Logger.debug('log_timestep [s]: ' + str(log_timestep)) duration_flag = 0 JPEGQs = [100, 95] WDWs = [7, 128] initial_relativeTime = relativeTime TLE = configFile.getTLE() MATS_skyfield = skyfield.api.EarthSatellite(TLE[0], TLE[1]) Altitude_defining_night = 45 # km Altitude_defining_day = 25 # km R_mean = 6371 # Estimation of the angle [degrees] between the sun and the FOV position when it enters eclipse NightAngle = arccos(R_mean / (R_mean + Altitude_defining_night)) / pi * 180 + 90 DayAngle = arccos(R_mean / (R_mean + Altitude_defining_day)) / pi * 180 + 90 Logger.debug('') Logger.debug('DayAngle : ' + str(DayAngle)) Logger.debug('NightAngle : ' + str(NightAngle)) Logger.debug('') withinLat = 30 Mode_name = sys._getframe(0).f_code.co_name t = 0 timestep = 4 # latMargin = 360/5400 * timestep * 5 #Overly estimated change of latitude per timestep "Start looping the CCD nadir settings and call for macros" for mode in ['Day', 'Night']: for JPEGQ, WDW in zip(JPEGQs, WDWs): CCD_settings[64]['JPEGQ'] = JPEGQ CCD_settings[64]['WDW'] = WDW for ExpTime in ExpTimes: CCD_settings[64]['TEXPMS'] = ExpTime ############################################################################ ########################## Orbit simulator ################################# ############################################################################ # for lat in [-30, 0, 30]: "Calculate the current angle between MATS and the Sun" "and Loop until it is either day or night and the right latitude" while (True): mode_relativeTime = relativeTime - initial_relativeTime current_time = ephem.Date(date + ephem.second * mode_relativeTime) if (mode_relativeTime > duration and duration_flag == 0): Logger.warning( 'Warning!! The scheduled time for the Test has ran out.' ) #input('Enter anything to continue:\n') duration_flag = 1 if (t * timestep % log_timestep == 0): LogFlag = True else: LogFlag = False Satellite_dict = Library.Satellite_Simulator( MATS_skyfield, current_time, Timeline_settings, altitude / 1000, LogFlag, Logger) r_MATS = Satellite_dict['Position [km]'] lat_MATS = Satellite_dict['Latitude [degrees]'] sun_angle = Library.SunAngle(r_MATS, current_time) if (t * timestep % log_timestep == 0 == 0 or t == 1): Logger.debug('') Logger.debug('current_time: ' + str(current_time)) Logger.debug('lat_MATS [degrees]: ' + str(lat_MATS)) Logger.debug('sun_angle [degrees]: ' + str(sun_angle)) Logger.debug('mode: ' + str(mode)) Logger.debug('') # if( (sun_angle < DayAngle and lat-latMargin <= lat_MATS <= lat+latMargin and mode == 'Day' ) or # (sun_angle > NightAngle and lat-latMargin <= lat_MATS <= lat+latMargin and mode == 'Night' )): if ((sun_angle < DayAngle and abs(lat_MATS) < withinLat and mode == 'Day') or (sun_angle > NightAngle and abs(lat_MATS) < withinLat and mode == 'Night')): Logger.debug('!!Break of Loop!!') Logger.debug('Loop Counter (t): ' + str(t)) Logger.debug('current_time: ' + str(current_time)) Logger.debug('lat_MATS [degrees]: ' + str(lat_MATS)) Logger.debug('sun_angle [degrees]: ' + str(sun_angle)) Logger.debug('mode: ' + str(mode)) Logger.debug('') break "Increase Loop counter" t = t + 1 "Timestep for propagation of MATS" relativeTime = round(relativeTime + timestep, 1) ############################################################################ ########################## End of Orbit simulator ########################## ############################################################################ comment = (Mode_name + ', ' + str(date) + ', ' + ', pointing_altitude = ' + str(altitude) + ', ExpTime = ' + str(ExpTime) + ', JPEGQ = ' + str(JPEGQ)) Logger.debug(comment) relativeTime = Macros.NadirSnapshot_Limb_Pointing_macro( root=root, relativeTime=relativeTime, pointing_altitude=altitude, CCD_settings=CCD_settings, Timeline_settings=Timeline_settings, configFile=configFile, comment=comment) #"Postpone next command until at least the end of ExpTime" #relativeTime = round(float(relativeTime) + ExpTime/1000,2) mode_relativeTime = relativeTime - initial_relativeTime current_time = ephem.Date(date + ephem.second * mode_relativeTime) Logger.info('End of Nadir_functional_test') return relativeTime, current_time
def q2tg( q ): global fz if not fz: qq = q q=q0 slack = 1.0/1000 t0 = 10.7/1000 #10.9124/1000 P = mm_array(5.725,13.215) PA = mm_array(10.198,-2.0) B = mm_array(15.087,5.585) C = mm_array(51.43,3.878) D = mm_array(60,0) E = mm_array(-6.9,41) W = mm_array(17.5,-6) rp = 4.0/1000 # POM is 3.96 rb = 3.2/2/1000 # metal is 3.175/2, but loose, then tendon rc = rb rd = 3.1/1000 qd2= -p.pi # Abitrary. Needs to be enough to stay wrapped. re0= 5.4/1000 re1= 3.2/1000 beta = twoDang(B) AB = twoDmag_ang(B,q+beta) PB = PA+AB gamma = twoDang(C) AC = twoDmag_ang(C,q+gamma) BC = AC-AB delta = twoDang(D) AD = twoDmag_ang(D,q+delta) CD = AD-AC DE = E WA = W WE = WA+AD+DE g = 2*WE[0] qp2 = twoDang(PB) + p.arccos((rp+rb)/p.norm(PB)) fPB = hypleg(PB,rp+rb) qb1 = qp2 + p.pi fBC = p.norm(BC) qb2 = twoDang(BC)+3*p.pi/2 sB = rb*(qb2-qb1) qc1 = qb2 qc2 = twoDang(CD) + 2*p.pi - p.arccos((rc+rd)/p.norm(CD)) fCD = hypleg(CD,rc+rd) sC = rc*(qc2-qc1) qd1 = qc2 - p.pi sD = rd*(qd1-qd2) fBD = fPB + sB + fBC + sC + fCD + sD if not fz: # COMPUTE TOTAL TENDON LENGTH AT OPEN GRIPPER TP = P+p.array([0.0,slack]) fTP = hypleg(TP,rp) qp1 = twoDang(TP) + p.pi - p.arccos(rp/p.norm(TP)) sP = rp*(qp1-qp2) fz = fTP + sP + fBD # OUTPUT INFO ABOUT START POINT print ("t0=%.4f, TPz=[%.4f,%.4f], fTPz=%.4f, qp1=%.1f, fz=%.4f"%(t0,TP[0],TP[1],fTP,qp1*R2D,fz)) # APPROX qp1 as constant qp1_approx = 173.0 * D2R qp1 = qp1_approx sP = rp*(qp1-qp2) P1x = rp*p.cos(qp1) P1y = rp*p.sin(qp1) fTP = fz-sP-fBD fTPx = P[0] + P1x fTPy = hypleg(fTP,fTPx) t = P[1] + t0 + slack + P1y - fTPy # PLOT THE "SKELETON" OF IMPORTANT POINTS TO SANITY CHECK skel = propkin([[0.0,t-t0],P+p.array([0.0,t0-t]),PA,AB,BC,CD,DE]) p.figure(10); p.axis("equal") p.plot(skel[0,:],skel[1,:]) # #################### # # FORCES FOR SPRING # Ft = 1.0 # unit force # # Fb = twoDmag_ang( 2*Ft * p.sin((qb2-qb1)/2), (qb2+qb1)/2 - p.pi) # TQb = p.cross(AB,Fb) # # Fc = twoDmag_ang( 2*Ft * p.sin((qc2-qc1)/2), (qc2+qc1)/2 - p.pi) # TQc = p.cross(AC,Fc) # # # NOTE: NET TORQUE ABOUT DISTAL IS ZERO. # # WE DO NOT SOLVE TORQUE ABOUT DISTAL PROBLEM. # # REACTION FORCES ON PROXIMAL LINK AXLE CAUSE TORQUES ON PROXIMAL # # # FLEXOR TENDON FORCE ON DISTAL, TRANSFERED TO AXLE # Ff1 = twoDmag_ang( Ft, qd1 + p.pi/2 ) # TQf = p.cross(AD,Ff1) # # # SPRING TENDON FORCE ON DISTAL, TRANSFERED TO AXLE # Fs = 1.0 # unit force # Fe1 = twoDmag_ang( Fs, q + p.arcsin((re0-re1)/p.norm(AD)) + p.pi ) # TQFe= p.cross(AD,Fe1) # # Ft_per_Fs = -TQFe/(TQb + TQc + TQf) ###################### # Moment arm for proximal PP1 = twoDmag_ang( rp, qp1 ) AB1 = AB + twoDmag_ang( rb, qb1 ) PB1 = PA + AB1 dirB1P1 = (PP1 - PB1)/p.norm(PP1 - PB1) mF = p.cross( AB1, dirB1P1 ) return (t,q,g, mF)
def date_calculator(): """Subfunction, Simulates MATS FOV and the Moon. Determines when the Moon is entering the FOV at an vertical offset-angle equal to *#V-offset* and also being located at a horizontal off-set angle equal to less than *#H-offset* when pointing at an LP altitude equal to *#pointing_altitude*. \n A timeskip equal to 1/2 an orbit of MATS is applied after a successful spotting of the Moon to save processing time. \n A timeskip equal to the time it takes for the Moon orbital position to change by *#H-offset*/4 degrees are also applied if the Moon is determined to be at an horizontal off-set angle larger then the horizontal FOV of the instrument, equal to *#HFOV*. \n (# as defined in the *Configuration File*). \n Saves the date and parameters regarding the spotting of the Moon to the variable SpottedMoonList. Arguments: Returns: SpottedMoonList ((:obj:`list` of :obj:`dict`)) or (str): A list containing dictionaries containing parameters for each time the Moon is spotted. Or just a date depending on 'automatic' in *Mode124_settings*. """ Timeline_settings = OPT_Config_File.Timeline_settings() Mode124_settings = OPT_Config_File.Mode124_settings() log_timestep = Mode124_settings['log_timestep'] Logger.debug('log_timestep: ' + str(log_timestep)) ################################################## "Check how many times Mode124 have been scheduled" Mode124Iteration = _Globals.Mode124Iteration "Make the V_offset_Index go from 0 to len(Mode124_settings['V_offset']" V_offset_Index = (Mode124Iteration - 1) % (len( Mode124_settings['V_offset'])) "Constants" V_offset = Mode124_settings['V_offset'][V_offset_Index] H_offset = Mode124_settings['H_offset'] pointing_altitude = Mode124_settings['pointing_altitude'] / 1000 Moon_orbital_period = 3600 * 24 * 27.32 yaw_correction = Timeline_settings['yaw_correction'] Logger.debug('H_offset set to [degrees]: ' + str(H_offset)) Logger.debug('V_offset set to [degrees]: ' + str(V_offset)) Logger.debug('Moon_orbital_period [s]: ' + str(Moon_orbital_period)) Logger.debug('yaw_correction set to: ' + str(yaw_correction)) TLE = OPT_Config_File.getTLE() Logger.debug('TLE used: ' + TLE[0] + TLE[1]) ########################################################## "Simulation length and timestep" timestep = Mode124_settings['timestep'] #In seconds Logger.info('Timestep set to [s]: ' + str(timestep)) if (Mode124_settings['TimeToConsider'] <= Timeline_settings['duration']): duration = Mode124_settings['TimeToConsider'] else: duration = Timeline_settings['duration'] Logger.info('Duration set to [s]: ' + str(duration)) timesteps = int(ceil(duration / timestep)) + 2 timeline_start = ephem.Date(Timeline_settings['start_date']) initial_time = ephem.Date(timeline_start + ephem.second * Mode124_settings['freeze_start']) Logger.info('Initial simulation date set to: ' + str(initial_time)) "Pre-allocate space" r_MATS = zeros((timesteps, 3)) lat_MATS = zeros((timesteps, 1)) long_MATS = zeros((timesteps, 1)) optical_axis = zeros((timesteps, 3)) negative_normal_orbit = zeros((timesteps, 3)) r_H_offset_normal = zeros((timesteps, 3)) r_V_offset_normal = zeros((timesteps, 3)) MATS_P = zeros((timesteps, 1)) r_Moon = zeros((timesteps, 3)) r_MATS_2_Moon = zeros((timesteps, 3)) r_MATS_2_Moon_norm = zeros((timesteps, 3)) Moon_r_V_offset_plane = zeros((timesteps, 3)) Moon_r_H_offset_plane = zeros((timesteps, 3)) Moon_r_orbital_plane = zeros((timesteps, 3)) Moon_vert_offset = zeros((timesteps, 1)) Moon_hori_offset = zeros((timesteps, 1)) angle_between_orbital_plane_and_moon = zeros((timesteps, 1)) SpottedMoonList = [] r_Moon_unit_vector = zeros((timesteps, 3)) Dec_optical_axis = zeros((timesteps, 1)) RA_optical_axis = zeros((timesteps, 1)) ts = api.load.timescale(builtin=True) MATS_skyfield = api.EarthSatellite(TLE[0], TLE[1]) planets = api.load('de421.bsp') Moon = planets['Moon'] Earth = planets['Earth'] t = 0 current_time = initial_time Logger.info('') Logger.info('Start of simulation for Mode124') ######### SIMULATION ################ while (current_time < initial_time + ephem.second * duration): if (t * timestep % log_timestep == 0): LogFlag = True else: LogFlag = False Satellite_dict = Satellite_Simulator(MATS_skyfield, current_time, Timeline_settings, pointing_altitude, LogFlag, Logger) r_MATS[t] = Satellite_dict['Position [km]'] MATS_P[t] = Satellite_dict['OrbitalPeriod [s]'] lat_MATS[t] = Satellite_dict['Latitude [degrees]'] long_MATS[t] = Satellite_dict['Longitude [degrees]'] optical_axis[t] = Satellite_dict['OpticalAxis'] Dec_optical_axis[t] = Satellite_dict['Dec_OpticalAxis [degrees]'] RA_optical_axis[t] = Satellite_dict['RA_OpticalAxis [degrees]'] ascending_node = Satellite_dict['AscendingNode'] yaw_offset_angle = Satellite_dict['Yaw [degrees]'] arg_of_lat = Satellite_dict['ArgOfLat [degrees]'] negative_normal_orbit[t] = -Satellite_dict['OrbitNormal'] r_H_offset_normal[t] = Satellite_dict['Normal2H_offset'] r_V_offset_normal[t] = Satellite_dict['Normal2V_offset'] ############# End of Calculations of orbital and pointing vectors ##### current_time_datetime = ephem.Date(current_time).datetime() year = current_time_datetime.year month = current_time_datetime.month day = current_time_datetime.day hour = current_time_datetime.hour minute = current_time_datetime.minute second = current_time_datetime.second + current_time_datetime.microsecond / 1000000 current_time_skyfield = ts.utc(year, month, day, hour, minute, second) Moon_apparent_from_Earth = Earth.at(current_time_skyfield).observe( Moon).apparent() r_Moon[t, 0:3] = Moon_apparent_from_Earth.position.km r_Moon_unit_vector[t, 0:3] = r_Moon[t, 0:3] / norm(r_Moon[t, 0:3]) r_MATS_2_Moon[t] = r_Moon[t] - r_MATS[t] r_MATS_2_Moon_norm[t] = r_MATS_2_Moon[t] / norm(r_MATS_2_Moon[t]) "Calculate Dec and RA of moon" Dec_Moon = arctan( r_Moon[t, 2] / sqrt(r_Moon[t, 0]**2 + r_Moon[t, 1]**2)) / pi * 180 RA_Moon = arccos( dot([1, 0, 0], [r_Moon[t, 0], r_Moon[t, 1], 0]) / norm([r_Moon[t, 0], r_Moon[t, 1], 0])) / pi * 180 if (r_Moon[t, 1] < 0): RA_Moon = 360 - RA_Moon "Project 'r_MATS_2_Moon' ontop of orbital plane" Moon_r_orbital_plane[t] = r_MATS_2_Moon_norm[t] - dot( r_MATS_2_Moon_norm[t], negative_normal_orbit[t]) * negative_normal_orbit[t] "Project 'r_MATS_2_Moon' ontop pointing H-offset and V-offset plane" Moon_r_V_offset_plane[t] = r_MATS_2_Moon_norm[t] - dot( r_MATS_2_Moon_norm[t], r_V_offset_normal[t]) * r_V_offset_normal[t] Moon_r_H_offset_plane[t] = r_MATS_2_Moon_norm[t] - dot( r_MATS_2_Moon_norm[t], r_H_offset_normal[t]) * r_H_offset_normal[t] "Dot product to get the Vertical and Horizontal angle offset of the Moon" Moon_vert_offset[t] = arccos( dot(optical_axis[t], Moon_r_V_offset_plane[t]) / (norm(optical_axis[t]) * norm(Moon_r_V_offset_plane[t]))) / pi * 180 Moon_hori_offset[t] = arccos( dot(optical_axis[t], Moon_r_H_offset_plane[t]) / (norm(optical_axis[t]) * norm(Moon_r_H_offset_plane[t]))) / pi * 180 "Get the offset angle sign correct" if (dot(cross(optical_axis[t], Moon_r_V_offset_plane[t]), negative_normal_orbit[t, 0:3]) > 0): Moon_vert_offset[t] = -Moon_vert_offset[t] if (dot(cross(optical_axis[t], Moon_r_H_offset_plane[t]), r_H_offset_normal[t]) > 0): Moon_hori_offset[t] = -Moon_hori_offset[t] "Angle between orbital plane and moon" angle_between_orbital_plane_and_moon[t] = arccos( dot(r_MATS_2_Moon_norm[t], Moon_r_orbital_plane[t]) / norm(Moon_r_orbital_plane[t])) / pi * 180 if (t * timestep % log_timestep == 0 or t == 1): Logger.debug('angle_between_orbital_plane_and_moon [degrees]: ' + str(angle_between_orbital_plane_and_moon[t])) Logger.debug('Moon_vert_offset [degrees]: ' + str(Moon_vert_offset[t])) Logger.debug('Moon_hori_offset [degrees]: ' + str(Moon_hori_offset[t])) #print('angle_between_orbital_plane_and_moon = ' + str(angle_between_orbital_plane_and_moon[t])) if (t != 0): "Check that the Moon is entering at V-offset degrees and within the H-offset angle" if (Moon_vert_offset[t] <= V_offset and Moon_vert_offset[t - 1] > V_offset and abs(Moon_hori_offset[t]) < H_offset): Logger.debug('') Logger.debug('!!!!!!!!Moon available!!!!!!!!!!') Logger.debug('t (loop iteration number): ' + str(t)) Logger.debug('Current time: ' + str(current_time)) Logger.debug('Orbital Period in s: ' + str(MATS_P[t])) Logger.debug('Vector to MATS [km]: ' + str(r_MATS[t, 0:3])) Logger.debug('Latitude in radians: ' + str(lat_MATS[t])) Logger.debug('Longitude in radians: ' + str(long_MATS[t])) if (yaw_correction == True): Logger.debug('ascending_node: ' + str(ascending_node)) Logger.debug('arg_of_lat [degrees]: ' + str(arg_of_lat)) Logger.debug('yaw_offset_angle [degrees]: ' + str(yaw_offset_angle)) Logger.debug( 'angle_between_orbital_plane_and_moon [degrees]: ' + str(angle_between_orbital_plane_and_moon[t])) Logger.debug('Moon_vert_offset [degrees]: ' + str(Moon_vert_offset[t])) Logger.debug('Moon_hori_offset [degrees]: ' + str(Moon_hori_offset[t])) Logger.debug('normal_orbit: ' + str(-negative_normal_orbit[t, 0:3])) Logger.debug('r_V_offset_normal: ' + str(r_V_offset_normal[t, 0:3])) Logger.debug('r_H_offset_normal: ' + str(r_H_offset_normal[t, 0:3])) Logger.debug('optical_axis: ' + str(optical_axis[t, 0:3])) Logger.debug('') SpottedMoonList.append({ 'Date': str(current_time), 'V-offset': Moon_vert_offset[t], 'H-offset': Moon_hori_offset[t], 'long_MATS': float(long_MATS[t]), 'lat_MATS': float(lat_MATS[t]), 'Dec': Dec_Moon, 'RA': RA_Moon, 'Dec FOV': Dec_optical_axis[t], 'RA FOV': RA_optical_axis[t] }) Logger.debug('Jump ahead half an orbit in time') "Skip ahead half an orbit" current_time = ephem.Date(current_time + ephem.second * MATS_P[t] / 2) Logger.debug('Current time: ' + str(current_time)) Logger.debug('') "To be able to make time skips when the moon is far outside the orbital plane of MATS" if ((angle_between_orbital_plane_and_moon[t] > H_offset and yaw_correction == False) or angle_between_orbital_plane_and_moon[t] > H_offset + abs(Timeline_settings['yaw_amplitude']) and yaw_correction == True): current_time = ephem.Date(current_time + ephem.second * H_offset / 4 / 360 * Moon_orbital_period) #if( t*timestep % floor(log_timestep/400) == 0 ): Logger.debug('') Logger.debug('angle_between_orbital_plane_and_moon [degrees]: ' + str(angle_between_orbital_plane_and_moon[t])) Logger.debug('Moon currently not visible -> jump ahead') Logger.debug('current_time after jump is is: ' + str(current_time)) t = t + 1 else: t = t + 1 current_time = ephem.Date(current_time + ephem.second * timestep) Logger.info('End of simulation for Mode124') Logger.debug('SpottedMoonList: ' + str(SpottedMoonList)) return SpottedMoonList
long=nvargrd['lon_rho'][:] nlat,nlon=long.shape cang=nvargrd['tide_Cangle'][:] cangr=pl.zeros_like(cang) u0=pl.ones_like (long) v0=pl.zeros_like(latg) ur=pl.zeros_like (long) vr=pl.zeros_like(latg) ur,vr=proj.rotate_vector(u0,v0,long,latg) alpha=pl.arccos(ur)*180./pi for id in range(len(cang)): cangr[id,:]=cang[id,:]-alpha cangr[cangr<0.] =cangr[cangr<0.] +360. cangr[cangr>360.]=cangr[cangr>360.]-360. nvargrd['tide_Cangle'][:]=cangr #dimensions: # two = 2 ; # eta_rho = 300 ; # xi_rho = 240 ; # tide_period = UNLIMITED ; // (8 currently)
def Mode120_date_calculator(): #if(True): Logger = logging.getLogger(Logger_name()) log_timestep = 3600 "Simulation length and timestep" duration = Timeline_params()['duration'] Logger.info('Duration set to: ' + str(duration) + ' s') timestep = Mode120_calculator_defaults()['timestep'] #In seconds Logger.info('timestep set to: ' + str(timestep) + ' s') timesteps = int(floor(duration / timestep)) date = Timeline_params()['start_time'] Logger.info('date set to: ' + str(date)) "Get relevant stars" result = Vizier(columns=['all'], row_limit=200).query_constraints( catalog='I/239/hip_main', Vmag=Mode120_calculator_defaults()['Vmag']) star_cat = result[0] ROWS = star_cat[0][:].count() stars = [] stars_dec = zeros((ROWS, 1)) stars_ra = zeros((ROWS, 1)) "Insert stars into Pyephem" for t in range(ROWS): s = "{},f|M|F7,{},{},{},2000" s = s.format(star_cat[t]['HIP'], deg2HMS(ra=star_cat[t]['_RA.icrs']), deg2HMS(dec=star_cat[t]['_DE.icrs']), star_cat[t]['Vmag']) stars.append(ephem.readdb(s)) stars[t].compute(epoch='2018') stars_dec[t] = stars[t].dec stars_ra[t] = stars[t].ra Logger.debug('List of stars used: ' + str(star_cat)) "Calculate unit-vectors of stars" stars_x = cos(stars_dec) * cos(stars_ra) stars_y = cos(stars_dec) * sin(stars_ra) stars_z = sin(stars_dec) stars_r = array([stars_x, stars_y, stars_z]) stars_r = stars_r.transpose() "Prepare the excel file output" star_list_excel = [] star_list_excel.append(['Name;']) star_list_excel.append(['t1;']) star_list_excel.append(['t2;']) star_list_excel.append(['long1;']) star_list_excel.append(['lat1;']) star_list_excel.append(['long2;']) star_list_excel.append(['lat2;']) star_list_excel.append(['mag;']) star_list_excel.append(['H_offset;']) star_list_excel.append(['V_offset;']) star_list_excel.append(['H_offset2;']) star_list_excel.append(['V_offset2;']) star_list_excel.append(['e_Hpmag;']) star_list_excel.append(['Hpscat;']) star_list_excel.append(['o_Hpmag;']) star_list_excel.append(['Classification;']) "Prepare the output" star_list = [] "Pre-allocate space" lat_MATS = zeros((timesteps, 1)) long_MATS = zeros((timesteps, 1)) altitude_MATS = zeros((timesteps, 1)) g_ra_MATS = zeros((timesteps, 1)) g_dec_MATS = zeros((timesteps, 1)) x_MATS = zeros((timesteps, 1)) y_MATS = zeros((timesteps, 1)) z_MATS = zeros((timesteps, 1)) r_MATS = zeros((timesteps, 3)) r_FOV = zeros((timesteps, 3)) r_FOV_unit_vector = zeros((timesteps, 3)) r_FOV_norm = zeros((timesteps, 3)) r_azi_norm = zeros((timesteps, 3)) stars_r_V_offset_plane = zeros((ROWS, 3)) stars_r_H_offset_plane = zeros((ROWS, 3)) stars_vert_offset = zeros((timesteps, ROWS)) stars_hori_offset = zeros((timesteps, ROWS)) stars_offset = zeros((timesteps, ROWS)) normal_orbital = zeros((timesteps, 3)) r_V_offset_normal = zeros((timesteps, 3)) r_H_offset_normal = zeros((timesteps, 3)) pitch_sensor_array = zeros((timesteps, 1)) star_counter = 0 spotted_star_name = [] spotted_star_timestamp = [] spotted_star_timecounter = [] skip_star_list = [] MATS_p = zeros((timesteps, 1)) MATS_P = zeros((timesteps, 1)) angle_between_orbital_plane_and_star = zeros((timesteps, ROWS)) "Constants" R_mean = 6371 #Earth radius Logger.info('Earth radius used [km]: ' + str(R_mean)) U = 398600.4418 #Earth gravitational parameter FOV_altitude = Mode120_calculator_defaults( )['default_pointing_altitude'] / 1000 #Altitude at which MATS center of FOV is looking Logger.info('FOV_altitude set to [km]: ' + str(FOV_altitude)) pointing_adjustment = 3 #Angle in degrees that the pointing can be adjusted V_FOV = Mode120_calculator_defaults()['V_FOV'] #0.91 is actual V_FOV H_FOV = Mode120_calculator_defaults()['H_FOV'] #5.67 is actual H_FOV Logger.info('V_FOV set to [degrees]: ' + str(V_FOV)) Logger.info('H_FOV set to [degrees]: ' + str(H_FOV)) pitch_offset_angle = 0 yaw_offset_angle = 0 Logger.info('TLE used: ' + getTLE()[0] + getTLE()[1]) MATS = ephem.readtle('MATS', getTLE()[0], getTLE()[1]) Logger.info('') Logger.info('Start of simulation of MATS for Mode120') ################## Start of Simulation ######################################## "Loop and calculate the relevant angle of each star to each direction of MATS's FOV" for t in range(timesteps): current_time = ephem.Date(date + ephem.second * timestep * t) MATS.compute(current_time) (lat_MATS[t], long_MATS[t], altitude_MATS[t], g_ra_MATS[t], g_dec_MATS[t]) = (MATS.sublat, MATS.sublong, MATS.elevation / 1000, MATS.g_ra, MATS.g_dec) R = lat_2_R(lat_MATS[t]) z_MATS[t] = sin(g_dec_MATS[t]) * (altitude_MATS[t] + R) x_MATS[t] = cos(g_dec_MATS[t]) * (altitude_MATS[t] + R) * cos( g_ra_MATS[t]) y_MATS[t] = cos(g_dec_MATS[t]) * (altitude_MATS[t] + R) * sin( g_ra_MATS[t]) r_MATS[t, 0:3] = [x_MATS[t], y_MATS[t], z_MATS[t]] #Semi-Major axis of MATS, assuming circular orbit MATS_p[t] = norm(r_MATS[t, 0:3]) #Orbital Period of MATS MATS_P[t] = 2 * pi * sqrt(MATS_p[t]**3 / U) #Estimated pitch or elevation angle for MATS pointing pitch_sensor_array[t] = array( arccos( (R_mean + FOV_altitude) / (R + altitude_MATS[t])) / pi * 180) pitch_sensor = pitch_sensor_array[t][0] if (t * timestep % log_timestep == 0): Logger.debug('') Logger.debug('log_timestep: ' + str(log_timestep)) Logger.debug('timestep: ' + str(timestep)) Logger.debug('t (loop iteration number): ' + str(t)) Logger.debug('Current time: ' + str(current_time)) Logger.debug('Semimajor axis in km: ' + str(MATS_p[t])) Logger.debug('Orbital Period in s: ' + str(MATS_P[t])) Logger.debug('Vector to MATS [km]: ' + str(r_MATS[t, 0:3])) Logger.debug('Latitude in radians: ' + str(lat_MATS[t])) Logger.debug('Longitude in radians: ' + str(long_MATS[t])) Logger.debug('Altitude in km: ' + str(altitude_MATS[t])) Logger.debug('FOV pitch in degrees: ' + str(pitch_sensor)) if (t != 0): ############# Calculations of orbital and pointing vectors ############ "Vector normal to the orbital plane of MATS" normal_orbital[t, 0:3] = cross(r_MATS[t], r_MATS[t - 1]) normal_orbital[t, 0:3] = normal_orbital[t, 0:3] / norm( normal_orbital[t, 0:3]) "Rotate 'vector to MATS', to represent pointing direction, includes vertical offset change (Parallax is negligable)" rot_mat = rot_arbit( -pi / 2 + (-pitch_sensor + pitch_offset_angle) / 180 * pi, normal_orbital[t, 0:3]) r_FOV[t, 0:3] = (r_MATS[t] @ rot_mat) / 2 "Rotate yaw of pointing direction, meaning to rotate around the vector to MATS" rot_mat = rot_arbit(yaw_offset_angle / 180 * pi, r_MATS[t, 0:3]) r_FOV[t, 0:3] = (r_FOV[t, 0:3] @ rot_mat) r_FOV_unit_vector[t, 0:3] = r_FOV[t, 0:3] / norm(r_FOV[t, 0:3]) '''Rotate 'vector to MATS', to represent vector normal to satellite H-offset plane, which will be used to project stars onto it which allows the H-offset of stars to be found''' rot_mat = rot_arbit((-pitch_sensor) / 180 * pi, normal_orbital[t, 0:3]) r_H_offset_normal[t, 0:3] = (r_MATS[t] @ rot_mat) r_H_offset_normal[t, 0:3] = r_H_offset_normal[t, 0:3] / norm( r_H_offset_normal[t, 0:3]) "If pointing direction has a Yaw defined, Rotate yaw of normal to pointing direction H-offset plane, meaning to rotate around the vector to MATS" rot_mat = rot_arbit(yaw_offset_angle / 180 * pi, r_MATS[t, 0:3]) r_H_offset_normal[t, 0:3] = (r_H_offset_normal[t, 0:3] @ rot_mat) r_H_offset_normal[t, 0:3] = r_H_offset_normal[t, 0:3] / norm( r_H_offset_normal[t, 0:3]) "Rotate orbital plane normal to make it into pointing V-offset plane normal" r_V_offset_normal[t, 0:3] = (normal_orbital[t, 0:3] @ rot_mat) r_V_offset_normal[t, 0:3] = r_V_offset_normal[t, 0:3] / norm( r_V_offset_normal[t, 0:3]) if (t * timestep % log_timestep == 0 or t == 1): Logger.debug('Pointing direction of FOV: ' + str(r_FOV_unit_vector[t, 0:3])) Logger.debug('Orthogonal direction to H-offset plane: ' + str(r_H_offset_normal[t, 0:3])) Logger.debug('Orthogonal direction to V-offset plane: ' + str(r_V_offset_normal[t, 0:3])) Logger.debug('Orthogonal direction to the orbital plane: ' + str(normal_orbital[t, 0:3])) Logger.debug('') # '''Rotate 'vector to MATS', to represent vector normal to satellite yaw plane, # which will be used to rotate the yaw of the pointing''' # rot_mat = rot_arbit((-pitch_sensor)/180*pi, normal_orbital[t,0:3]) # r_azi_norm[t,0:3] = (r_MATS[t] @ rot_mat) # r_azi_norm[t,0:3] = r_azi_norm[t,0:3] / norm(r_azi_norm[t,0:3]) # # "Rotate horizontal offset of pointing direction, around satellite yaw plane" # rot_mat = rot_arbit(yaw_offset_angle/180*pi, r_azi_norm[t,0:3]) # r_FOV[t,0:3] = (r_FOV[t,0:3] @ rot_mat) # r_FOV_unit_vector[t,0:3] = r_FOV[t,0:3]/norm(r_FOV[t,0:3])/2 # # "Rotate orbital plane normal to match pointing V-offset plane normal" # r_V_offset_normal[t,0:3] = (normal_orbital[t,0:3] @ rot_mat) # # '''Rotate pointing vector 90 degrees in the pointing elevation plane to get a vector, # which is normal to pointing azimuth plane''' # rot_mat = rot_arbit(pi/2, r_V_offset_normal[t,0:3]) # r_FOV_norm[t,0:3] = (r_FOV[t,0:3] @ rot_mat) # r_FOV_norm[t,0:3] = r_FOV_norm[t,0:3] / norm(r_FOV_norm[t,0:3]) ############# End of Calculations of orbital and pointing vectors ##### ###################### Star-mapper #################################### "Check position of stars relevant to pointing direction" for x in range(ROWS): "Skip star if it is not visible during this epoch" if (stars[x].name in skip_star_list): continue "Check if a star has already been spotted during this orbit." if (stars[x].name in spotted_star_name): '''Check if not enough time has passed so that the star has not left FOV''' if ((current_time - spotted_star_timestamp[spotted_star_name.index( stars[x].name)]) < ephem.second * (V_FOV * 2 * MATS_P[t] / 360)): '''Check if enough time has passed so that the star is roughly in the same direction as original FOV and save lat,long, Hoffset, Voffset and time. Otherwise skip star.''' if ((t - spotted_star_timecounter[spotted_star_name.index( stars[x].name)]) * timestep == around( MATS_P[t] * (pitch_offset_angle + V_FOV / 2) / 360)): "Project 'star vectors' ontop pointing H-offset and V-offset plane" stars_r_V_offset_plane[x] = stars_r[0][x] - dot( stars_r[0][x], r_V_offset_normal[ t, 0:3]) * r_V_offset_normal[t, 0:3] stars_r_H_offset_plane[x] = stars_r[0][x] - ( (dot(stars_r[0][x], r_H_offset_normal[t]) * r_H_offset_normal[t]) / ((norm(r_H_offset_normal[t]))**2)) "Dot product to get the Vertical and Horizontal angle offset of the star in the FOV" stars_vert_offset[t][x] = arccos( dot(r_FOV[t], stars_r_V_offset_plane[x]) / (norm(r_FOV[t]) * norm(stars_r_V_offset_plane[x]))) / pi * 180 stars_hori_offset[t][x] = arccos( dot(r_FOV[t], stars_r_H_offset_plane[x]) / (norm(r_FOV[t]) * norm(stars_r_H_offset_plane[x]))) / pi * 180 "Determine sign of off-set angle where positive V-offset angle is when looking at higher altitude" if (dot(cross(r_FOV[t], stars_r_V_offset_plane[x]), r_V_offset_normal[t, 0:3]) > 0): stars_vert_offset[t][ x] = -stars_vert_offset[t][x] if (dot(cross(r_FOV[t], stars_r_H_offset_plane[x]), r_H_offset_normal[t]) > 0): stars_hori_offset[t][ x] = -stars_hori_offset[t][x] star_list_excel[2].append(str(current_time) + ';') star_list_excel[5].append( str(float(long_MATS[t] / pi * 180)) + ';') star_list_excel[6].append( str(float(lat_MATS[t] / pi * 180)) + ';') star_list_excel[10].append( str(stars_hori_offset[t][x]) + ';') star_list_excel[11].append( str(stars_vert_offset[t][x]) + ';') continue "If enough time has passed (half an orbit), the star can be removed from the exception list" elif ((current_time - spotted_star_timestamp[spotted_star_name.index( stars[x].name)]) >= ephem.second * (180 * MATS_P[t] / 360)): spotted_star_timestamp.pop( spotted_star_name.index(stars[x].name)) spotted_star_timecounter.pop( spotted_star_name.index(stars[x].name)) spotted_star_name.remove(stars[x].name) "Total angle offset of the star compared to MATS's FOV" stars_offset[t][x] = arccos( dot(r_FOV[t], stars_r[0][x]) / (norm(r_FOV[t]) * norm(stars_r[0][x]))) / pi * 180 "Project 'star vectors' ontop pointing H-offset and V-offset plane" stars_r_V_offset_plane[x] = stars_r[0][x] - ( dot(stars_r[0][x], r_V_offset_normal[t, 0:3]) * r_V_offset_normal[t, 0:3]) stars_r_H_offset_plane[x] = stars_r[0][x] - ( dot(stars_r[0][x], r_H_offset_normal[t]) * r_H_offset_normal[t]) "Dot product to get the Vertical and Horizontal angle offset of the star in the FOV" stars_vert_offset[t][x] = arccos( dot(r_FOV[t], stars_r_V_offset_plane[x]) / (norm(r_FOV[t]) * norm(stars_r_V_offset_plane[x]))) / pi * 180 stars_hori_offset[t][x] = arccos( dot(r_FOV[t], stars_r_H_offset_plane[x]) / (norm(r_FOV[t]) * norm(stars_r_H_offset_plane[x]))) / pi * 180 "Determine sign of off-set angle where positive V-offset angle is when looking at higher altitude" if (dot(cross(r_FOV[t], stars_r_V_offset_plane[x]), r_V_offset_normal[t, 0:3]) > 0): stars_vert_offset[t][x] = -stars_vert_offset[t][x] if (dot(cross(r_FOV[t], stars_r_H_offset_plane[x]), r_H_offset_normal[t]) > 0): stars_hori_offset[t][x] = -stars_hori_offset[t][x] "To be able to skip stars far outside the orbital plane of MATS" angle_between_orbital_plane_and_star[t][x] = arccos( dot(stars_r[0][x], stars_r_V_offset_plane[x]) / norm(stars_r_V_offset_plane[x])) / pi * 180 "For first loop of stars, make exception list for stars not visible during this epoch" if (t == 1 and abs(angle_between_orbital_plane_and_star[t][x]) > H_FOV / 2 + (duration * 2) / (365 * 24 * 3600) * 360): Logger.debug( 'Skip star: ' + stars[x].name + ', with H-offset of: ' + str(angle_between_orbital_plane_and_star[t][x]) + ' degrees') skip_star_list.append(stars[x].name) continue "Check if star is in FOV" if (abs(stars_vert_offset[t][x]) < V_FOV / 2 and abs(stars_hori_offset[t][x]) < H_FOV / 2): #print('Star number:',stars[x].name,'is visible at',stars_vert_offset[t][x],'degrees VFOV and', \ #stars_hori_offset[t][x],'degrees HFOV','during',ephem.Date(current_time)) if (t % log_timestep == 0): Logger.debug('Star: ' + stars[x].name + ', with H-offset: ' + str(stars_hori_offset[t][x]) + ' V-offset: ' + str(stars_vert_offset[t][x]) + ' in degrees is visible') "Add the spotted star to the exception list and timestamp it" spotted_star_name.append(stars[x].name) spotted_star_timestamp.append(current_time) spotted_star_timecounter.append(t) "Log all relevent data for the star" star_list_excel[0].append(stars[x].name + ';') star_list_excel[1].append(str(current_time) + ';') star_list_excel[3].append( str(float(long_MATS[t] / pi * 180)) + ';') star_list_excel[4].append( str(float(lat_MATS[t] / pi * 180)) + ';') star_list_excel[7].append(str(stars[x].mag) + ';') star_list_excel[8].append( str(stars_hori_offset[t][x]) + ';') star_list_excel[9].append( str(stars_vert_offset[t][x]) + ';') star_list_excel[12].append( str(star_cat[x]['e_Hpmag']) + ';') star_list_excel[13].append( str(star_cat[x]['Hpscat']) + ';') star_list_excel[14].append( str(star_cat[x]['o_Hpmag']) + ';') star_list_excel[15].append( str(star_cat[x]['SpType']) + ';') "Log data of star relevant to filtering process" star_list.append({ 'Date': str(current_time), 'V-offset': stars_vert_offset[t][x], 'H-offset': stars_hori_offset[t][x], 'long_MATS': float(long_MATS[t] / pi * 180), 'lat_MATS': float(lat_MATS[t] / pi * 180), 'Vmag': stars[x].mag, 'Name': stars[x].name }) star_counter = star_counter + 1 ######################### End of star_mapper ############################# ########################## Optional plotter ########################################### ''' from mpl_toolkits.mplot3d import axes3d "Orbital points to plot" points_2_plot_start = 0#0*24*120 points_2_plot = points_2_plot_start+200 "Plotting of orbit and FOV" fig = figure(1) ax = fig.add_subplot(111,projection='3d') ax.set_xlim3d(-7000, 7000) ax.set_ylim3d(-7000, 7000) ax.set_zlim3d(-7000, 7000) ax.scatter(x_MATS[points_2_plot_start:points_2_plot],y_MATS[points_2_plot_start:points_2_plot],z_MATS[points_2_plot_start:points_2_plot]) ax.scatter(r_FOV[points_2_plot_start:points_2_plot,0],r_FOV[points_2_plot_start:points_2_plot,1],r_FOV[points_2_plot_start:points_2_plot,2]) "Plotting of stars and FOV unit-vectors" fig = figure(2) ax = fig.add_subplot(111,projection='3d') ax.scatter(stars_r[0][:,0],stars_r[0][:,1],stars_r[0][:,2]) ax.scatter(r_FOV_unit_vector[points_2_plot_start:points_2_plot,0],r_FOV_unit_vector[points_2_plot_start:points_2_plot,1],r_FOV_unit_vector[points_2_plot_start:points_2_plot,2]) ax.scatter(r_V_offset_normal[points_2_plot_start:points_2_plot,0]/2, r_V_offset_normal[points_2_plot_start:points_2_plot,1]/2, r_V_offset_normal[points_2_plot_start:points_2_plot,2]/2) ax.scatter(normal_orbital[points_2_plot_start:points_2_plot,0]/2, normal_orbital[points_2_plot_start:points_2_plot,1]/2, normal_orbital[points_2_plot_start:points_2_plot,2]/2) ax.scatter(r_H_offset_normal[points_2_plot_start:points_2_plot,0]/2, r_H_offset_normal[points_2_plot_start:points_2_plot,1]/2, r_H_offset_normal[points_2_plot_start:points_2_plot,2]/2) ''' ########################### END of Optional plotter ######################################## "Write spotted stars to file" with open('MATS_Visible_Stars.csv', 'w', newline='') as write_file: writer = csv.writer(write_file, dialect='excel-tab') writer.writerows(star_list_excel) Logger.debug('Visible star list to be filtered:') Logger.debug(str(star_list)) Logger.debug('') Logger.debug('Exit ' + str(__name__)) Logger.debug('') return (star_list)
def date_calculator(Settings): """Simulates MATS FOV and stars. Used by Mode121-123. Simuates MATS FOV and visible stars for one orbit then skips ahead for *Settings['Timeskip']* amount of days (as defined in the *Configuration File*). Saves the date, pointing RA and Dec, and the magnitude of the brightest visible star at each timestep. Arguments: Settings (dict): Dictionary containing settings for this simulation. Returns: (array): Array containing date in first column and brightest magnitude visible in the second. Contains current Dec and RA in 3rd and 4th column respectively. """ Timeline_settings = OPT_Config_File.Timeline_settings() "To either calculate when stars are visible and schedule from that data or just schedule at a given time given by Mode120_settings['start_date']" if (Settings['automatic'] == False): if (Settings['start_date'] == '0'): date = ephem.Date(Timeline_settings['start_date']) else: try: date = ephem.Date(Settings['start_date']) except: Logger.error( 'Could not get Settings["start_date"], exiting...') sys.exit() return date elif (Settings['automatic'] == True): "Simulation length and timestep" log_timestep = Settings['log_timestep'] Logger.debug('log_timestep: ' + str(log_timestep)) timestep = Settings['timestep'] #In seconds Logger.info('timestep set to: ' + str(timestep) + ' s') if (Settings['TimeToConsider'] <= Timeline_settings['duration']): duration = Settings['TimeToConsider'] else: duration = Timeline_settings['duration'] Logger.info('Duration set to: ' + str(duration) + ' s') timesteps = int(ceil(duration / timestep)) + 2 Logger.info('Maximum number of timesteps set to: ' + str(timesteps)) timeline_start = ephem.Date(Timeline_settings['start_date']) initial_time = ephem.Date(timeline_start + ephem.second * Settings['freeze_start']) Logger.info('initial_time set to: ' + str(initial_time)) "Get relevant stars" result = Vizier(columns=['all'], row_limit=3000).query_constraints( catalog='I/239/hip_main', Vmag=Settings['Vmag']) star_cat = result[0] ROWS = star_cat[0][:].count() stars = [] stars_dec = zeros((ROWS, 1)) stars_ra = zeros((ROWS, 1)) "Insert stars into Pyephem" for t in range(ROWS): s = "{},f|M|F7,{},{},{},2000/01/01 11:58:55.816" s = s.format(star_cat[t]['HIP'], deg2HMS(ra=star_cat[t]['_RA.icrs']), deg2HMS(dec=star_cat[t]['_DE.icrs']), star_cat[t]['Vmag']) stars.append(ephem.readdb(s)) stars[t].compute(epoch='2000/01/01 11:58:55.816') stars_dec[t] = stars[t].dec stars_ra[t] = stars[t].ra Logger.debug('') Logger.debug('List of stars used: ' + str(star_cat)) Logger.debug('') "Calculate unit-vectors of stars" stars_x = cos(stars_dec) * cos(stars_ra) stars_y = cos(stars_dec) * sin(stars_ra) stars_z = sin(stars_dec) stars_r = array([stars_x, stars_y, stars_z]) stars_r = stars_r.transpose() "Prepare the output" "Array containing date in first column and brightest magnitude visible in the second. Contains current Dec and RA in 3rd and 4th column" date_magnitude_array = zeros((timesteps, 4)) "Set magntidues arbitrary large, which will correspond to no star being visible" date_magnitude_array[:, 1] = 100 "Pre-allocate space" lat_MATS = zeros((timesteps, 1)) long_MATS = zeros((timesteps, 1)) optical_axis = zeros((timesteps, 3)) stars_r_V_offset_plane = zeros((ROWS, 3)) stars_r_H_offset_plane = zeros((ROWS, 3)) stars_vert_offset = zeros((timesteps, ROWS)) stars_hori_offset = zeros((timesteps, ROWS)) r_V_offset_normal = zeros((timesteps, 3)) r_H_offset_normal = zeros((timesteps, 3)) star_counter = 0 skip_star_list = [] MATS_P = zeros((timesteps, 1)) Dec_optical_axis = zeros((timesteps, 1)) RA_optical_axis = zeros((timesteps, 1)) angle_between_orbital_plane_and_star = zeros((timesteps, ROWS)) "Constants" pointing_altitude = Settings['pointing_altitude'] / 1000 V_FOV = Settings['V_FOV'] H_FOV = Settings['H_FOV'] #5.67 is actual H_FOV yaw_correction = Timeline_settings['yaw_correction'] Logger.debug('H_FOV set to [degrees]: ' + str(H_FOV)) Logger.debug('V_FOV set to [degrees]: ' + str(V_FOV)) Logger.debug('yaw_correction set to: ' + str(yaw_correction)) TLE = OPT_Config_File.getTLE() Logger.debug('TLE used: ' + TLE[0] + TLE[1]) MATS_skyfield = api.EarthSatellite(TLE[0], TLE[1]) "Loop counter" t = 0 TimeSkips = 0 #time_skip_counter = 0 Timeskip = Settings[ 'TimeSkip'] #Days to skip ahead after each completed orbit current_time = initial_time Logger.info('') Logger.info('Start of simulation of MATS for Mode121/122/123') ################## Start of Simulation ######################################## "Loop and calculate the relevant angle of each star to each direction of MATS's FOV" while (current_time < timeline_start + ephem.second * duration): if (t * timestep % log_timestep == 0): LogFlag = True else: LogFlag = False Satellite_dict = Satellite_Simulator(MATS_skyfield, current_time, Timeline_settings, pointing_altitude, LogFlag, Logger) MATS_P[t] = Satellite_dict['OrbitalPeriod [s]'] lat_MATS[t] = Satellite_dict['Latitude [degrees]'] long_MATS[t] = Satellite_dict['Longitude [degrees]'] optical_axis[t] = Satellite_dict['OpticalAxis'] Dec_optical_axis[t] = Satellite_dict['Dec_OpticalAxis [degrees]'] RA_optical_axis[t] = Satellite_dict['RA_OpticalAxis [degrees]'] r_H_offset_normal[t] = Satellite_dict['Normal2H_offset'] r_V_offset_normal[t] = Satellite_dict['Normal2V_offset'] ############# End of Calculations of orbital and pointing vectors ##### "Add current date to date_magnitude_array" date_magnitude_array[t, 0] = current_time "Add optical axis Dec and RA to date_magnitude_array" date_magnitude_array[t, 2] = Dec_optical_axis[t] date_magnitude_array[t, 3] = RA_optical_axis[t] ###################### Star-mapper #################################### "Check position of stars relevant to pointing direction" for x in range(ROWS): "Skip star if it is not visible during this epoch" if (stars[x].name in skip_star_list): continue "Project 'star vectors' ontop pointing H-offset and V-offset plane" stars_r_V_offset_plane[x] = stars_r[0][x] - ( dot(stars_r[0][x], r_V_offset_normal[t]) * r_V_offset_normal[t]) stars_r_H_offset_plane[x] = stars_r[0][x] - ( dot(stars_r[0][x], r_H_offset_normal[t]) * r_H_offset_normal[t]) "Dot product to get the Vertical and Horizontal angle offset of the star in the FOV" stars_vert_offset[t][x] = arccos( dot(optical_axis[t], stars_r_V_offset_plane[x]) / (norm(optical_axis[t]) * norm(stars_r_V_offset_plane[x]))) / pi * 180 stars_hori_offset[t][x] = arccos( dot(optical_axis[t], stars_r_H_offset_plane[x]) / (norm(optical_axis[t]) * norm(stars_r_H_offset_plane[x]))) / pi * 180 "For first loop of stars, make exception list for stars not visible during this epoch" if (t == 1): "To be able to skip stars far outside the orbital plane of MATS" angle_between_orbital_plane_and_star[t][x] = arccos( dot(stars_r[0][x], stars_r_V_offset_plane[x]) / norm(stars_r_V_offset_plane[x])) / pi * 180 if (abs(angle_between_orbital_plane_and_star[t][x]) > H_FOV / 2 + (duration * 2) / (365 * 24 * 3600) * 360): Logger.debug( 'Skip star: ' + stars[x].name + ', with angle_between_orbital_plane_and_star of: ' + str(angle_between_orbital_plane_and_star[t][x]) + ' degrees') skip_star_list.append(stars[x].name) continue "Check if star is in FOV" if (abs(stars_vert_offset[t][x]) < V_FOV / 2 and abs(stars_hori_offset[t][x]) < H_FOV / 2): #print('Star number:',stars[x].name,'is visible at',stars_vert_offset[t][x],'degrees VFOV and', \ #stars_hori_offset[t][x],'degrees HFOV','during',ephem.Date(current_time)) if (t % log_timestep == 0 or t == 1): Logger.debug('Current time: ' + str(current_time)) Logger.debug('Star: ' + stars[x].name + ', with H-offset: ' + str(stars_hori_offset[t][x]) + ' V-offset: ' + str(stars_vert_offset[t][x]) + ' in degrees is visible') "Check if it is the brightest star spotted in the current FOV at the current date, and if so, replace the current value" if (stars[x].mag < date_magnitude_array[t, 1]): date_magnitude_array[t, 1] = stars[x].mag star_counter = star_counter + 1 ######################### End of star_mapper ############################# "Increase Simulation Time with a timestep, or skip ahead if 1 orbit is completed" t += 1 if (t * timestep >= MATS_P[t - 1] * (TimeSkips + 1)): current_time = ephem.Date(current_time + ephem.second * Timeskip) TimeSkips += 1 else: current_time = ephem.Date(current_time + ephem.second * timestep) ''' "Increment time with timestep or jump ahead in time if a whole orbit was completed" if( (current_time - initial_time)/ephem.second > (timeskip/ephem.second * time_skip_counter + MATS_P[t] * (time_skip_counter+1)) ): "If one orbit has passed -> increment 'current_time' with 'timeskip' amount of days" time_skip_counter = time_skip_counter + 1 current_time = ephem.Date(current_time + timeskip) else: "Else just increment the current_time with timestep" current_time = ephem.Date(current_time + ephem.second * timestep) "Loop counter" t = t + 1 ''' ################## End of Simulation ######################################## return (date_magnitude_array)