|
|
|
@ -4,7 +4,9 @@
|
|
|
|
|
that can be found in the LICENSE file, herein included
|
|
|
|
|
as part of this header.
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
gps.go: GPS functions, GPS init, AHRS status messages, other external sensor monitoring.
|
|
|
|
|
compile and install: clear && make www && make gen_gdl90 && mv gen_gdl90 /opt/stratux/bin/ && stxrestart
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
package main
|
|
|
|
@ -206,9 +208,21 @@ func makeNMEACmd(cmd string) []byte {
|
|
|
|
|
return []byte(fmt.Sprintf("$%s*%02x\x0d\x0a", cmd, chk_sum))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func logChipConfig(line1 string, chip string, device string, baudrate int, append string) {
|
|
|
|
|
if line1 == "auto" {
|
|
|
|
|
logInf("Gps - autodected gps, using following parameters:")
|
|
|
|
|
} else if line1 == "man" {
|
|
|
|
|
logInf("GPS - manual configuration with following parameters from /boot/stratux.conf:")
|
|
|
|
|
}
|
|
|
|
|
msg := "GPS - chip: %s, device: %s, baudrate: %d"
|
|
|
|
|
if(append != "") { msg += ", " + append}
|
|
|
|
|
logInf(msg, chip, device, baudrate)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func initGPSSerial() bool {
|
|
|
|
|
var device string
|
|
|
|
|
var targetBaudRate int = 115200
|
|
|
|
|
if (globalStatus.GPS_detected_type & 0x0f) == GPS_TYPE_NETWORK {
|
|
|
|
|
return true
|
|
|
|
|
}
|
|
|
|
@ -218,19 +232,64 @@ func initGPSSerial() bool {
|
|
|
|
|
ognTrackerConfigured = false;
|
|
|
|
|
globalStatus.GPS_detected_type = 0 // reset detected type on each initialization
|
|
|
|
|
|
|
|
|
|
if _, err := os.Stat("/dev/ublox9"); err == nil { // u-blox 8 (RY83xAI over USB).
|
|
|
|
|
|
|
|
|
|
if globalSettings.GpsManualConfig {
|
|
|
|
|
//logInf("GPS - manual configuration with parameters from /boot/stratux.conf:")
|
|
|
|
|
|
|
|
|
|
var chip string = globalSettings.GpsManualChip
|
|
|
|
|
device = globalSettings.GpsManualDevice
|
|
|
|
|
targetBaudRate = globalSettings.GpsManualTargetBaud
|
|
|
|
|
baudrates = []int{115200, 38400, 9600, 230400, 500000, 1000000, 2000000}
|
|
|
|
|
|
|
|
|
|
switch chip {
|
|
|
|
|
case "ublox6":
|
|
|
|
|
case "ublox7":
|
|
|
|
|
globalStatus.GPS_detected_type = GPS_TYPE_UBX6or7
|
|
|
|
|
logChipConfig("man", "ublox 6 or 7", device, targetBaudRate, "")
|
|
|
|
|
break;
|
|
|
|
|
case "ublox8":
|
|
|
|
|
globalStatus.GPS_detected_type = GPS_TYPE_UBX8
|
|
|
|
|
logChipConfig("man", "ublox 8", device, targetBaudRate, "")
|
|
|
|
|
break;
|
|
|
|
|
case "ublox9":
|
|
|
|
|
globalStatus.GPS_detected_type = GPS_TYPE_UBX9
|
|
|
|
|
logChipConfig("man", "ublox 9", device, targetBaudRate, "")
|
|
|
|
|
break;
|
|
|
|
|
case "ublox10":
|
|
|
|
|
globalStatus.GPS_detected_type = GPS_TYPE_UBX10
|
|
|
|
|
logChipConfig("man", "ublox 10", device, targetBaudRate, "")
|
|
|
|
|
break;
|
|
|
|
|
case "ublox":
|
|
|
|
|
globalStatus.GPS_detected_type = GPS_TYPE_UBX_GEN
|
|
|
|
|
logChipConfig("man", "generic ublox", device, targetBaudRate, "")
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
globalStatus.GPS_detected_type = GPS_TYPE_ANY
|
|
|
|
|
logInf("GPS - configuring gps chip as other -> no further configuration will be done, use gps as it is")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
} else if _, err := os.Stat("/dev/ublox9"); err == nil {
|
|
|
|
|
device = "/dev/ublox9"
|
|
|
|
|
globalStatus.GPS_detected_type = GPS_TYPE_UBX9
|
|
|
|
|
} else if _, err := os.Stat("/dev/ublox8"); err == nil { // u-blox 8 (RY83xAI or GPYes 2.0).
|
|
|
|
|
logChipConfig("auto", "ublox 9", device, targetBaudRate, "")
|
|
|
|
|
|
|
|
|
|
} else if _, err := os.Stat("/dev/ublox8"); err == nil { // u-blox 8 (RY83xAI or GPYes 2.0).
|
|
|
|
|
device = "/dev/ublox8"
|
|
|
|
|
globalStatus.GPS_detected_type = GPS_TYPE_UBX8
|
|
|
|
|
gpsTimeOffsetPpsMs = 80 * time.Millisecond // Ublox 8 seems to have higher delay
|
|
|
|
|
} else if _, err := os.Stat("/dev/ublox7"); err == nil { // u-blox 7 (VK-172, VK-162 Rev 2, GPYes, RY725AI over USB).
|
|
|
|
|
gpsTimeOffsetPpsMs = 80 * time.Millisecond // Ublox 8 seems to have higher delay
|
|
|
|
|
logChipConfig("auto", "ublox 8", device, targetBaudRate, "")
|
|
|
|
|
|
|
|
|
|
} else if _, err := os.Stat("/dev/ublox7"); err == nil { // u-blox 7 (VK-172, VK-162 Rev 2, GPYes, RY725AI over USB).
|
|
|
|
|
device = "/dev/ublox7"
|
|
|
|
|
globalStatus.GPS_detected_type = GPS_TYPE_UBX7
|
|
|
|
|
} else if _, err := os.Stat("/dev/ublox6"); err == nil { // u-blox 6 (VK-162 Rev 1).
|
|
|
|
|
globalStatus.GPS_detected_type = GPS_TYPE_UBX6or7
|
|
|
|
|
logChipConfig("auto", "ublox 7", device, targetBaudRate, "")
|
|
|
|
|
|
|
|
|
|
} else if _, err := os.Stat("/dev/ublox6"); err == nil { // u-blox 6 (VK-162 Rev 1).
|
|
|
|
|
device = "/dev/ublox6"
|
|
|
|
|
globalStatus.GPS_detected_type = GPS_TYPE_UBX6
|
|
|
|
|
globalStatus.GPS_detected_type = GPS_TYPE_UBX6or7
|
|
|
|
|
logChipConfig("auto", "ublox 6", device, targetBaudRate, "")
|
|
|
|
|
|
|
|
|
|
} else if _, err := os.Stat("/dev/prolific0"); err == nil { // Assume it's a BU-353-S4 SIRF IV.
|
|
|
|
|
//TODO: Check a "serialout" flag and/or deal with multiple prolific devices.
|
|
|
|
|
isSirfIV = true
|
|
|
|
@ -248,19 +307,21 @@ func initGPSSerial() bool {
|
|
|
|
|
device = "/dev/softrf_dongle"
|
|
|
|
|
globalStatus.GPS_detected_type = GPS_TYPE_SOFTRF_DONGLE
|
|
|
|
|
baudrates[0] = 115200
|
|
|
|
|
} else if _, err := os.Stat("/dev/ttyAMA0"); err == nil { // ttyAMA0 is PL011 UART (GPIO pins 8 and 10) on all RPi.
|
|
|
|
|
} else if _, err := os.Stat("/dev/ttyAMA0"); err == nil {
|
|
|
|
|
// ttyAMA0 is PL011 UART (GPIO pins 8 and 10) on all RPi.
|
|
|
|
|
// assume that any GPS connected to serial GPIO is ublox
|
|
|
|
|
device = "/dev/ttyAMA0"
|
|
|
|
|
globalStatus.GPS_detected_type = GPS_TYPE_UART
|
|
|
|
|
globalStatus.GPS_detected_type = GPS_TYPE_UBX_GEN
|
|
|
|
|
baudrates = []int{115200, 38400, 9600}
|
|
|
|
|
logInf("GPS - device detected at serial port /dev/ttyAMA0, assuming this is an ublox device, configuring as generic ublox:")
|
|
|
|
|
logChipConfig("", "generic ublox", device, targetBaudRate, "")
|
|
|
|
|
logInf("GPS - consider to configure this device manually in /boot/stratux.conf for optimal performance")
|
|
|
|
|
} else {
|
|
|
|
|
if globalSettings.DEBUG {
|
|
|
|
|
log.Printf("No GPS device found.\n")
|
|
|
|
|
}
|
|
|
|
|
logDbg("GPS - no gps device found.\n")
|
|
|
|
|
return false
|
|
|
|
|
}
|
|
|
|
|
if globalSettings.DEBUG {
|
|
|
|
|
log.Printf("Using %s for GPS\n", device)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
logDbg("GPS - using device: %s", device)
|
|
|
|
|
|
|
|
|
|
// try to open port with previously defined baud rate
|
|
|
|
|
// port remains opend if detectOpenSerialPort finds matching baurate parameter
|
|
|
|
@ -268,7 +329,7 @@ func initGPSSerial() bool {
|
|
|
|
|
|
|
|
|
|
p, err := detectOpenSerialPort(device, baudrates)
|
|
|
|
|
if err != nil {
|
|
|
|
|
log.Printf("serial port/baudrate detection err: %s\n", err.Error())
|
|
|
|
|
log.Printf("GPS - serial port/baudrate detection err: %s\n", err.Error())
|
|
|
|
|
return false
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -293,9 +354,13 @@ func initGPSSerial() bool {
|
|
|
|
|
if globalSettings.DEBUG {
|
|
|
|
|
log.Printf("Finished writing SiRF GPS config to %s. Opening port to test connection.\n", device)
|
|
|
|
|
}
|
|
|
|
|
} else if globalStatus.GPS_detected_type == GPS_TYPE_UBX6 || globalStatus.GPS_detected_type == GPS_TYPE_UBX7 ||
|
|
|
|
|
globalStatus.GPS_detected_type == GPS_TYPE_UBX8 || globalStatus.GPS_detected_type == GPS_TYPE_UBX9 ||
|
|
|
|
|
globalStatus.GPS_detected_type == GPS_TYPE_UART {
|
|
|
|
|
} else if (
|
|
|
|
|
globalStatus.GPS_detected_type == GPS_TYPE_UBX6or7 ||
|
|
|
|
|
globalStatus.GPS_detected_type == GPS_TYPE_UBX8 ||
|
|
|
|
|
globalStatus.GPS_detected_type == GPS_TYPE_UBX9 ||
|
|
|
|
|
globalStatus.GPS_detected_type == GPS_TYPE_UBX10 ||
|
|
|
|
|
globalStatus.GPS_detected_type == GPS_TYPE_UBX_GEN ) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Byte order for UBX configuration is little endian.
|
|
|
|
|
|
|
|
|
@ -313,21 +378,15 @@ func initGPSSerial() bool {
|
|
|
|
|
//time.Sleep(100* time.Millisecond) // pause and wait for the GPS to finish configuring itself before closing / reopening the port
|
|
|
|
|
|
|
|
|
|
if globalStatus.GPS_detected_type == GPS_TYPE_UBX9 {
|
|
|
|
|
if globalSettings.DEBUG {
|
|
|
|
|
log.Printf("ublox 9 detected\n")
|
|
|
|
|
}
|
|
|
|
|
logDbg("GPS - configuring as ublox 9\n")
|
|
|
|
|
// ublox 9
|
|
|
|
|
writeUblox9ConfigCommands(p)
|
|
|
|
|
} else if (globalStatus.GPS_detected_type == GPS_TYPE_UBX8) || (globalStatus.GPS_detected_type == GPS_TYPE_UART) { // assume that any GPS connected to serial GPIO is ublox8 (RY835/6AI)
|
|
|
|
|
if globalSettings.DEBUG {
|
|
|
|
|
log.Printf("ublox 8 detected\n")
|
|
|
|
|
}
|
|
|
|
|
} else if (globalStatus.GPS_detected_type == GPS_TYPE_UBX8) {
|
|
|
|
|
logDbg("GPS - configuring as ublox 8\n")
|
|
|
|
|
// ublox 8
|
|
|
|
|
writeUblox8ConfigCommands(p)
|
|
|
|
|
} else if (globalStatus.GPS_detected_type == GPS_TYPE_UBX7) || (globalStatus.GPS_detected_type == GPS_TYPE_UBX6) {
|
|
|
|
|
if globalSettings.DEBUG {
|
|
|
|
|
log.Printf("ublox 6 or 7 detected\n")
|
|
|
|
|
}
|
|
|
|
|
} else if (globalStatus.GPS_detected_type == GPS_TYPE_UBX6or7) {
|
|
|
|
|
logDbg("GPS - configuring as ublox 6 or 7\n")
|
|
|
|
|
// ublox 6,7
|
|
|
|
|
cfgGnss := []byte{0x00, 0x00, 0xFF, 0x04} // numTrkChUse=0xFF: number of tracking channels to use will be set to number of tracking channels available in hardware
|
|
|
|
|
gps := []byte{0x00, 0x04, 0xFF, 0x00, 0x01, 0x00, 0x01, 0x01} // enable GPS with 4-255 channels (ublox default)
|
|
|
|
@ -360,7 +419,7 @@ func initGPSSerial() bool {
|
|
|
|
|
cfg[7] = 0x00
|
|
|
|
|
|
|
|
|
|
// Baud rate. Little endian order.
|
|
|
|
|
bdrt := uint32(115200)
|
|
|
|
|
bdrt := uint32(targetBaudRate)
|
|
|
|
|
cfg[11] = byte((bdrt >> 24) & 0xFF)
|
|
|
|
|
cfg[10] = byte((bdrt >> 16) & 0xFF)
|
|
|
|
|
cfg[9] = byte((bdrt >> 8) & 0xFF)
|
|
|
|
@ -384,12 +443,9 @@ func initGPSSerial() bool {
|
|
|
|
|
p.Write(makeUBXCFG(0x06, 0x00, 20, cfg))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// time.Sleep(100* time.Millisecond) // pause and wait for the GPS to finish configuring itself before closing / reopening the port
|
|
|
|
|
baudrates[0] = int(bdrt)
|
|
|
|
|
|
|
|
|
|
if globalSettings.DEBUG {
|
|
|
|
|
log.Printf("Finished writing u-blox GPS config to %s. Opening port to test connection.\n", device)
|
|
|
|
|
}
|
|
|
|
|
//baudrates[0] = int(bdrt) // replaced by line below -> insert at pos 0 instead of overwriting ...
|
|
|
|
|
baudrates = append([]int{targetBaudRate}, baudrates...)
|
|
|
|
|
logDbg("GPS - finished writing u-blox GPS config to %s. Opening port to test connection.\n", device)
|
|
|
|
|
} else if globalStatus.GPS_detected_type == GPS_TYPE_SOFTRF_DONGLE {
|
|
|
|
|
p.Write([]byte("@GNS 0x7\r\n")) // enable SBAS
|
|
|
|
|
p.Flush()
|
|
|
|
@ -407,7 +463,7 @@ func initGPSSerial() bool {
|
|
|
|
|
|
|
|
|
|
p, err = detectOpenSerialPort(device, baudrates)
|
|
|
|
|
if err != nil {
|
|
|
|
|
log.Printf("serial port err: %s\n", err.Error())
|
|
|
|
|
logErr("GPS - serial port err: %s\n", err.Error())
|
|
|
|
|
return false
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -422,6 +478,7 @@ func detectOpenSerialPort(device string, baudrates []int) (*(serial.Port), error
|
|
|
|
|
return serial.OpenPort(serialConfig)
|
|
|
|
|
} else {
|
|
|
|
|
for _, baud := range baudrates {
|
|
|
|
|
logDbg("GPS - trying to open serial with %d baud ...", baud)
|
|
|
|
|
serialConfig := &serial.Config{Name: device, Baud: baud, ReadTimeout: time.Millisecond * 2500}
|
|
|
|
|
p, err := serial.OpenPort(serialConfig)
|
|
|
|
|
if err != nil {
|
|
|
|
@ -436,17 +493,19 @@ func detectOpenSerialPort(device string, baudrates []int) (*(serial.Port), error
|
|
|
|
|
_, validNMEAcs := validateNMEAChecksum(line)
|
|
|
|
|
if validNMEAcs {
|
|
|
|
|
// looks a lot like NMEA.. use it
|
|
|
|
|
log.Printf("Detected serial port %s with baud %d", device, baud)
|
|
|
|
|
logInf("GPS - successfully opened serial port %s with baud %d (Valid NMEA msg received)", device, baud)
|
|
|
|
|
// Make sure the NMEA is immediately parsed once, so updateStatus() doesn't see the GPS as disconnected before
|
|
|
|
|
// first msg arrives
|
|
|
|
|
processNMEALine(line)
|
|
|
|
|
return p, nil
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
logDbg("GPS - could not open serial port with %d baud, no valid NMea received ...", baud)
|
|
|
|
|
p.Close()
|
|
|
|
|
time.Sleep(250 * time.Millisecond)
|
|
|
|
|
}
|
|
|
|
|
return nil, errors.New("Failed to detect GPS serial baud rate")
|
|
|
|
|
logErr("GPS - none of the baud rates worked, gps not connected ...")
|
|
|
|
|
return nil, errors.New("GPS - Failed to detect gps serial baud rate")
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -550,7 +609,7 @@ func writeUbloxGenericCommands(navrate uint16, p *serial.Port) {
|
|
|
|
|
p.Write(makeUBXCFG(0x06, 0x08, 6, []byte{0xE8, 0x03, 0x01, 0x00, 0x01, 0x00})) // 1000ms & 1 cycle -> 1Hz (UBX-CFG-RATE payload bytes: little endian!)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
logDbg("GPS - applying generic ublox settings (refresh rate: %d)" , navrate)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -1032,15 +1091,11 @@ func calculateNavRate() float64 {
|
|
|
|
|
var halfwidth float64
|
|
|
|
|
dt_avg, valid := common.Mean(tempSpeedTime)
|
|
|
|
|
if valid && dt_avg > 0 {
|
|
|
|
|
if globalSettings.DEBUG {
|
|
|
|
|
log.Printf("GPS attitude: Average delta time is %.2f s (%.1f Hz)\n", dt_avg, 1/dt_avg)
|
|
|
|
|
}
|
|
|
|
|
logDbg("GPS attitude: Average delta time is %.2f s (%.1f Hz)\n", dt_avg, 1/dt_avg)
|
|
|
|
|
halfwidth = 9 * dt_avg
|
|
|
|
|
mySituation.GPSPositionSampleRate = 1 / dt_avg
|
|
|
|
|
} else {
|
|
|
|
|
if globalSettings.DEBUG {
|
|
|
|
|
log.Printf("GPS attitude: Couldn't determine sample rate\n")
|
|
|
|
|
}
|
|
|
|
|
// logDbg("GPS attitude: Couldn't determine sample rate\n")
|
|
|
|
|
halfwidth = 3.5
|
|
|
|
|
mySituation.GPSPositionSampleRate = 0
|
|
|
|
|
}
|
|
|
|
@ -1493,13 +1548,13 @@ func processNMEALineLow(l string, fakeGpsTimeToCurr bool) (sentenceUsed bool) {
|
|
|
|
|
return false
|
|
|
|
|
}
|
|
|
|
|
if tmpSituation.GPSFixQuality == 2 { // Rough 95% confidence estimate for SBAS solution
|
|
|
|
|
if globalStatus.GPS_detected_type == GPS_TYPE_UBX9 {
|
|
|
|
|
if globalStatus.GPS_detected_type == GPS_TYPE_UBX9 || globalStatus.GPS_detected_type == GPS_TYPE_UBX10 {
|
|
|
|
|
tmpSituation.GPSHorizontalAccuracy = float32(hdop * 3.0) // ublox 9
|
|
|
|
|
} else {
|
|
|
|
|
tmpSituation.GPSHorizontalAccuracy = float32(hdop * 4.0) // ublox 6/7/8
|
|
|
|
|
}
|
|
|
|
|
} else { // Rough 95% confidence estimate non-SBAS solution
|
|
|
|
|
if globalStatus.GPS_detected_type == GPS_TYPE_UBX9 {
|
|
|
|
|
if globalStatus.GPS_detected_type == GPS_TYPE_UBX9 || globalStatus.GPS_detected_type == GPS_TYPE_UBX10 {
|
|
|
|
|
tmpSituation.GPSHorizontalAccuracy = float32(hdop * 4.0) // ublox 9
|
|
|
|
|
} else {
|
|
|
|
|
tmpSituation.GPSHorizontalAccuracy = float32(hdop * 5.0) // ublox 6/7/8
|
|
|
|
@ -1556,9 +1611,7 @@ func processNMEALineLow(l string, fakeGpsTimeToCurr bool) (sentenceUsed bool) {
|
|
|
|
|
lenGSV := len(x)
|
|
|
|
|
satsThisMsg := (lenGSV - 4) / 4
|
|
|
|
|
|
|
|
|
|
if globalSettings.DEBUG {
|
|
|
|
|
log.Printf("%s message [%d of %d] is %v fields long and describes %v satellites\n", x[0], msgIndex, msgNum, lenGSV, satsThisMsg)
|
|
|
|
|
}
|
|
|
|
|
logDbg("%s message [%d of %d] is %v fields long and describes %v satellites\n", x[0], msgIndex, msgNum, lenGSV, satsThisMsg)
|
|
|
|
|
|
|
|
|
|
var sv, elev, az, cno int
|
|
|
|
|
var svType uint8
|
|
|
|
@ -1653,8 +1706,9 @@ func processNMEALineLow(l string, fakeGpsTimeToCurr bool) (sentenceUsed bool) {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if globalSettings.DEBUG {
|
|
|
|
|
inSolnStr := " "
|
|
|
|
|
inSolnStr := " "
|
|
|
|
|
if thisSatellite.InSolution {
|
|
|
|
|
inSolnStr = "+"
|
|
|
|
|
}
|
|
|
|
@ -2182,9 +2236,7 @@ func gpsAttitudeSender() {
|
|
|
|
|
<-timer.C
|
|
|
|
|
|
|
|
|
|
if !isGPSValid() || !calcGPSAttitude() {
|
|
|
|
|
if globalSettings.DEBUG {
|
|
|
|
|
log.Printf("Couldn't calculate GPS-based attitude statistics\n")
|
|
|
|
|
}
|
|
|
|
|
logDbg("Couldn't calculate GPS-based attitude statistics\n")
|
|
|
|
|
} else {
|
|
|
|
|
mySituation.muGPSPerformance.Lock()
|
|
|
|
|
index := len(myGPSPerfStats) - 1
|
|
|
|
@ -2309,3 +2361,7 @@ func initGPS(isReplayMode bool) {
|
|
|
|
|
go pollGPS()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|