Table of Contents |
---|
Introduction
FusionHub is a software application that has the purpose of combining a number of sensor data inputs to create a higher level information output. LPVR-POS is based on FusionHub and combines odometry, GPS and IMU data from a vehicle to calculate high-accuracy and low-latency global localization information. There is a range of typical applications such as automotive and robot localization.
...
Parameter name | Description | Default | ||
---|---|---|---|---|
type | Data output format for gnss data source. Currently only | NMEA | ||
port | Serial port number for gnss source. | baudrate | Serial port baudrate to connect to GNSS source.
| |
baudrate | Serial port baudrate to connect to GNSS source. | |||
rtcm | Set true to enable RTCM correction data forwarding from RTCM source to gnss module. | false |
Odometry
The vehicle source is the data source that reads raw CAN data messages from a given CAN bus interface and parses the vehicle data using to the provided CAN protocol.
This section explains how to set up the configuration for a custom CAN parsing node. Depending on the available information about the vehicle CAN protocol, there are three types of CAN parsing available.
Minimal
parsing where we only have information about the vehicle speed CAN message.External
separate four wheel speed parsing, velocity sign information may be added if the gear stick reading is available.ExternalWithSteering
parsing with steering model information, there are two ways to specify the steering tables depending on the information available:steering wheel angle vs (right or left) wheel angles
orsteering wheel angle vs average wheel angles
. Using this data we can perform linear interpolation to compute the wheel angles for any given steering angle and use it forAckermann
steering.
Info |
---|
In most cases, having the overall vehicle speed message or the separate wheel speed messages is more than enough and no steering information is needed. If available, the gear stick reading is useful to help identify the reverse driving. |
Minimal Vehicle Parsing
This parser only requires information about the overall vehicle speed message. So it only provide this data as input to the fusion algorithm. Even though this can be enough for some use cases, it may be better to provide separate wheel speeds to extract and use the vehicle angular velocity information as well.
...
Parameter name
...
Description
...
Default
...
canInterface
...
CAN bus interface, supported values are "PeakCAN"
and "Vector"
...
PeakCAN
...
vehicleType
...
"Minimal"
...
n/a
...
velocityCanId
...
CAN id for the velocities message
...
n/a
...
velocityScale
...
Value to multiply the parsed raw velocity by in order to get velocities in m/s.
...
1.0
...
velocityStartBit
...
Start bit of the vehicle wheel velocity.
...
0
...
velocityBitsLength
...
Number of bits used for wheel velocity encoding.
...
16
Configuration example
Code Block |
---|
"vehicle": {
"type": "Automotive",
"vehicleStateEndpoint": "tcp://*:8999",
"settings": {
"canInterface": "Internal",
"canEndpoint": "tcp://localhost:9921",
"vehicleType": "Minimal",
"canProtocol": {
"velocityCanId": 209,
"velocityScale": 0.015625012,
"endianness": "little",
"velocityBitsLength": 16,
"velocityStartBit": 0
}
}
} |
...
Parameter name
...
Description
...
Default
...
canInterface
...
CAN bus interface, supported values are "PeakCAN"
and "Vector"
...
PeakCAN
...
vehicleType
...
Used to specify the parser type, available values are:
"Minimal", "External"
and "ExternalWithSteering"
...
n/a
...
wheelBase
...
Distance between front and back wheels.
...
n/a
...
trackWidth
...
Distance between right and left back wheels.
...
n/a
...
velocityCanId
...
CAN id for the velocities message
...
n/a
...
velocityScale
...
Value to multiply the parsed raw velocities by in order to get velocities in m/s.
...
1.0
...
velocityStartBits
...
Within this parameter, one need to specify the starting bits of each wheel velocity "FrontLeftWheel", "FrontRightWheel", "RearLeftWheel"and "RearRightWheel"
.
...
0, 16, 32, 48
respectively.
...
velocityBitsLength
...
Number of bits used for each wheel velocity encoding.
...
16
...
endianness
...
Specify if the CAN data endianness is "little"
or "big"
.
...
little
...
driveModel
...
When no steering information is available, only Differential
model can be used.
...
Differential
...
canEndpoint
...
Output endpoint of Vehicle data. This parameter is optional.
...
tcp://*:8802
Configuration example
...
For details about the overall configuration of the RTK-GPS system refer to this section.
GNSS Output Format
JSON
Code Block |
---|
"gnssData": {
"altitude": 0.0,
"hdop": 0.0,
"heading": 0,
"latitude": 0.0,
"longitude": 0.0,
"height": 0.0,
"nSat": 0,
"orientation": {
"w": 1.0,
"x": 0.0,
"y": 0.0,
"z": 0.0
},
"quality": 0,
"sensorName": "",
"timestamp": 0,
"tmg": 0.0,
"undulation": 0.0
} |
Protobuf
Code Block |
---|
message GnssData {
int64 timestamp = 1;
double latitude = 3;
double longitude = 4;
double period = 5;
int32 frame_count = 6;
double latency = 8;
string sensor_name = 11;
Quaternion orientation = 12;
double height = 13;
double vertical_accuracy = 14;
double horizontal_accuracy = 15;
int32 quality = 16;
int32 n_sat = 17;
double hdop = 18;
double tmg = 19;
double heading = 20;
double altitude = 21;
double undulation = 22;
} |
Important Output Data
Parameter name | Description | Unit |
---|---|---|
timestamp | Timestamp of current GNSS data | nanoseconds (in case GPS time is used as clock this is the duration since start of the day in UTC time) |
longitude | Longitude part of GPS position | degree |
latitude | Latitude part of GPS position | degree |
height | The height of the receiver above the earth surface reference ellipsoid | m |
quality | Quality of the GPS signal: 0: Fix not valid | n/a (comment: for RTK enabled systems RTK fix provides the highest cm accuracy. If this quality can’t be reached, the number of visible satellites or connection to base station might be an issue.) |
Odometry
The vehicle source is the data source that reads raw CAN data messages from a given CAN bus interface and parses the vehicle data using to the provided CAN protocol.
This section explains how to set up the configuration for a custom CAN parsing node. Depending on the available information about the vehicle CAN protocol, there are three types of CAN parsing available.
Minimal
parsing where we only have information about the vehicle speed CAN message.External
separate four wheel speed parsing, velocity sign information may be added if the gear stick reading is available.ExternalWithSteering
parsing with steering model information, there are two ways to specify the steering tables depending on the information available:steering wheel angle vs (right or left) wheel angles
orsteering wheel angle vs average wheel angles
. Using this data we can perform linear interpolation to compute the wheel angles for any given steering angle and use it forAckermann
steering.
Info |
---|
In most cases, having the overall vehicle speed message or the separate wheel speed messages is more than enough and no steering information is needed. If available, the gear stick reading is useful to help identify the reverse driving. |
Minimal Vehicle Parsing
This parser only requires information about the overall vehicle speed message. So it only provide this data as input to the fusion algorithm. Even though this can be enough for some use cases, it may be better to provide separate wheel speeds to extract and use the vehicle angular velocity information as well.
Parameter name | Description | Default |
---|---|---|
canInterface | CAN bus interface, supported values are | PeakCAN |
vehicleType |
| n/a |
velocityCanId | CAN id for the velocities message | n/a |
velocityScale | Value to multiply the parsed raw velocity by in order to get velocities in m/s. | 1.0 |
velocityStartBit | Start bit of the vehicle wheel velocity. | 0 |
velocityBitsLength | Number of bits used for wheel velocity encoding. | 16 |
Configuration example
Code Block |
---|
"vehicle": { "type": "Automotive", "vehicleStateEndpoint": "tcp://*:8999", "settings": { "canInterface": "Internal", "canEndpoint": "tcp://localhost:9921", "vehicleType": "ExternalMinimal", "wheelBase": 2.750, "trackWidth": 1.595, " "canProtocol": { "velocityCanId": 212209, "velocityScale": 0.015625012, "endianness": "little", "velocityStartBits "velocityBitsLength": { "FrontLeftWheel16, "velocityStartBit": 0, } "FrontRightWheel": 16, "RearLeftWheel": 32, "RearRightWheel": 48 } } } } |
Additional Parameters
Gear Stick Position for Velocity Sign
If available, the gear stick reading data can be parsed to determine the velocity sign.
...
Parameter name
...
Description
...
Default
...
gearCanId
...
Gear stick message CAN id
...
n/a
...
gearStartBit
...
Gear stick message start bit
...
n/a
...
gearBitsLength
...
Number of bits used for gear stick message encoding.
...
n/a
...
gearReverseValue
...
Reverse driving gear stick value.
...
n/a
Configuration template
Code Block |
---|
"vehicle": {
...
"settings": {
...
"vehicleType": "External",
...
"canProtocol": {
...
},
"gearCanId": 1,
"gearStartBit": 2,
"gearBitslength": 3,
"gearReverseValue": 4
}
}
} |
Steering information for Ackermann model
...
}
} |
Vehicle Parsing with Separate Wheel Velocities
Anchor | ||||
---|---|---|---|---|
|
Parameter name | Description | Default |
---|---|---|
canInterface | CAN bus interface, supported values are | PeakCAN |
vehicleType | Used to specify the parser type, available values are:
| n/a |
wheelBase | Distance between front and back wheels. | n/a |
trackWidth | Distance between right and left back wheels. | n/a |
velocityCanId | CAN id for the velocities message | n/a |
velocityScale | Value to multiply the parsed raw velocities by in order to get velocities in m/s. | 1.0 |
velocityStartBits | Within this parameter, one need to specify the starting bits of each wheel velocity | 0, 16, 32, 48 respectively. |
velocityBitsLength | Number of bits used for each wheel velocity encoding. | 16 |
endianness | Specify if the CAN data endianness is | little |
driveModel | When no steering information is available, only | Differential |
canEndpoint | Output endpoint of Vehicle data. This parameter is optional. | tcp://*:8802 |
Configuration example
Code Block |
---|
"vehicle": {
"type": "Automotive",
"vehicleStateEndpoint": "tcp://*:8999",
"settings": {
"canInterface": "PeakCAN",
"canEndpoint": "tcp://localhost:9921",
"vehicleType": "External",
"wheelBase": 2.750,
"trackWidth": 1.595,
"canProtocol": {
"velocityCanId": 212,
"velocityScale": 0.015625012,
"endianness": "little",
"velocityStartBits": {
"FrontLeftWheel": 0,
"FrontRightWheel": 16,
"RearLeftWheel": 32,
"RearRightWheel": 48
}
}
}
} |
Additional Parameters
Gear Stick Position for Velocity Sign
If available, the gear stick reading data can be parsed to determine the velocity sign.
Parameter name | Description | Default |
---|
gearCanId |
Gear stick message CAN id | n/a | |
gearStartBit | Gear stick message start bit | n/a |
steeringScale
Value to multiply the parsed raw steering wheel angle by in order to get angle in degrees.
1.0
steeringWheelAngles
gearBitsLength | Number of bits used for gear stick message encoding. | n/a |
gearReverseValue | Reverse driving gear stick value. | n/a |
Configuration template
Configuration template
...
...
wheelAngleType
...
Specification of provided wheelAngles
type, valid options are "Right", "Left" or "Average"
...
n/a
...
wheelAngles
...
Steering table column containing corresponding wheel angle values.
...
n/a
...
driveModel
...
In addition to Differential
model, Ackermann
or SimpleAckermann
can be used. the latter is a version of Ackermann steering that uses the average wheel angles.
...
Differential
Code Block |
---|
"vehicle": {
...
"settings": {
...
"vehicleType": "External",
"canProtocol": {
"gearCanId": 1,
"gearStartBit": 2,
"gearBitslength": 3,
"gearReverseValue": 4
}
}
} |
Steering information for Ackermann model
If available, the steering wheel message can also be parsed but using it in the drive model requires input about the vehicle steering model as detailed below. Although we provide this option, using simpler drive models proved to work just fine.
Parameter name | Description | Default |
---|---|---|
steeringCanId | CAN id for the steering wheel angle message | n/a |
steeringScale | Value to multiply the parsed raw steering wheel angle by in order to get angle in degrees. | 1.0 |
steeringWheelAngles | The steering table column containing sample steering wheel angles. | n/a |
wheelAngleType | Specification of provided | n/a |
wheelAngles | Steering table column containing corresponding wheel angle values. | n/a |
driveModel | In addition to | Differential |
Configuration template
If the input steering table is like follows (note that the input table should contain values for both right and left turns aka: positive and negative steering wheel angles),
...
The steeringTable
configuration block would look something like below.
Code Block |
---|
"vehicle""vehicle": { ... "settings": { ... "vehicleType": "ExternalWithSteering", ... "canProtocol": { ... }, "steeringTable": { "steeringWheelAngles": [ -360, -340, -320, -300, ... ... 300 300, 320, 340, 360], "wheelAngleType": "Right", "wheelAngles": [ -30.0, -25.5, -20.0, -15.0, ... 19.0, 26.0, 35.5, 40.0 ] } } } } } } |
Predefined Vehicle Parsing
...
See a technical description of FusionHub’s communication interface in one of the following chapters.
JSON
Code Block |
---|
{ "fusedVehiclePose": { "acceleration": { "x": 0.0, "y": 0.0, "z": 0.0 }, "globalPosition": { "x": 0.0, "y": 0.0 }, "lastDataTime": { "timestamp": 0 }, "position": { "x": 0, "y": 0 }, "timestamp": { "timestamp": 0 }, "utmZone": "31T", "yaw": 0 } } |
Protobuf
Code Block |
---|
syntax = "proto3"; package Fusion.proto; message Vector2 { double x = 2; double y = 3; } message Vector { double x = 2; double y = 3; double z = 4; } message FusedVehiclePose { int64 timestamp = 1; Vector2 position = 2; Vector2 global_position = 3; double yaw = 4; string utm_zone = 5; int64 timecode = 6; // Optional: if 0 not set. Vector acceleration = 7; } message StreamData { int32 sequence_number = 1; FusedVehiclePose fused_vehicle_pose = 9; } |
...
Parameter name
...
Description
...
Unit
...
acceleration
...
3D acceleration vector as measured by IMU. Describes the orientation of the vehicle in the vehicle coordinate system.
...
m/s^2
...
globalPosition
...
Longitude and latitude in degrees
...
degrees
...
lastDataTime
...
Unused
...
s
...
position
...
Position relative to starting point with X pointing North and Y pointing East in the current UTM frame
...
m
...
timestamp
...
Timestamp of data acquisition
...
ns
...
utmZone
...
UTM zone
...
UTM string
...
yaw
...
Globally referenced yaw angle
...
rad
Info |
---|
After starting FusionHub, while the car is static, the filter will not deliver a correct yaw angle. The angle will be adjusted to the correct direction after a few seconds of driving the vehicle. |
Fusion Filter Option 2 - High-Dynamics Filter
General
The high dynamics filter combines IMU and GPS data to calculate the global position of a vehicle. Instead of using the odometry it uses IMU data to determine the orientation changes of a car on the X, Y and Z axis. The direction of the vehicle is globally referenced from the GPS system. For increasing the direction reference quality a dual-antenna GPS system can be used.
The high dynamics filter works well for scenarios with agressive driving maneuvers such as drifting and cornering. During such maneuvers the turning motion of the wheels generally doesn’t directly correspond with the direction of the vehicle. Therefore for this filter doesn’t rely on wheel velocity measurements. This filter uses information from the wheels to determine if the car has come to a full stop.
As the filter relies heavily on GPS measurements it doesn’t deliver good results indoors. The better the GPS reception, the better the resulting output of the filter. In it’s current state it therefore only works outdoors. In a future version that combines LD and HD filters, this issue will be resolved.
Notes on Filter Output
The HD filter outputs the following data:
fusedVehiclePose
(2D pose): Output equivalent to the LD filter output. Includes position in meters relative to starting point, global position (lon, lat) and heading.fusedPose
(3D pose): relative to starting point, x, y (in meters) + z (height) + 3D orientation quaternionglobalFusedPose:
globally referenced 3D position (longitude, latitude, height) + 3D orientation quaternion in ENU frame
Which filter output works best depends on your application. For augmented reality applications we reommend using globalFusedPose
.
You can find more information regarding the ENU coordinate system here.
Notes on IMU Arrangement
The used car frame is the Volkswagen (VW) coordinate frame convention:
Code Block |
---|
VW frame
x: back
y: right
z: up |
...
The IMU sensor can be mounted in any way but the ImuToCarRotation
quaternion needs to be provided to transform the IMU data into VW frame. For example, if the IMU is mounted like follows:
Code Block |
---|
IMU mounting
x: forward
y: left
z: up |
To match the VW frame, we need a 180° rotation around the z axis (clockwise). Therefore, the rotation matrix would be:
Code Block |
---|
[ -1, 0, 0;
0, -1, 0;
0, 0, 1 ] |
And the orientation quaternion woud be [x, y, z, w] = [ 0, 0, 1, 0 ]
which can be specified in the configuration like below:
Code Block |
---|
"imuToCarRotation": {
"w": 0,
"x": 0,
"y": 0,
"z": 1
} |
Check this page for more information on how to calculate the orientation quaternion.
Configuration Block
Insert the following configuration block into your config.json
file in the sinks
section to activate the HD filter. The filter's node name is gnssImuFusion
.
Code Block |
---|
..
"sinks |
Parameter name | Description | Unit |
---|---|---|
acceleration | 3D acceleration vector as measured by IMU. Describes the orientation of the vehicle in the vehicle coordinate system. | m/s^2 |
globalPosition | Longitude and latitude in degrees | degrees |
lastDataTime | Unused | s |
position | Position relative to starting point with X pointing North and Y pointing East in the current UTM frame | m |
timestamp | Timestamp of data acquisition | ns |
utmZone | UTM zone | UTM string |
yaw | Globally referenced yaw angle | rad |
Info |
---|
After starting FusionHub, while the car is static, the filter will not deliver a correct yaw angle. The angle will be adjusted to the correct direction after a few seconds of driving the vehicle. |
Fusion Filter Option 2 - High-Dynamics Filter
General
The high dynamics filter combines IMU and GPS data to calculate the global position of a vehicle. Instead of using the odometry it uses IMU data to determine the orientation changes of a car on the X, Y and Z axis. The direction of the vehicle is globally referenced from the GPS system. For increasing the direction reference quality a dual-antenna GPS system can be used.
The high dynamics filter works well for scenarios with agressive driving maneuvers such as drifting and cornering. During such maneuvers the turning motion of the wheels generally doesn’t directly correspond with the direction of the vehicle. Therefore this filter doesn’t rely on wheel velocity measurements for localization like the low-dynamics (LD) filter. This filter uses information from the wheels to determine if the car has come to a full stop.
As the filter relies heavily on GPS measurements it doesn’t deliver good results indoors. The better the GPS reception, the better the resulting output of the filter. In it’s current state it therefore only works outdoors. In a future version that combines LD and HD filters, this issue will be resolved.
Notes on Filter Output
The HD filter outputs the following data:
fusedVehiclePose
(2D pose): Output equivalent to the LD filter output. Includes position in meters relative to starting point, global position (lon, lat) and heading.fusedPose
(3D pose): relative to starting point, x, y (in meters) + z (height in meters) + 3D orientation quaternionglobalFusedPose:
globally referenced 3D position (longitude, latitude, height in meters) + 3D orientation quaternion in ENU frame
Which filter output works best depends on your application. For augmented reality applications we recommend using globalFusedPose
.
You can find more information regarding the ENU coordinate system here.
Notes on IMU Arrangement
For the car frame we use the Volkswagen (VW) coordinate frame convention:
|
The IMU sensor can be mounted in any way but the ImuToCarRotation
quaternion needs to be provided to transform the IMU data into VW frame. For example, if the IMU is mounted like follows:
Code Block |
---|
IMU mounting
x: forward
y: left
z: up |
To match the VW frame, we need a 180° rotation around the z axis (clockwise). Therefore, the rotation matrix would be:
Code Block |
---|
[ -1, 0, 0;
0, -1, 0;
0, 0, 1 ] |
And the orientation quaternion woud be [w, x, y, z] = [ 0, 0, 0, 1 ]
which can be specified in the configuration like below:
Code Block |
---|
"imuToCarRotation": {
"w": 0,
"x": 0,
"y": 0,
"z": 1
} |
Check this page for more information on how to calculate the orientation quaternion.
Note: The orientation of the IMU for a unity quaternion [ 1, 0, 0, 0 ]
would be
Code Block |
---|
IMU mounting
x: backwards
y: right
z: up |
Configuration Block
Insert the following configuration block into your config.json
file in the sinks
section to activate the HD filter. The filter's node name is gnssImuFusion
.
Code Block |
---|
.. "sinks": { .., "gnssImuFusion": { "echoFusedPose": false, "endpoint": "tcp://*:8803", "fuser": { "fitModel": "ModelGnssImu", "accelError": 0.01, "omegaError": 0.02, "measurementError": 0.05, "imuToCarRotation": { .., "gnssImuFusion": { "echoFusedPosew": false1, "endpoint": "tcp://*:8803", "x": 0, "fuser": { "fitModely": "ModelGnssImu"0, "accelErrorz": 0.01, "omegaError": 0.02}, "measurementErroroutputWhenFilterNotReady": 0.05false, "imuToCarRotationretainStateWhenStopped": { true, "wsmoothFit": 1true, "xglobalOrigin": 0,{ "ylongitude": 0139.73226516666668, "zlatitude": 035.657632 } } } .. |
See below a description of the parameter options for the HD filter.
Parameter name | Description | Default | ||||
---|---|---|---|---|---|---|
echoFusedPose |
| false | ||||
endpoint | Output port for the fusion result | 8801 | ||||
fitModel | Model to use for fusion. | ModelGnssImu | ||||
accelError | Acceleration error for Kalman filter. Keep default value. | 0.01 | ||||
omegaError | Omega error for Kalman filter. Keep default value. | 0.02 | ||||
measurementError | Measurement error for Kalman filter. Keep default value. | 0.05 | ||||
imuToCarRotation | Orientation quaternion of IMU relative to car frame | 1, 0, 0, 0 | ||||
smoothFit | Enable this option to prevent filter output from jumping between IMU data and GPS measurement. Keep enabled. | true | ||||
singleEndpoint |
| true | ||||
poseEndpoint | Output port for the |
| ||||
globalPoseEndpoint | Output port for the |
| ||||
outputRawGnssData | Publishes raw Gnss data position instead of the fusion output. Useful for debugging. | false | outputWhenFilterNotReady | Publishes a temporary raw Gnss data output while the filter is initializing. Useful for a minimal check before moving the vehicle. | falseoutput. Useful for debugging. | false |
outputWhenFilterNotReady | Publishes temporary raw Gnss data output while the filter is initializing. Useful for a sanity check before moving the vehicle. | false | ||||
retainStateWhenStopped | If the vehicle is detected to be stationary by looking at data from CAN bus, then the current filter state (position, rotation etc.) will be automatically retained until motion is detected. | true | ||||
globalOrigin | A global position as longitude and latitude: For | { 0, 0 } |
Output Data Format
FusedVehiclePose
JSON
Code Block |
---|
{ "fusedVehiclePose": { "acceleration": { "x": 0.0, "y": 0.0, "z": 0.0 }, "globalPosition": { "x": 0.0, "y": 0.0 }, "lastDataTime": { "timestamp": 0 }, "position": { "x": 0.0, "y": 0.0 }, "timestamp": { "timestamp": 0 }, "utmZone": "31T", "yaw": 0.0 } } |
Protobuf
Code Block |
---|
syntax = "proto3"; package Fusion.proto; message Vector2 { double x = 2; double y = 3; } message Vector { double x = 2; double y = 3; double z = 4; } message FusedVehiclePose { int64 timestamp = 1; Vector2 position = 2; Vector2 global_position = 3; double yaw = 4; string utm_zone = 5; int64 timecode = 6; // Optional: if 0 not set. Vector acceleration = 7; } message StreamData { int32 sequence_number = 1; FusedVehiclePose fused_vehicle_pose = 9; } |
Parameter name | Description | Unit |
---|---|---|
acceleration | 3D acceleration vector as measured by IMU. Describes the orientation of the vehicle. | m/s^2 |
globalPosition | Longitude and latitude in degrees | degrees |
lastDataTime | Unused | s |
position | Position within UTM zone | m |
timestamp | Timestamp of data acquisition | ns |
utmZone | UTM zone | UTM string |
yaw | Globally referenced yaw angle | rad |
FusedPose
JSON
Code Block |
---|
{ "fusedPose": { "lastDataTime": { "timestamp": 0 }, "orientation": { "w": 1.0, "x": 0.0, "y": 0.0, "z": 0.0 }, "position": { "x": 0.0, "y": 0.0, "z": 0.0 }, "timestamp": { "timestamp": 0 } } } |
Protobuf
Code Block |
---|
syntax = "proto3"; package Fusion.proto; message Quaternion { double w = 1; double x = 2; double y = 3; double z = 4; } message Vector { double x = 2; double y = 3; double z = 4; } message FusedPose { int64 timestamp = 1; Vector position = 2; Quaternion orientation = 3; Vector angular_velocity = 4; int64 timecode = 5; // Optional: if 0 not set. } message StreamData { int32 sequence_number = 1; FusedPose fused_pose = 4; } |
Parameter name | Description | Unit |
---|---|---|
lastDataTime | Unused | s |
orientation | Orientation quaternion in ENU coordinate frame | without unit |
position | X, y position + height | m |
timestamp | Time of data acqusition | ns |
GlobalFusedPose
JSON
Code Block |
---|
{ "globalFusedPose" { "orientation": { "w": 1.0, "x": 0.0, "y": 0.0, "z": 0.0 }, "timestamp": { "timestamp": 0 }, "position": { "longitude": 0.0, "latitude": 0.0, "height": 0.0 } } } |
Protobuf
Code Block |
---|
syntax = "proto3";
package Fusion.proto;
message Quaternion {
double w = 1;
double x = 2;
double y = 3;
double z = 4;
}
message GpsPoint {
double longitude = 2;
double latitude = 3;
double height = 4;
}
message GlobalFusedPose {
int64 timecode = 5; // Optional: if 0 not set.
int64 timestamp = 1;
GpsPoint position = 2;
Quaternion orientation = 3;
}
message StreamData {
int32 sequence_number = 1;
GlobalFusedPose global_fused_pose = 10;
} |
...
Parameter name
...
Description
...
Unit
...
orientation
...
Orientation quaternion
...
without unit
...
position
...
Longitude, latitude, height
...
deg, deg, m
...
timestamp
...
Time of data acqusition
...
ns
Recording and Replaying Data
Data Recording
You can record the output from FusionHub to a file by adding the following lines to the sink
section of config.json
. All JSON output that's printed to the screen during the operation of FusionHub will be written into the log file.
Code Block |
---|
"record": {
"filename": "driveData.json",
"format": "json"
} |
...
Parameter name
...
Description
...
Default
...
filename
...
Filename of the file to be recorded.
...
driveData.json
...
format
...
The file format. At the moment only JSON is possible.
...
json
Data Replay
Replay executable
In order to replay data from a JSON file a separate application ReplayExecutable.exe
that we deliver with LPVR-POS is used. The replay executable reads the JSON data from a defined file, pushes the data to a replay queue and sends them to the network (tcp://localhost:9921
by default). To run the ReplayExecutable use the following command:
Code Block |
---|
ReplayExecutable.exe -r <path/to/file.json> [--replay-speed 1] [--queue-size 100] [--echo-data] [--verbose] |
...
Key
...
Description
...
Type
...
Example value
...
-r
...
Path to read in file
...
String
...
“log.json”
...
--replay-speed
...
Speed to the actual recording
...
Double
...
1
...
--queue-size
...
The size of queue that file reader would stop pushing new data to the replay queue.
Increase this value when you see lots of data is published at the same time when running with --verbose
...
Integer
...
100
...
--echo-data
...
Listen to the publishing endpoint and display the replayed data
...
N/A
...
N/A
...
--verbose
...
Print the debugging information, i.e., the timestamp a packet is added to the replay queue, replayed from the replay queue, and discarded from the replay queue.
...
N/A
...
N/A
FusionHub can receive data from the replay application by adding the replay application’s endpoint source to the configuration file:
Code Block | ||
---|---|---|
| ||
{
...,
"sources": {
"endpoints": ["tcp://localhost:9921"]
}
} |
Info |
---|
The Replay executable allows to replay the recorded data in order to use it as input to the fusion nodes. For that please keep the same “sinks“ block that was used in the live testing. The “sources“ block should be replaced by just the replay endpoint as shown above instead of the different hardware data sources. |
Compatibility with old data recordings
Starting from 19/10/2023, the odometry message type used as input to the filter nodes has changed.
Panel | ||||||
---|---|---|---|---|---|---|
| ||||||
To be able to replay data recorded with older FusionHub versions, please make sure to include the "vehicle" source block in the sources in addition to the replay endpoint and change "canInterface" to "Internal" . / Optional: if 0 not set.
int64 timestamp = 1;
GpsPoint position = 2;
Quaternion orientation = 3;
}
message StreamData {
int32 sequence_number = 1;
GlobalFusedPose global_fused_pose = 10;
} |
Parameter name | Description | Unit |
---|---|---|
orientation | Orientation quaternion | without unit |
position | Longitude, latitude, height | deg, deg, m |
timestamp | Time of data acqusition | ns |
Recording and Replaying Data
Data Recording
You can record the output from FusionHub to a file by adding the following lines to the sink
section of config.json
. All JSON output that's printed to the screen during the operation of FusionHub will be written into the log file.
Code Block |
---|
"record": {
"filename": "driveData.json",
"format": "json"
} |
Parameter name | Description | Default |
---|---|---|
filename | Filename of the file to be recorded. | driveData.json |
format | The file format. At the moment only JSON is possible. | json |
Data Replay
Replay executable
In order to replay data from a JSON file a separate application ReplayExecutable.exe
that we deliver with LPVR-POS is used. The replay executable reads the JSON data from a defined file, pushes the data to a replay queue and sends them to the network (tcp://localhost:9921
by default). To run the ReplayExecutable use the following command:
Code Block |
---|
ReplayExecutable.exe -r <path/to/file.json> [--replay-speed 1] [--queue-size 100] [--echo-data] [--verbose] |
Key | Description | Type | Example value |
---|---|---|---|
-r | Path to read in file | String | “log.json” |
--replay-speed | Speed to the actual recording | Double | 1 |
--queue-size | The size of queue that file reader would stop pushing new data to the replay queue. Increase this value when you see lots of data is published at the same time when running with | Integer | 100 |
--echo-data | Listen to the publishing endpoint and display the replayed data | N/A | N/A |
--verbose | Print the debugging information, i.e., the timestamp a packet is added to the replay queue, replayed from the replay queue, and discarded from the replay queue. | N/A | N/A |
FusionHub can receive data from the replay application by adding the replay application’s endpoint source to the configuration file:
Code Block | ||
---|---|---|
| ||
{
...,
"sources": {
"endpoints": ["tcp://localhost:9921"]
}
} |
Info |
---|
The Replay executable allows to replay the recorded data in order to use it as input to the fusion nodes. For that please keep the same “sinks“ block that was used in the live testing. The “sources“ block should be replaced by just the replay endpoint as shown above instead of the different hardware data sources. |
Compatibility with old data recordings
Starting from 19/10/2023, the odometry message type used as input to the filter nodes has changed.
Panel | ||||||
---|---|---|---|---|---|---|
| ||||||
To be able to replay data recorded with older FusionHub versions, please make sure to include the |
Code Block |
---|
"vehicle": {
"type": "Automotive",
"vehicleStateEndpoint": "tcp://*:8999",
"settings": {
"canInterface": "Internal",
"canEndpoint": "tcp://localhost:9921",
...
}
} |
This way the recorded CAN messages are reprocessed to produce the expected input.
...
Quality flag value | Name | Result |
---|---|---|
2 | DGPS | The GNSS unit is operating as normal GPS unit. It is not receiving correction information from an NTRIP server or other RTCM source. |
4 | RTK fixed | The RTK-GPS system is locked and operating with ~2cm positioning accuracy. This is the desired state. |
5 | RTK float | The GNSS unit is receiving correction information from an RTCM source, but so far hasn’t been able to lock to high precision mode. There might not be enough satellites in view or the system needs more time to stabilize. |
Preferably we always want the system to operate in Fix mode. This requires working connection to the NTRIP caster, decent antenna placement and a sufficient number of satellites in view of the car’s antenna and the base station antenna.
As for LPVR-POS we are using a multi-channel GPS system, performance should be relatively robust. Check the output of the Emlid software to check the number of satellites the base station is seeing.
...
satellites in view or the system needs more time to stabilize. |
Preferably we always want the system to operate in Fix mode. This requires working connection to the NTRIP caster, decent antenna placement and a sufficient number of satellites in view of the car’s antenna and the base station antenna.
As for LPVR-POS we are using a multi-channel GPS system, performance should be relatively robust. Check the output of the Emlid software to check the number of satellites the base station is seeing.
If you managed to get an RTK-GPS fix, your LPVR-POS system is now ready to operate with RTK-GPS as global centimeter-accurate position reference.
Using Alternate NTRIP Servers
In principle the FusionHub RTCM node can be used with any NTRIP server. We’ve so far only tested it using the Emlid caster described above and the Softbank Ichimili service in Japan. When configuring FusionHub for an alternate NTRIP server make sure to correctly modify all fields of the RTCM node. Make sure that the initialLatitude
and initialLongitude
coordinates point roughly to the area where you would like to operate the system. Check the command line output of FusionHub, if the connection to the NTRIP server was successful:
There should be a line saying "Output to NTRIP server: .." with the initial GET command that's sent to the NTRIP server
The output "Successfully connected to NTRIP Caster" should follow a few lines further on
If you see these messages, we know that FusionHub connected correctly to the NTRIP server. Check the GnssData
message as described above for connection state.
References
...