This repository contains the implementation and artifacts for the paper Trajectory-based Serving Satellite Identification with User Terminal's Field-of-View accepted in LEO-NET'24.
Since the Starlink dish firmware update (286014e2-fea5-46e5-805f-85cd72450533.uterm_manifest.release
) in August 2024, a new mapReferenceFrame
field was introduced to the output of the dish_get_obstruction_map
gRPC call.
type ObstructionMapReferenceFrame int32
const (
ObstructionMapReferenceFrame_FRAME_UNKNOWN ObstructionMapReferenceFrame = 0
ObstructionMapReferenceFrame_FRAME_EARTH ObstructionMapReferenceFrame = 1
ObstructionMapReferenceFrame_FRAME_UT ObstructionMapReferenceFrame = 2
)
// Enum value maps for ObstructionMapReferenceFrame.
var (
ObstructionMapReferenceFrame_name = map[int32]string{
0: "FRAME_UNKNOWN",
1: "FRAME_EARTH",
2: "FRAME_UT",
}
ObstructionMapReferenceFrame_value = map[string]int32{
"FRAME_UNKNOWN": 0,
"FRAME_EARTH": 1,
"FRAME_UT": 2,
}
)
Example output from grpcurl -plaintext -d {\"dish_get_obstruction_map\":{}} 192.168.100.1:9200 SpaceX.API.Device.Device/Handle
:
{
"apiVersion": "26",
"dishGetObstructionMap": {
"numRows": 123,
"numCols": 123,
"snr": [
-1,
...
-1
],
"minElevationDeg": 10,
"maxThetaDeg": 80,
"mapReferenceFrame": "FRAME_UT"
}
}
Based on our measurement and observation, the mapReferenceFrame
specifies the coordinate system used for the obstruction map data.
The possible values for mapReferenceFrame
are:
- FRAME_UNKNOWN (0): The reference frame is unspecified.
- FRAME_EARTH (1): The obstruction map is aligned with the Earth and uses a fixed geographic coordinate system, with the top center pixel oriented toward the true north.
- FRAME_UT (2): The obstruction map is aligned with the User Terminal, using a coordinate system relative to the dish's orientation. The bottom center pixel corresponds to the UT's boresight direction.
Our observation shows that most active Starlink dishes show FRAME_EARTH
, most likely because they are in fixed, stationary locations and utilize a geographic coordinate system to track obstructions more efficiently, while dishes on Roam
/Mobile
or inactive dishes show FRAME_UT
, partially because these dishes are often moved or relocated, requiring a coordinate system relative to the dish’s orientation to adapt dynamically to changing positions or conditions.
Thus, in addition to the method presented in the LEO-NET'24 paper, we also included the data processing notebook for UTs using FRAME_EARTH
.
-
Clone the repository.
git clone --recurse-submodules https://github.com/aliahan/SatInView.git cd SatInView
-
Create a Python virtual environment and install dependencies.
python3 -m venv .venv source .venv/bin/activate pip install -r requirements.txt pip install -r starlink-grpc-tools/requirements.txt
Note: On a dual-homed machine connected to an inactive Starlink dish (i.e., without an active Starlink subscription), the Starlink router still advertises an IPv6 address to the local network.
Pip
would prefer to use IPv6 when installing packages, while an inactive dish cannot reach the Internet, which could halt the installation process. In this case, you can forcepip
to use IPv4 by setting the IPv4 addresses for the following domains in/etc/hosts
or configure routing properly.151.101.0.223 pypi.org 151.101.68.223 files.pythonhosted.org
-
Install
grpcurl
from https://github.com/fullstorydev/grpcurl to your$PATH
.
- Edit
config.py
, and setIFCE
to the interface connected to Starlink. SetDISH_ID
to the ID of the dish. - If IRTT tests are used, set
ENABLE_IRTT
toTrue
, setLOCAL_IP
to the local IP address for the Starlink interfaceIFCE
, and setIRTT_SERVER_PORT
to the IRTT server address and port. - The gateway of inactive Starlink dishes can be reached at
fe80::200:5eff:fe00:101
, which requires the stock Starlink router to be set in thebypass
mode. - You may need to install the
iputils-ping
package instead of theinetutils-ping
package on Debian-based systems to use the-D
timestamp option.
apt list --installed | grep ping
-
You may also need to assign root privileges to the
ping
command to use the packet intervals less than 200ms or installiputils-ping>=20210722
, which lowered the limit to 2ms. -
By default, task scheduling is defined in
main.py
as follows, which can be modified as needed.
if ENABLE_IRTT:
schedule.every(1).hours.at(":00").do(run, irtt_ping).tag("Latency")
schedule.every(1).hours.at(":00").do(run, icmp_ping).tag("Latency")
schedule.every(1).hours.at(":00").do(run, grpc_get_status).tag("gRPC")
schedule.every(6).hours.at(":00").do(run, load_satellites).tag("TLE")
schedule.every(1).hours.at(":00").do(run, collect_obstruction_data).tag("TLE")
You can get the GPS location of your dish by running the following command, which requires the Allow access on local network
option to be enabled in the Starlink app at Advanced
-> Debug data
-> Starlink location
.
grpcurl -plaintext -d {\"get_location\":{}} 192.168.100.1:9200 SpaceX.API.Device.Device/Handle
The GPS location is required to calculate and estimate the selected and serving satellites in post-processing.
Run main.py
to collect the latency data to the Starlink gateway (100.64.0.1
) and the satellite trajectory data from the obstruction map.
By default, the data structure of the collected data is as follows:
data
├── grpc
│ └── 2024-10-08
│ └── GetStatus-2024-10-08-19-10-00.txt
├── latency
│ └── 2024-10-08
│ ├── irtt-10ms-5m-2024-10-08-19-10-00.json
│ └── ping-10ms-5m-2024-10-08-19-10-00.txt
└── TLE
└── 2024-10-08
├── obstruction-data-<dish_id>-2024-10-08-19-10-01.csv
└── starlink-tle-2024-10-08-19-10-00.txt
- The
grpc
directory contains the dish diagnostic and alignment data from Starlink dish's gRPC interface (192.168.100.1:9200
). - The
latency
directory contains the ICMP ping RTT measurement to Starlink's gateway. When IRTT test is enabled, the IRTT measurement data is stored in the same directory after each round finishes. - The
TLE
directory contains the collected obstruction and satellite trajectory data and the TLE snapshots of all Starlink satellites from Celestrak.
Thank you for your interest in our work. To replicate our results precisely, you will need to have the exact GPS location, UT orientation, and TLE data from the specific time of observation for that UT. Due to privacy concerns, I cannot share this information. However, I encourage you to gather data from your own UT and attempt to replicate the results at your location.
After gathering the data, run findmatch-FrameUT.ipynb
notebook if your dish uses FRAME_UT
or findmatch-FrameEarth.ipynb
notebook if your dish uses FRAME_EARTH
, to first create the processed_observed_data.csv
containing the topocentric coordinates of the observed satellites and then to find
the matching satellites and have the matched_satellite_data.csv
dataset.
Ensure you set your location, dish orientation, and data collection time in the code accordingly, and use the TLE data from the exact time of data collection.
To re-generate the figures in the paper you can run the figure.ipynb
notebook.