Computing Earth orbit position and rotations - language-agnostic

I want to compute the Earth position (relative to the sun) and axis rotations for a given date and time. It's ok to assume the Sun is stationary at the 0,0,0 coordinate. Very minor deflections, due to the Moons gravitational pull for example, can also be ignored. Anything accurate within a degree or so is good enough.
Are there any libraries/source/data out there that will help me accomplish this?

The aa-56 code, which can be downloaded from here, includes a solar ephemeris that will probably meet your needs. For high-precision work you'd want something more accurate like JPL's DE421, but there are some inconveniently large tables of coefficients involved, and it's probably extreme overkill if you're happy with 1 degree accuracy.
The Earth's rotation at a given time is given by the Greenwich sidereal time.
Jean Meeus' "Astronomical Algorithms" (a good reference to have for these sorts
of calculations!) gives a formula for theta0 (cumulative rotation angle in degrees)
in terms of the Julian date JD:
T = (JD - 2451545.0 ) / 36525
theta0 = 280.46061837 + 360.98564736629*(JD-2451545.0) +
0.000387933*T*T - T*T*T/38710000.0
theta0 = 0 degrees mod 360 represents the instant when the Greenwich meridian is aligned with right ascension 0:00 in celestial coordinates.

Yes. What you need is an Ephemeris package.
The JPL has an online Ephemeris service that will do the computations for you, so if you are web-capable you can hit that up.
I found a free Ephermeris package too, but it looks like it just hits the JPL site for you. However, there's a link there to download the JPL's database and have it work off of that. So if you want to work offline and don't mind updating your database from the JPL manually every now and then, that might be an option.

In Python, using the ephem library:
>>> import ephem
>>> sun = ephem.Sun()
>>> sun.compute(ephem.now())
>>> sun.hlong, sun.hlat, sun.earth_distance
(69:41:32.6, 0:00:00.2, 0.98602390289306641)
ephem doesn't provide a convenient representation of the Earth as a body, but sun.hlong and sun.hlat give the heliocentric longitude and latitude of the Earth. This could be better documented.
For Earth rotation, maybe you can say what value you're looking for here. (Normally we use the time of day, but I think it's generally clear how to get hold of that!)

Related

How can I find the shortest distance from a point to a path over the surface of the earth

I have a list of lat/long points which form a path on the surface of the earth.
I have another point on the surface of the earth and I want to find the shortest distance from that point to a point that falls on the path.
While I could approximate the surface of the earth as a plane, accuracy is important.
The distance between points on the path could be anywhere from 1-1000m. The distance to the point not on the path is from 1-50m. The maximum acceptable error is 0.1m.
Any method of calculating this is acceptable, whether assuming a plane, sphere, or the real shape of the earth as long as the error would not exceed 0.1m for any point on land.
This question is marked language agnostic to encourage answers from people not familiar with the language used. The implementation will be in Dart.
It sounds like you need to calculate the Great Circle Distance across the surface of the earth. A Great Circle calculation permits the calculation of distance along the earth's surface between two arbitrary latitudes and longitudes.
A trivial example of a Great Circle calculation would be to migrate along the Earth's surface along the line of equator (zero degrees latitude). Each degree of longitude of migration along that line (for instance from [0 deg N, 90 deg W] to [0 deg N to 91 deg W]) equates to 1/360th of 40,070km, or 111.306km. Moving between two latitudes and two longitudes requires transformation of coordinates and is outside the scope of this quick note.
Summary and equations found here:
https://en.wikipedia.org/wiki/Great-circle_distance
The accuracy you are seeking of 0.1m requires further refinement; using a sphere to approximate the shape of the Earth will limit the accuracy to perhaps 0.5% (see paragraph from Wikipedia, below). Put another way, a 0.5% error of two points 1000 km apart would be 5000 m.
A more formal and precise calculation will use the true shape of the earth, known as a geoid. This is determined by gravitational measurements and is updated from time to time by the geodesic community.
It is possible to determine one's absolute position on Earth to +/- 0.1m (or better) with advanced GPS surveying techniques, such as RTK or satellite correction services (e.g. Omnistar), but determining the path distance to that accuracy is not the same thing. A survey-quality receiver has corrections built into it for current geoids so that it can translate the lat/long/height calculation it makes using GPS signals to the current reference geoid used by the surveying / geodesic community.
You may not actually require 0.1m accuracy for your application; very few applications require 0.1m absolute accuracy over any distance except (for example) geographic determinations of movement in the Earth's surface. Relative accuracy is more important; e.g. measuring the same point at different times. It is more important to know how much a seismic fault moved relative to its position yesterday or last week, or whether a critical point on a pipeline has moved 2 cm to the north in the past year.
I hope this helps.
Cheers
GP
Per Wikipedia:
So long as a spherical Earth is assumed, any single formula for distance on the Earth is only guaranteed correct within 0.5% (though better accuracy is possible if the formula is only intended to apply to a limited area). [7]

How do I convert a geodetic location to an ECF position that works with the terrain model in Cesium

I'm trying to put a point at the top of Mount Everest in Cesium. My most likely candidate as of last night was the code I borrowed to do geodetic to ecef conversion (from PySatel.coord). Upon review this morning, it appears to be correct:
a = 6378.137
b = 6356.7523142
esq = 6.69437999014 * 0.001
e1sq = 6.73949674228 * 0.001
f = 1 / 298.257223563
def geodetic2ecef(lat, lon, alt):
"""Convert geodetic coordinates to ECEF.
Units are degrees and kilometers.
"""
lat, lon = radians(lat), radians(lon)
xi = sqrt(1 - esq * sin(lat))
x = (a / xi + alt) * cos(lat) * cos(lon)
y = (a / xi + alt) * cos(lat) * sin(lon)
z = (a / xi * (1 - esq) + alt) * sin(lat)
return x, y, z
I pulled the lat / lon / alt for the peak of Mt. Everest from Wikipedia. I multiplied the ECF coordinates provided by the above code by 1000(m/km) before positioning the object in my CZML. I get an ECF location of: [302995.41122130124, 5640733.98308375, 2981975.8695256836]. With the default terrain provider (described in the tutorial), this point is significantly higher than the peak of Mt. Everest.
Here's the relevant CZML snippet:
{"position":
{"cartesian": [302995.41122130124, 5640733.98308375, 2981975.8695256836]},
"id": "ellipsoid-1",
"ellipsoid":
{
"radii": {"cartesian": [3545.5375159540376,
164.44985193756034,
164.62702908803794]},
"material": {"solidColor": {"color": {"rgba": [0, 255, 0, 100]}}}
},
"orientation": {"unitQuaternion": [0.00014107125875577922,
-0.011462389405915903,
-0.010254110199791062,
-0.70702315200093502]}
}
There are several factors at work here.
First, the source data that Cesium uses for terrain may have a lower than expected height for the peak of Mount Everest. We use the CGIAR SRTM dataset, so this item in their FAQ is relevant:
Why do some mountain regions have peaks significantly lower than they should be?
As mentioned earlier, many original data voids are concentrated in mountainous areas and in snow-covered regions. Hence, many peaks in high-mountain areas are actually interpolated. Without using a high resolution co-variable for the interpolation, the interpolation fails to identify that the data void is actually a peak, and tends to “flatten” the peak, leading to underestimates in the true elevation for that region. This issue is largely resolved in Version 4.
They say that it is largely resolved in v4, the version Cesium uses, so hopefully this first factor is not the actual problem.
Second, our processing of the source terrain data for use with Cesium may flatten the peak a bit. This problem will be corrected soon, hopefully within the next couple of months.
Third, Wikipedia provides the height as an elevation above mean sea level (MSL). MSL is a complicated surface that is hard to work with mathematically, so your geodetic2ecef is not doing so. Instead, it, like Cesium, is assuming that the altitude is relative to the WGS84 ellipsoid, which is a much nicer surface to work with.
NGA has a web site that can be used to find the height of MSL above the WGS84 ellipsoid, also known as the geoid height:
http://earth-info.nga.mil/GandG/wgs84/gravitymod/egm96/intpt.html
It reports that for the peak of Mount Everest (27° 59′ 17″ N, 86° 55′ 31″ E), MSL is 28.73 meters below WGS84. If you subtract that number from the altitude of the peak reported on Wikipedia, you should get closer, at least.
This page has information on computing geoid heights programmatically:
http://earth-info.nga.mil/GandG/wgs84/gravitymod/egm96/egm96.html
I recommend interpolating over the 15-minute geoid height file instead of computing heights from coefficients.
A couple of other notes not directly related to the question:
Cesium has code to convert LLA (we call it Cartographic) to Cartesian. See Ellipsoid.cartographicToCartesian.
You can specify coordinates in CZML in cartographicDegrees or cartographicRadians instead of cartesian, and then Cesium will do the conversion for you automatically. You still have to adjust for the geoid when specifying the height, however. Also, don't forget that longitude is first.
Proj4js - a port of the famous proj4 library - might do the job for you.

Calculate distance between similar pixels - Euclidean distance - ArcGIS 10.1 - Erdas Imagine

I have an unsigned 1-bit thematic forest cover raster (.img). 1 = forest and 0 = not forest. I want to calculate the distance between forest patches. It appears that the Euclidean Distance tool in ArcGIS does this but I get an output with all 0s.
Has anyone had experience with this before? Am I doing something incorrectly? Will I have to write a script to take care of it?
I can use either ArcGIS or Erdas Imagine. Whichever is easiest.
Thanks
It should work with a raster with values 0 and 1. Export your .img to .tiff with 8 bit unsigned and try it again.

How to calculate where each sensor is when I have only few variables

Suppose I have 3 sensors: sensor1, sensor2 and sensor3.
The only variables I know are:
Distance from sensor1 to origin is 36.05
Distance from sensor2 to origin is 62.00
Distance from sensor3 to origin is 63.19
Distance from sensor1 to sensor2 is 61.03
Distance from sensor1 to sensor3 is 90.07
Distance from sensor2 to sensor3 is 59.50
This is how it would look like if you had the positions:
How can I calculate the position of every point using only those variables?
This is not homework, just curiosity.
You cannot find the position of the points exactly, as any rotation around the origin, as well as symmetry still give the same distances.
Do you want a way to find all the possible results?
Finding the points is pretty straightforward, but do you need the method to be robust on noise?
This process is called trilateration. As others have noted, finding absolute, unambiguous positions for the sensors is not possible without more information - you'll need the positions of three non-coincident, non-colinear sensors in 2D, 4 non-coincident, non-coplanar sensors in 3D, to resolve all rotation/reflection ambiguities.
There's been an enormous amount of research into this problem in the field of wireless sensor network localisation - dealing with incomplete, noisy range measurements, unreliable communication and highly constrained resources make it interesting.
This might be an apt approach - the basic idea is to build up a system of located nodes piecewise - start with a seed formation of 3 or 4 nodes with well-defined relative locations and add nodes one by one as their locations become unambiguously computable relative to already-located nodes.
The anchor nodes with known locations can be used as the seed for system growth if possible, or used to compute a corrective transform after all nodes have been located.
The problem as posed is impossible without more information. If you add more information and some noise, then it is doable. See Finding a point that best fits the intersection of n spheres discusses how to solve that type of problem.
Look at these images.
And
You will see that the triangle can rotate freely (so no "fixed" position exists), and also the third intersensor distance is not needed in the general case, as it is determined by the other two distances.

How do I convert coordinates to a Latitude & Longitude?

I am reverse engineering a transportation visualization app. I need to find out the latitude for the origin of their data feed. Specifically what XY 0,0 is. The only formulas I have found calculate distance between two points, or location of a bearing/distance.
They use the XY to display a map in a very legacy application. The XY is in FEET.
I have these coordinates:
47.70446615506108, -122.34469839507263: x=1268314, y=260622
47.774182540800616,-122.3412994737105: x=1269649, y=286031
47.60024792289405, -122.32767331735774: x=1271767, y=222532
47.57012494413499, -122.29129609983679: x=1280532, y=211374
I need to find out what the latitude and longitude of x=0, y=0 is and what the formula would be to find this out.
They have two data feeds, one is more current than the other. The feed with the most current data does NOT include latitude, longitude, but only XY. I am trying to extrapolate based on their less current, yet more informative (includes lat, lon) data feed what 0,0 is so I can simply convert their (more current) data feed's XY coordinates to latitude and longitude.
If you look at the first 2 lines of data, and subtract the latitude
47.7044 - 47.7741 = -0.06972 degrees
There are 60 nautical miles per degree of latitude, and 6076 feet per nautical mile.
-.06972 * 60 * 6076 = 25,415 ft
Subtracting the two 'Y' values:
260662 - 286031 = 25,409 ft
So indeed that seems to prove the X and Y values are in feet.
If you take any of the Y values, and convert back to degrees, for example
260622 ft / ( 6076 ft/nm ) / ( 60 nm/degree ) = .71
286031 ft / 6076 / 60 = .78
So subtracting those values from the latitudes of (47.70 and 47.77) gives you very close to exactly 47 degrees, which should be your y=0 point.
For longitude, a degree is 60 nautical miles at the equator and 0 miles at the poles. So the number of miles per degree has to be multiplied by the cosine of the latitude, so approx cos(47 degrees), or .68. So instead of 6076 nm per degree, it's about 4145 nm.
So for the X values,
1268314 ft / ( 4145 ft/nm ) / ( 60 nm/degree ) = 5.10 degrees
1269649 ft / 4145 / 60 = 5.10 degrees
These X numbers increase as the latitude increases (less negative), so I believe you should add 5.1 degrees, which means the X base point is about
-122.3 + 5.1 = 117.2 West longitude for your x=0 point.
This is roughly the position of Spokane WA.
So given X=1280532, Y=211374
Lat = 47 + ( 211374 / 6096 / 60 ) = 47.58
Lon = -117.2 - ( 1280532 / ( 6096 * cos(47.58)) / 60 ) = -122.35
Which is roughly equivalent to the given data 47.57 and -122.29
The variance may be due to different projections - the X,Y system may be a "flattened" projection as opposed to lat/long which apply to a spherical projection? So to be accurate you may yet need more advanced math or that open source library :)
This question may also be helpful, it contains code for calculating great circle distances:
Calculate distance between two latitude-longitude points? (Haversine formula)
There are many different coordinate systems. You need to find out the what the coordinate systems are for both the lat/lon's (e.g. WGS84 etc) and x/y's first (e.g. some sort of projected system probably).
Once you have that information there are several tools you can use to do conversions and manipulations. One example (of a free open source coding library) is proj4.
Ask them what coordinate system they're using! (or if you got the dataset from some database, look at the metadata for the dataset and it should tell you. Otherwise I'd be skeptical of its value)
Most likely this is one of the state plane coordinate systems. They're for localized areas of the earth (kind of like UTM), and are frequently used for surveying.
You can use CORPSCON (or other GIS programs; ExpertGPS will do this if you have the GIS Option Pack but it's not free. I forget whether GPSBabel does conversion) to convert between lat/long and any of the state plane coordinate systems. You'll also need to know which datum the coordinates are in. WGS84 and NAD83 are very close but NAD27 is different.
You've got good advice on coordinate systems already, so I'll just chime in with the library I've used with great success in the past.
Geotrans is approved for use by the US Department of Defence, so you can be sure that it is well tested. You can grab it from here:
http://earth-info.nga.mil/GandG/geotrans/index.html
That might not be the right link as that page talks about the application, not the library. I expect the library is in the Developers package. Licensing terms were very liberal from memory, but make sure you review the terms before using it commercially.
Edit:
An interesting discussion on Geotrans licensing can be found here:
http://www.mail-archive.com/debian-legal#lists.debian.org/msg39263.html
Over here, I said this:
In Java, I would use the OpenMap converter from a point's expression in UTM to one using Latitude and Longitude (assuming a WGS-84 ellipsoid which is most commonly used in GPS).
OpenMap is open source and I would post a link to their download page but they have a short license script in the way. So, to avoid being rude, I won't deep link. Instead, head to their homepage and click Downloads.
That should either solve your problem directly or at least point you towards a useful algorithm.
I've used Brenor Brophey's gPoint PHP class to do this on a couple of occasions. Solid results, GPL code, and easily deployed. Recommended.