Using pyephem to calculate when a satellite crosses a Longitude - python

I am having a hard time figuring out how to calculate when a satellite crosses a specific Longitude. It would be nice to able to provide a time period and a TLE and be able to return all the times at which the satellite crosses a given longitude during the specified time period. Does pyephem support something like this?

There are so many possible circumstances that users might ask about — when a satellite crosses a specific longitude; when it reaches a specific latitude; when it reaches a certain height or descends to its lowest altitude; when its velocity is greatest or least — that PyEphem does not try to provide built-in functions for all of them. Instead, it provides a newton() function that lets you find the zero-crossing of whatever comparison you want to make between a satellite attribute and a pre-determined value of that attribute that you want to search for.
Note that the SciPy Python library contains several very careful search functions that are much more sophisticated than PyEphem's newton() function, in case you are dealing with a particularly poorly-behaved function:
http://docs.scipy.org/doc/scipy/reference/optimize.html
Here is how you might search for when a satellite — in this example, the ISS — passes a particular longitude, to show the general technique. This is not the fastest possible approach — the minute-by-minute search, in particular, could be sped up if we were very careful — but it is written to be very general and very safe, in case there are other values besides longitude that you also want to search for. I have tried to add documentation and comments to explain what is going on, and why I use znorm instead of returning the simple difference. Let me know if this script works for you, and explains its approach clearly enough!
import ephem
line0 = 'ISS (ZARYA) '
line1 = '1 25544U 98067A 13110.27262069 .00008419 00000-0 14271-3 0 6447'
line2 = '2 25544 51.6474 35.7007 0010356 160.4171 304.1803 15.52381363825715'
sat = ephem.readtle(line0, line1, line2)
target_long = ephem.degrees('-83.8889')
def longitude_difference(t):
'''Return how far the satellite is from the target longitude.
Note carefully that this function does not simply return the
difference of the two longitudes, since that would produce a
terrible jagged discontinuity from 2pi to 0 when the satellite
crosses from -180 to 180 degrees longitude, which could happen to be
a point close to the target longitude. So after computing the
difference in the two angles we run degrees.znorm on it, so that the
result is smooth around the point of zero difference, and the
discontinuity sits as far away from the target position as possible.
'''
sat.compute(t)
return ephem.degrees(sat.sublong - target_long).znorm
t = ephem.date('2013/4/20')
# How did I know to make jumps by minute here? I experimented: a
# `print` statement in the loop showing the difference showed huge jumps
# when looping by a day or hour at a time, but minute-by-minute results
# were small enough steps to bring the satellite gradually closer to the
# target longitude at a rate slow enough that we could stop near it.
#
# The direction that the ISS travels makes the longitude difference
# increase with time; `print` statements at one-minute increments show a
# series like this:
#
# -25:16:40.9
# -19:47:17.3
# -14:03:34.0
# -8:09:21.0
# -2:09:27.0
# 3:50:44.9
# 9:45:50.0
# 15:30:54.7
#
# So the first `while` loop detects if we are in the rising, positive
# region of this negative-positive pattern and skips the positive
# region, since if the difference is positive then the ISS has already
# passed the target longitude and is on its way around the rest of
# the planet.
d = longitude_difference(t)
while d > 0:
t += ephem.minute
sat.compute(t)
d = longitude_difference(t)
# We now know that we are on the negative-valued portion of the cycle,
# and that the ISS is closing in on our longitude. So we keep going
# only as long as the difference is negative, since once it jumps to
# positive the ISS has passed the target longitude, as in the sample
# data series above when the difference goes from -2:09:27.0 to
# 3:50:44.9.
while d < 0:
t += ephem.minute
sat.compute(t)
d = longitude_difference(t)
# We are now sitting at a point in time when the ISS has just passed the
# target longitude. The znorm of the longitude difference ought to be a
# gently sloping zero-crossing curve in this region, so it should be
# safe to set Newton's method to work on it!
tn = ephem.newton(longitude_difference, t - ephem.minute, t)
# This should be the answer! So we print it, and also double-check
# ourselves by printing the longitude to see how closely it matches.
print 'When did ISS cross this longitude?', target_long
print 'At this specific date and time:', ephem.date(tn)
sat.compute(tn)
print 'To double-check, at that time, sublong =', sat.sublong
The output that I get when running this script suggests that it has indeed found the moment (within reasonable tolerance) when the ISS reaches the target longitude:
When did ISS cross this longitude? -83:53:20.0
At this specific date and time: 2013/4/20 00:18:21
To double-check, at that time, sublong = -83:53:20.1

There is a difference of time between the time the program calculates the passes over the longitude and the real time. I've checked it with the LIS system ( that it's inside the ISS ) of the Nasa to find lightnings.
And I have discovered that in Europe in some orbits the time that the program calculates the pass, it's 30 seconds in advanced than the real time. And in Colombia in some orbits the time in advanced is about 3 minutes ( perhaps because 1 degree of longitud in Colombia is bigger in amount of Km than 1 degree of longitude in Europe ). But this problem only happens in 2 particular orbits ! The one that pass over France and goes down in Sicilia. And the one that pass over USA, and goes down in Cuba.
Why could this be possible ?
In my pinion I think maybe there's some mistake in the ephem.newton algorithm or maybe with the TLE, that normally it reads the one created at 00:00:00 at night when it changes of day (and not the actual, because the ISS creates 3-4 TLE per day ) or maybe with the sat.sublong function that calculates a wrong Nadir of the satellite.
Does anyone has an idea or an explanation for this problem ?
Why it happens ?.
PS: I need to checked it for sure because I need to know when the ISS crosses an area ( for detecting the lightnings inside the area ). And if the time that the program calculates in some orbits it's in advanced than the real time, then the sat.sublong function calculates it's outside the area ( it calculates it hasn't arrived to the area yet ) but the program shows it's inside the area. So the real time doesn't match with the one that the program calculates, in some occasions.
Thanks a lot for your time !

Related

How do I calculate GPS distance accurately in Python

I am trying to update distance traveled between GPS coordinates. My error is that the GPS can move short distances while sitting still. I am currently adding the new coordinates to a list every second, calculating the distance between this second and last second, then appending the distances to a new list then add them all together.
The issue is that the small movements in distance while standing still keep accumulating. Does anyone know the proper way to do this?
self.breadcrumbs = []
#Calc Linear Distance GPS
while 1:
report = gpsp.get_current_value() #Retrieves GPS Values
try:
self.lat = report.lat
self.lon = report.lon
self.latlon = (self.lat, self.lon) #Put lat lon into tuple
self.breadcrumbs.append(self.latlon) #Append lat lon to breadcrumb list
breadcrumb_distances = [] #Holds distances between latlon data points
for i, b in enumerate(self.breadcrumbs):
current_location = b
last_location = self.breadcrumbs[i - 1]
miles = geodesic(current_location, last_location).miles
feet = miles * 5280 #convert to feet
breadcrumb_distances.append(feet)
cumulative_distance = round(sum(breadcrumb_distances),2)
print(cumulative_distance)
except Exception as e:
print(e)
sleep(1)
There is no single "right" way to do this. The problem is that when you are moving very slowly, the "erroneous" movement overwhelms what the user would perceive as the actual movement. It becomes a tradeoff between taking data that is in error and dropping data that represents actual motion. The problem increases the faster you take data and the slower the velocity.
One method is to set a minimum distance that will cause you to log new data. If the new point is within some distance ϵ of the previous one, drop the point. For good choices, this will ignore motion when actually stopped. You then need to not care about the time between data points, or you need to log the time for points (or somehow indicate the location and duration of the gaps). If the problem is due to stopped periods, this may be the best.
Another method is to reduce the logging frequency. For some applications, backing off to 5s or similar may be sufficient.

PyEphem: mag function not returning right magnitude for the Sun at specific places on Earth?

I am trying to get the apparent magnitude of the Sun at various locations on Earth using PyEphem. When I change different locations on Earth or even change the time the apparent magnitude of the Sun remains the same. This doesn't make any sense because I changed one of the times to night. What's wrong here?
I believe mag is the right function for me. If not, do you know how I could do this: get the apparent magnitude or illuminance of the Sun at various spots of Earth at varying times?
>>> gatech = ephem.Observer()
>>> gatech.lon = '-84.39733'
>>> gatech.lat = '33.775867'
>>> gatech.elevation = 320
>>> gatech.date = '2017/6/19 16:22:56' #Changing the time here does nothing.
>>> v = ephemeral.Sun(gatech)
>>> print(v.mag)
The magnitude of a celestial object does not change as it dips below the horizon and then later rises again. If you are asked the magnitude of Sirius, for example, you can answer that it is -1.46 without stopping to check whether it is above or below your particular horizon at the moment. It is the same with the Sun: “what is its magnitude” is a question about its properties as visible to whomever can see it, and does not vary with any particular observer.

Fast great circle for multiple points - Python geopy

Is it possible to speed up the great_circle(pos1, pos2).miles from geopy if using it for multiple thousand points?
I want to create something like a distance matrix and at the moment my machine needs 5 seconds for 250,000 calculations.
Actually pos1 is always the same if it helps.
Another "restriction" in my case is that I only want all points pos2 which have a distance less than a constant x.
(The exact distance doesn't matter in my case)
Is there a fast method? Do I need to use a faster function than great_circle which is less accurate or is it possible to speed it up without losing accuracy?
Update
In my case the question is whether a point is inside a circle.
Therefore it is easily possible to first get whether a point is inside a square.
start = geopy.Point(mid_point_lat, mid_point_lon)
d = geopy.distance.VincentyDistance(miles=radius)
p_north_lat = d.destination(point=start, bearing=0).latitude
# check whether the given point lat is > p_north_lat
# and so on for east, south and west

Python - Cosine gradually reveals small-amp oscillations ("wobbles")

I have a problem that is equal parts trig and Python. I am plotting a cosine over time interval [0,t] whose frequency changes (slightly) according to another cosine function. So what I'd expect to see is a repeating pattern of higher-to-lower frequency that repeats over the duration of the window [0,t].
Instead what I'm seeing is that over time a low-freq motif emerges in the cosine plot and repeats over time, each time becoming lower and lower in freq until eventually the cosine doesn't even oscillate properly it just "wobbles", for lack of a better term.
I don't understand how this is emerging over the course of the window [0,t] because cosine is (obviously) periodic and the function modulating it is as well. So how can "new" behavior emerge?? The behavior should be identical across all periods of the modulatory cosine that tunes the freq of the base cosine, right?
As a note, I'm technically using a modified cosine, instead of cos(wt) I'm using e^(cos(wt)) [called von mises eq or something similar].
Minimum needed Code:
cos_plot = []
for wind,pos_theta in zip(window,pos_theta_vec): #window is vec of time increments
# for ref: DBFT(pos_theta) = (1/(2*np.pi))*np.cos(np.radians(pos_theta - base_pos))
f = float(baserate+DBFT(pos_theta)) # DBFT() returns a val [-0.15,0.15] periodically depending on val of pos_theta
cos_plot.append(np.exp(np.cos(f*2*np.pi*wind)))
plt.plot(cos_plot)
plt.show()
What you are observing could depend on "aliasing", i.e. the emergence of low-frequency figures because of sampling of an high frequency function with a step that is too big.
(picture taken from the linked Wikipedia page)
If the issue is NOT aliasing consider that any function shape between -1 and 1 can be obtained with cos(f(x)*x) by simply choosing f(x).
For, consider any function -1 <= g(x) <= 1 and set f(x) = arccos(g(x))/x.
To look for the problem try plotting your "frequency" and see if anything really strange is present in it. May be you've a bug in DBFT.
In the interest of posterity, in case anyone ever needs an answer to this question:
I wanted a cosine whose frequency was a time-varying function freq(t). My mistake was simply evaluating this function at each time t like this: Acos(2pifreq(t)t). Instead you need to integrate freq(t) from 0 to t at each time point: y = cos(2%piintegral(f(t)) + 2%pi*f0*t + phase). The term for this procedure is a frequency sweep or chirp (not identical terms, but similar if you need to google/SO answers).
Thanks to those who responded with help :)
SB

How to calculate correct longitude and constellation of planets using PyEphem

i tried to calculate sun lat and long using PyEphem what i dont understand is when i calculate suns longitude and constellation
>>> sun = ephem.Sun()
>>> sun.compute('2011/05/04')
>>> print ephem.Ecliptic(sun).lon
43:02:58.8
so 43:02:58.8 is 13.02 Taurus
but when i try to get the constellation
>>> print ephem.constellation(sun)
('Ari', 'Aries')
it says Aries what is wrong i don't understand please some one help
Good question!
There are two reasons that you are getting a different answer than you might expect.
First, the constellation boundaries currently used by astronomers were established using the position in which the ecliptic happened to lie in 1875. Since then the point of “zero longitude” on the ecliptic has continued to move as the earth's axis has precessed, so that the answers you get will be a few degrees off. To actually learn the longitude in 1875 coordinates, you have to ask like this:
import ephem
sun = ephem.Sun()
sun.compute('2011/05/04')
print "Today's coordinates:", ephem.Ecliptic(sun).lon
sun.compute('2011/05/04', epoch='1875')
print "In 1875 coordinates:", ephem.Ecliptic(sun).lon
When running this script I get the output:
Today's coordinates: 43:02:58.8
In 1875 coordinates: 41:18:14.1
So that removes one source of error from your result. Note that the PyEphem constellation() function converts coordinates to 1875 automatically before looking up a sky position in its table of constellation boundaries, if you provide a body as its argument that has an epoch that is different than 1875.
The other problem you are running into is that the official constellation boundaries mark the actual groups of stars in the sky that form the figures of the Ram (Taurus), the Scales (Libra), and so forth. And it happens that these figures do not even come close to each spanning exactly 30° across the ecliptic (as you may have expected, since you are subtracting 30° from the angle you get back?). If you print out the constellation at every degree along the ecliptic, you will (a) find that the constellations vary greatly in their width, and (b) you will find that 13, not 12, constellations cross the ecliptic since part of Ophiuchus lies along the 1875 ecliptic.
Here are some references that might be helpful:
http://en.wikipedia.org/wiki/Constellation#IAU_constellations
http://en.wikipedia.org/wiki/Precession
It's in Aries. Here's my computation using Beta Ari as the reference:
>>> sun = e.Sun()
>>> sun.compute('2011/05/04')
>>> e.Ecliptic(sun).lon
43:02:58.8
>>> beta_ari = e.readdb('Sheratan,f|S|A5,01:54:38.5|98.74,28:48:28.9|-110.41,2.65,2000,0')
>>> beta_ari.compute('2011/05/04')
>>> e.Ecliptic(beta_ari).lon
36:53:55.2
>>> e.Ecliptic(sun).lon - e.Ecliptic(beta_ari).lon
0.10735523133236013
>>> e.degrees(e.Ecliptic(sun).lon - e.Ecliptic(beta_ari).lon)
6:09:03.6
Sun on the Ecliptic line is 6:09 degree away from Beta Ari, so it's still in Aries.
I also double checked this result with other programs using that date, and the results are the same.

Categories