Protobuf
Here is the protobuf file that you will need to encode your trajectories. Create the proto trajectory and then send the data as a binary file to the API. You can read more about protobuf from here
Running locally
For debugging it might be simple to use Python on your local machine. You can install the protobuf-compiler from github. We suggest using version 3.0
https://github.com/protocolbuffers/protobuf/releases?expanded=true&page=3&q=3.0. Be careful if you use a package manager installation method such as apt
as it may be a more recent version that breaks the protocol running on the server.
And then generate a protobug python class using the command line and the below specification (saved locally on your machine as traj.proto)
protoc --proto_path=my_base_path --python_out=my_output_path traj.proto
You can then make protobuf packets quite simply in python and test the dummy API to verify your approach
import <path_to_class_that_you_generated> as Traj
traj = Traj.Trajectory()
pdr = generate_my_awesome_pdr()
for _, row in pdr.iterrows():
pdr_data = Traj.Pdr_Sample()
pdr_data.x = row.x
pdr_data.y = row.y
pdr_data.relative_timestamp = int(row.timestamp)
traj.pdr_data.extend([pdr_data])
# Add rest of the data...
You can send the data to the API using requests
import requests
outpath = 'proto_packet.pkt'
with open(outpath, "wb") as f:
f.write(bin)
headers = {
'accept': 'application/json',
}
files = {
'file': open('proto_packet.pkt', 'rb'),
}
response = requests.post('https://openpositioning.org/api/dummy/trajectory/upload/', headers=headers, files=files )
Or you can do it via curl
curl -X 'POST' \
'https://openpositioning.org/api/dummy/trajectory/upload/' \
-H 'accept: application/json' \
-H 'Content-Type: multipart/form-data' \
-F 'file=@proto_packet.pkt'
Protobuf specification
Create your packets to this specification and you should have no trouble sending the data to the API. This version of protobuf has no restrictions on optional/required fields. But we will validate the existence and quality of some of the fields when you send your data in. The server will let you know if it thinks there are issues with your data.
syntax = "proto3";
message Trajectory {
string android_version = 1;
repeated Motion_Sample imu_data = 2;
repeated Pdr_Sample pdr_data = 3;
repeated Position_Sample position_data = 4;
repeated Pressure_Sample pressure_data = 5;
repeated Light_Sample light_data = 6;
repeated GNSS_Sample gnss_data = 7;
repeated WiFi_Sample wifi_data = 8;
repeated AP_Data aps_data = 9;
// UNIX timestamp (in milliseconds) recorded from the start of this
// trajectory data collection event. All future
// timestamps in sub classes are to be RELATIVE timestamps
// (in milliseconds) to this start time.
// E.g.
// start_timestamp = 1674819807315 (UTC 27 Jan 2023 in the morning)
// relative_timestamp = 3000 (3s)
int64 start_timestamp = 10;
string data_identifier = 11;
Sensor_Info accelerometer_info = 12;
Sensor_Info gyroscope_info = 13;
Sensor_Info rotation_vector_info = 14;
Sensor_Info magnetometer_info = 15;
Sensor_Info barometer_info = 16;
Sensor_Info light_sensor_info = 17;
}
message Pdr_Sample {
// milliseconds from the start_timestamp
int64 relative_timestamp = 1;
// Both in metres. You should implement an algorithm to estimate
// these values. The values are always relative to your start point
// so the first entry should always be x = 0.0, y = 0.0
float x = 2;
float y = 3;
}
message Motion_Sample {
// milliseconds
int64 relative_timestamp = 1;
// m/s^2
float acc_x = 2;
float acc_y = 3;
float acc_z = 4;
// radians/s
float gyr_x = 5;
float gyr_y = 6;
float gyr_z = 7;
// unitless, 4 components should sum to ~1
float rotation_vector_x = 8;
float rotation_vector_y = 9;
float rotation_vector_z = 10;
float rotation_vector_w = 11;
// Integer
int32 step_count = 12;
}
message Position_Sample {
int64 relative_timestamp = 1;
// uT
float mag_x = 2;
float mag_y = 3;
float mag_z = 4;
}
message Pressure_Sample {
int64 relative_timestamp = 1;
// mbar
float pressure = 2;
}
message Light_Sample {
int64 relative_timestamp = 1;
// lux
float light = 2;
}
message GNSS_Sample {
int64 relative_timestamp = 1;
// degrees (minimum 6 significant figures)
// latitude between -90 and 90
float latitude = 2;
// longitude between -180 and 180
float longitude = 3;
//metres
float altitude = 4;
// metres
float accuracy = 5;
// m/s
float speed = 6;
// e.g 'gps' or 'network'
string provider = 7;
}
message WiFi_Sample {
int64 relative_timestamp = 1;
repeated Mac_Scan mac_scans = 2;
}
message Mac_Scan {
int64 relative_timestamp = 1;
// Integer encoding of the hex mac address
// e.g. 207394925843984
int64 mac = 2;
// rssi integer in dBm.
// typically between -120 and -10
int32 rssi = 3;
}
message AP_Data {
// Integer encoding of the hex mac address
// e.g. 207394925843984
int64 mac = 1;
// E.g. 'Eduroam' or 'Starbucks_free_wifi'
string ssid = 2;
// Typically 2.4GHz or 5GHz
int64 frequency = 3;
}
message Sensor_Info {
string name = 1;
string vendor = 2;
float resolution = 3;
float power = 4;
int32 version = 5;
int32 type = 6;
}