mirror of
https://github.com/cosinekitty/astronomy.git
synced 2026-05-19 06:17:03 -04:00
add Arduino part 1
This commit is contained in:
268
demo/arduino/altazsearch/altazsearch.ino
Normal file
268
demo/arduino/altazsearch/altazsearch.ino
Normal file
@@ -0,0 +1,268 @@
|
||||
/*
|
||||
altazsearch.cpp - Don Cross - 2023-06-17
|
||||
|
||||
https://github.com/cosinekitty/astronomy/discussions/308
|
||||
|
||||
Problem: given a range of altitudes and azimuths that
|
||||
form a "window" on the sky, search for when the Moon
|
||||
enters/exits that window starting from a given search time.
|
||||
*/
|
||||
|
||||
#include <cmath>
|
||||
#include <cstdio>
|
||||
#include <string>
|
||||
#include <stdexcept>
|
||||
#include "astronomy.h"
|
||||
|
||||
|
||||
struct Event
|
||||
{
|
||||
astro_time_t time;
|
||||
double azimuth = NAN;
|
||||
double altitude = NAN;
|
||||
|
||||
Event()
|
||||
{
|
||||
time.tt = time.ut = time.eps = time.psi = time.st = NAN;
|
||||
}
|
||||
|
||||
void Print() const
|
||||
{
|
||||
char text[TIME_TEXT_BYTES];
|
||||
Astronomy_FormatTime(time, TIME_FORMAT_SECOND, text, sizeof(text));
|
||||
Serial.printf("%s az=%0.2lf alt=%0.2lf", text, azimuth, altitude);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
struct Solution
|
||||
{
|
||||
bool valid = false;
|
||||
Event start;
|
||||
Event finish;
|
||||
|
||||
void Print() const
|
||||
{
|
||||
if (valid)
|
||||
{
|
||||
Serial.printf("Start: ");
|
||||
start.Print();
|
||||
Serial.printf("; Finish: ");
|
||||
finish.Print();
|
||||
Serial.printf(".\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
Serial.printf("No solution.\n");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
void Verify(astro_status_t status, const char *message)
|
||||
{
|
||||
if (status != ASTRO_SUCCESS)
|
||||
Serial.printf(message , ": error " , static_cast<int>(status));
|
||||
}
|
||||
|
||||
|
||||
class SearchProblem
|
||||
{
|
||||
private:
|
||||
astro_body_t body;
|
||||
astro_observer_t observer;
|
||||
double az1;
|
||||
double az2;
|
||||
double alt1;
|
||||
double alt2;
|
||||
astro_vector_t center;
|
||||
|
||||
astro_horizon_t Position(astro_time_t time) const
|
||||
{
|
||||
// Get topocentric equatorial coordinates of body, using the Earth's equator of date.
|
||||
astro_equatorial_t equ = Astronomy_Equator(body, &time, observer, EQUATOR_OF_DATE, ABERRATION);
|
||||
Verify(equ.status, "Equator");
|
||||
|
||||
// Convert to observer's horizontal coordinates, correcting for atmospheric refraction.
|
||||
return Astronomy_Horizon(&time, observer, equ.ra, equ.dec, REFRACTION_NORMAL);
|
||||
}
|
||||
|
||||
double AngularDistance(astro_time_t time) const
|
||||
{
|
||||
astro_horizon_t hor = Position(time);
|
||||
|
||||
// Translate angular horizontal coordinates to a vector.
|
||||
// Do NOT remove the refraction from the vector (REFRACTION_NONE).
|
||||
astro_spherical_t sphere;
|
||||
sphere.status = ASTRO_SUCCESS;
|
||||
sphere.dist = 1.0;
|
||||
sphere.lat = hor.altitude;
|
||||
sphere.lon = hor.azimuth;
|
||||
astro_vector_t vec = Astronomy_VectorFromHorizon(sphere, time, REFRACTION_NONE);
|
||||
Verify(vec.status, "VectorFromHorizon");
|
||||
|
||||
// Calculate the angle in degrees between the body and the center of the window.
|
||||
astro_angle_result_t result = Astronomy_AngleBetween(center, vec);
|
||||
Verify(result.status, "AngleBetween");
|
||||
|
||||
return result.angle;
|
||||
}
|
||||
|
||||
static astro_func_result_t DistanceSlopeCallback(void *context, astro_time_t time)
|
||||
{
|
||||
const SearchProblem& p = *static_cast<const SearchProblem *>(context);
|
||||
astro_func_result_t result;
|
||||
result.value = p.DistanceSlope(time);
|
||||
result.status = ASTRO_SUCCESS;
|
||||
return result;
|
||||
}
|
||||
|
||||
double DistanceSlope(astro_time_t time) const
|
||||
{
|
||||
const double dt = 0.1 / 86400.0;
|
||||
astro_time_t t1 = Astronomy_AddDays(time, -dt);
|
||||
astro_time_t t2 = Astronomy_AddDays(time, +dt);
|
||||
double a1 = AngularDistance(t1);
|
||||
double a2 = AngularDistance(t2);
|
||||
return (a2 - a1) / (2 * dt);
|
||||
}
|
||||
|
||||
bool IsInsideWindow(astro_time_t time) const
|
||||
{
|
||||
astro_horizon_t hor = Position(time);
|
||||
bool insideAzimuthLimits;
|
||||
if (az1 <= az2)
|
||||
insideAzimuthLimits = (az1 <= hor.azimuth && hor.azimuth <= az2);
|
||||
else
|
||||
insideAzimuthLimits = (az1 <= hor.azimuth || hor.azimuth <= az2);
|
||||
|
||||
return insideAzimuthLimits && alt1 <= hor.altitude && hor.altitude <= alt2;
|
||||
}
|
||||
|
||||
Solution FindBracket(astro_time_t closestTime) const
|
||||
{
|
||||
Solution solution;
|
||||
|
||||
// If the closestTime is inside the window, we can find a bracket.
|
||||
// Otherwise, there is no bracket here.
|
||||
if (IsInsideWindow(closestTime))
|
||||
{
|
||||
const double dt = 10.0 / (24.0 * 60.0); // 10 minutes, converted to days
|
||||
|
||||
// Look backwards until we find a time before entering the window.
|
||||
// Do a binary search to find the moment when we enter the window.
|
||||
solution.start = FindTransition(closestTime, -dt);
|
||||
|
||||
// Look forward until we find a time after leaving the window.
|
||||
// Do a binary search to find the moment we leave the window.
|
||||
solution.finish = FindTransition(closestTime, +dt);
|
||||
|
||||
solution.valid = true;
|
||||
}
|
||||
|
||||
return solution;
|
||||
}
|
||||
|
||||
Event FindTransition(astro_time_t closestTime, double dt) const
|
||||
{
|
||||
// Find a bracket [t1, t2] that straddles being inside/outside the window.
|
||||
astro_time_t t1 = closestTime;
|
||||
astro_time_t t2 = Astronomy_AddDays(closestTime, dt);
|
||||
while (IsInsideWindow(t2))
|
||||
{
|
||||
t1 = t2;
|
||||
t2 = Astronomy_AddDays(t2, dt);
|
||||
}
|
||||
|
||||
// Do a binary search to find the moment of transition, within tolerance.
|
||||
const double tolerance = 0.1 / (3600.0 * 24.0); // one tenth of a second, expressed in days
|
||||
astro_time_t tm = Astronomy_TimeFromDays((t1.ut + t2.ut) / 2);
|
||||
while (fabs(t2.ut - t1.ut) > tolerance)
|
||||
{
|
||||
if (IsInsideWindow(tm))
|
||||
t1 = tm;
|
||||
else
|
||||
t2 = tm;
|
||||
tm = Astronomy_TimeFromDays((t1.ut + t2.ut) / 2);
|
||||
}
|
||||
|
||||
astro_horizon_t hor = Position(tm);
|
||||
|
||||
Event event;
|
||||
event.time = tm;
|
||||
event.altitude = hor.altitude;
|
||||
event.azimuth = hor.azimuth;
|
||||
return event;
|
||||
}
|
||||
|
||||
public:
|
||||
SearchProblem(astro_body_t _body, astro_observer_t _observer, double _az1, double _az2, double _alt1, double _alt2)
|
||||
: body(_body)
|
||||
, observer(_observer)
|
||||
, az1(_az1)
|
||||
, az2(_az2)
|
||||
, alt1(_alt1)
|
||||
, alt2(_alt2)
|
||||
{
|
||||
astro_time_t dummyTime = Astronomy_TimeFromDays(0.0);
|
||||
astro_spherical_t sphere;
|
||||
sphere.status = ASTRO_SUCCESS;
|
||||
sphere.dist = 1.0;
|
||||
sphere.lat = (_alt1 + _alt2) / 2;
|
||||
sphere.lon = (_az1 + _az2) / 2;
|
||||
center = Astronomy_VectorFromHorizon(sphere, dummyTime, REFRACTION_NONE);
|
||||
}
|
||||
|
||||
Solution FindNext(astro_time_t startTime, double limitDays)
|
||||
{
|
||||
astro_time_t stopTime = Astronomy_AddDays(startTime, limitDays);
|
||||
const double stepDays = 1.0 / 24.0; // one hour
|
||||
astro_time_t t1 = startTime;
|
||||
double m1 = DistanceSlope(t1);
|
||||
|
||||
while (t1.ut < stopTime.ut)
|
||||
{
|
||||
astro_time_t t2 = Astronomy_AddDays(t1, stepDays);
|
||||
double m2 = DistanceSlope(t2);
|
||||
if (m1 <= 0.0 && m2 >= 0.0)
|
||||
{
|
||||
astro_search_result_t result = Astronomy_Search(DistanceSlopeCallback, this, t1, t2, 0.1);
|
||||
if (result.status == ASTRO_SUCCESS)
|
||||
{
|
||||
// We found a time bracket [t1, t2] where the body passes closest to
|
||||
// the center of the target window. Now search nearby for when the
|
||||
// body enters and exits the window.
|
||||
Solution solution = FindBracket(result.time);
|
||||
if (solution.valid)
|
||||
return solution;
|
||||
}
|
||||
}
|
||||
t1 = t2;
|
||||
m1 = m2;
|
||||
}
|
||||
|
||||
// We could not find a solution.
|
||||
// Return a default-constructed Solution, which indicates failure.
|
||||
return Solution();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(9600);
|
||||
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
// 2023-06-17T12:00:00Z Moon AZ = 74.03 ALT = 27.44
|
||||
// 2023-06-17T13:00:00Z Moon AZ = 79.22 ALT = 39.74
|
||||
astro_observer_t observer = Astronomy_MakeObserver(30.0, -80.0, 0.0);
|
||||
SearchProblem problem(BODY_MOON, observer, 74.0, 78.0, 25.0, 40.0);
|
||||
astro_time_t startTime = Astronomy_MakeTime(2023, 6, 17, 0, 0, 0.0);
|
||||
Solution solution = problem.FindNext(startTime, 2.0);
|
||||
solution.Print();
|
||||
|
||||
}
|
||||
|
||||
154
demo/arduino/camera/camera.ino
Normal file
154
demo/arduino/camera/camera.ino
Normal file
@@ -0,0 +1,154 @@
|
||||
/*
|
||||
camera.c - Don Cross - 2021-03-21
|
||||
|
||||
Example C program for Astronomy Engine:
|
||||
https://github.com/cosinekitty/astronomy
|
||||
|
||||
Suppose you want to photograph the Moon,
|
||||
and you want to know what it will look like in the photo.
|
||||
Given a location on the Earth, and a date/time,
|
||||
this program calculates the orientation of the sunlit
|
||||
side of the Moon with respect to the top of your
|
||||
photo image. It assumes the camera faces directly
|
||||
toward the Moon's azimuth and tilts upward to its
|
||||
altitude angle above the horizon.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
#include "astro_demo_common.h"
|
||||
|
||||
#define FAIL(...) do{fprintf(stderr, __VA_ARGS__); error = 1; goto fail;}while(0)
|
||||
|
||||
static int CameraImage(astro_observer_t observer, astro_time_t time);
|
||||
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(9600);
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
int error;
|
||||
astro_observer_t observer;
|
||||
astro_time_t time;
|
||||
|
||||
observer.height = 22.2;
|
||||
observer.latitude = 33.33;
|
||||
observer.longitude = 88.8;
|
||||
// time = "1988-02-02T12:55:33Z";
|
||||
// const char *argvs[] = {"22.2","11.8","1988-02-02T12:55:33Z"};
|
||||
const char *argvs[] = {"22.2","33.8","2023-10-07T00:38:57+03:30"};
|
||||
int argcs = 3;
|
||||
error = ParseArgs(argcs, argvs, &observer, &time);
|
||||
if (error)
|
||||
Serial.println("error.......");
|
||||
CameraImage(observer, time);
|
||||
}
|
||||
|
||||
|
||||
static int CameraImage(astro_observer_t observer, astro_time_t time)
|
||||
{
|
||||
int error;
|
||||
astro_equatorial_t moon_equ;
|
||||
astro_equatorial_t sun_equ;
|
||||
astro_horizon_t moon_hor;
|
||||
astro_rotation_t rot;
|
||||
astro_vector_t vec;
|
||||
astro_illum_t illum;
|
||||
astro_angle_result_t angle;
|
||||
double radius;
|
||||
double tilt;
|
||||
const double tolerance = 1.0e-15;
|
||||
|
||||
/* Calculate the topocentric equatorial coordinates of date for the Moon. */
|
||||
/* Assume aberration does not matter because the Moon is so close and has such a small relative velocity. */
|
||||
moon_equ = Astronomy_Equator(BODY_MOON, &time, observer, EQUATOR_OF_DATE, NO_ABERRATION);
|
||||
if (moon_equ.status != ASTRO_SUCCESS)
|
||||
FAIL("Error %d calculating Moon position.\n", moon_equ.status);
|
||||
|
||||
/* Also calculate the Sun's topocentric position in the same coordinate system. */
|
||||
sun_equ = Astronomy_Equator(BODY_SUN, &time, observer, EQUATOR_OF_DATE, NO_ABERRATION);
|
||||
if (sun_equ.status != ASTRO_SUCCESS)
|
||||
FAIL("Error %d calculating Sun position.\n", sun_equ.status);
|
||||
|
||||
/* Get the Moon's horizontal coordinates, so we know how much to pivot azimuth and altitude. */
|
||||
moon_hor = Astronomy_Horizon(&time, observer, moon_equ.ra, moon_equ.dec, REFRACTION_NONE);
|
||||
Serial.printf("Moon horizontal position: azimuth = %0.3lf, altitude = %0.3lf\n", moon_hor.azimuth, moon_hor.altitude);
|
||||
|
||||
/* Get the rotation matrix that converts equatorial to horizontal coordintes for this place and time. */
|
||||
rot = Astronomy_Rotation_EQD_HOR(&time, observer);
|
||||
|
||||
/*
|
||||
Modify the rotation matrix in two steps:
|
||||
First, rotate the orientation so we are facing the Moon's azimuth.
|
||||
We do this by pivoting around the zenith axis.
|
||||
Horizontal axes are: 0 = north, 1 = west, 2 = zenith.
|
||||
Tricky: because the pivot angle increases counterclockwise, and azimuth
|
||||
increases clockwise, we undo the azimuth by adding the positive value.
|
||||
*/
|
||||
rot = Astronomy_Pivot(rot, 2, moon_hor.azimuth);
|
||||
if (rot.status != ASTRO_SUCCESS)
|
||||
FAIL("Error %d in Astronomy_Pivot(azimuth)\n", rot.status);
|
||||
|
||||
/*
|
||||
Second, pivot around the leftward axis to bring the Moon to the camera's altitude level.
|
||||
From the point of view of the leftward axis, looking toward the camera,
|
||||
adding the angle is the correct sense for subtracting the altitude.
|
||||
*/
|
||||
rot = Astronomy_Pivot(rot, 1, moon_hor.altitude);
|
||||
if (rot.status != ASTRO_SUCCESS)
|
||||
FAIL("Error %d in Astronomy_Pivot(altitude)\n", rot.status);
|
||||
|
||||
/* As a sanity check, apply this rotation to the Moon's equatorial (EQD) coordinates and verify x=0, y=0. */
|
||||
vec = Astronomy_RotateVector(rot, moon_equ.vec);
|
||||
if (vec.status != ASTRO_SUCCESS)
|
||||
FAIL("Error %d in Astronomy_RotateVector(moon)\n", vec.status);
|
||||
|
||||
/* Convert to unit vector. */
|
||||
radius = Astronomy_VectorLength(vec);
|
||||
vec.x /= radius;
|
||||
vec.y /= radius;
|
||||
vec.z /= radius;
|
||||
Serial.printf("Moon check: x = %0.6lf, y = %0.6lf, z = %0.6lf\n", vec.x, fabs(vec.y), fabs(vec.z));
|
||||
if (!isfinite(vec.x) || fabs(vec.x - 1.0) > tolerance)
|
||||
FAIL("Excessive error in moon check (x)\n");
|
||||
|
||||
if (!isfinite(vec.y) || fabs(vec.y) > tolerance)
|
||||
FAIL("Excessive error in moon check (y)\n");
|
||||
|
||||
if (!isfinite(vec.z) || fabs(vec.z) > tolerance)
|
||||
FAIL("Excessive error in moon check (z)\n");
|
||||
|
||||
/* Apply the same rotation to the Sun's equatorial vector. */
|
||||
/* The x- and y-coordinates now tell us which side appears sunlit in the camera! */
|
||||
|
||||
vec = Astronomy_RotateVector(rot, sun_equ.vec);
|
||||
if (vec.status != ASTRO_SUCCESS)
|
||||
FAIL("Error %d in Astronomy_RotateVector(sun)\n", vec.status);
|
||||
|
||||
/* Don't bother normalizing the Sun vector, because in AU it will be close to unit anyway. */
|
||||
Serial.printf("Sun vector: x = %0.6lf, y = %0.6lf, z = %0.6lf\n", vec.x, vec.y, vec.z);
|
||||
|
||||
/* Calculate the tilt angle of the sunlit side, as seen by the camera. */
|
||||
/* The x-axis is now pointing directly at the object, z is up in the camera image, y is to the left. */
|
||||
tilt = RAD2DEG * atan2(vec.y, vec.z);
|
||||
Serial.printf("Tilt angle of sunlit side of the Moon = %0.3lf degrees counterclockwise from up.\n", tilt);
|
||||
|
||||
illum = Astronomy_Illumination(BODY_MOON, time);
|
||||
if (illum.status != ASTRO_SUCCESS)
|
||||
FAIL("Error %d trying to calculate Moon illumination.\n", illum.status);
|
||||
|
||||
Serial.printf("Moon magnitude = %0.2lf, phase angle = %0.2lf degrees.\n", illum.mag, illum.phase_angle);
|
||||
|
||||
angle = Astronomy_AngleFromSun(BODY_MOON, time);
|
||||
if (angle.status != ASTRO_SUCCESS)
|
||||
FAIL("Error %d trying to calculate angle between Moon and Sun\n", angle.status);
|
||||
|
||||
Serial.printf("Angle between Moon and Sun as seen from Earth = %0.2lf degrees.\n", angle.angle);
|
||||
|
||||
error = 0;
|
||||
fail:
|
||||
return error;
|
||||
}
|
||||
80
demo/arduino/culminate/culminate.ino
Normal file
80
demo/arduino/culminate/culminate.ino
Normal file
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
culminate.c - by Don Cross - 2019-06-18
|
||||
|
||||
Example C program for Astronomy Engine:
|
||||
https://github.com/cosinekitty/astronomy
|
||||
|
||||
This example program shows how to calculate the time
|
||||
the Sun, Moon, and planets will next reach their highest point in the sky
|
||||
as seen by an observer at a given location on the Earth.
|
||||
This is called culmination, and is found by finding when
|
||||
each body's "hour angle" is 0.
|
||||
|
||||
Having an hour angle of 0 is another way of saying that the body is
|
||||
crossing the meridian, the imaginary semicircle in the sky that passes
|
||||
from due north on the horizon, through the zenith (straight up),
|
||||
toward due south on the horizon. At this moment the body appears to
|
||||
have an azimuth of either 180 degrees (due south) or 0 (due north).
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "astro_demo_common.h"
|
||||
|
||||
int PrintEvent(const char *name, astro_hour_angle_t evt)
|
||||
{
|
||||
Serial.printf("%-8s : ", name);
|
||||
if (evt.status == ASTRO_SUCCESS)
|
||||
{
|
||||
PrintTime(evt.time);
|
||||
Serial.printf(" altitude=%6.2lf azimuth=%6.2lf\n", evt.hor.altitude, evt.hor.azimuth);
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
Serial.printf("ERROR %d\n", evt.status);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(9600);
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
static const astro_body_t bodies[] =
|
||||
{
|
||||
BODY_SUN, BODY_MOON, BODY_MERCURY, BODY_VENUS, BODY_MARS,
|
||||
BODY_JUPITER, BODY_SATURN, BODY_URANUS, BODY_NEPTUNE, BODY_PLUTO
|
||||
};
|
||||
static const int nbodies = sizeof(bodies) / sizeof(bodies[0]);
|
||||
|
||||
astro_observer_t observer;
|
||||
astro_time_t time;
|
||||
astro_hour_angle_t evt;
|
||||
int i;
|
||||
|
||||
// if (ParseArgs(argc, argv, &observer, &time))
|
||||
// return 1;
|
||||
// const char *argvs[] = {"22.2","11.8","1988-02-02T12:55:33Z"};
|
||||
const char *argvs[] = {"22.2","33.8","2023-10-07T00:38:57+03:30"};
|
||||
int argcs = 3;
|
||||
int error;
|
||||
error = ParseArgs(argcs, argvs, &observer, &time);
|
||||
if (error)
|
||||
Serial.println("error.......");
|
||||
|
||||
Serial.printf("search : ");
|
||||
PrintTime(time);
|
||||
Serial.printf("\n");
|
||||
|
||||
for (i=0; i < nbodies; ++i)
|
||||
{
|
||||
evt = Astronomy_SearchHourAngleEx(bodies[i], observer, 0.0, time, +1);
|
||||
PrintEvent(Astronomy_BodyName(bodies[i]), evt);
|
||||
}
|
||||
delay(1000);
|
||||
// return 0;
|
||||
}
|
||||
124
demo/arduino/ecliptic_vector/astro_demo_common.cpp
Normal file
124
demo/arduino/ecliptic_vector/astro_demo_common.cpp
Normal file
@@ -0,0 +1,124 @@
|
||||
/*
|
||||
astro_demo_common.h - by Don Cross <cosinekitty@gmail.com>
|
||||
https://github.com/cosinekitty/astronomy
|
||||
|
||||
Helper code for Astronomy Engine demo programs.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
#include "Arduino.h"
|
||||
#include "astro_demo_common.h"
|
||||
|
||||
static const char ObserverVarName[] = "ASTRONOMY_ENGINE_OBSERVER";
|
||||
|
||||
static int IsValid(double x, double lo, double hi)
|
||||
{
|
||||
return isfinite(x) && (x >= lo) && (x <= hi);
|
||||
}
|
||||
|
||||
|
||||
int ParseArgs(int argc, const char *argv[], astro_observer_t *observer, astro_time_t *time)
|
||||
{
|
||||
int time_arg = 0;
|
||||
|
||||
observer->height = 0.0;
|
||||
|
||||
if ((argc==2 || argc==3) && !strcmp(argv[1], "-e"))
|
||||
{
|
||||
/* Use an environment variable to specify the observer's location. */
|
||||
const char *obstext = getenv(ObserverVarName);
|
||||
if (obstext == NULL)
|
||||
{
|
||||
fprintf(stderr, "ERROR: The -e option was specified but environment variable %s is not defined.\n", ObserverVarName);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (2 != sscanf(obstext, "%lf %lf", &observer->latitude, &observer->longitude) ||
|
||||
!IsValid(observer->latitude, -90.0, +90.0) ||
|
||||
!IsValid(observer->longitude, -180.0, +180.0))
|
||||
{
|
||||
fprintf(stderr, "ERROR: Invalid geographic coordinates in environment variable %s.\n", ObserverVarName);
|
||||
return 1;
|
||||
}
|
||||
|
||||
time_arg = 2;
|
||||
}
|
||||
else if (argc==3 || argc==4)
|
||||
{
|
||||
/* The observer's location must appear in the command line. */
|
||||
|
||||
if (1 != sscanf(argv[1], "%lf", &observer->latitude) ||
|
||||
!IsValid(observer->latitude, -90.0, +90.0))
|
||||
{
|
||||
fprintf(stderr, "ERROR: Invalid latitude '%s' on command line\n", argv[1]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (1 != sscanf(argv[2], "%lf", &observer->longitude) ||
|
||||
!IsValid(observer->longitude, -180.0, +180.0))
|
||||
{
|
||||
fprintf(stderr, "ERROR: Invalid longitude '%s' on command line\n", argv[2]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
time_arg = 3;
|
||||
}
|
||||
|
||||
if (time_arg && argc == 1+time_arg)
|
||||
{
|
||||
/* Time is present on command line, so use it. */
|
||||
return ParseTime(argv[time_arg], time);
|
||||
}
|
||||
|
||||
if (time_arg && argc == time_arg)
|
||||
{
|
||||
/* Time is absent on command line, so use current time. */
|
||||
*time = Astronomy_CurrentTime();
|
||||
return 0;
|
||||
}
|
||||
|
||||
fprintf(stderr, "USAGE: %s [-e | latitude longitude] [yyyy-mm-ddThh:mm:ssZ]\n", argv[0]);
|
||||
fprintf(stderr, "\n");
|
||||
fprintf(stderr, "If '-e' is specified, an environment variable must be set as follows:\n");
|
||||
fprintf(stderr, "%s='latitude longitude'\n", ObserverVarName);
|
||||
fprintf(stderr, "Otherwise, the latitude and longitude must appear in the command line.\n");
|
||||
fprintf(stderr, "\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
int ParseTime(const char *text, astro_time_t *time)
|
||||
{
|
||||
astro_utc_t utc;
|
||||
int nscanned = sscanf(text, "%d-%d-%dT%d:%d:%lfZ",
|
||||
&utc.year, &utc.month, &utc.day,
|
||||
&utc.hour, &utc.minute, &utc.second);
|
||||
|
||||
if (nscanned != 6)
|
||||
{
|
||||
fprintf(stderr, "ERROR: Invalid date/time format in '%s'\n", text);
|
||||
return 1;
|
||||
}
|
||||
|
||||
*time = Astronomy_TimeFromUtc(utc);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void PrintTime(astro_time_t time)
|
||||
{
|
||||
astro_status_t status;
|
||||
char text[TIME_TEXT_BYTES];
|
||||
|
||||
status = Astronomy_FormatTime(time, TIME_FORMAT_SECOND, text, sizeof(text));
|
||||
if (status != ASTRO_SUCCESS)
|
||||
{
|
||||
Serial.printf(stderr, "\nFATAL(PrintTime): status %d\n", status);
|
||||
// exit(1);
|
||||
}
|
||||
// printf("%s", text);
|
||||
}
|
||||
|
||||
9
demo/arduino/ecliptic_vector/astro_demo_common.h
Normal file
9
demo/arduino/ecliptic_vector/astro_demo_common.h
Normal file
@@ -0,0 +1,9 @@
|
||||
#ifndef __ASTRONOMY_DEMO_COMMON_H
|
||||
#define __ASTRONOMY_DEMO_COMMON_H
|
||||
#include "astronomy.h"
|
||||
|
||||
int ParseArgs(int argc, const char *argv[], astro_observer_t *observer, astro_time_t *time);
|
||||
int ParseTime(const char *text, astro_time_t *time);
|
||||
void PrintTime(astro_time_t time);
|
||||
|
||||
#endif /* __ASTRONOMY_DEMO_COMMON_H */
|
||||
58
demo/arduino/ecliptic_vector/ecliptic_vector.ino
Normal file
58
demo/arduino/ecliptic_vector/ecliptic_vector.ino
Normal file
@@ -0,0 +1,58 @@
|
||||
|
||||
#include "stdio.h"
|
||||
#include "astro_demo_common.h"
|
||||
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(9600);
|
||||
|
||||
// setSyncProvider(syncProvider);//sets internal clock
|
||||
// if(timeStatus() != timeSet)
|
||||
// Serial.println("Unable to sync with the unixTimeStamp");
|
||||
// else
|
||||
// Serial.println("unixTimeStamp has set the system time");
|
||||
|
||||
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
static const astro_body_t body[] = {
|
||||
BODY_SUN, BODY_MERCURY, BODY_VENUS, BODY_EARTH, BODY_MOON, BODY_MARS,
|
||||
BODY_JUPITER, BODY_SATURN, BODY_URANUS, BODY_NEPTUNE, BODY_PLUTO
|
||||
};
|
||||
int i;
|
||||
int num_bodies;
|
||||
astro_time_t time;
|
||||
astro_rotation_t rot;
|
||||
astro_time_t time2;
|
||||
num_bodies = sizeof(body) / sizeof(body[0]);;
|
||||
|
||||
const char *argv[] = {"123","2023-10-07T00:38:57+03:30"};
|
||||
|
||||
if (0 == ParseTime(argv[1], &time))
|
||||
{
|
||||
|
||||
rot = Astronomy_Rotation_EQJ_ECL();
|
||||
// Serial.println("BODY X Y Z\n");
|
||||
for (i=0; i < num_bodies; ++i)
|
||||
{
|
||||
astro_vector_t eqj = Astronomy_HelioVector(body[i], time);
|
||||
astro_vector_t ecl = Astronomy_RotateVector(rot, eqj);
|
||||
const char *name = Astronomy_BodyName(body[i]);
|
||||
if (ecl.status != ASTRO_SUCCESS)
|
||||
{
|
||||
Serial.println( "ERROR %d calculating vector for %s.\n");
|
||||
Serial.println((int)ecl.status);
|
||||
Serial.println(name);
|
||||
}
|
||||
|
||||
Serial.printf("%-8s %11.6lf %11.6lf %11.6lf\n", name, ecl.x, ecl.y, ecl.z);
|
||||
}
|
||||
}
|
||||
|
||||
delay(1000);
|
||||
}
|
||||
|
||||
|
||||
117
demo/arduino/galactic/galactic.ino
Normal file
117
demo/arduino/galactic/galactic.ino
Normal file
@@ -0,0 +1,117 @@
|
||||
/*
|
||||
galactic.c - Don Cross - 2021-06-10
|
||||
|
||||
Example C program for Astronomy Engine:
|
||||
https://github.com/cosinekitty/astronomy
|
||||
|
||||
This program illustrates how to convert a location
|
||||
in the sky expressed in IAU 1958 galactic coordinates
|
||||
into the local altitude and azimuth of someone wanting
|
||||
to aim a radio dish at it.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
#include "astro_demo_common.h"
|
||||
|
||||
|
||||
int GalaticToHorizontal(
|
||||
astro_time_t time,
|
||||
astro_observer_t observer,
|
||||
double glat,
|
||||
double glon,
|
||||
double *altitude,
|
||||
double *azimuth) {
|
||||
astro_rotation_t rot, adjust_rot;
|
||||
astro_spherical_t gsphere, hsphere;
|
||||
astro_vector_t gvec, hvec;
|
||||
|
||||
/*
|
||||
Calculate a rotation matrix that converts
|
||||
galactic coordinates to J2000 equatorial coordinates.
|
||||
*/
|
||||
rot = Astronomy_Rotation_GAL_EQJ();
|
||||
|
||||
/*
|
||||
Adjust the rotation matrix to convert galatic to horizontal (HOR).
|
||||
*/
|
||||
adjust_rot = Astronomy_Rotation_EQJ_HOR(&time, observer);
|
||||
rot = Astronomy_CombineRotation(rot, adjust_rot);
|
||||
|
||||
/*
|
||||
Convert the galactic coordinates from angles to a unit vector.
|
||||
*/
|
||||
gsphere.status = ASTRO_SUCCESS;
|
||||
gsphere.lat = glat;
|
||||
gsphere.lon = glon;
|
||||
gsphere.dist = 1.0;
|
||||
gvec = Astronomy_VectorFromSphere(gsphere, time);
|
||||
if (gvec.status != ASTRO_SUCCESS) {
|
||||
Serial.printf("Astronomy_VectorFromSphere returned error %d\n", gvec.status);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
Use the rotation matrix to convert the galactic vector to a horizontal vector.
|
||||
*/
|
||||
hvec = Astronomy_RotateVector(rot, gvec);
|
||||
if (hvec.status != ASTRO_SUCCESS) {
|
||||
Serial.printf("Astronomy_RotateVector returned error %d\n", hvec.status);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
Convert the horizontal vector back to angular coordinates: altitude and azimuth.
|
||||
Assuming this is a radio source (not optical), do not correct for refraction.
|
||||
*/
|
||||
hsphere = Astronomy_HorizonFromVector(hvec, REFRACTION_NONE);
|
||||
if (hsphere.status != ASTRO_SUCCESS) {
|
||||
Serial.printf("Astronomy_HorizonFromVector returned error %d\n", hsphere.status);
|
||||
return 1;
|
||||
}
|
||||
|
||||
*altitude = hsphere.lat;
|
||||
*azimuth = hsphere.lon;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void setup() {
|
||||
Serial.begin(9600);
|
||||
}
|
||||
|
||||
void loop() {
|
||||
astro_observer_t observer;
|
||||
astro_time_t time;
|
||||
double glat, glon;
|
||||
double azimuth, altitude;
|
||||
|
||||
|
||||
const char *argvs[] = { "22.2", "33.8", "2023-10-07T00:38:57+03:30" };
|
||||
glat = 23.3; //-90.0 to 90.0
|
||||
glon = 17.6; //-90.0 to 90.0
|
||||
int argcs = 3;
|
||||
int error;
|
||||
error = ParseArgs(argcs, argvs, &observer, &time);
|
||||
|
||||
|
||||
if (glat < -90.0 || glat > +90.0) {
|
||||
Serial.printf("ERROR: Invalid galatic latitude '%s' on command line\n", glat);
|
||||
error = 1;
|
||||
}
|
||||
|
||||
|
||||
if (glon <= -360.0 || glon >= +360.0) {
|
||||
Serial.printf("ERROR: Invalid galatic longitude '%s' on command line\n", glon);
|
||||
error = 1;
|
||||
}
|
||||
|
||||
if (GalaticToHorizontal(time, observer, glat, glon, &altitude, &azimuth)) {
|
||||
Serial.println("error.......");
|
||||
}
|
||||
if (error) {
|
||||
Serial.println("error.......");
|
||||
}
|
||||
Serial.printf("altitude = %10.3lf, azimuth = %10.3lf\n", altitude, azimuth);
|
||||
|
||||
delay(1000);
|
||||
}
|
||||
123
demo/arduino/gravity/astro_demo_common.cpp
Normal file
123
demo/arduino/gravity/astro_demo_common.cpp
Normal file
@@ -0,0 +1,123 @@
|
||||
/*
|
||||
astro_demo_common.h - by Don Cross <cosinekitty@gmail.com>
|
||||
https://github.com/cosinekitty/astronomy
|
||||
|
||||
Helper code for Astronomy Engine demo programs.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
#include "astro_demo_common.h"
|
||||
|
||||
static const char ObserverVarName[] = "ASTRONOMY_ENGINE_OBSERVER";
|
||||
|
||||
static int IsValid(double x, double lo, double hi)
|
||||
{
|
||||
return isfinite(x) && (x >= lo) && (x <= hi);
|
||||
}
|
||||
|
||||
|
||||
int ParseArgs(int argc, const char *argv[], astro_observer_t *observer, astro_time_t *time)
|
||||
{
|
||||
int time_arg = 0;
|
||||
|
||||
observer->height = 0.0;
|
||||
|
||||
if ((argc==2 || argc==3) && !strcmp(argv[1], "-e"))
|
||||
{
|
||||
/* Use an environment variable to specify the observer's location. */
|
||||
const char *obstext = getenv(ObserverVarName);
|
||||
if (obstext == NULL)
|
||||
{
|
||||
fprintf(stderr, "ERROR: The -e option was specified but environment variable %s is not defined.\n", ObserverVarName);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (2 != sscanf(obstext, "%lf %lf", &observer->latitude, &observer->longitude) ||
|
||||
!IsValid(observer->latitude, -90.0, +90.0) ||
|
||||
!IsValid(observer->longitude, -180.0, +180.0))
|
||||
{
|
||||
fprintf(stderr, "ERROR: Invalid geographic coordinates in environment variable %s.\n", ObserverVarName);
|
||||
return 1;
|
||||
}
|
||||
|
||||
time_arg = 2;
|
||||
}
|
||||
else if (argc==3 || argc==4)
|
||||
{
|
||||
/* The observer's location must appear in the command line. */
|
||||
|
||||
if (1 != sscanf(argv[1], "%lf", &observer->latitude) ||
|
||||
!IsValid(observer->latitude, -90.0, +90.0))
|
||||
{
|
||||
fprintf(stderr, "ERROR: Invalid latitude '%s' on command line\n", argv[1]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (1 != sscanf(argv[2], "%lf", &observer->longitude) ||
|
||||
!IsValid(observer->longitude, -180.0, +180.0))
|
||||
{
|
||||
fprintf(stderr, "ERROR: Invalid longitude '%s' on command line\n", argv[2]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
time_arg = 3;
|
||||
}
|
||||
|
||||
if (time_arg && argc == 1+time_arg)
|
||||
{
|
||||
/* Time is present on command line, so use it. */
|
||||
return ParseTime(argv[time_arg], time);
|
||||
}
|
||||
|
||||
if (time_arg && argc == time_arg)
|
||||
{
|
||||
/* Time is absent on command line, so use current time. */
|
||||
*time = Astronomy_CurrentTime();
|
||||
return 0;
|
||||
}
|
||||
|
||||
fprintf(stderr, "USAGE: %s [-e | latitude longitude] [yyyy-mm-ddThh:mm:ssZ]\n", argv[0]);
|
||||
fprintf(stderr, "\n");
|
||||
fprintf(stderr, "If '-e' is specified, an environment variable must be set as follows:\n");
|
||||
fprintf(stderr, "%s='latitude longitude'\n", ObserverVarName);
|
||||
fprintf(stderr, "Otherwise, the latitude and longitude must appear in the command line.\n");
|
||||
fprintf(stderr, "\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
int ParseTime(const char *text, astro_time_t *time)
|
||||
{
|
||||
astro_utc_t utc;
|
||||
int nscanned = sscanf(text, "%d-%d-%dT%d:%d:%lfZ",
|
||||
&utc.year, &utc.month, &utc.day,
|
||||
&utc.hour, &utc.minute, &utc.second);
|
||||
|
||||
if (nscanned != 6)
|
||||
{
|
||||
fprintf(stderr, "ERROR: Invalid date/time format in '%s'\n", text);
|
||||
return 1;
|
||||
}
|
||||
|
||||
*time = Astronomy_TimeFromUtc(utc);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void PrintTime(astro_time_t time)
|
||||
{
|
||||
astro_status_t status;
|
||||
char text[TIME_TEXT_BYTES];
|
||||
|
||||
status = Astronomy_FormatTime(time, TIME_FORMAT_SECOND, text, sizeof(text));
|
||||
if (status != ASTRO_SUCCESS)
|
||||
{
|
||||
fprintf(stderr, "\nFATAL(PrintTime): status %d\n", status);
|
||||
exit(1);
|
||||
}
|
||||
printf("%s", text);
|
||||
}
|
||||
|
||||
9
demo/arduino/gravity/astro_demo_common.h
Normal file
9
demo/arduino/gravity/astro_demo_common.h
Normal file
@@ -0,0 +1,9 @@
|
||||
#ifndef __ASTRONOMY_DEMO_COMMON_H
|
||||
#define __ASTRONOMY_DEMO_COMMON_H
|
||||
#include "astronomy.h"
|
||||
|
||||
int ParseArgs(int argc, const char *argv[], astro_observer_t *observer, astro_time_t *time);
|
||||
int ParseTime(const char *text, astro_time_t *time);
|
||||
void PrintTime(astro_time_t time);
|
||||
|
||||
#endif /* __ASTRONOMY_DEMO_COMMON_H */
|
||||
31
demo/arduino/gravity/gravity.ino
Normal file
31
demo/arduino/gravity/gravity.ino
Normal file
@@ -0,0 +1,31 @@
|
||||
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "astronomy.h"
|
||||
|
||||
void setup() {
|
||||
// put your setup code here, to run once:
|
||||
|
||||
Serial.begin(9600);
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
void loop() {
|
||||
// put your main code here, to run repeatedly:
|
||||
|
||||
const double MAX_HEIGHT_METERS = 100000.0;
|
||||
double latitude, height, gravity;
|
||||
latitude = 23.3;
|
||||
height = 1000;
|
||||
gravity = Astronomy_ObserverGravity(latitude, height);
|
||||
// printf("latitude = %8.4lf, height = %6.0lf, gravity = %8.6lf\n", latitude, height, gravity);
|
||||
Serial.printf("latitude = %8.4lf, height = %6.0lf, gravity = %8.6lf\n", latitude, height, gravity);
|
||||
// Serial.println(gravity,6);
|
||||
delay(500);
|
||||
}
|
||||
//--->ASTRONOMY_ENGINE_WHOLE_SECOND
|
||||
75
source/arduino/astro_demo_common.cpp
Normal file
75
source/arduino/astro_demo_common.cpp
Normal file
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
astro_demo_common.h - by Don Cross <cosinekitty@gmail.com>
|
||||
https://github.com/cosinekitty/astronomy
|
||||
|
||||
Helper code for Astronomy Engine demo programs.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
#include "astro_demo_common.h"
|
||||
|
||||
static const char ObserverVarName[] = "ASTRONOMY_ENGINE_OBSERVER";
|
||||
|
||||
static int IsValid(double x, double lo, double hi)
|
||||
{
|
||||
return isfinite(x) && (x >= lo) && (x <= hi);
|
||||
}
|
||||
|
||||
int ParseArgs(int argc, const char *argv[], astro_observer_t *observer, astro_time_t *time)
|
||||
{
|
||||
|
||||
int time_arg = 2;
|
||||
|
||||
observer->height = 0.0;
|
||||
// fprintf(stderr, "USAGE: %s [0 first]\n", argv[0]);
|
||||
// fprintf(stderr, "USAGE: %s [2 doo]\n", argv[1]);
|
||||
// fprintf(stderr, "USAGE: %s [3 se]\n", argv[2]);
|
||||
// fprintf(stderr, "%s='asdasd asdasd'\n", argv[2]);
|
||||
observer->latitude = atof(argv[0]);
|
||||
observer->longitude = atof(argv[1]);
|
||||
// time_arg = 2;
|
||||
|
||||
if (!IsValid(observer->latitude, -90.0, +90.0) || !IsValid(observer->longitude, -180.0, +180.0))
|
||||
{
|
||||
fprintf(stderr, "ERROR: Invalid geographic coordinates in environment variable %s.\n", ObserverVarName);
|
||||
return 1;
|
||||
}
|
||||
|
||||
time_arg = 2;
|
||||
return ParseTime(argv[time_arg], time);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ParseTime(const char *text, astro_time_t *time)
|
||||
{
|
||||
astro_utc_t utc;
|
||||
int nscanned = sscanf(text, "%d-%d-%dT%d:%d:%lfZ",
|
||||
&utc.year, &utc.month, &utc.day,
|
||||
&utc.hour, &utc.minute, &utc.second);
|
||||
|
||||
if (nscanned != 6)
|
||||
{
|
||||
fprintf(stderr, "ERROR: Invalid date/time format in '%s'\n", text);
|
||||
return 1;
|
||||
}
|
||||
|
||||
*time = Astronomy_TimeFromUtc(utc);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void PrintTime(astro_time_t time)
|
||||
{
|
||||
astro_status_t status;
|
||||
char text[TIME_TEXT_BYTES];
|
||||
|
||||
status = Astronomy_FormatTime(time, TIME_FORMAT_SECOND, text, sizeof(text));
|
||||
if (status != ASTRO_SUCCESS)
|
||||
{
|
||||
fprintf(stderr, "\nFATAL(PrintTime): status %d\n", status);
|
||||
exit(1);
|
||||
}
|
||||
printf("%s", text);
|
||||
}
|
||||
9
source/arduino/astro_demo_common.h
Normal file
9
source/arduino/astro_demo_common.h
Normal file
@@ -0,0 +1,9 @@
|
||||
#ifndef __ASTRONOMY_DEMO_COMMON_H
|
||||
#define __ASTRONOMY_DEMO_COMMON_H
|
||||
#include "astronomy.h"
|
||||
|
||||
int ParseArgs(int argc, const char *argv[], astro_observer_t *observer, astro_time_t *time);
|
||||
int ParseTime(const char *text, astro_time_t *time);
|
||||
void PrintTime(astro_time_t time);
|
||||
|
||||
#endif /* __ASTRONOMY_DEMO_COMMON_H */
|
||||
12969
source/arduino/astronomy.cpp
Normal file
12969
source/arduino/astronomy.cpp
Normal file
File diff suppressed because it is too large
Load Diff
1431
source/arduino/astronomy.h
Normal file
1431
source/arduino/astronomy.h
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user