Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 10 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,18 +75,20 @@ We can then use this calibration information to now make some position estimates
```bash
./build/bin/found distance \
--image test/common/assets/example_earth1.png \
--image-time "2025-11-11 19:30:00.00" \
--calibration-data example-df.found \
--camera-focal-length 85e-3 \
--camera-pixel-size 20e-6 \
--reference-orientation 110,0,0
--reference-orientation 110,0,0 \
```

For the distance flags:
1. The image is just the path to the image we want to use. In this case, we reference an image we use in our test cases
2. We then specify our calibration data, which we generated from `tools.generator` (check out [our tools folder](tools) for more information)
3. We can specify camera parameters, like the focal length (m)
4. Or the pixel size (m)
5. We then have our reference orientation, which we need to use in conjunction with our calibration data
2. The time that the image was taken in UT1 time in the format YYYY-MM-DD HH:MM:SS.NS
3. We then specify our calibration data, which we generated from `tools.generator` (check out [our tools folder](tools) for more information)
4. We can specify camera parameters, like the focal length (m)
5. Or the pixel size (m)
6. We then have our reference orientation, which we need to use in conjunction with our calibration data

Feeding all this information, the program now analyzes the image, the calibration data and the rest of the parameters to give us its estimate, which is seen below:

Expand All @@ -103,6 +105,7 @@ Another thing to point out is the reference orientation, which was `{110,0,0}`.
```bash
./build/bin/found distance \
--image "test/common/assets/example_earth1.png" \
--image-time "2025-11-11 19:30:00.00" \
--reference-as-orientation \
--camera-focal-length 85e-3 \
--camera-pixel-size 20e-6 \
Expand All @@ -115,6 +118,7 @@ Lastly, one thing you will not notice is that the `temp.found` file has changed.
```bash
./build/bin/found distance \
--image test/common/assets/example_earth1.png \
--image-time "2025-11-11 19:30:00.00" \
--calibration-data example-df.found \
--camera-focal-length 85e-3 \
--camera-pixel-size 20e-6 \
Expand Down Expand Up @@ -177,4 +181,4 @@ FetchContent_MakeAvailable(found)
add_executable(your_executable ...)
target_link_libraries(test PRIVATE found::found_lib) # Link our library
```
The library `found::found_lib` already has all the include statements needed inside of it, so no need to locate them.
The library `found::found_lib` already has all the include statements needed inside of it, so no need to locate them.
5 changes: 3 additions & 2 deletions src/command-line/execution/executors.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,8 @@ void DistancePipelineExecutor::OutputResults() {
outputDF.relative_attitude = SphericalToQuaternion(this->options_.relOrientation);
outputDF.positions = std::make_unique<LocationRecord[]>(1);
}
outputDF.positions[outputDF.header.num_positions++] = {static_cast<uint64_t>(getUT1Time().epochs), *positionVector};
// epochs is already in nanoseconds
outputDF.positions[outputDF.header.num_positions++] = {this->options_.imageTime.epochs, *positionVector};
if (this->options_.outputFile != "") {
std::ofstream outputFile(this->options_.outputFile);
serializeDataFile(outputDF, outputFile);
Expand Down Expand Up @@ -110,7 +111,7 @@ void OrbitPipelineExecutor::OutputResults() {
<< futurePosition.position.y << ", "
<< futurePosition.position.z << ") m"
<< " at time "
<< futurePosition.timestamp << " s");
<< futurePosition.timestamp << " ns");
}

} // namespace found
40 changes: 21 additions & 19 deletions src/command-line/parsing/options.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#include "providers/converters.hpp"
#include "datafile/datafile.hpp"
#include "datafile/serialization.hpp"
#include "common/time/time.hpp"

/// Version for an empty/null Data File
#define emptyDFVer 0U
Expand All @@ -46,25 +47,26 @@ FOUND_CLI_OPTION("output-file" , std::string , outputFile

/// Distance Flags
#define DISTANCE \
FOUND_CLI_OPTION("image" , found::Image , image , {} , found::strtoimage(optarg) , kNoDefaultArgument, REQ_ASSIGN, "The image to process (JPG, PNG, TGA, BMP, PSD, GIF, HDR, PIC)") \
FOUND_CLI_OPTION("calibration-data" , found::DataFile , calibrationData , {defaultDFHead} , found::strtodf(optarg) , kNoDefaultArgument, REQ_ASSIGN, "The calibration data (*.found)" ) \
FOUND_CLI_OPTION("reference-as-orientation", bool , refAsOrientation, false , found::strtobool(optarg) , true , OPT_ASSIGN, "Use reference-orientation as the orientation of the camera" ) \
FOUND_CLI_OPTION("camera-focal-length" , decimal , focalLength , 0.012 , found::strtodecimal(optarg), kNoDefaultArgument, REQ_ASSIGN, "The camera focal length (m)" ) \
FOUND_CLI_OPTION("camera-pixel-size" , decimal , pixelSize , 20E-6 , found::strtodecimal(optarg), kNoDefaultArgument, REQ_ASSIGN, "The camera pixel size (m)" ) \
FOUND_CLI_OPTION("reference-orientation" , found::EulerAngles, refOrientation , found::EulerAngles(0, 0, 0), found::strtoea(optarg) , kNoDefaultArgument, REQ_ASSIGN, "The reference orientation (deg)" ) \
FOUND_CLI_OPTION("relative-orientation" , found::EulerAngles, relOrientation , found::EulerAngles(0, 0, 0), found::strtoea(optarg) , kNoDefaultArgument, REQ_ASSIGN, "The relative orientation to use (if no calibration) (deg)" ) \
FOUND_CLI_OPTION("planetary-radius" , decimal , radius , DECIMAL_M_R_E , found::strtodecimal(optarg), kNoDefaultArgument, REQ_ASSIGN, "The planetary radius to use (m)" ) \
FOUND_CLI_OPTION("seda-threshold" , unsigned char , SEDAThreshold , 25 , found::strtouc(optarg) , kNoDefaultArgument, REQ_ASSIGN, "Threshold for the SEDA Algorithm ([0,255])" ) \
FOUND_CLI_OPTION("seda-border-len" , int , SEDABorderLen , 1 , atoi(optarg) , kNoDefaultArgument, REQ_ASSIGN, "The border thickness for SEDA (pixels)" ) \
FOUND_CLI_OPTION("seda-offset" , decimal , SEDAOffset , 0.0 , found::strtodecimal(optarg), kNoDefaultArgument, REQ_ASSIGN, "The edge offset for SEDA (pixels)" ) \
FOUND_CLI_OPTION("distance-algo" , std::string , distanceAlgo , SDDA , optarg , kNoDefaultArgument, REQ_ASSIGN, "The distance algorithm to use (SDDA or ISDDA)" ) \
FOUND_CLI_OPTION("isdda-min-iterations" , size_t , ISDDAMinIters , 0 , found::strtosize(optarg) , kNoDefaultArgument, REQ_ASSIGN, "The minimum number of iterations for ISDDA" ) \
FOUND_CLI_OPTION("isdda-max-refreshes" , size_t , ISDDAMaxRefresh , 0 , found::strtosize(optarg) , kNoDefaultArgument, REQ_ASSIGN, "The maximum number of reference refreshes for ISDDA" ) \
FOUND_CLI_OPTION("isdda-dist-ratio" , decimal , ISDDADistRatio , DECIMAL_INF , found::strtodecimal(optarg), kNoDefaultArgument, REQ_ASSIGN, "The distance ratio for calculated positions for ISDDA (m)" ) \
FOUND_CLI_OPTION("isdda-discrim-ratio" , decimal , ISDDADiscimRatio, DECIMAL_INF , found::strtodecimal(optarg), kNoDefaultArgument, REQ_ASSIGN, "The loss discrimination ratio for ISSDA" ) \
FOUND_CLI_OPTION("isdda-pdf-order" , int , ISDDAPdfOrd , 2 , atoi(optarg) , kNoDefaultArgument, REQ_ASSIGN, "The Probability Density Function Order for ISSDA (even int)" ) \
FOUND_CLI_OPTION("isdda-radius-loss-order" , int , ISDDARadLossOrd , 4 , atoi(optarg) , kNoDefaultArgument, REQ_ASSIGN, "The Radius Loss Order ISSDA (even int)" ) \
FOUND_CLI_OPTION("output-file" , std::string , outputFile , "" , optarg , kNoDefaultArgument, REQ_ASSIGN, "The output file (*.found)" ) \
FOUND_CLI_OPTION("image" , found::Image , image , {} , found::strtoimage(optarg) , kNoDefaultArgument, REQ_ASSIGN, "The image to process (JPG, PNG, TGA, BMP, PSD, GIF, HDR, PIC)") \
FOUND_CLI_OPTION("image-time" , found::DateTime , imageTime , {} , found::strtodatetime(optarg), kNoDefaultArgument, REQ_ASSIGN, "Image capture time (in UT1 in format YYYY-MM-DD HH:MM:SS.NS)" ) \
FOUND_CLI_OPTION("calibration-data" , found::DataFile , calibrationData , {defaultDFHead} , found::strtodf(optarg) , kNoDefaultArgument, REQ_ASSIGN, "The calibration data (*.found)" ) \
FOUND_CLI_OPTION("reference-as-orientation", bool , refAsOrientation, false , found::strtobool(optarg) , true , OPT_ASSIGN, "Use reference-orientation as the orientation of the camera" ) \
FOUND_CLI_OPTION("camera-focal-length" , decimal , focalLength , 0.012 , found::strtodecimal(optarg) , kNoDefaultArgument, REQ_ASSIGN, "The camera focal length (m)" ) \
FOUND_CLI_OPTION("camera-pixel-size" , decimal , pixelSize , 20E-6 , found::strtodecimal(optarg) , kNoDefaultArgument, REQ_ASSIGN, "The camera pixel size (m)" ) \
FOUND_CLI_OPTION("reference-orientation" , found::EulerAngles, refOrientation , found::EulerAngles(0, 0, 0) , found::strtoea(optarg) , kNoDefaultArgument, REQ_ASSIGN, "The reference orientation (deg)" ) \
FOUND_CLI_OPTION("relative-orientation" , found::EulerAngles, relOrientation , found::EulerAngles(0, 0, 0) , found::strtoea(optarg) , kNoDefaultArgument, REQ_ASSIGN, "The relative orientation to use (if no calibration) (deg)" ) \
FOUND_CLI_OPTION("planetary-radius" , decimal , radius , DECIMAL_M_R_E , found::strtodecimal(optarg) , kNoDefaultArgument, REQ_ASSIGN, "The planetary radius to use (m)" ) \
FOUND_CLI_OPTION("seda-threshold" , unsigned char , SEDAThreshold , 25 , found::strtouc(optarg) , kNoDefaultArgument, REQ_ASSIGN, "Threshold for the SEDA Algorithm ([0,255])" ) \
FOUND_CLI_OPTION("seda-border-len" , int , SEDABorderLen , 1 , atoi(optarg) , kNoDefaultArgument, REQ_ASSIGN, "The border thickness for SEDA (pixels)" ) \
FOUND_CLI_OPTION("seda-offset" , decimal , SEDAOffset , 0.0 , found::strtodecimal(optarg) , kNoDefaultArgument, REQ_ASSIGN, "The edge offset for SEDA (pixels)" ) \
FOUND_CLI_OPTION("distance-algo" , std::string , distanceAlgo , SDDA , optarg , kNoDefaultArgument, REQ_ASSIGN, "The distance algorithm to use (SDDA or ISDDA)" ) \
FOUND_CLI_OPTION("isdda-min-iterations" , size_t , ISDDAMinIters , 0 , found::strtosize(optarg) , kNoDefaultArgument, REQ_ASSIGN, "The minimum number of iterations for ISDDA" ) \
FOUND_CLI_OPTION("isdda-max-refreshes" , size_t , ISDDAMaxRefresh , 0 , found::strtosize(optarg) , kNoDefaultArgument, REQ_ASSIGN, "The maximum number of reference refreshes for ISDDA" ) \
FOUND_CLI_OPTION("isdda-dist-ratio" , decimal , ISDDADistRatio , DECIMAL_INF , found::strtodecimal(optarg) , kNoDefaultArgument, REQ_ASSIGN, "The distance ratio for calculated positions for ISDDA (m)" ) \
FOUND_CLI_OPTION("isdda-discrim-ratio" , decimal , ISDDADiscimRatio, DECIMAL_INF , found::strtodecimal(optarg) , kNoDefaultArgument, REQ_ASSIGN, "The loss discrimination ratio for ISSDA" ) \
FOUND_CLI_OPTION("isdda-pdf-order" , int , ISDDAPdfOrd , 2 , atoi(optarg) , kNoDefaultArgument, REQ_ASSIGN, "The Probability Density Function Order for ISSDA (even int)" ) \
FOUND_CLI_OPTION("isdda-radius-loss-order" , int , ISDDARadLossOrd , 4 , atoi(optarg) , kNoDefaultArgument, REQ_ASSIGN, "The Radius Loss Order ISSDA (even int)" ) \
FOUND_CLI_OPTION("output-file" , std::string , outputFile , "" , optarg , kNoDefaultArgument, REQ_ASSIGN, "The output file (*.found)" ) \


// Orbit Flags
Expand Down
51 changes: 36 additions & 15 deletions src/common/decimal.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,21 +25,42 @@
#define DECIMAL(x) (static_cast<decimal>(x))

// Math Constants wrapped with Decimal typecast
#define DECIMAL_M_E (DECIMAL(M_E)) /* e */
#define DECIMAL_M_LOG2E (DECIMAL(M_LOG2E)) /* log_2 e */
#define DECIMAL_M_LOG10E (DECIMAL(M_LOG10E)) /* log_10 e */
#define DECIMAL_M_LN2 (DECIMAL(M_LN2)) /* log_e 2 */
#define DECIMAL_M_LN10 (DECIMAL(M_LN10)) /* log_e 10 */
#define DECIMAL_M_PI (DECIMAL(M_PI)) /* pi */
#define DECIMAL_M_PI_2 (DECIMAL(M_PI_2)) /* pi/2 */
#define DECIMAL_M_PI_4 (DECIMAL(M_PI_4)) /* pi/4 */
#define DECIMAL_M_1_PI (DECIMAL(M_1_PI)) /* 1/pi */
#define DECIMAL_M_2_PI (DECIMAL(M_2_PI)) /* 2/pi */
#define DECIMAL_M_2_SQRTPI (DECIMAL(M_2_SQRTPI)) /* 2/sqrt(pi) */
#define DECIMAL_M_SQRT2 (DECIMAL(M_SQRT2)) /* sqrt(2) */
#define DECIMAL_M_SQRT1_2 (DECIMAL(M_SQRT1_2)) /* 1/sqrt(2) */
#define DECIMAL_M_R_E (DECIMAL(6371008.7714)) /* Earth's Radius */
#define DECIMAL_INF (DECIMAL(INFINITY)) /* Infinity */
// e
#define DECIMAL_M_E (DECIMAL(M_E))
// log_2 e
#define DECIMAL_M_LOG2E (DECIMAL(M_LOG2E))
// log_10 e
#define DECIMAL_M_LOG10E (DECIMAL(M_LOG10E))
// log_e 2
#define DECIMAL_M_LN2 (DECIMAL(M_LN2))
// log_e 10
#define DECIMAL_M_LN10 (DECIMAL(M_LN10))
// pi
#define DECIMAL_M_PI (DECIMAL(M_PI))
// pi/2
#define DECIMAL_M_PI_2 (DECIMAL(M_PI_2))
// pi/4
#define DECIMAL_M_PI_4 (DECIMAL(M_PI_4))
// 1/pi
#define DECIMAL_M_1_PI (DECIMAL(M_1_PI))
// 2/pi
#define DECIMAL_M_2_PI (DECIMAL(M_2_PI))
// 2/sqrt(pi)
#define DECIMAL_M_2_SQRTPI (DECIMAL(M_2_SQRTPI))
// sqrt(2)
#define DECIMAL_M_SQRT2 (DECIMAL(M_SQRT2))
// 1/sqrt(2)
#define DECIMAL_M_SQRT1_2 (DECIMAL(M_SQRT1_2))
// Earth's Radius
#define DECIMAL_M_R_E (DECIMAL(6371008.7714))
// WGS84 Semi-major axis (m)
#define DECIMAL_M_A_E (DECIMAL(6378137.0))
// WGS84 eccentricity^2
#define DECIMAL_M_E2_E (DECIMAL(0.00669437999014))
// WGS84 Semi-minor axis (m)
#define DECIMAL_M_B_E (DECIMAL_M_A_E * DECIMAL_SQRT(DECIMAL(1.0) - DECIMAL_M_E2_E))
// Infinity
#define DECIMAL_INF (DECIMAL(INFINITY))

// Math Functions wrapped with Decimal typecast
#define DECIMAL_POW(base,power) (DECIMAL(std::pow(base, power)))
Expand Down
13 changes: 13 additions & 0 deletions src/common/spatial/attitude-utils.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,19 @@ class Vec3 {
Mat3 OuterProduct(const Vec3 &) const;
};

/**
* Represents Earth-Centered, Earth-Fixed (ECEF) coordinates.
*
* ECEF is a Cartesian coordinate system with its origin at Earth's center.
* The axes are:
* - x-axis: Points to the intersection of the equator and prime meridian (0° latitude, 0° longitude)
* - y-axis: Points to 90°E longitude on the equator (0° latitude, 90°E longitude)
* - z-axis: Points to the North Pole (90°N latitude)
*
* All coordinates are in meters.
*/
typedef Vec3 ECEFCoordinates;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

At this point, it probably belongs in style.hpp instead (or possibly the output file, but you should defend either decision you make). Alternately, you could forgo ECEFCoordinates altogether and just use Vec3. The primary reason I use typedefs is to clarify what kind of info is being fed between and as an output from each pipeline, but this is not one of those data types. You could still keep the typedef, but also defend that decision as well.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since Quaternion is also defined in attitude-utils.hpp, wouldn't it be appropriate to define the different coordinate systems in the same file? I do think that it may be worth separating the mathematical definitions like Vec2 and Vec3 from definitions related to the coordinate system, like Attitude, Quaternion, etc. since Vec2 and Vec3 have more broader use cases then just to define the coordinate system.

Additionally, I do think it may be beneficial to keep a typedef ECEFCoordinates because I believe it would be confusing if we are converting between multiple types of coordinate points and all of them are defined with a Vec3.


///////////////////////////////////
///// VECTOR UTILITY FUNCTIONS ////
///////////////////////////////////
Expand Down
2 changes: 1 addition & 1 deletion src/common/style.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ typedef std::vector<Component> Components;
*/
struct LocationRecord {
/**
* @brief Timestamp associated with the position, in microseconds or appropriate units.
* @brief Timestamp associated with the position, in nanoseconds since epoch.
*/
uint64_t timestamp;

Expand Down
Loading
Loading