Lunar Librations and Subsolar Point in Matlab - matlab

So I have been trying to write a program to generate the latitude and longitude of the lunar subsolar point in Matlab.
I have the ephemeris data from aero toolbox, but I can't seem to get values that make sense.
The method I'm currently trying (without success) is...
Generate a juliandate for a specific time
Find the position of the sun relative to the moon from the ephemeris data for the specified date
Find the (φ, θ, ψ) lunar attitude from the ephemeris data
Create a rotational matrix from the lunar attitude values
Transpose the matrix to get the inverse rotation (to convert the vector from the ICRF frame to the moon's coordinate system)
Apply that rotation to the direction of the sun vector
Convert to spherical coordinates (longitude, latitude)
mission_time = juliandate(2022, 1, 1);
sun_pos = planetEphemeris(mission_time, 'Moon', 'Sun');
moon_rot = moonLibration(mission_time);
rotm = eul2rotm(moon_rot);
rotm = transpose(rotm);
sun_vec = sun_pos / norm(sun_pos);
sun_vec = sun_vec * rotm;
[ss_long, ss_lat] = cart2sph(sun_vec(1), sun_vec(2), sun_vec(3))
fprintf("Subsolar Lat: %2.2f°\tSubsolar Long: %2.2f°\n", rad2deg(ss_long), rad2deg(ss_lat))
The subsolar latitude should be like ±1.57° but this calculation goes all over the place. What am I missing?

Related

Problem to converting km to geographical coordinates

I have some questions about converting kilometers to geographical coordinates.
As you can see figure attached, the left one is trajectory interms of kilometers. I entered geographical coordinates and calculate trajectory as kilometers. For my calculations I need to convert degrees to kilometers. I used this code:
LAT=[41.030503; 41.048334; 41.071551 ]*pi/180;
LON=[28.999000; 29.037494; 29.052138 ]*pi/180;
for i=1:length(LAT)-1
psi_coordinate(i,1) = atan2( sin (LON(i+1)-LON(i)) * cos (LAT(i+1)) , cos (LAT(i)) *sin (LAT(i+1)) - sin (LAT(i)) * cos (LAT(i+1)) * cos (LON(i+1)-LON(i)) );
a=(sin((LAT(i+1)-LAT(i))/2))^2+cos(LAT(i))*cos(LAT(i+1))*(sin((LON(i+1)-LON(i))/2))^2;
c=2*atan2(sqrt(a),sqrt(1-a));
d(i,1)=R*c;
pos_x(i+1,1)=pos_x(i,1)+d(i,1)*cos(psi_coordinate(i,1)); %convert to kilometer
pos_y(i+1,1)=pos_y(i,1)+d(i,1)*sin(psi_coordinate(i,1)); %convert to kilometer
distance_h(i,1)=sqrt(((LAT(i+1)-LAT(i))^2)+((LON(i+1)-LON(i))^2))*1000 ; %kilometer
end
distance=sum(d);
pos_x=pos_x*1000; %convert to meter
pos_y=pos_y*1000; %convert to meter
pos_x and pos_y are ploted as circle at the figure (left).
After I calculate ship trajectory, I need to convert them degrees again.
If I use "km2deg" command I obtained my coordinates as given figure (right) and the code that I used is:
ydeg=LON(1)*180/pi+km2deg(y/1000);
xdeg=LAT(1)*180/pi+km2deg(x/1000);
But as you can see the blue line (ship trajectory) is not close to the desired path as figure given left. Normally it should be the same trend for these two plot. Because all I do is here is just converting the units. I guess I have some troubles to used "km2deg" command.
Do you have any suggestions to convert my points correctly from km to deg?

Finding the tangent on a given point of a polyline

I have a list of X,Y coordinates that represents a road. For every 5 meters, I need to calculate the angle of the tangent on this road, as I have tried to illustrate in the image.
My problem is that this road is not represented by a mathematical function that I can simply derive, it is represented by a list of coordinates (UTM33N).
In my other similar projects we use ArcGIS/ESRI libraries to perform geographical functions such as this, but in this project I need to be independent of any software that require the end user to have a license, so I need to do the calculations myself (or find a free/open source library that can do it).
I am using a cubic spline function to make the line rounded between the coordinates, since all tangents on a line segment would just be parallell to the segment otherwise.
But now I am stuck. I am considering simply calculating the angle between any three points on the line (given enough points), and using this to find the tangents, but that doesn't sound like a good method. Any suggestions?
In the end, I concluded that the points were plentiful enough to give an accurate angle using simple geometry:
//Calculate delta values
var dx = next.X - curr.X;
var dy = next.Y - curr.Y;
var dz = next.Z - curr.Z;
//Calculate horizontal and 3D length of this segment.
var hLength = Math.Sqrt(dx * dx + dy * dy);
var length = Math.Sqrt(hLength * hLength + dz * dz);
//Calculate horizontal and vertical angles.
hAngle = Math.Atan(dy/dx);
vAngle = Math.Atan(dz/hLength);

Ecliptic coordinates of an Observer in PyEphem

I would like to have the ecliptic coordinates of a point on Earth. I can set up an observer using Pyephem:
station = ephem.Observer()
station.lon = '14:18:40.7'
station.lat = '48:19:14.0'
station.pressure = 0
station.epoch = ephem.J2000
station.elevation = 100.0
Then setup a date
station.date = ephem.date(datetime.utcnow())
But I don't know how to get this point coordinates in the Ecliptic system. If I try the Ecliptic function on the station Object it fails. Is there a way to do that in PyEphem?
If by “the ecliptic coordinates of a point on Earth” you mean “the ecliptic latitude and longitude which are overhead for a point on Earth,” then you might be able to generate a correct position by asking for the RA and declination of the point in the sky directly overhead for the location — where “directly overhead” is expressed astronomically as “at 90° altitude in the sky.” You would follow your code above with something like:
ra, dec = station.radec_of('0', '90')
ec = ephem.Ecliptic(ra, dec)
print 'Ecliptic latitude:', ec.lat
print 'Ecliptic longitude:', ec.lon
Try this technique out and see whether it returns a value anything like what you are expecting!

How to interpolate ECEF coordinates on an WGS84 ellipsoid

Is there a direct method (not involving converting the coordinates to lat/lon) to interpolate between 2 ECEF coordinates (xyz) in order for the interpolated point to be located on the WGS84 ellispoid. The original 2 points are computed from geodetic coordinates.
Interpolating on a sphere seem obvious but I can't seem to derive a solution for the ellipsoid.
Thank you in advance.
Let assume you got 2 points p0(x,y,z) and p1(x,y,z) and want to interpolate some p(t) where t=<0.0,1.0> between the two.
you can:
rescale your ellipsoid to sphere
simply like this:
const double mz=6378137.00000/6356752.31414; // [m] equatoreal/polar radius of Earth
p0.z*=mz;
p1.z*=mz;
now you got Cartesian coordinates refering to spherical Earth model.
interpolate
simple linear interpolation would do
p(t) = p0+(p1-p0)*t
but of coarse you also need to normalize to earth curvature so:
r0 = |p0|
r1 = |p1|
p(t) = p0+(p1-p0)*t
r(t) = r0+(r1-r0)*t
p(t)*=r/|p(t)|
where |p0| means length of vector p0.
rescale back to ellipsoid
by dividing with the same value
p(t).z/=mz
This is simple and cheap but the interpolated path will not have linear time scale.
Here C++ example:
void XYZ_interpolate(double *pt,double *p0,double *p1,double t)
{
const double mz=6378137.00000/6356752.31414;
const double _mz=6356752.31414/6378137.00000;
double p[3],r,r0,r1;
// compute spherical radiuses of input points
r0=sqrt((p0[0]*p0[0])+(p0[1]*p0[1])+(p0[2]*p0[2]*mz*mz));
r1=sqrt((p1[0]*p1[0])+(p1[1]*p1[1])+(p1[2]*p1[2]*mz*mz));
// linear interpolation
r = r0 +(r1 -r0 )*t;
p[0]= p0[0]+(p1[0]-p0[0])*t;
p[1]= p0[1]+(p1[1]-p0[1])*t;
p[2]=(p0[2]+(p1[2]-p0[2])*t)*mz;
// correct radius and rescale back
r/=sqrt((p[0]*p[0])+(p[1]*p[1])+(p[2]*p[2]));
pt[0]=p[0]*r;
pt[1]=p[1]*r;
pt[2]=p[2]*r*_mz;
}
And preview:
Yellow squares are the used p0,p1 Cartesian coordinates, the White curve is the interpolated path where t=<0.0,1.0> ...

Converting 3D point clouds to range image

I have many 3D point clouds gathered by velodyne sensor. eg(x, y, z) in meter.
I'd like to convert 3D point clouds to range image.
Firstly, I've got transformtation from Catesian to spherical coordinate.
r = sqrt(x*x + y*y + z*z)
azimuth angle = atan2(x, z)
elevation angle = asin(y/r)
Now. How can I convert 3D point to Range image using these transformation in matlab?
Whole points are about 180,000 and I want 870*64 range image.
azimuth angle range(-180 ~ 180), elevation angle range(-15 ~ 15)
Divide up your azimuth and elevation into M and N ranges respectively. Now you have M*N "bins" (M = 870, N = 64).
Then (per bin) accumulate a histogram of points that project into that bin.
Finally, pick a representative value from each bin for the final range image. You could pick the average value (noisy, fast) or fit some distribution and then use that to pick the value (more precise, slow).
The pointcloud2image code available from Matlab File Exchange can help you to directly convert point cloud (in x,y,z format) to 2D raster image.