{"id":16706784,"url":"https://github.com/nhz2/xyzgeomag","last_synced_at":"2025-08-10T08:05:05.851Z","repository":{"id":48076589,"uuid":"217181000","full_name":"nhz2/XYZgeomag","owner":"nhz2","description":"Lightweight C++ header-only library for calculating the magnetic field on earth given geocentric cartesian coordinates using the World Magnetic Model(WMM). Compatible with Arduino.","archived":false,"fork":false,"pushed_at":"2024-12-23T18:02:57.000Z","size":577,"stargazers_count":16,"open_issues_count":1,"forks_count":5,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-04-10T05:15:29.658Z","etag":null,"topics":["arduino","compass"],"latest_commit_sha":null,"homepage":"","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/nhz2.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2019-10-24T00:55:04.000Z","updated_at":"2025-04-09T10:14:54.000Z","dependencies_parsed_at":"2025-02-16T16:34:11.890Z","dependency_job_id":"d6ac3896-0ee1-4817-975c-810d43185d12","html_url":"https://github.com/nhz2/XYZgeomag","commit_stats":null,"previous_names":[],"tags_count":3,"template":false,"template_full_name":null,"purl":"pkg:github/nhz2/XYZgeomag","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nhz2%2FXYZgeomag","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nhz2%2FXYZgeomag/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nhz2%2FXYZgeomag/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nhz2%2FXYZgeomag/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/nhz2","download_url":"https://codeload.github.com/nhz2/XYZgeomag/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nhz2%2FXYZgeomag/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":269693593,"owners_count":24460248,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-08-10T02:00:08.965Z","response_time":71,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["arduino","compass"],"created_at":"2024-10-12T19:36:26.429Z","updated_at":"2025-08-10T08:05:05.816Z","avatar_url":"https://github.com/nhz2.png","language":"C++","funding_links":[],"categories":[],"sub_categories":[],"readme":"# XYZgeomag\n\n[![Build Status](https://github.com/nhz2/XYZgeomag/workflows/test/badge.svg)](https://github.com/nhz2/XYZgeomag/actions)\n\nLightweight C++ header-only library for calculating the magnetic field on earth given geocentric cartesian coordinates using the [World Magnetic Model(WMM)](https://www.ncei.noaa.gov/products/world-magnetic-model). Compatible with Arduino.\n\nThe main function `geomag::GeoMag` calculates the magnetic field around earth in the International Terrestrial Reference System(ITRS) and uses units of decimal year, meter, and tesla.\n\nUnlike most WMM software, which uses latitude, longitude, and altitude inputs to calculate the North East Down components of the magnetic field, `geomag::GeoMag` uses geocentric cartesian coordinates as input, and outputs the magnetic field in the same geocentric cartesian coordinate system as the inputs.\n\nIf you want to provide geodetic latitude, longitude, and height, and receive the local North East Down components of the magnetic field and the magnetic declination: \nsee the `geomag::geodetic2ecef` and `geomag::magField2Elements` example below.\nNote that latitude and longitude are in units of degrees, and the seven magnetic elements are in units of nanotesla and degrees.\n\n## Error\n\nXYZgeomag is within 0.5 nT of the official WMM software.\n\nFor more information on the limitations of the WMM model, see:\n\u003chttps://www.ncei.noaa.gov/products/world-magnetic-model/accuracy-limitations-error-model\u003e\n\n## Performance\n\nXYZgeomag uses single precision floating points. It's designed to minimize ram usage for embedded systems.\n\n| Device      | Speed    |\n|-------------|----------|\n| Arduino Uno R3 | 52 ms    |\n| Raspberry Pi Pico RP2040 | 4.5 ms |\n| Teensy 3.6  |  83 µs |\n| Teensy 4.0  |  21 µs |\n\n## Using XYZgeomag\n\nJust download [XYZgeomag.hpp](https://github.com/nhz2/XYZgeomag/releases/download/v2.1.0/XYZgeomag.hpp) and include it.\nHere is an example Arduino sketch:\n\n~~~cpp\n#include \"XYZgeomag.hpp\"\nvoid setup() {\n  // put your setup code here, to run once:\n  pinMode(1,INPUT);\n  Serial.begin(9600);\n}\n\nvoid loop() {\n  // put your main code here, to run repeatedly:\n  int val= digitalRead(1);\n  geomag::Vector in;\n  in.x=val+1128529.6885767058f;\n  in.y=val+0.0;\n  in.z=val+6358023.736329913f;\n  geomag::Vector out;\n  int starttime=micros();\n  int starttimemil=millis();\n  out=geomag::GeoMag(2027.5,in,geomag::WMM2025);\n  int endtime=micros();\n  int endtimemil=millis();\n  Serial.print(out.x*1E9);\n  Serial.println(\" nT x\");\n  Serial.print(out.y*1E9);\n  Serial.println(\" nT y\");\n  Serial.print(out.z*1E9);\n  Serial.println(\" nT z\");\n  Serial.print(\"time in micro seconds: \");\n  Serial.println(endtime-starttime);\n  Serial.print(\"time in milli seconds: \");\n  Serial.println(endtimemil-starttimemil);\n  delay(2000);\n}\n~~~\n\nIf you have a position in latitude, longitude, and height, \nyou can convert it to geocentric cartesian coordinates \nwith `geodetic2ecef`. Note that `geodetic2ecef` uses \nsingle precision floats, so it will only be accurate to about 1 meter.\nYou can also convert the magnetic field to \nthe [seven magnetic elements](https://www.ncei.noaa.gov/products/world-magnetic-model) \nin units of nanotesla and degrees.\n~~~cpp\n#include \"XYZgeomag.hpp\"\nvoid setup() {\n  // put your setup code here, to run once:\n  pinMode(1,INPUT);\n  Serial.begin(9600);\n}\n\nvoid loop() {\n  // put your main code here, to run repeatedly:\n  int val= digitalRead(1);\n  float lat = val + 43.0f; // latitude in degrees\n  float lon = val + 75.0f; // longitude in degrees\n  float height = val + 305; // height above WGS84 ellipsoid in meters\n  geomag::Vector position = geomag::geodetic2ecef(lat,lon,height);\n  geomag::Vector mag_field = geomag::GeoMag(2027.5,position,geomag::WMM2025);\n  geomag::Elements out = geomag::magField2Elements(mag_field, lat, lon);\n  Serial.print(out.north);\n  Serial.println(\" nT north\");\n  Serial.print(out.east);\n  Serial.println(\" nT east\");\n  Serial.print(out.down);\n  Serial.println(\" nT down\");\n  Serial.print(out.horizontal);\n  Serial.println(\" nT horizontal\");\n  Serial.print(out.total);\n  Serial.println(\" nT total\");\n  Serial.print(out.inclination);\n  Serial.println(\" deg inclination\");\n  Serial.print(out.declination);\n  Serial.println(\" deg declination\");\n  Serial.println();\n  delay(2000);\n}\n~~~\n\n\n\n## Adding New Coefficents\n\nTo add new coefficents, download the new `.COF` file from \u003chttps://www.ncei.noaa.gov/products/world-magnetic-model\u003e\n\nAdd the .COF file to the `extras` directory.\n\nThen run for example\n`python3 wmmcodeupdate.py -f WMM2015.COF -f WMM2015v2.COF -f WMM2020.COF -f WMM2025.COF -o ../src/XYZgeomag.hpp -n 12` from the `extras` directory.\n\nIn this example, `WMM2015.COF` ,  `WMM2015v2.COF`, and  `WMM2020.COF` are the `.COF` files to use in `src/XYZgeomag.hpp`.\n\n## Run Tests\n\nIn the `extras` directory.\n\nCompile `geomag_test.cpp` for example with the command `g++ geomag_test.cpp -std=c++14`\n\nRun the tests for example with the command `./a.out`\n\nTo add new models to the test update `wmmtestgen.py` and run it.\n\n## References\n\nUsing spherical harmonics algorithm, described in sections 3.2.4 and 3.2.5:\n\n  Satellite Orbits Models, Methods and Applications,\n    by Oliver Montenbruck and Eberhard Gill 2000\n    \nUsing geodetic2ecef algorithm from https://geographiclib.sourceforge.io/\n\nUsing coefficients and test points from:\n\nNOAA NCEI Geomagnetic Modeling Team; British Geological Survey. 2024: World Magnetic Model 2025. NOAA National Centers for Environmental Information. https://doi.org/10.25921/aqfd-sd83. Accessed [22 DEC 2024].\n\nNCEI Geomagnetic Modeling Team and British Geological Survey. 2019. World Magnetic Model 2020. NOAA National Centers for Environmental Information. doi: 10.25921/11v3-da71, 2020, [10 DEC 2019].\n\nChulliat, A., W. Brown, P. Alken, S. Macmillan, M. Nair, C. Beggan, A. Woods, B. Hamilton, B. Meyer and R. Redmon, 2019, Out-of-Cycle Update of the US/UK World Magnetic Model for 2015-2020: Technical Note, National Centers for Environmental Information, NOAA. doi: 10.25921/xhr3-0t19.\n\nChulliat, A., S. Macmillan, P. Alken, C. Beggan, M. Nair, B. Hamilton, A. Woods, V. Ridley, S. Maus and A. Thomson, 2015. The US/UK World Magnetic Model for 2015-2020: Technical Report, NOAA National Geophysical Data Center, Boulder, CO, doi: 10.7289/V5TB14V7.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnhz2%2Fxyzgeomag","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnhz2%2Fxyzgeomag","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnhz2%2Fxyzgeomag/lists"}