{"id":22835985,"url":"https://github.com/ysoldak/magcal","last_synced_at":"2026-01-16T16:27:40.615Z","repository":{"id":57638282,"uuid":"429214885","full_name":"ysoldak/magcal","owner":"ysoldak","description":"(Magical) Magnetometer Calibration","archived":false,"fork":false,"pushed_at":"2021-11-29T23:41:41.000Z","size":26,"stargazers_count":7,"open_issues_count":2,"forks_count":1,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-08-10T21:34:30.943Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-3-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ysoldak.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}},"created_at":"2021-11-17T22:04:58.000Z","updated_at":"2025-05-13T07:48:05.000Z","dependencies_parsed_at":"2022-09-21T10:42:03.538Z","dependency_job_id":null,"html_url":"https://github.com/ysoldak/magcal","commit_stats":null,"previous_names":[],"tags_count":3,"template":false,"template_full_name":null,"purl":"pkg:github/ysoldak/magcal","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ysoldak%2Fmagcal","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ysoldak%2Fmagcal/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ysoldak%2Fmagcal/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ysoldak%2Fmagcal/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ysoldak","download_url":"https://codeload.github.com/ysoldak/magcal/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ysoldak%2Fmagcal/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28479852,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-16T11:59:17.896Z","status":"ssl_error","status_checked_at":"2026-01-16T11:55:55.838Z","response_time":107,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"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":[],"created_at":"2024-12-12T23:00:49.690Z","updated_at":"2026-01-16T16:27:40.596Z","avatar_url":"https://github.com/ysoldak.png","language":"Go","funding_links":[],"categories":["Embedded Systems"],"sub_categories":["Instrumentation and control with sensors and actuators"],"readme":"# (Magical) Magnetometer Calibration\n\nThis library provides hassle-free implicit real-time calibration of magnetometer for [portable devices](https://tinygo.org).  \n\nIdeally, no manual calibration shall be needed. The library eventually finds some good enough solution that can then be extracted and stored on device flash to warm-up the same library on the next boot.  \n_Flash manipulations are highly device specific, not covered here and shall be dealt separately._\n\nThe library can adapt to changing environment and provide stable low-error results on the go, something that is important for portable.\n\nInternally, the library applies [gradient descent](https://blog.skz.dev/gradient-descent) to task of finding magnetometer calibration parameters.  \nCalibration happens on background, continuously.  \nOptimising for embedded, we use `float32` instead of standard `float64`.  \n\n## Magnetometer calibration is a tedious task\n\nMagnetometer sensor returns a vector along [Earth's magnetic field](https://en.wikipedia.org/wiki/Earth%27s_magnetic_field).  \nReadings, collected while rotating the sensor around, shall produce points on a sensor-centered sphere.\n\nSensor, though, is affected by hard- and soft-iron effects.  \nThese effects distort sphere to something resembling an elongated melon, offset from origin too.\n\nThere is a [mathematical model that describes this distortion](https://www.vectornav.com/resources/inertial-navigation-primer/specifications--and--error-budgets/specs-hsicalibration) and a formula to bring raw readings back on centered sphere.  \nThe task of calibration is to find parameters for that formula, since every sensor is different and no two environments are the same.\n\nFirst, we need to collect some raw data to work with.  \nNext, one can try and solve the task analytically, in theory.  \nIn practice, due to noise in incoming data, it's more convenient to use classic gadient descent approach and find a solution that's _good enough_.\n\n## Continuous magnetometer calibration on background\n\nLibrary keeps current best state and applies calibration transformation to all incoming vectors.  \nIt also keeps a buffer of previous seen vectors for reference and use them to run gradient descent on.  \nVectors in the buffer are organised in quadrants and library tries to maintain diversity here, this helps with finding the best solution.\n\nAfter processing an incoming vector, library may trigger re-calibration on background.  \nThis heppens when length of resulting vector differs from target value too much.  \nIf that happens and no calibration is already running on background, this new vector is pushed to the buffer (releasing some another vector) and a goroutine starts that tries to reconcile vectors in the buffer with calibration state and find a solution that gives minimal error.\n\nThis library is targeted for [embedded systems](https://tinygo.org) with low resources there number or cores is usually limited to just one and no real parallelism possible (cooperative runtime). Thus, to let other processes to run smoothly, the background task can be throttled.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fysoldak%2Fmagcal","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fysoldak%2Fmagcal","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fysoldak%2Fmagcal/lists"}