Documentation
¶
Overview ¶
Package erb provides primitives for parsing the Emlid Reach Binary protocol (ERB).
Implementation is based on the ERB Protocol spec version 0.1.0:
https://files.emlid.com/ERB.pdf
Index ¶
- Constants
- func ScanPackets(data []byte, _ bool) (advance int, token []byte, err error)
- type DOPS
- type FixType
- type ID
- type POS
- type STAT
- type SV
- type SVI
- type SVType
- type Scanner
- func (c *Scanner) Bytes() []byte
- func (c *Scanner) DOPS() DOPS
- func (c *Scanner) Err() error
- func (c *Scanner) ID() ID
- func (c *Scanner) POS() POS
- func (c *Scanner) STAT() STAT
- func (c *Scanner) SV() SV
- func (c *Scanner) SVI() SVI
- func (c *Scanner) Scan() bool
- func (c *Scanner) ScanSVI() bool
- func (c *Scanner) VEL() VEL
- func (c *Scanner) VER() VER
- type VEL
- type VER
Examples ¶
Constants ¶
const ( SupportedProtocolVersionHigh = 0 SupportedProtocolVersionMedium = 1 SupportedProtocolVersionLow = 0 )
Supported protocol versions.
Variables ¶
This section is empty.
Functions ¶
Types ¶
type DOPS ¶
type DOPS struct { // TimeGPS is the time of week in milliseconds of the navigation epoch. TimeGPS uint32 // Geometric DOP. Geometric float64 // Position DOP. Position float64 // Vertical DOP. Vertical float64 // Horizontal DOP. Horizontal float64 }
DOPS message outputs dimensionless values of DOP.
The raw values are scaled by factor 100.
For example, if received value is 123, then real is 1.23.
type ID ¶
type ID uint8
ID represents an ERB message ID.
const ( // IDVER is the ID of the VER message. IDVER ID = 0x01 // IDPOS is the ID of the POS message. IDPOS ID = 0x02 // IDSTAT is the ID of the STAT message. IDSTAT ID = 0x03 // IDDOPS is the ID of the DOPS message. IDDOPS ID = 0x04 // IDVEL is the ID of the VEL message. IDVEL ID = 0x05 // IDSVI is the ID of the SVI message. IDSVI ID = 0x06 )
type POS ¶
type POS struct { // TimeGPS is the time of week in milliseconds of the navigation epoch. TimeGPS uint32 // Longitude component (degrees). LongitudeDegrees float64 // Latitude component (degrees). LatitudeDegrees float64 // AltitudeEllipsoid is the height above ellipsoid (m). AltitudeEllipsoidMeters float64 // AltitudeMeanSeaLevel is the height above mean sea level (m). AltitudeMeanSeaLevelMeters float64 // HorizontalAccuracyMillimeters is the horizontal accuracy estimate (mm). HorizontalAccuracyMillimeters uint32 // VerticalAccuracy is the vertical accuracy estimate (mm). VerticalAccuracyMillimeters uint32 }
POS message contains the geodetic coordinates.
Longitude, latitude, altitude and information about accuracy estimate.
type STAT ¶
type STAT struct { // TimeGPS is the time of week in milliseconds of the navigation epoch. TimeGPS uint32 // WeekGPS is the week number of the navigation epoch. WeekGPS uint16 // FixType is the fix type. FixType FixType // HasFix is true when position and velocity are valid. HasFix bool // NumSVs is the number of used space vehicles. NumSVs uint8 }
STAT message contains status of fix, its type and also the number of used satellites.
type SV ¶
type SV struct { // ID of SV. ID uint8 // Type of SV. Type SVType // SignalStrength of SV in dB-Hz. SignalStrength float64 // CarrierPhase of SV in cycles. CarrierPhase float64 // PseudoRangeResidual of SV (m). PseudoRangeResidualMeters int32 // DopplerFrequencyHz of SV. DopplerFrequencyHz float64 // Azimuth of SV (degrees). AzimuthDegrees float64 // Elevation of SV (degrees). ElevationDegrees float64 }
SV message contains information about a single observation satellite.
type SVI ¶
type SVI struct { // TimeGPS is the time of week in milliseconds of the navigation epoch. TimeGPS uint32 // NumSVs is the number of visible SVs. NumSVs uint8 }
SVI message contains information about used observation satellites.
type Scanner ¶
type Scanner struct {
// contains filtered or unexported fields
}
Scanner provides a convenient interface for reading and parsing ERB messages from a stream.
Example ¶
package main import ( "bufio" "context" "fmt" "net" "os" "strconv" "strings" "time" "go.einride.tech/reach/erb" ) func main() { ctx, cancel := context.WithTimeout(context.Background(), time.Second) defer cancel() // This example uses a mocked Reach unit that answers with recorded data. reach := newExampleReach(ctx) // Connect to the Emlid Reach Binary (ERB) protocol port of the Reach. conn, err := net.Dial("tcp", reach.Address) if err != nil { panic(err) } // Wrap the connection in an ERB protocol scanner. sc := erb.NewScanner(conn) // Scan 5 packets then exit. const maxPacketCount = 5 packetCount := 0 for sc.Scan() { // Handle packet. switch sc.ID() { case erb.IDVER: ver := sc.VER() fmt.Printf("VER: %d.%d.%d\n", ver.High, ver.Medium, ver.Low) case erb.IDPOS: pos := sc.POS() fmt.Printf("POS: %f,%f\n", pos.LatitudeDegrees, pos.LongitudeDegrees) case erb.IDSTAT: stat := sc.STAT() fmt.Printf("STAT: fix:%t type:%v satellites:%d\n", stat.HasFix, stat.FixType, stat.NumSVs) case erb.IDDOPS: dops := sc.DOPS() fmt.Printf("DOPS: pdop:%f\n", dops.Position) case erb.IDVEL: vel := sc.VEL() fmt.Printf("VEL: speed:%dcm/s\n", vel.SpeedCentimetersPerSecond) case erb.IDSVI: svi := sc.SVI() fmt.Printf("SVI: satellites:%d\n", svi.NumSVs) for sc.ScanSVI() { sv := sc.SV() fmt.Printf("SV: id:%v\n", sv.ID) } } packetCount++ if packetCount >= maxPacketCount { break } } if sc.Err() != nil { panic(err) } if err := conn.Close(); err != nil { panic(err) } } type exampleReach struct { Address string } func newExampleReach(ctx context.Context) *exampleReach { lis, err := (&net.ListenConfig{}).Listen(ctx, "tcp", "localhost:0") if err != nil { panic(err) } go func() { conn, err := lis.Accept() if err != nil { panic(err) } if _, err := conn.Write(loadHexDump("testdata/hexdump.asta")); err != nil { panic(err) } if err := conn.Close(); err != nil { panic(err) } if err := lis.Close(); err != nil { panic(err) } }() return &exampleReach{ Address: lis.Addr().String(), } } func loadHexDump(filename string) []byte { var data []byte f, err := os.Open(filename) if err != nil { panic(err) } sc := bufio.NewScanner(f) sc.Split(bufio.ScanLines) for sc.Scan() { fields := strings.Fields(sc.Text()) if len(fields) == 0 { continue } for _, field := range fields[1:] { b, err := strconv.ParseUint(field, 8, 8) if err != nil { panic(err) } data = append(data, byte(b)) } } if sc.Err() != nil { panic(sc.Err()) } if err := f.Close(); err != nil { panic(err) } return data }
Output: VER: 0.1.0 POS: 57.777683,12.780540 STAT: fix:true type:Single satellites:20 DOPS: pdop:1.210000 VEL: speed:0cm/s
func NewScanner ¶
NewScanner returns a new Scanner to read from r.
func (*Scanner) Scan ¶
Scan advances the Scanner to the next message, whose ID will then be available through the ID method.
type VEL ¶
type VEL struct { // TimeGPS is the time of week in milliseconds of the navigation epoch. TimeGPS uint32 // North velocity component (cm/s). NorthCentimetersPerSecond int32 // East velocity component (cm/s). EastCentimetersPerSecond int32 // Down velocity component (cm/s). DownCentimetersPerSecond int32 // Speed is the 2D ground speed (cm/s). SpeedCentimetersPerSecond int32 // Heading is the 2D heading of motion. HeadingDegrees float64 // SpeedAccuracy is the speed accuracy estimate. SpeedAccuracyCentimetersPerSecond uint32 }
VEL message contains the velocity in NED (North East Down) coordinates.
type VER ¶
type VER struct { // TimeGPS is the time of week in milliseconds of the navigation epoch. TimeGPS uint32 // High level of version. High uint8 // Medium level of version. Medium uint8 // Low level of version. Low uint8 }
VER message contains version of the ERB protocol.
It comprises 3 numbers: high level of version, medium level of version and low level of version.