Sylphase SDGPS
The software-defined GPS(/GNSS) toolkit
solution

The solution interface describes the trajectory of a point or a rigid body. If the motion of only a point is being described, then the position and velocity of the point are provided at evenly-spaced time instants. If a rigid body is being described, then the orientation and angular velocity of the body are also included.

The following nodes consume or generate solution streams:

Node Node
generate-simple-trajectory Generates a rigid-body solution stream
kf2 / static-kf2 Generates a rigid-body solution stream
simple-pvt-solver Generates a point solution stream
simulate-INTERFACE Consumes a rigid-body solution stream
plot-solution Consumes any solution stream
pretty-print Consumes any solution stream

You can run ...

sdgps generate-simple-trajectory --angular-velocity-enu '[0,0,1]' ! pretty-print

... to see an example of a rigid-body solution stream. Note that the output of the pretty-print node is not itself a valid solution stream (e.g. because newlines are inserted in the middle of packets to make them more readable). Use ...

sdgps generate-simple-trajectory --angular-velocity-enu '[0,0,1]' ! write-solution-file test.sol

... to generate a valid solution stream file.

Format

The solution interface representation consists of one or more newline-delimited JSON Objects. Unix-style line endings (\n) are used.

The first line contains a header with the following keys:

Key Type Unit Required Description
type String Yes Stream type and format version. Must be solution_v3.
sample_rate Real Hz Yes The rate of trajectory samples in the following stream
metadata Object No Information about the program and command that were used to generate the file

All subsequent lines contain packets, which are the trajectory sampled at a given time t = index / sample_rate. The sample packets have the following keys:

Key Type Unit Required Description
index Integer Yes Zero-based index of sample packet; must start at 0 and increment by 1 with every packet
running Boolean Yes true if a solution is available
running_reason String Iff running is false Reason that running is false
Example: "not enough SVs being tracked"
time Object seconds Iff running is true GPS Time (represented as an Object with "sec" and "fs" keys, representing integer seconds + femtoseconds)
Example: {"sec": 1813335305, "fs": 770000000000000}
position_ecef 3-vector meters Iff running is true Position of body origin in ECEF frame
Example: [ 740883.0, -5497747.0, 3136908.0 ]
velocity_ecef 3-vector meters Iff running is true Velocity of body origin in ECEF frame
orientation_ecef quaternion Iff running is true and
this is a rigid-body stream
Quaternion that rotates body-frame vectors into ECEF frame
Example: {"w": -0.850, "x": -0.477, "y": -0.157, "z": 0.159}
angular_velocity_body 3-vector radians/second Iff running is true and
this is a rigid-body stream
Angular velocity of body frame with respect to ECEF frame, given in body frame
Example: [ 0.0, 0.0, 1.0 ]

iff stands for if and only if.

Sample

The following was produced as the output of sdgps generate-simple-trajectory --duration 1 --rate 10 ! write-solution-file test.sol --allow-overwrite:

{"metadata":{"cmdline":["sdgps","generate-simple-trajectory","--duration","1","--sample-rate","10","!","write-solution-file","test.sol","--allow-overwrite"],"source":"sdgps","source_version":"7f049d1a4-dirty\n"},"sample_rate":10.000000000000000,"type":"solution_v3"}
{"angular_velocity_body":[0.0000000000000000,0.0000000000000000,0.0000000000000000],"index":0,"orientation_ecef":{"w":0.86256464144857614,"x":0.50150075911832626,"y":0.033639382315581993,"z":0.057858619788739664},"position_ecef":[740883.00000000000,-5497747.0000000000,3136908.0000000000],"running":true,"time":{"fs":0,"sec":1813335300},"velocity_ecef":[0.0000000000000000,0.0000000000000000,0.0000000000000000]}
{"angular_velocity_body":[0.0000000000000000,0.0000000000000000,0.0000000000000000],"index":1,"orientation_ecef":{"w":0.86256464144857614,"x":0.50150075911832626,"y":0.033639382315581993,"z":0.057858619788739664},"position_ecef":[740883.00000000000,-5497747.0000000000,3136908.0000000000],"running":true,"time":{"fs":100000000000000,"sec":1813335300},"velocity_ecef":[0.0000000000000000,0.0000000000000000,0.0000000000000000]}
{"angular_velocity_body":[0.0000000000000000,0.0000000000000000,0.0000000000000000],"index":2,"orientation_ecef":{"w":0.86256464144857614,"x":0.50150075911832626,"y":0.033639382315581993,"z":0.057858619788739664},"position_ecef":[740883.00000000000,-5497747.0000000000,3136908.0000000000],"running":true,"time":{"fs":200000000000000,"sec":1813335300},"velocity_ecef":[0.0000000000000000,0.0000000000000000,0.0000000000000000]}
{"angular_velocity_body":[0.0000000000000000,0.0000000000000000,0.0000000000000000],"index":3,"orientation_ecef":{"w":0.86256464144857614,"x":0.50150075911832626,"y":0.033639382315581993,"z":0.057858619788739664},"position_ecef":[740883.00000000000,-5497747.0000000000,3136908.0000000000],"running":true,"time":{"fs":300000000000000,"sec":1813335300},"velocity_ecef":[0.0000000000000000,0.0000000000000000,0.0000000000000000]}
{"angular_velocity_body":[0.0000000000000000,0.0000000000000000,0.0000000000000000],"index":4,"orientation_ecef":{"w":0.86256464144857614,"x":0.50150075911832626,"y":0.033639382315581993,"z":0.057858619788739664},"position_ecef":[740883.00000000000,-5497747.0000000000,3136908.0000000000],"running":true,"time":{"fs":400000000000000,"sec":1813335300},"velocity_ecef":[0.0000000000000000,0.0000000000000000,0.0000000000000000]}
{"angular_velocity_body":[0.0000000000000000,0.0000000000000000,0.0000000000000000],"index":5,"orientation_ecef":{"w":0.86256464144857614,"x":0.50150075911832626,"y":0.033639382315581993,"z":0.057858619788739664},"position_ecef":[740883.00000000000,-5497747.0000000000,3136908.0000000000],"running":true,"time":{"fs":500000000000000,"sec":1813335300},"velocity_ecef":[0.0000000000000000,0.0000000000000000,0.0000000000000000]}
{"angular_velocity_body":[0.0000000000000000,0.0000000000000000,0.0000000000000000],"index":6,"orientation_ecef":{"w":0.86256464144857614,"x":0.50150075911832626,"y":0.033639382315581993,"z":0.057858619788739664},"position_ecef":[740883.00000000000,-5497747.0000000000,3136908.0000000000],"running":true,"time":{"fs":600000000000000,"sec":1813335300},"velocity_ecef":[0.0000000000000000,0.0000000000000000,0.0000000000000000]}
{"angular_velocity_body":[0.0000000000000000,0.0000000000000000,0.0000000000000000],"index":7,"orientation_ecef":{"w":0.86256464144857614,"x":0.50150075911832626,"y":0.033639382315581993,"z":0.057858619788739664},"position_ecef":[740883.00000000000,-5497747.0000000000,3136908.0000000000],"running":true,"time":{"fs":700000000000000,"sec":1813335300},"velocity_ecef":[0.0000000000000000,0.0000000000000000,0.0000000000000000]}
{"angular_velocity_body":[0.0000000000000000,0.0000000000000000,0.0000000000000000],"index":8,"orientation_ecef":{"w":0.86256464144857614,"x":0.50150075911832626,"y":0.033639382315581993,"z":0.057858619788739664},"position_ecef":[740883.00000000000,-5497747.0000000000,3136908.0000000000],"running":true,"time":{"fs":800000000000000,"sec":1813335300},"velocity_ecef":[0.0000000000000000,0.0000000000000000,0.0000000000000000]}
{"angular_velocity_body":[0.0000000000000000,0.0000000000000000,0.0000000000000000],"index":9,"orientation_ecef":{"w":0.86256464144857614,"x":0.50150075911832626,"y":0.033639382315581993,"z":0.057858619788739664},"position_ecef":[740883.00000000000,-5497747.0000000000,3136908.0000000000],"running":true,"time":{"fs":900000000000000,"sec":1813335300},"velocity_ecef":[0.0000000000000000,0.0000000000000000,0.0000000000000000]}

Sample (pretty-printed with an external tool)

This is the same data, but pretty-printed for ease of reading. Note that it SDGPS will not accept it due to the newlines present within the header and packets.

{
"metadata" : {
"cmdline" : [
"sdgps",
"generate-simple-trajectory",
"--duration",
"1",
"--sample-rate",
"10",
"!",
"write-solution-file",
"test.sol",
"--allow-overwrite"
],
"source" : "sdgps",
"source_version" : "7f049d1a4-dirtyn"
},
"sample_rate" : 10,
"type" : "solution_v3"
}
{
"angular_velocity_body" : [
0,
0,
0
],
"index" : 0,
"orientation_ecef" : {
"w" : 0.862564641448576,
"x" : 0.501500759118326,
"y" : 0.033639382315582,
"z" : 0.0578586197887397
},
"position_ecef" : [
740883,
-5497747,
3136908
],
"running" : true,
"time" : {
"fs" : 0,
"sec" : 1813335300
},
"velocity_ecef" : [
0,
0,
0
]
}
{
"angular_velocity_body" : [
0,
0,
0
],
"index" : 1,
"orientation_ecef" : {
"w" : 0.862564641448576,
"x" : 0.501500759118326,
"y" : 0.033639382315582,
"z" : 0.0578586197887397
},
"position_ecef" : [
740883,
-5497747,
3136908
],
"running" : true,
"time" : {
"fs" : 100000000000000,
"sec" : 1813335300
},
"velocity_ecef" : [
0,
0,
0
]
}
{
"angular_velocity_body" : [
0,
0,
0
],
"index" : 2,
"orientation_ecef" : {
"w" : 0.862564641448576,
"x" : 0.501500759118326,
"y" : 0.033639382315582,
"z" : 0.0578586197887397
},
"position_ecef" : [
740883,
-5497747,
3136908
],
"running" : true,
"time" : {
"fs" : 200000000000000,
"sec" : 1813335300
},
"velocity_ecef" : [
0,
0,
0
]
}
{
"angular_velocity_body" : [
0,
0,
0
],
"index" : 3,
"orientation_ecef" : {
"w" : 0.862564641448576,
"x" : 0.501500759118326,
"y" : 0.033639382315582,
"z" : 0.0578586197887397
},
"position_ecef" : [
740883,
-5497747,
3136908
],
"running" : true,
"time" : {
"fs" : 300000000000000,
"sec" : 1813335300
},
"velocity_ecef" : [
0,
0,
0
]
}
{
"angular_velocity_body" : [
0,
0,
0
],
"index" : 4,
"orientation_ecef" : {
"w" : 0.862564641448576,
"x" : 0.501500759118326,
"y" : 0.033639382315582,
"z" : 0.0578586197887397
},
"position_ecef" : [
740883,
-5497747,
3136908
],
"running" : true,
"time" : {
"fs" : 400000000000000,
"sec" : 1813335300
},
"velocity_ecef" : [
0,
0,
0
]
}
{
"angular_velocity_body" : [
0,
0,
0
],
"index" : 5,
"orientation_ecef" : {
"w" : 0.862564641448576,
"x" : 0.501500759118326,
"y" : 0.033639382315582,
"z" : 0.0578586197887397
},
"position_ecef" : [
740883,
-5497747,
3136908
],
"running" : true,
"time" : {
"fs" : 500000000000000,
"sec" : 1813335300
},
"velocity_ecef" : [
0,
0,
0
]
}
{
"angular_velocity_body" : [
0,
0,
0
],
"index" : 6,
"orientation_ecef" : {
"w" : 0.862564641448576,
"x" : 0.501500759118326,
"y" : 0.033639382315582,
"z" : 0.0578586197887397
},
"position_ecef" : [
740883,
-5497747,
3136908
],
"running" : true,
"time" : {
"fs" : 600000000000000,
"sec" : 1813335300
},
"velocity_ecef" : [
0,
0,
0
]
}
{
"angular_velocity_body" : [
0,
0,
0
],
"index" : 7,
"orientation_ecef" : {
"w" : 0.862564641448576,
"x" : 0.501500759118326,
"y" : 0.033639382315582,
"z" : 0.0578586197887397
},
"position_ecef" : [
740883,
-5497747,
3136908
],
"running" : true,
"time" : {
"fs" : 700000000000000,
"sec" : 1813335300
},
"velocity_ecef" : [
0,
0,
0
]
}
{
"angular_velocity_body" : [
0,
0,
0
],
"index" : 8,
"orientation_ecef" : {
"w" : 0.862564641448576,
"x" : 0.501500759118326,
"y" : 0.033639382315582,
"z" : 0.0578586197887397
},
"position_ecef" : [
740883,
-5497747,
3136908
],
"running" : true,
"time" : {
"fs" : 800000000000000,
"sec" : 1813335300
},
"velocity_ecef" : [
0,
0,
0
]
}
{
"angular_velocity_body" : [
0,
0,
0
],
"index" : 9,
"orientation_ecef" : {
"w" : 0.862564641448576,
"x" : 0.501500759118326,
"y" : 0.033639382315582,
"z" : 0.0578586197887397
},
"position_ecef" : [
740883,
-5497747,
3136908
],
"running" : true,
"time" : {
"fs" : 900000000000000,
"sec" : 1813335300
},
"velocity_ecef" : [
0,
0,
0
]
}