{"id":17618237,"url":"https://github.com/sebsebmc/starlink-coverage","last_synced_at":"2025-04-30T16:07:29.818Z","repository":{"id":47554289,"uuid":"272094811","full_name":"sebsebmc/starlink-coverage","owner":"sebsebmc","description":"Calculating some statistics about Starlink satellites","archived":false,"fork":false,"pushed_at":"2023-05-01T16:44:51.000Z","size":10338,"stargazers_count":68,"open_issues_count":15,"forks_count":15,"subscribers_count":7,"default_branch":"master","last_synced_at":"2025-03-30T17:44:42.673Z","etag":null,"topics":["cesiumjs","h3","skyfield","starlink"],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/sebsebmc.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"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":"2020-06-13T22:22:14.000Z","updated_at":"2024-11-03T15:59:26.000Z","dependencies_parsed_at":"2024-10-23T02:21:03.651Z","dependency_job_id":"9f67a36c-ddd8-4f5d-ae64-ba8880643189","html_url":"https://github.com/sebsebmc/starlink-coverage","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sebsebmc%2Fstarlink-coverage","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sebsebmc%2Fstarlink-coverage/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sebsebmc%2Fstarlink-coverage/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sebsebmc%2Fstarlink-coverage/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/sebsebmc","download_url":"https://codeload.github.com/sebsebmc/starlink-coverage/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":251738890,"owners_count":21635890,"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","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":["cesiumjs","h3","skyfield","starlink"],"created_at":"2024-10-22T19:28:05.138Z","updated_at":"2025-04-30T16:07:29.741Z","avatar_url":"https://github.com/sebsebmc.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Goals:\r\n\r\n1. % of day covered\r\n2. Average coverage - factoring the number of satellites covering a location which would be more useful for approximating average bandwith available for an area\r\n\r\n## Original Implementation\r\n\r\n1. TLE to simulate satellites\r\n2. Altitude,x,y to conical section on sphere\r\n    1. Adjustable minimum elevation\r\n    2. Swap out for more accurate model of earth (WGS-84 ellipsoid)\r\n3. Map conical section to equi-rectangular area\r\n4. Translate to pixel coords with resolution of about 100sq mi\r\n5. Normalize? Overlay\r\n\r\nFor the core there is this naive implementation:\r\n\r\n```\r\nfor each time step:\r\n    for each pixel:\r\n        convert to lat/long\r\n        for each sat:\r\n            if visible\r\n                increase counter for pixel\r\n```\r\n\r\nThis seems like a pretty gross way to do it. We touch every pixel \\* numSats, when we could reduce to\r\nnumSats \\* visible area. However, the math to calculate visible area for a satellite doesn't seem to\r\nbe a part of any library I've found. This is even more relevant with VLEO satellites since they cover\r\nso much less area. I'm not sure how efficient it is to go from sphere to lat/long\r\non an equi-rectangular projection.\r\n\r\n## Resolution\r\n\r\n2 options for spatial resolution in my head originally:\r\n- 2048 x 1024 = 2,097,152\r\n- 4096 x 2048 = 8,388,608‬\r\n\r\nInstead of trying to use a 2d array to represent the footprints and dealing with the spherical nature\r\nof the Earth, I am instead going to try and use S2 level 9 cells to track coverage. According to the\r\nstatistics page of the S2 library, this is about 1537000 cells, so I would need about 12MB of data to\r\ntrack the whole Earth. Each cell covers 324.29km^2 on average.\r\n\r\nFor temporal resolution:\r\nThese satellites move across a location quite quickly, using a website like https://findstarlink.com\r\nwe can find that a whole \"train\" of Starlink satellites crosses a locations view in about 4 or 5 minutes\r\nso our temporal resolution needs to be a minute if not faster if we want accurate results. \r\n\r\n## S2 based approach\r\nThe original implementation has lots of gross properties and requires dealing with many projections.\r\nSo I tried using a new approach that used ~ equal area tesselated grids. The one I knew about was S2 so I tried that first.\r\n```\r\nfor each time step:\r\n    for each sat:\r\n        calculate footprint\r\n        get cells to cover footprint\r\n        for each cell:\r\n            increment counter\r\n```\r\n\r\nThis means we only have to iterate over ~2000 (+/-600?) cells per satellite instead of ~2 million \r\npoints each. However, this approach seems too slow. Comptuing all the covering cells of each satellite\r\ntakes about 90s on a single core in Python. While this could be parallelized, I think maybe there\r\nare even smarter approaches to consider. Could we maybe just store S2Cap objects and test points\r\nagainst them to count the amount of coverage? What I really like from S2 is that it handles the\r\nissues of latitude and longitude meaning different distances at the equator vs the poles.\r\n\r\nIn the end for plotting, if we used the cell vertices as plotting locations we would cover the whole\r\nglobe and not oversample at the poles or undersample at the equator.\r\n\r\n## S2, more like 2Slow... An H3 approach\r\nSo S2 was just being way to slow to return cells for a given covering. (90s to simulate one timestep)\r\nNow I have to make some guesses about projections for H3 and but it is ~4.5 times faster to simulate \r\na timestep than S2 (now takes 20 seconds on my machine). I'm gonna proceed with the H3 approach for\r\nnow.\r\n\r\n## Used constants\r\n\r\n- Earth Mean Equitorial Radius = 6,378.1km\r\n- Minimum angle for user terminals = 35deg\r\n\r\n(It has recently come to my attention that there may be newer data from SpaceX that the minimum user terminal angle would be 25 degrees, so my data may be more conservative. The data I used is from the FCC document linked below.)\r\n\r\n## Starlink details\r\n\r\nFrom the second reference below I found that Starlink is targeting user terminal minimum angles of 35deg\r\nThis means that each satellite covers around 600,000km^2 at an altitude of about 340km. However, most of\r\nthe starlink satellites already in space are elevating or are at 550 km\r\n\r\nStralink TLE's\r\nhttps://celestrak.com/NORAD/elements/starlink.txt\r\n\r\n### References\r\n\r\n- https://arxiv.org/pdf/1906.12318.pdf\r\n- https://licensing.fcc.gov/myibfs/download.do?attachment_key=1190019\r\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsebsebmc%2Fstarlink-coverage","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsebsebmc%2Fstarlink-coverage","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsebsebmc%2Fstarlink-coverage/lists"}