kopia lustrzana https://github.com/cyoung/stratux
Merge remote-tracking branch 'origin/master' into ahrs_dev_protocolfun
commit
fcf524b03c
10
README.md
10
README.md
|
@ -13,9 +13,6 @@ Raspberry Pi 2 with the Edimax EW-7811Un Wi-Fi dongle is supported but not recom
|
|||
|
||||
Tested and works well with most common R820T and R820T2 RTL-SDR devices.
|
||||
|
||||
Tested with and preliminary support added for [uAvionix pingEFB dual-link ADS-B receiver](http://www.uavionix.com/products/pingefb/).
|
||||
|
||||
|
||||
Apps with stratux recognition/support:
|
||||
* Seattle Avionics FlyQ EFB 2.1.1+.
|
||||
* AvNav EFB 2.0.0+.
|
||||
|
@ -31,10 +28,17 @@ Tested weather/traffic displays:
|
|||
* ForeFlight 7+ - weather, traffic. AHRS not functional.
|
||||
* Avare
|
||||
|
||||
Other EFBs? See the [app vendor integration guide](https://github.com/cyoung/stratux/blob/master/notes/app-vendor-integration.md).
|
||||
|
||||
Dangerzone builds (AHRS display):
|
||||
* ForeFlight 7+ - weather, traffic, AHRS.
|
||||
|
||||
Questions? [See the FAQ](https://github.com/cyoung/stratux/wiki/FAQ)
|
||||
|
||||
http://stratux.me/
|
||||
|
||||
http://slack.stratux.me/
|
||||
|
||||
https://www.reddit.com/r/stratux
|
||||
|
||||
Jet tests (high gain antennas):
|
||||
|
|
|
@ -18,3 +18,6 @@ deployment:
|
|||
branch: master
|
||||
commands:
|
||||
- yes | ssh -i ~/.ssh/id_updates.stratux.me stratux-updates@updates.stratux.me "touch queue/`git log -n 1 --pretty=%H`"
|
||||
branch: ahrs_dev
|
||||
commands:
|
||||
- yes | ssh -i ~/.ssh/id_updates.stratux.me stratux-updates@updates.stratux.me "touch queue/`git log -n 1 --pretty=%H`"
|
||||
|
|
2
goflying
2
goflying
|
@ -1 +1 @@
|
|||
Subproject commit 083dd940f35eed0505f3cded7d8b6aa5f70b4e35
|
||||
Subproject commit a9f32832e8fd8cac2b2e10cf673f0b79e1cec67d
|
|
@ -1,6 +1,8 @@
|
|||
auto lo
|
||||
|
||||
iface lo inet loopback
|
||||
|
||||
allow-hotplug eth0
|
||||
iface eth0 inet dhcp
|
||||
|
||||
allow-hotplug wlan0
|
||||
|
|
|
@ -108,6 +108,65 @@ var maxSignalStrength int
|
|||
var stratuxBuild string
|
||||
var stratuxVersion string
|
||||
|
||||
var product_name_map = map[int]string{
|
||||
0: "METAR",
|
||||
1: "TAF",
|
||||
2: "SIGMET",
|
||||
3: "Conv SIGMET",
|
||||
4: "AIRMET",
|
||||
5: "PIREP",
|
||||
6: "Severe Wx",
|
||||
7: "Winds Aloft",
|
||||
8: "NOTAM", //"NOTAM (Including TFRs) and Service Status";
|
||||
9: "D-ATIS", //"Aerodrome and Airspace – D-ATIS";
|
||||
10: "Terminal Wx", //"Aerodrome and Airspace - TWIP";
|
||||
11: "AIRMET", //"Aerodrome and Airspace - AIRMET";
|
||||
12: "SIGMET", //"Aerodrome and Airspace - SIGMET/Convective SIGMET";
|
||||
13: "SUA", //"Aerodrome and Airspace - SUA Status";
|
||||
20: "METAR", //"METAR and SPECI";
|
||||
21: "TAF", //"TAF and Amended TAF";
|
||||
22: "SIGMET", //"SIGMET";
|
||||
23: "Conv SIGMET", //"Convective SIGMET";
|
||||
24: "AIRMET", //"AIRMET";
|
||||
25: "PIREP", //"PIREP";
|
||||
26: "Severe Wx", //"AWW";
|
||||
27: "Winds Aloft", //"Winds and Temperatures Aloft";
|
||||
51: "NEXRAD", //"National NEXRAD, Type 0 - 4 level";
|
||||
52: "NEXRAD", //"National NEXRAD, Type 1 - 8 level (quasi 6-level VIP)";
|
||||
53: "NEXRAD", //"National NEXRAD, Type 2 - 8 level";
|
||||
54: "NEXRAD", //"National NEXRAD, Type 3 - 16 level";
|
||||
55: "NEXRAD", //"Regional NEXRAD, Type 0 - low dynamic range";
|
||||
56: "NEXRAD", //"Regional NEXRAD, Type 1 - 8 level (quasi 6-level VIP)";
|
||||
57: "NEXRAD", //"Regional NEXRAD, Type 2 - 8 level";
|
||||
58: "NEXRAD", //"Regional NEXRAD, Type 3 - 16 level";
|
||||
59: "NEXRAD", //"Individual NEXRAD, Type 0 - low dynamic range";
|
||||
60: "NEXRAD", //"Individual NEXRAD, Type 1 - 8 level (quasi 6-level VIP)";
|
||||
61: "NEXRAD", //"Individual NEXRAD, Type 2 - 8 level";
|
||||
62: "NEXRAD", //"Individual NEXRAD, Type 3 - 16 level";
|
||||
63: "NEXRAD Regional", //"Global Block Representation - Regional NEXRAD, Type 4 – 8 level";
|
||||
64: "NEXRAD CONUS", //"Global Block Representation - CONUS NEXRAD, Type 4 - 8 level";
|
||||
81: "Tops", //"Radar echo tops graphic, scheme 1: 16-level";
|
||||
82: "Tops", //"Radar echo tops graphic, scheme 2: 8-level";
|
||||
83: "Tops", //"Storm tops and velocity";
|
||||
101: "Lightning", //"Lightning strike type 1 (pixel level)";
|
||||
102: "Lightning", //"Lightning strike type 2 (grid element level)";
|
||||
151: "Lightning", //"Point phenomena, vector format";
|
||||
201: "Surface", //"Surface conditions/winter precipitation graphic";
|
||||
202: "Surface", //"Surface weather systems";
|
||||
254: "G-AIRMET", //"AIRMET, SIGMET: Bitmap encoding";
|
||||
351: "Time", //"System Time";
|
||||
352: "Status", //"Operational Status";
|
||||
353: "Status", //"Ground Station Status";
|
||||
401: "Imagery", //"Generic Raster Scan Data Product APDU Payload Format Type 1";
|
||||
402: "Text",
|
||||
403: "Vector Imagery", //"Generic Vector Data Product APDU Payload Format Type 1";
|
||||
404: "Symbols",
|
||||
405: "Text",
|
||||
411: "Text", //"Generic Textual Data Product APDU Payload Format Type 1";
|
||||
412: "Symbols", //"Generic Symbolic Product APDU Payload Format Type 1";
|
||||
413: "Text", //"Generic Textual Data Product APDU Payload Format Type 2";
|
||||
}
|
||||
|
||||
// CRC16 table generated to use to work with GDL90 messages.
|
||||
var Crc16Table [256]uint16
|
||||
|
||||
|
@ -795,6 +854,15 @@ func updateStatus() {
|
|||
if err == nil {
|
||||
globalStatus.Logfile_Size = fileInfo.Size()
|
||||
}
|
||||
|
||||
var ahrsLogSize int64
|
||||
ahrsLogFiles, _ := ioutil.ReadDir("/var/log")
|
||||
for _, f := range ahrsLogFiles {
|
||||
if v, _ := filepath.Match("sensors_*.csv", f.Name()); v {
|
||||
ahrsLogSize += f.Size()
|
||||
}
|
||||
}
|
||||
globalStatus.AHRS_LogFiles_Size = ahrsLogSize
|
||||
}
|
||||
|
||||
type WeatherMessage struct {
|
||||
|
@ -963,65 +1031,6 @@ func parseInput(buf string) ([]byte, uint16) {
|
|||
return frame, msgtype
|
||||
}
|
||||
|
||||
var product_name_map = map[int]string{
|
||||
0: "METAR",
|
||||
1: "TAF",
|
||||
2: "SIGMET",
|
||||
3: "Conv SIGMET",
|
||||
4: "AIRMET",
|
||||
5: "PIREP",
|
||||
6: "Severe Wx",
|
||||
7: "Winds Aloft",
|
||||
8: "NOTAM", //"NOTAM (Including TFRs) and Service Status";
|
||||
9: "D-ATIS", //"Aerodrome and Airspace – D-ATIS";
|
||||
10: "Terminal Wx", //"Aerodrome and Airspace - TWIP";
|
||||
11: "AIRMET", //"Aerodrome and Airspace - AIRMET";
|
||||
12: "SIGMET", //"Aerodrome and Airspace - SIGMET/Convective SIGMET";
|
||||
13: "SUA", //"Aerodrome and Airspace - SUA Status";
|
||||
20: "METAR", //"METAR and SPECI";
|
||||
21: "TAF", //"TAF and Amended TAF";
|
||||
22: "SIGMET", //"SIGMET";
|
||||
23: "Conv SIGMET", //"Convective SIGMET";
|
||||
24: "AIRMET", //"AIRMET";
|
||||
25: "PIREP", //"PIREP";
|
||||
26: "Severe Wx", //"AWW";
|
||||
27: "Winds Aloft", //"Winds and Temperatures Aloft";
|
||||
51: "NEXRAD", //"National NEXRAD, Type 0 - 4 level";
|
||||
52: "NEXRAD", //"National NEXRAD, Type 1 - 8 level (quasi 6-level VIP)";
|
||||
53: "NEXRAD", //"National NEXRAD, Type 2 - 8 level";
|
||||
54: "NEXRAD", //"National NEXRAD, Type 3 - 16 level";
|
||||
55: "NEXRAD", //"Regional NEXRAD, Type 0 - low dynamic range";
|
||||
56: "NEXRAD", //"Regional NEXRAD, Type 1 - 8 level (quasi 6-level VIP)";
|
||||
57: "NEXRAD", //"Regional NEXRAD, Type 2 - 8 level";
|
||||
58: "NEXRAD", //"Regional NEXRAD, Type 3 - 16 level";
|
||||
59: "NEXRAD", //"Individual NEXRAD, Type 0 - low dynamic range";
|
||||
60: "NEXRAD", //"Individual NEXRAD, Type 1 - 8 level (quasi 6-level VIP)";
|
||||
61: "NEXRAD", //"Individual NEXRAD, Type 2 - 8 level";
|
||||
62: "NEXRAD", //"Individual NEXRAD, Type 3 - 16 level";
|
||||
63: "NEXRAD Regional", //"Global Block Representation - Regional NEXRAD, Type 4 – 8 level";
|
||||
64: "NEXRAD CONUS", //"Global Block Representation - CONUS NEXRAD, Type 4 - 8 level";
|
||||
81: "Tops", //"Radar echo tops graphic, scheme 1: 16-level";
|
||||
82: "Tops", //"Radar echo tops graphic, scheme 2: 8-level";
|
||||
83: "Tops", //"Storm tops and velocity";
|
||||
101: "Lightning", //"Lightning strike type 1 (pixel level)";
|
||||
102: "Lightning", //"Lightning strike type 2 (grid element level)";
|
||||
151: "Lightning", //"Point phenomena, vector format";
|
||||
201: "Surface", //"Surface conditions/winter precipitation graphic";
|
||||
202: "Surface", //"Surface weather systems";
|
||||
254: "G-AIRMET", //"AIRMET, SIGMET: Bitmap encoding";
|
||||
351: "Time", //"System Time";
|
||||
352: "Status", //"Operational Status";
|
||||
353: "Status", //"Ground Station Status";
|
||||
401: "Imagery", //"Generic Raster Scan Data Product APDU Payload Format Type 1";
|
||||
402: "Text",
|
||||
403: "Vector Imagery", //"Generic Vector Data Product APDU Payload Format Type 1";
|
||||
404: "Symbols",
|
||||
405: "Text",
|
||||
411: "Text", //"Generic Textual Data Product APDU Payload Format Type 1";
|
||||
412: "Symbols", //"Generic Symbolic Product APDU Payload Format Type 1";
|
||||
413: "Text", //"Generic Textual Data Product APDU Payload Format Type 2";
|
||||
}
|
||||
|
||||
func getProductNameFromId(product_id int) string {
|
||||
name, present := product_name_map[product_id]
|
||||
if present {
|
||||
|
@ -1036,26 +1045,27 @@ func getProductNameFromId(product_id int) string {
|
|||
}
|
||||
|
||||
type settings struct {
|
||||
UAT_Enabled bool
|
||||
ES_Enabled bool
|
||||
Ping_Enabled bool
|
||||
GPS_Enabled bool
|
||||
BMP_Sensor_Enabled bool
|
||||
IMU_Sensor_Enabled bool
|
||||
NetworkOutputs []networkConnection
|
||||
SerialOutputs map[string]serialConnection
|
||||
DisplayTrafficSource bool
|
||||
DEBUG bool
|
||||
ReplayLog bool
|
||||
AHRSLog bool
|
||||
IMUMapping [2]int // Map from aircraft axis to sensor axis: accelerometer
|
||||
SensorQuaternion [4]float64 // Quaternion mapping from sensor frame to aircraft frame
|
||||
PPM int
|
||||
OwnshipModeS string
|
||||
WatchList string
|
||||
DeveloperMode bool
|
||||
GLimits string
|
||||
StaticIps []string
|
||||
UAT_Enabled bool
|
||||
ES_Enabled bool
|
||||
Ping_Enabled bool
|
||||
GPS_Enabled bool
|
||||
BMP_Sensor_Enabled bool
|
||||
IMU_Sensor_Enabled bool
|
||||
NetworkOutputs []networkConnection
|
||||
SerialOutputs map[string]serialConnection
|
||||
DisplayTrafficSource bool
|
||||
DEBUG bool
|
||||
ReplayLog bool
|
||||
AHRSLog bool
|
||||
IMUMapping [2]int // Map from aircraft axis to sensor axis: accelerometer
|
||||
SensorQuaternion [4]float64 // Quaternion mapping from sensor frame to aircraft frame
|
||||
C, D [3]float64 // IMU Accel, Gyro zero bias
|
||||
PPM int
|
||||
OwnshipModeS string
|
||||
WatchList string
|
||||
DeveloperMode bool
|
||||
GLimits string
|
||||
StaticIps []string
|
||||
}
|
||||
|
||||
type status struct {
|
||||
|
@ -1100,6 +1110,7 @@ type status struct {
|
|||
UAT_OTHER_total uint32
|
||||
Errors []string
|
||||
Logfile_Size int64
|
||||
AHRS_LogFiles_Size int64
|
||||
BMPConnected bool
|
||||
IMUConnected bool
|
||||
}
|
||||
|
@ -1122,7 +1133,7 @@ func defaultSettings() {
|
|||
globalSettings.DisplayTrafficSource = false
|
||||
globalSettings.ReplayLog = false //TODO: 'true' for debug builds.
|
||||
globalSettings.AHRSLog = false
|
||||
globalSettings.IMUMapping = [2]int{-1, -3} // OpenFlightBox AHRS normal mapping
|
||||
globalSettings.IMUMapping = [2]int{-1, 0}
|
||||
globalSettings.OwnshipModeS = "F00000"
|
||||
globalSettings.DeveloperMode = false
|
||||
globalSettings.StaticIps = make([]string, 0)
|
||||
|
|
|
@ -26,6 +26,8 @@ import (
|
|||
"syscall"
|
||||
"text/template"
|
||||
"time"
|
||||
"archive/zip"
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
type SettingMessage struct {
|
||||
|
@ -387,10 +389,28 @@ func doReboot() {
|
|||
}
|
||||
|
||||
func handleDeleteLogFile(w http.ResponseWriter, r *http.Request) {
|
||||
log.Printf("handleDeleteLogFile called!!!\n")
|
||||
log.Println("handleDeleteLogFile called!!!")
|
||||
clearDebugLogFile()
|
||||
}
|
||||
|
||||
func handleDeleteAHRSLogFiles(w http.ResponseWriter, r *http.Request) {
|
||||
files, err := ioutil.ReadDir("/var/log")
|
||||
if err != nil {
|
||||
http.Error(w, fmt.Sprintf("error deleting AHRS logs: %s", err), http.StatusNotFound)
|
||||
return
|
||||
}
|
||||
|
||||
var fn string
|
||||
for _, f := range files {
|
||||
fn = f.Name()
|
||||
if v, _ := filepath.Match("sensors_*.csv", fn) ; v {
|
||||
os.Remove("/var/log/" + fn)
|
||||
log.Printf("Deleting AHRS log file %s\n", fn)
|
||||
}
|
||||
analysisLogger = nil
|
||||
}
|
||||
}
|
||||
|
||||
func handleDevelModeToggle(w http.ResponseWriter, r *http.Request) {
|
||||
log.Printf("handleDevelModeToggle called!!!\n")
|
||||
globalSettings.DeveloperMode = true
|
||||
|
@ -410,8 +430,6 @@ func handleRebootRequest(w http.ResponseWriter, r *http.Request) {
|
|||
go delayReboot()
|
||||
}
|
||||
|
||||
var f int // We need this to be global to handle successive calls to handleOrientAHRS.
|
||||
|
||||
func handleOrientAHRS(w http.ResponseWriter, r *http.Request) {
|
||||
// define header in support of cross-domain AJAX
|
||||
setNoCache(w)
|
||||
|
@ -425,7 +443,6 @@ func handleOrientAHRS(w http.ResponseWriter, r *http.Request) {
|
|||
if r.Method == "POST" {
|
||||
var (
|
||||
action []byte = make([]byte, 1)
|
||||
u int
|
||||
err error
|
||||
)
|
||||
|
||||
|
@ -436,38 +453,22 @@ func handleOrientAHRS(w http.ResponseWriter, r *http.Request) {
|
|||
|
||||
switch action[0] {
|
||||
case 'f': // Set sensor "forward" direction (toward nose of airplane).
|
||||
if f, err = getMinAccelDirection(); err != nil {
|
||||
f, err := getMinAccelDirection()
|
||||
if err != nil {
|
||||
log.Printf("AHRS Error: sensor orientation: couldn't read accelerometer: %s\n", err)
|
||||
http.Error(w, fmt.Sprintf("couldn't read accelerometer: %s\n", err), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
log.Printf("AHRS Info: sensor orientation: received forward direction %d\n", f)
|
||||
case 'u': // Set sensor "up" direction (toward top of airplane).
|
||||
if u, err = getMinAccelDirection(); err != nil {
|
||||
log.Printf("AHRS Error: sensor orientation: couldn't read accelerometer: %s\n", err)
|
||||
http.Error(w, fmt.Sprintf("couldn't read accelerometer: %s\n", err), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
log.Printf("AHRS Info: sensor orientation: received up direction %d\n", u)
|
||||
|
||||
if f == u || f == -u {
|
||||
log.Printf("AHRS Error: sensor orientation: up (%d) and forward (%d) axes cannot be the same\n", u, f)
|
||||
http.Error(w, fmt.Sprintf("up (%d) and forward (%d) axes cannot be the same", u, f),
|
||||
http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
globalSettings.IMUMapping = [2]int{f, u}
|
||||
log.Printf("AHRS Info: sensor orientation success! forward axis is %d\n", f)
|
||||
globalSettings.IMUMapping = [2]int{f, 0}
|
||||
case 'd': // Set sensor "up" direction (toward top of airplane).
|
||||
globalSettings.SensorQuaternion = [4]float64{0, 0, 0, 0}
|
||||
saveSettings()
|
||||
myIMUReader.Close()
|
||||
globalStatus.IMUConnected = false // restart the processes depending on the orientation
|
||||
CageAHRS()
|
||||
log.Printf("AHRS Info: sensor orientation success! forward: %d; up: %d\n", f, u)
|
||||
default: // Cancel the sensor calibration.
|
||||
f = 0
|
||||
log.Println("AHRS Info: sensor orientation: canceled")
|
||||
ResetAHRSGLoad()
|
||||
time.Sleep(2000 * time.Millisecond)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -486,6 +487,21 @@ func handleCageAHRS(w http.ResponseWriter, r *http.Request) {
|
|||
}
|
||||
}
|
||||
|
||||
func handleCalibrateAHRS(w http.ResponseWriter, r *http.Request) {
|
||||
// define header in support of cross-domain AJAX
|
||||
setNoCache(w)
|
||||
w.Header().Set("Content-Type", "text/plain")
|
||||
w.Header().Set("Access-Control-Allow-Origin", "*")
|
||||
w.Header().Set("Access-Control-Allow-Method", "GET, POST, OPTIONS")
|
||||
w.Header().Set("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept")
|
||||
|
||||
// For an OPTION method request, we return header without processing.
|
||||
// This ensures we are recognized as supporting cross-domain AJAX REST calls.
|
||||
if r.Method == "POST" {
|
||||
CalibrateAHRS()
|
||||
}
|
||||
}
|
||||
|
||||
func handleResetGMeter(w http.ResponseWriter, r *http.Request) {
|
||||
// define header in support of cross-domain AJAX
|
||||
setNoCache(w)
|
||||
|
@ -528,13 +544,63 @@ func delayReboot() {
|
|||
}
|
||||
|
||||
func handleDownloadLogRequest(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Content-Type", "applicaiton/zip")
|
||||
w.Header().Set("Content-Type", "application/zip")
|
||||
w.Header().Set("Content-Disposition", "attachment; filename='stratux.log'")
|
||||
http.ServeFile(w, r, "/var/log/stratux.log")
|
||||
}
|
||||
|
||||
func handleDownloadAHRSLogsRequest(w http.ResponseWriter, r *http.Request) {
|
||||
// Common error handler
|
||||
httpErr := func(w http.ResponseWriter, e error) {
|
||||
http.Error(w, fmt.Sprintf("error zipping AHRS logs: %s", e), http.StatusNotFound)
|
||||
}
|
||||
|
||||
files, err := ioutil.ReadDir("/var/log")
|
||||
if err != nil {
|
||||
httpErr(w, err)
|
||||
return
|
||||
}
|
||||
|
||||
z := zip.NewWriter(w)
|
||||
defer z.Close()
|
||||
|
||||
for _, f := range files {
|
||||
fn := f.Name()
|
||||
v1, _ := filepath.Match("sensors_*.csv", fn)
|
||||
v2, _ := filepath.Match("stratux.log", fn)
|
||||
if !(v1 || v2) {
|
||||
continue
|
||||
}
|
||||
|
||||
unzippedFile, err := os.Open("/var/log/" + fn)
|
||||
if err != nil {
|
||||
httpErr(w, err)
|
||||
return
|
||||
}
|
||||
|
||||
fh, err := zip.FileInfoHeader(f)
|
||||
if err != nil {
|
||||
httpErr(w, err)
|
||||
return
|
||||
}
|
||||
zippedFile, err := z.CreateHeader(fh)
|
||||
if err != nil {
|
||||
httpErr(w, err)
|
||||
return
|
||||
}
|
||||
|
||||
_, err = io.Copy(zippedFile, unzippedFile)
|
||||
if err != nil {
|
||||
httpErr(w, err)
|
||||
return
|
||||
}
|
||||
}
|
||||
w.Header().Set("Content-Type", "application/zip")
|
||||
w.Header().Set("Content-Disposition", "attachment; filename=\"ahrs_logs.zip\"")
|
||||
}
|
||||
|
||||
func handleDownloadDBRequest(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Content-Type", "applicaiton/zip")
|
||||
w.Header().Set("Content-Type", "application/zip")
|
||||
w.Header().Set("Content-Disposition", "attachment; filename='stratux.sqlite'")
|
||||
http.ServeFile(w, r, "/var/log/stratux.sqlite")
|
||||
}
|
||||
|
@ -747,13 +813,14 @@ func managementInterface() {
|
|||
http.HandleFunc("/updateUpload", handleUpdatePostRequest)
|
||||
http.HandleFunc("/roPartitionRebuild", handleroPartitionRebuild)
|
||||
http.HandleFunc("/develmodetoggle", handleDevelModeToggle)
|
||||
|
||||
http.HandleFunc("/orientAHRS", handleOrientAHRS)
|
||||
http.HandleFunc("/calibrateAHRS", handleCalibrateAHRS)
|
||||
http.HandleFunc("/cageAHRS", handleCageAHRS)
|
||||
http.HandleFunc("/resetGMeter", handleResetGMeter)
|
||||
|
||||
http.HandleFunc("/deletelogfile", handleDeleteLogFile)
|
||||
http.HandleFunc("/downloadlog", handleDownloadLogRequest)
|
||||
http.HandleFunc("/deleteahrslogfiles", handleDeleteAHRSLogFiles)
|
||||
http.HandleFunc("/downloadahrslogs", handleDownloadAHRSLogsRequest)
|
||||
http.HandleFunc("/downloaddb", handleDownloadDBRequest)
|
||||
|
||||
err := http.ListenAndServe(managementAddr, nil)
|
||||
|
|
179
main/sensors.go
179
main/sensors.go
|
@ -5,6 +5,7 @@ import (
|
|||
"log"
|
||||
"math"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"../goflying/ahrs"
|
||||
|
@ -16,16 +17,17 @@ import (
|
|||
|
||||
const (
|
||||
numRetries uint8 = 5
|
||||
calCLimit = 0.15
|
||||
calDLimit = 10.0
|
||||
)
|
||||
|
||||
var (
|
||||
i2cbus embd.I2CBus
|
||||
myPressureReader sensors.PressureReader
|
||||
myIMUReader sensors.IMUReader
|
||||
s ahrs.AHRSProvider
|
||||
cal chan (bool)
|
||||
cal chan (string)
|
||||
analysisLogger *ahrs.AHRSLogger
|
||||
ahrsCalibrating, needsCage bool // Does the sensor orientation matrix need to be recalculated?
|
||||
ahrsCalibrating bool
|
||||
logMap map[string]interface{}
|
||||
)
|
||||
|
||||
|
@ -44,7 +46,6 @@ func pollSensors() {
|
|||
|
||||
// If it's not currently connected, try connecting to pressure sensor
|
||||
if globalSettings.BMP_Sensor_Enabled && !globalStatus.BMPConnected {
|
||||
log.Println("AHRS Info: attempting pressure sensor connection.")
|
||||
globalStatus.BMPConnected = initPressureSensor() // I2C temperature and pressure altitude.
|
||||
go tempAndPressureSender()
|
||||
}
|
||||
|
@ -125,39 +126,31 @@ func tempAndPressureSender() {
|
|||
}
|
||||
|
||||
func initIMU() (ok bool) {
|
||||
log.Println("AHRS Info: attempting to connect to MPU9250")
|
||||
imu, err := sensors.NewMPU9250()
|
||||
if err == nil {
|
||||
myIMUReader = imu
|
||||
time.Sleep(200 * time.Millisecond)
|
||||
log.Println("AHRS Info: Successfully connected MPU9250")
|
||||
return true
|
||||
}
|
||||
|
||||
// TODO westphae: try to connect to MPU9150 or other IMUs.
|
||||
|
||||
log.Println("AHRS Error: couldn't initialize MPU9250")
|
||||
log.Println("AHRS Error: couldn't initialize an IMU")
|
||||
return false
|
||||
}
|
||||
|
||||
func sensorAttitudeSender() {
|
||||
var (
|
||||
roll, pitch, heading float64
|
||||
t time.Time
|
||||
m *ahrs.Measurement
|
||||
a, b, c, d, mm [3]float64 // IMU measurements: accel, gyro, accel bias, gyro bias, magnetometer
|
||||
f [4]float64 // Sensor orientation quaternion
|
||||
ff [3][3]float64 // Sensor orientation matrix
|
||||
cc float64
|
||||
roll, pitch, heading float64
|
||||
mpuError, magError error
|
||||
failNum uint8
|
||||
)
|
||||
|
||||
log.Println("AHRS Info: initializing new Simple AHRS")
|
||||
s = ahrs.InitializeSimple()
|
||||
m = ahrs.NewMeasurement()
|
||||
cal = make(chan (bool), 1)
|
||||
needsCage = true
|
||||
s := ahrs.NewSimpleAHRS()
|
||||
m := ahrs.NewMeasurement()
|
||||
cal = make(chan (string), 1)
|
||||
|
||||
// Set up loggers for analysis
|
||||
ahrswebListener, err := ahrsweb.NewKalmanListener()
|
||||
|
@ -171,74 +164,81 @@ func sensorAttitudeSender() {
|
|||
// Need a sampling freq faster than 10Hz
|
||||
timer := time.NewTicker(50 * time.Millisecond) // ~20Hz update.
|
||||
for {
|
||||
// Do an initial calibration
|
||||
select { // Don't block if cal isn't receiving: only need one calibration in the queue at a time.
|
||||
case cal <- true:
|
||||
default:
|
||||
// Set sensor gyro calibrations
|
||||
if c, d := &globalSettings.C, &globalSettings.D; d[0]*d[0] + d[1]*d[1] + d[2]*d[2] > 0 {
|
||||
s.SetCalibrations(c, d)
|
||||
log.Printf("AHRS Info: IMU Calibrations read from settings: accel %6f %6f %6f; gyro %6f %6f %6f\n",
|
||||
c[0], c[1], c[2], d[0], d[1], d[2])
|
||||
} else {
|
||||
// Do an initial calibration
|
||||
select { // Don't block if cal isn't receiving: only need one calibration in the queue at a time.
|
||||
case cal <- "cal":
|
||||
default:
|
||||
}
|
||||
}
|
||||
|
||||
// Set sensor rotation matrix / quaternion
|
||||
f[0] = globalSettings.SensorQuaternion[0]
|
||||
f[1] = globalSettings.SensorQuaternion[1]
|
||||
f[2] = globalSettings.SensorQuaternion[2]
|
||||
f[3] = globalSettings.SensorQuaternion[3]
|
||||
if f[0]*f[0]+f[1]*f[1]+f[2]*f[2]+f[3]*f[3] > 0.5 {
|
||||
// Use the sensor rotation quaternion from config.
|
||||
ff = *ahrs.QuaternionToRotationMatrix(f[0], f[1], f[2], f[3])
|
||||
needsCage = false
|
||||
// Set sensor quaternion
|
||||
if f := &globalSettings.SensorQuaternion; f[0]*f[0] + f[1]*f[1] + f[2]*f[2] + f[3]*f[3] > 0 {
|
||||
s.SetSensorQuaternion(f)
|
||||
} else {
|
||||
select { // Don't block if cal isn't receiving: only need one calibration in the queue at a time.
|
||||
case cal <- "level":
|
||||
default:
|
||||
}
|
||||
}
|
||||
|
||||
failNum = 0
|
||||
<-timer.C
|
||||
time.Sleep(950 * time.Millisecond)
|
||||
for globalSettings.IMU_Sensor_Enabled && globalStatus.IMUConnected {
|
||||
<-timer.C
|
||||
|
||||
// Process calibration and level requests
|
||||
select {
|
||||
case <-cal:
|
||||
log.Println("AHRS Info: Calibrating IMU")
|
||||
case action := <-cal:
|
||||
log.Printf("AHRS Info: cal received action %s\n", action)
|
||||
ahrsCalibrating = true
|
||||
//TODO westphae: check for errors when reading IMU
|
||||
myIMUReader.Read() // Clear out the averages
|
||||
time.Sleep(1 * time.Second)
|
||||
_, d[0], d[1], d[2], c[0], c[1], c[2], _, _, _, _, _ = myIMUReader.Read()
|
||||
log.Printf("AHRS Info: IMU Calibrated: accel %6f %6f %6f; gyro %6f %6f %6f\n",
|
||||
c[0], c[1], c[2], d[0], d[1], d[2])
|
||||
var (
|
||||
nTries uint8
|
||||
cc, dd float64
|
||||
)
|
||||
for (math.Abs(cc-1) > calCLimit || dd > calDLimit) && nTries < numRetries {
|
||||
time.Sleep(1 * time.Second)
|
||||
_, d1, d2, d3, c1, c2, c3, _, _, _, mpuError, _ := myIMUReader.Read()
|
||||
cc = math.Sqrt(c1*c1 + c2*c2 + c3*c3)
|
||||
dd = math.Sqrt(d1*d1 + d2*d2 + d3*d3)
|
||||
nTries++
|
||||
log.Printf("AHRS Info: IMU calibration attempt #%d\n", nTries)
|
||||
if mpuError != nil {
|
||||
log.Printf("AHRS Info: Error reading IMU while calibrating: %s\n", mpuError)
|
||||
} else {
|
||||
if strings.Contains(action, "cal") { // Calibrate gyros
|
||||
globalSettings.D = [3]float64{d1, d2, d3}
|
||||
s.SetCalibrations(nil, &globalSettings.D)
|
||||
log.Printf("AHRS Info: IMU gyro calibration: %3f %3f %3f\n", d1, d2, d3)
|
||||
}
|
||||
if strings.Contains(action, "level") { // Calibrate accel / level
|
||||
globalSettings.C = [3]float64{c1, c2, c3}
|
||||
s.SetCalibrations(&globalSettings.C, nil)
|
||||
globalSettings.SensorQuaternion = *makeOrientationQuaternion(globalSettings.C)
|
||||
s.SetSensorQuaternion(&globalSettings.SensorQuaternion)
|
||||
s.Reset()
|
||||
log.Printf("AHRS Info: IMU accel calibration: %3f %3f %3f\n", c1, c2, c3)
|
||||
log.Printf("AHRS Info: Caged to quaternion %v\n", globalSettings.SensorQuaternion)
|
||||
}
|
||||
saveSettings()
|
||||
}
|
||||
}
|
||||
ahrsCalibrating = false
|
||||
cc = math.Sqrt(c[0]*c[0] + c[1]*c[1] + c[2]*c[2])
|
||||
s.Reset()
|
||||
<-timer.C // Make sure we get data for the actual algorithm
|
||||
default:
|
||||
}
|
||||
|
||||
if needsCage {
|
||||
log.Println("AHRS Info: Caging")
|
||||
ff = *makeSensorRotationMatrix([3]float64{c[0], c[1], c[2]})
|
||||
f[0], f[1], f[2], f[3] = ahrs.RotationMatrixToQuaternion(ff)
|
||||
globalSettings.SensorQuaternion[0] = f[0]
|
||||
globalSettings.SensorQuaternion[1] = f[1]
|
||||
globalSettings.SensorQuaternion[2] = f[2]
|
||||
globalSettings.SensorQuaternion[3] = f[3]
|
||||
saveSettings()
|
||||
needsCage = false
|
||||
}
|
||||
|
||||
// Make the IMU sensor measurements.
|
||||
t = stratuxClock.Time
|
||||
m.T = float64(t.UnixNano()/1000) / 1e6
|
||||
|
||||
_, b[0], b[1], b[2], a[0], a[1], a[2], mm[0], mm[1], mm[2], mpuError, magError = myIMUReader.Read()
|
||||
a[0] /= cc
|
||||
a[1] /= cc
|
||||
a[2] /= cc
|
||||
b[0] -= d[0]
|
||||
b[1] -= d[1]
|
||||
b[2] -= d[2]
|
||||
m.A1 = -(ff[0][0]*a[0] + ff[0][1]*a[1] + ff[0][2]*a[2])
|
||||
m.A2 = -(ff[1][0]*a[0] + ff[1][1]*a[1] + ff[1][2]*a[2])
|
||||
m.A3 = -(ff[2][0]*a[0] + ff[2][1]*a[1] + ff[2][2]*a[2])
|
||||
m.B1 = ff[0][0]*b[0] + ff[0][1]*b[1] + ff[0][2]*b[2]
|
||||
m.B2 = ff[1][0]*b[0] + ff[1][1]*b[1] + ff[1][2]*b[2]
|
||||
m.B3 = ff[2][0]*b[0] + ff[2][1]*b[1] + ff[2][2]*b[2]
|
||||
m.M1 = ff[0][0]*mm[0] + ff[0][1]*mm[1] + ff[0][2]*mm[2]
|
||||
m.M2 = ff[1][0]*mm[0] + ff[1][1]*mm[1] + ff[1][2]*mm[2]
|
||||
m.M3 = ff[2][0]*mm[0] + ff[2][1]*mm[1] + ff[2][2]*mm[2]
|
||||
_, m.B1, m.B2, m.B3, m.A1, m.A2, m.A3, m.M1, m.M2, m.M3, mpuError, magError = myIMUReader.Read()
|
||||
m.SValid = mpuError == nil
|
||||
m.MValid = magError == nil
|
||||
if mpuError != nil {
|
||||
|
@ -254,11 +254,13 @@ func sensorAttitudeSender() {
|
|||
}
|
||||
failNum = 0
|
||||
if magError != nil {
|
||||
log.Printf("AHRS Magnetometer Error, not using for this run: %s\n", magError)
|
||||
if globalSettings.DEBUG {
|
||||
log.Printf("AHRS Magnetometer Error, not using for this run: %s\n", magError)
|
||||
}
|
||||
m.MValid = false
|
||||
// Don't necessarily disconnect here, unless AHRSProvider deeply depends on magnetometer
|
||||
}
|
||||
|
||||
// Make the GPS measurements.
|
||||
m.TW = float64(mySituation.GPSLastGroundTrackTime.UnixNano()/1000) / 1e6
|
||||
m.WValid = isGPSGroundTrackValid()
|
||||
if m.WValid {
|
||||
|
@ -271,10 +273,10 @@ func sensorAttitudeSender() {
|
|||
}
|
||||
}
|
||||
|
||||
// Run the AHRS calcs
|
||||
// Run the AHRS calculations.
|
||||
s.Compute(m)
|
||||
|
||||
// If we have valid AHRS info, then update mySituation
|
||||
// If we have valid AHRS info, then update mySituation.
|
||||
mySituation.muAttitude.Lock()
|
||||
if s.Valid() {
|
||||
roll, pitch, heading = s.RollPitchHeading()
|
||||
|
@ -296,7 +298,6 @@ func sensorAttitudeSender() {
|
|||
|
||||
mySituation.AHRSLastAttitudeTime = t
|
||||
} else {
|
||||
s.Reset()
|
||||
mySituation.AHRSRoll = ahrs.Invalid
|
||||
mySituation.AHRSPitch = ahrs.Invalid
|
||||
mySituation.AHRSGyroHeading = ahrs.Invalid
|
||||
|
@ -307,28 +308,27 @@ func sensorAttitudeSender() {
|
|||
mySituation.AHRSGLoadMin = ahrs.Invalid
|
||||
mySituation.AHRSGLoadMax = 0
|
||||
mySituation.AHRSLastAttitudeTime = time.Time{}
|
||||
s.Reset()
|
||||
}
|
||||
mySituation.muAttitude.Unlock()
|
||||
|
||||
makeAHRSGDL90Report() // Send whether or not valid - the function will invalidate the values as appropriate
|
||||
// makeFFAHRSSimReport() // Simultaneous use of GDL90 and FFSIM not supported in FF 7.5.1 or later. Function definition will be kept for AHRS debugging and future workarounds.
|
||||
|
||||
// Send to AHRS debugging server:
|
||||
// Send to AHRS debugging server.
|
||||
if ahrswebListener != nil {
|
||||
if err = ahrswebListener.Send(s.GetState(), m); err != nil {
|
||||
log.Printf("Error writing to ahrsweb: %s\n", err)
|
||||
log.Printf("AHRS Error: couldn't write to ahrsweb: %s\n", err)
|
||||
ahrswebListener = nil
|
||||
}
|
||||
}
|
||||
|
||||
// Log it to csv for analysis
|
||||
// Log it to csv for later analysis.
|
||||
if globalSettings.AHRSLog && usage.Usage() < 0.95 {
|
||||
if analysisLogger == nil {
|
||||
analysisFilename := filepath.Join(logDirf, fmt.Sprintf("sensors_%s.csv",
|
||||
time.Now().Format("20060102_150405")))
|
||||
analysisFilename := fmt.Sprintf("sensors_%s.csv", time.Now().Format("20060102_150405"))
|
||||
logMap = s.GetLogMap()
|
||||
updateExtraLogging()
|
||||
analysisLogger = ahrs.NewAHRSLogger(analysisFilename, logMap)
|
||||
analysisLogger = ahrs.NewAHRSLogger(filepath.Join(logDirf, analysisFilename), logMap)
|
||||
}
|
||||
|
||||
if analysisLogger != nil {
|
||||
|
@ -353,10 +353,9 @@ func updateExtraLogging() {
|
|||
logMap["BaroVerticalSpeed"] = float64(mySituation.BaroVerticalSpeed)
|
||||
}
|
||||
|
||||
func makeSensorRotationMatrix(g [3]float64) (rotmat *[3][3]float64) {
|
||||
func makeOrientationQuaternion(g [3]float64) (f *[4]float64) {
|
||||
if globalSettings.IMUMapping[0] == 0 { // if unset, default to some standard orientation
|
||||
globalSettings.IMUMapping[0] = -1 // +2 for RY836AI
|
||||
globalSettings.IMUMapping[1] = -3 // +3 for RY836AI
|
||||
}
|
||||
|
||||
// This is the "forward direction" chosen during the orientation process.
|
||||
|
@ -370,8 +369,10 @@ func makeSensorRotationMatrix(g [3]float64) (rotmat *[3][3]float64) {
|
|||
// Normalize the gravity vector to be 1 G.
|
||||
z, _ := ahrs.MakeUnitVector(g)
|
||||
|
||||
rotmat, _ = ahrs.MakeHardSoftRotationMatrix(*z, *x, [3]float64{0, 0, 1}, [3]float64{1, 0, 0})
|
||||
return rotmat
|
||||
rotmat, _ := ahrs.MakeHardSoftRotationMatrix(*z, *x, [3]float64{0, 0, 1}, [3]float64{1, 0, 0})
|
||||
f = new([4]float64)
|
||||
f[0], f[1], f[2], f[3] = ahrs.RotationMatrixToQuaternion(*rotmat)
|
||||
return
|
||||
}
|
||||
|
||||
// This is used in the orientation process where the user specifies the forward and up directions.
|
||||
|
@ -407,10 +408,14 @@ func getMinAccelDirection() (i int, err error) {
|
|||
return
|
||||
}
|
||||
|
||||
// CageAHRS sends a signal to the AHRSProvider that it should be reset.
|
||||
// CageAHRS sends a signal to the AHRSProvider that it should recalibrate and reset its level orientation.
|
||||
func CageAHRS() {
|
||||
needsCage = true
|
||||
cal <- true
|
||||
cal <- "level"
|
||||
}
|
||||
|
||||
// CageAHRS sends a signal to the AHRSProvider that it should recalibrate and reset its level orientation.
|
||||
func CalibrateAHRS() {
|
||||
cal <- "cal"
|
||||
}
|
||||
|
||||
// ResetAHRSGLoad resets the min and max to the current G load value.
|
||||
|
|
|
@ -91,7 +91,7 @@ Stratux makes available a webserver to retrieve statistics which may be useful t
|
|||
|
||||
* `http://192.168.10.1/getStatus` - device status and statistics. Example output (commented JSON):
|
||||
|
||||
```json
|
||||
```javascript
|
||||
{
|
||||
"Version": "v0.5b1", // Software version.
|
||||
"Devices": 0, // Number of radios connected.
|
||||
|
|
|
@ -2,9 +2,6 @@
|
|||
package sensors
|
||||
|
||||
import (
|
||||
"log"
|
||||
"time"
|
||||
|
||||
"../goflying/mpu9250"
|
||||
)
|
||||
|
||||
|
@ -29,21 +26,16 @@ func NewMPU9250() (*MPU9250, error) {
|
|||
err error
|
||||
)
|
||||
|
||||
log.Println("AHRS Info: Making new MPU9250")
|
||||
mpu, err = mpu9250.NewMPU9250(gyroRange, accelRange, updateFreq, true, false)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Set Gyro (Accel) LPFs to 20 (21) Hz to filter out prop/glareshield vibrations above 1200 (1260) RPM
|
||||
log.Println("AHRS Info: Setting MPU9250 LPF")
|
||||
mpu.SetGyroLPF(21)
|
||||
mpu.SetAccelLPF(21)
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
|
||||
m.mpu = mpu
|
||||
|
||||
log.Println("AHRS Info: monitoring IMU")
|
||||
return &m, nil
|
||||
}
|
||||
|
||||
|
|
|
@ -1,26 +1,29 @@
|
|||
// application constants
|
||||
var URL_HOST_BASE = window.location.hostname;
|
||||
var URL_SETTINGS_GET = "http://" + URL_HOST_BASE + "/getSettings";
|
||||
var URL_SETTINGS_SET = "http://" + URL_HOST_BASE + "/setSettings";
|
||||
var URL_GPS_WS = "ws://" + URL_HOST_BASE + "/situation";
|
||||
var URL_TOWERS_GET = "http://" + URL_HOST_BASE + "/getTowers";
|
||||
var URL_STATUS_GET = "http://" + URL_HOST_BASE + "/getStatus";
|
||||
var URL_SATELLITES_GET = "http://" + URL_HOST_BASE + "/getSatellites";
|
||||
var URL_STATUS_WS = "ws://" + URL_HOST_BASE + "/status";
|
||||
var URL_TRAFFIC_WS = "ws://" + URL_HOST_BASE + "/traffic";
|
||||
var URL_WEATHER_WS = "ws://" + URL_HOST_BASE + "/weather";
|
||||
var URL_DEVELOPER_GET = "ws://" + URL_HOST_BASE + "/developer";
|
||||
var URL_UPDATE_UPLOAD = "http://" + URL_HOST_BASE + "/updateUpload";
|
||||
var URL_REBOOT = "http://" + URL_HOST_BASE + "/reboot";
|
||||
var URL_SHUTDOWN = "http://" + URL_HOST_BASE + "/shutdown";
|
||||
var URL_RESTARTAPP = "http://" + URL_HOST_BASE + "/restart";
|
||||
var URL_DEV_TOGGLE_GET = "http://" + URL_HOST_BASE + "/develmodetoggle";
|
||||
var URL_AHRS_ORIENT = "http://" + URL_HOST_BASE + "/orientAHRS";
|
||||
var URL_AHRS_CAGE = "http://" + URL_HOST_BASE + "/cageAHRS";
|
||||
var URL_GMETER_RESET = "http://" + URL_HOST_BASE + "/resetGMeter";
|
||||
var URL_DELETELOGFILE = "http://" + URL_HOST_BASE + "/deletelogfile";
|
||||
var URL_DOWNLOADLOGFILE = "http://" + URL_HOST_BASE + "/downloadlog";
|
||||
var URL_DOWNLOADDB = "http://" + URL_HOST_BASE + "/downloaddb";
|
||||
var URL_HOST_BASE = window.location.hostname;
|
||||
var URL_SETTINGS_GET = "http://" + URL_HOST_BASE + "/getSettings";
|
||||
var URL_SETTINGS_SET = "http://" + URL_HOST_BASE + "/setSettings";
|
||||
var URL_GPS_WS = "ws://" + URL_HOST_BASE + "/situation";
|
||||
var URL_TOWERS_GET = "http://" + URL_HOST_BASE + "/getTowers";
|
||||
var URL_STATUS_GET = "http://" + URL_HOST_BASE + "/getStatus";
|
||||
var URL_SATELLITES_GET = "http://" + URL_HOST_BASE + "/getSatellites";
|
||||
var URL_STATUS_WS = "ws://" + URL_HOST_BASE + "/status";
|
||||
var URL_TRAFFIC_WS = "ws://" + URL_HOST_BASE + "/traffic";
|
||||
var URL_WEATHER_WS = "ws://" + URL_HOST_BASE + "/weather";
|
||||
var URL_DEVELOPER_GET = "ws://" + URL_HOST_BASE + "/developer";
|
||||
var URL_UPDATE_UPLOAD = "http://" + URL_HOST_BASE + "/updateUpload";
|
||||
var URL_REBOOT = "http://" + URL_HOST_BASE + "/reboot";
|
||||
var URL_SHUTDOWN = "http://" + URL_HOST_BASE + "/shutdown";
|
||||
var URL_RESTARTAPP = "http://" + URL_HOST_BASE + "/restart";
|
||||
var URL_DEV_TOGGLE_GET = "http://" + URL_HOST_BASE + "/develmodetoggle";
|
||||
var URL_AHRS_ORIENT = "http://" + URL_HOST_BASE + "/orientAHRS";
|
||||
var URL_AHRS_CAL = "http://" + URL_HOST_BASE + "/calibrateAHRS";
|
||||
var URL_AHRS_CAGE = "http://" + URL_HOST_BASE + "/cageAHRS";
|
||||
var URL_GMETER_RESET = "http://" + URL_HOST_BASE + "/resetGMeter";
|
||||
var URL_DELETELOGFILE = "http://" + URL_HOST_BASE + "/deletelogfile";
|
||||
var URL_DOWNLOADLOGFILE = "http://" + URL_HOST_BASE + "/downloadlog";
|
||||
var URL_DELETEAHRSLOGFILES = "http://" + URL_HOST_BASE + "/deleteahrslogfiles";
|
||||
var URL_DOWNLOADAHRSLOGFILES = "http://" + URL_HOST_BASE + "/downloadahrslogs";
|
||||
var URL_DOWNLOADDB = "http://" + URL_HOST_BASE + "/downloaddb";
|
||||
|
||||
// define the module with dependency on mobile-angular-ui
|
||||
//var app = angular.module('stratux', ['ngRoute', 'mobile-angular-ui', 'mobile-angular-ui.gestures', 'appControllers']);
|
||||
|
@ -91,7 +94,7 @@ app.controller('MainCtrl', function ($scope, $http) {
|
|||
// any logic global logic
|
||||
$http.get(URL_SETTINGS_GET)
|
||||
.then(function(response) {
|
||||
settings = angular.fromJson(response.data);
|
||||
var settings = angular.fromJson(response.data);
|
||||
$scope.DeveloperMode = settings.DeveloperMode;
|
||||
}, function(response) {
|
||||
//Second function handles error
|
||||
|
|
|
@ -1,59 +1,78 @@
|
|||
<div class="col-sm-12">
|
||||
<div class="col-sm-12">
|
||||
<div class="panel-group col-sm-6">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
Restart Stratux application
|
||||
</div>
|
||||
|
||||
<div class="panel-body">
|
||||
<div class="form-group reset-flow" align="center">
|
||||
<div class="col-xs-12">
|
||||
<a ng-click="postRestart()" class=
|
||||
"btn btn-primary btn-block" style=
|
||||
"margin-bottom:1em;">Restart Application</a>
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
Restart Stratux application
|
||||
</div>
|
||||
|
||||
<div class="panel-body">
|
||||
<div class="form-group reset-flow" align="center">
|
||||
<div class="col-xs-12">
|
||||
<a ng-click="postRestart()" class="btn btn-primary btn-block"
|
||||
style="margin-bottom:1em;">Restart Application</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="panel-group col-sm-6">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
Logfile (Size: {{Logfile_Size}} bytes)
|
||||
</div>
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
Logfile (Size: {{Logfile_Size}})
|
||||
</div>
|
||||
|
||||
<div class="panel-body">
|
||||
<div class="col-xs-12">
|
||||
<a href="./downloadlog" ng-click="postDownloadLog()"
|
||||
class="btn btn-primary btn-block" style=
|
||||
"margin-bottom:0.5em;">Download Logfile</a>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<div class="col-xs-12">
|
||||
<a href="./downloadlog" ng-click="postDownloadLog()"
|
||||
class="btn btn-primary btn-block"
|
||||
style="margin-bottom:0.5em">Download Logfile</a>
|
||||
</div>
|
||||
|
||||
<div class="col-xs-12">
|
||||
<a ng-click="postDeleteLog()" class=
|
||||
"btn btn-primary btn-block" style=
|
||||
"margin-bottom:0.5em;">Delete Logfile</a>
|
||||
</div>
|
||||
<div class="col-xs-12">
|
||||
<a ng-click="postDeleteLog()"
|
||||
class="btn btn-primary btn-block"
|
||||
style="margin-bottom:0.5em">Delete Logfile</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="panel-group col-sm-6" style="float:right;">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
Database
|
||||
</div>
|
||||
<div class="panel-group col-sm-6">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
AHRS Log Files (Size: {{AHRS_LogFiles_Size}})
|
||||
</div>
|
||||
|
||||
<div class="panel-body">
|
||||
<div class="col-xs-12">
|
||||
|
||||
<a href="./downloaddb" ng-click="postDownloadDB()"
|
||||
class="btn btn-primary btn-block" style=
|
||||
"margin-bottom:0.5em;">Download Database</a>
|
||||
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<div class="col-xs-12">
|
||||
<a href="./downloadahrslogs" download="ahrs_logs.zip" ng-click="postDownloadAHRSLogs()"
|
||||
class="btn btn-primary btn-block"
|
||||
style="margin-bottom:0.5em">Download AHRS Logs</a>
|
||||
</div>
|
||||
|
||||
<div class="col-xs-12">
|
||||
<a ng-click="postDeleteAHRSLogs()"
|
||||
class="btn btn-primary btn-block"
|
||||
style="margin-bottom:0.5em">Delete AHRS Logs</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="panel-group col-sm-6">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
Database
|
||||
</div>
|
||||
|
||||
<div class="panel-body">
|
||||
<div class="col-xs-12">
|
||||
<a href="./downloaddb" ng-click="postDownloadDB()"
|
||||
class="btn btn-primary btn-block"
|
||||
style="margin-bottom:0.5em;">Download Database</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -3,7 +3,7 @@ function AHRSRenderer(locationId) {
|
|||
this.height = -1;
|
||||
|
||||
this.locationId = locationId;
|
||||
this.canvas = document.getElementById(locationId);
|
||||
this.canvas = document.getElementById(this.locationId);
|
||||
this.resize();
|
||||
|
||||
// State variables
|
||||
|
@ -13,7 +13,7 @@ function AHRSRenderer(locationId) {
|
|||
this.slipSkid = 0;
|
||||
this.altitude = 0;
|
||||
|
||||
var display = SVG(locationId).viewbox(-200, -200, 400, 400).group();
|
||||
var display = SVG(this.locationId).viewbox(-200, -200, 400, 400).group();
|
||||
|
||||
this.ai = display.group().addClass('ai');
|
||||
|
||||
|
@ -26,26 +26,24 @@ function AHRSRenderer(locationId) {
|
|||
this.ai = this.ai.clipWith(screenClip).group();
|
||||
|
||||
// card is the earth+sky+pitch marks, moves with both pitch and roll.
|
||||
this.pitchScale = 0.5;
|
||||
this.card = this.ai.group();
|
||||
this.card.circle(2400).cx(0).cy(0).addClass('sky'); // Sky
|
||||
this.card.line(-1200, 0, 1200, 0).addClass('marks'); // Horizon line
|
||||
this.card.circle(2400).cx(0).cy(0).addClass('earth').clipWith(earthClip); // Earth
|
||||
|
||||
var pitchMarks = this.card.group().addClass('marks').clipWith(this.pitchClip);
|
||||
for (i = -1050; i <= 1050; i+=25) {
|
||||
switch (i%100) {
|
||||
case 0:
|
||||
pitchMarks.line(-40, i, 40, i);
|
||||
if (i !== 0) {
|
||||
pitchMarks.text(Math.abs(i) <= 900 ? Math.abs(i / 10).toString() : '80').x(-55).cy(i).addClass('markText');
|
||||
pitchMarks.text(Math.abs(i) <= 900 ? Math.abs(i / 10).toString() : '80').x(+55).cy(i).addClass('markText');
|
||||
}
|
||||
break;
|
||||
case 50:
|
||||
pitchMarks.line(-20, i, 20, i);
|
||||
break;
|
||||
default:
|
||||
pitchMarks.line(-10, i, 10, i);
|
||||
var y;
|
||||
for (var i = -1050; i <= 1050; i+=50) {
|
||||
y = i * this.pitchScale;
|
||||
if (i%100 === 0) {
|
||||
pitchMarks.line(-30, y, 30, y);
|
||||
if (i !== 0) {
|
||||
pitchMarks.text(Math.abs(i) <= 900 ? Math.abs(i / 10).toString() : '80').x(-55).cy(y).addClass('markText');
|
||||
pitchMarks.text(Math.abs(i) <= 900 ? Math.abs(i / 10).toString() : '80').x(+55).cy(y).addClass('markText');
|
||||
}
|
||||
} else {
|
||||
pitchMarks.line(-15, y, 15, y);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -119,10 +117,10 @@ AHRSRenderer.prototype = {
|
|||
this.slipSkid = +10;
|
||||
}
|
||||
|
||||
this.pitchClip.translate(0, -10 * this.pitch);
|
||||
this.pitchClip.translate(0, -10 * this.pitch * this.pitchScale);
|
||||
this.rollClip.rotate(this.roll, 0, 0);
|
||||
this.card.rotate(0, 0, 0).translate(0, 10 * this.pitch);
|
||||
this.card.rotate(-this.roll, 0, -10 * this.pitch);
|
||||
this.card.rotate(0, 0, 0).translate(0, 10 * this.pitch * this.pitchScale);
|
||||
this.card.rotate(-this.roll, 0, -10 * this.pitch * this.pitchScale);
|
||||
this.rollMarks.rotate(-this.roll, 0, 0);
|
||||
this.headingMarks.translate(-2 * (this.heading % 360), 0);
|
||||
this.skidBar.translate(-2 * this.slipSkid, 0);
|
||||
|
@ -157,7 +155,7 @@ function GMeterRenderer(locationId, nlim, plim, resetCallback) {
|
|||
this.height = -1;
|
||||
|
||||
this.locationId = locationId;
|
||||
this.canvas = document.getElementById(locationId);
|
||||
this.canvas = document.getElementById(this.locationId);
|
||||
this.resize();
|
||||
|
||||
// State variables
|
||||
|
@ -166,7 +164,7 @@ function GMeterRenderer(locationId, nlim, plim, resetCallback) {
|
|||
this.max = 1;
|
||||
|
||||
// Draw the G Meter using the svg.js library
|
||||
var gMeter = SVG(locationId).viewbox(-200, -200, 400, 400).group().addClass('gMeter');
|
||||
var gMeter = SVG(this.locationId).viewbox(-200, -200, 400, 400).group().addClass('gMeter');
|
||||
|
||||
var el, card = gMeter.group().addClass('card');
|
||||
card.circle(390).cx(0).cy(0);
|
||||
|
|
|
@ -10,7 +10,7 @@ function DeveloperCtrl($rootScope, $scope, $state, $http, $interval) {
|
|||
return; // we are getting called once after clicking away from the status page
|
||||
|
||||
if (($scope.socket === undefined) || ($scope.socket === null)) {
|
||||
socket = new WebSocket(URL_STATUS_WS);
|
||||
var socket = new WebSocket(URL_STATUS_WS);
|
||||
$scope.socket = socket; // store socket in scope for enter/exit usage
|
||||
}
|
||||
|
||||
|
@ -36,9 +36,9 @@ function DeveloperCtrl($rootScope, $scope, $state, $http, $interval) {
|
|||
};
|
||||
|
||||
socket.onmessage = function (msg) {
|
||||
console.log('Received status update.')
|
||||
console.log('Received status update.');
|
||||
|
||||
var status = JSON.parse(msg.data)
|
||||
var status = JSON.parse(msg.data);
|
||||
// Update Status
|
||||
$scope.Version = status.Version;
|
||||
$scope.Build = status.Build.substr(0, 10);
|
||||
|
@ -62,7 +62,8 @@ function DeveloperCtrl($rootScope, $scope, $state, $http, $interval) {
|
|||
$scope.UAT_PIREP_total = status.UAT_PIREP_total;
|
||||
$scope.UAT_NOTAM_total = status.UAT_NOTAM_total;
|
||||
$scope.UAT_OTHER_total = status.UAT_OTHER_total;
|
||||
$scope.Logfile_Size = status.Logfile_Size;
|
||||
$scope.Logfile_Size = humanFileSize(status.Logfile_Size);
|
||||
$scope.AHRS_LogFiles_Size = humanFileSize(status.AHRS_LogFiles_Size);
|
||||
// Errors array.
|
||||
if (status.Errors.length > 0) {
|
||||
$scope.visible_errors = true;
|
||||
|
@ -70,7 +71,7 @@ function DeveloperCtrl($rootScope, $scope, $state, $http, $interval) {
|
|||
}
|
||||
|
||||
var uptime = status.Uptime;
|
||||
if (uptime != undefined) {
|
||||
if (uptime !== undefined) {
|
||||
var up_d = parseInt((uptime/1000) / 86400),
|
||||
up_h = parseInt((uptime/1000 - 86400*up_d) / 3600),
|
||||
up_m = parseInt((uptime/1000 - 86400*up_d - 3600*up_h) / 60),
|
||||
|
@ -80,7 +81,7 @@ function DeveloperCtrl($rootScope, $scope, $state, $http, $interval) {
|
|||
// $('#Uptime').text('unavailable');
|
||||
}
|
||||
var boardtemp = status.CPUTemp;
|
||||
if (boardtemp != undefined) {
|
||||
if (boardtemp !== undefined) {
|
||||
/* boardtemp is celcius to tenths */
|
||||
$scope.CPUTemp = String(boardtemp.toFixed(1) + 'C / ' + ((boardtemp * 9 / 5) + 32.0).toFixed(1) + 'F');
|
||||
} else {
|
||||
|
@ -125,6 +126,26 @@ function DeveloperCtrl($rootScope, $scope, $state, $http, $interval) {
|
|||
});
|
||||
};
|
||||
|
||||
$scope.postDeleteAHRSLogs = function () {
|
||||
$http.post(URL_DELETEAHRSLOGFILES).
|
||||
then(function (response) {
|
||||
// do nothing
|
||||
// $scope.$apply();
|
||||
}, function (response) {
|
||||
// do nothing
|
||||
});
|
||||
};
|
||||
|
||||
$scope.postDownloadAHRSLogs = function () {
|
||||
$http.post(URL_DOWNLOADAHRSLOGFILES).
|
||||
then(function (response) {
|
||||
// do nothing
|
||||
// $scope.$apply();
|
||||
}, function (response) {
|
||||
// do nothing
|
||||
});
|
||||
};
|
||||
|
||||
$scope.postDownloadDB = function () {
|
||||
$http.post(URL_DOWNLOADDB).
|
||||
then(function (response) {
|
||||
|
@ -137,4 +158,13 @@ function DeveloperCtrl($rootScope, $scope, $state, $http, $interval) {
|
|||
|
||||
connect($scope); // connect - opens a socket and listens for messages
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
function humanFileSize(size) {
|
||||
if (size === 0) {
|
||||
return '0 B'
|
||||
} else {
|
||||
var i = Math.floor(Math.log(size) / Math.log(1024));
|
||||
return ( size / Math.pow(1024, i) ).toFixed(2) * 1 + ' ' + ['B', 'kB', 'MB', 'GB', 'TB'][i];
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
angular.module('appControllers').controller('GPSCtrl', GPSCtrl); // get the main module contollers set
|
||||
angular.module('appControllers').controller('GPSCtrl', GPSCtrl); // get the main module controllers set
|
||||
GPSCtrl.$inject = ['$rootScope', '$scope', '$state', '$http', '$interval']; // Inject my dependencies
|
||||
|
||||
// create our controller function with all necessary logic
|
||||
|
|
|
@ -156,7 +156,7 @@ function SettingsCtrl($rootScope, $scope, $state, $location, $window, $http) {
|
|||
newsettings = {
|
||||
"GLimits": settings["GLimits"]
|
||||
};
|
||||
console.log(angular.toJson(newsettings));
|
||||
// console.log(angular.toJson(newsettings));
|
||||
setSettings(angular.toJson(newsettings));
|
||||
}
|
||||
};
|
||||
|
@ -228,22 +228,29 @@ function SettingsCtrl($rootScope, $scope, $state, $location, $window, $http) {
|
|||
};
|
||||
|
||||
$scope.setOrientation = function(action) {
|
||||
console.log("sending " + action + " message.");
|
||||
// console.log("sending " + action + " message.");
|
||||
$http.post(URL_AHRS_ORIENT, action).
|
||||
then(function (response) {
|
||||
console.log("sent " + action + " message.");
|
||||
// console.log("sent " + action + " message.");
|
||||
}, function(response) {
|
||||
// failure: cancel the calibration
|
||||
console.log(response.data);
|
||||
// console.log(response.data);
|
||||
$scope.Orientation_Failure_Message = response.data;
|
||||
switch (action) {
|
||||
case "forward":
|
||||
$scope.Ui.turnOff("modalCalibrateUp");
|
||||
break;
|
||||
case "up":
|
||||
$scope.Ui.turnOff('modalCalibrateDone');
|
||||
}
|
||||
$scope.Ui.turnOff('modalCalibrateDone');
|
||||
$scope.Ui.turnOn("modalCalibrateFailed");
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
$scope.calibrateGyros = function() {
|
||||
console.log("sending calibrate message.");
|
||||
$http.post(URL_AHRS_CAL).
|
||||
then(function(response) {
|
||||
console.log("Sent calibrate message.");
|
||||
}, function(response) {
|
||||
console.log(response.data);
|
||||
$scope.Calibration_Failure_Message = response.data;
|
||||
$scope.Ui.turnOff("modalCalibrateGyros");
|
||||
$scope.Ui.turnOn("modalCalibrateGyrosFailed");
|
||||
});
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,355 +1,348 @@
|
|||
<div class="col-sm-12">
|
||||
<div class="panel-group col-sm-6">
|
||||
<div class="panel-group col-sm-6">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">Hardware</div>
|
||||
<div class="panel-body">
|
||||
<div class="form-group">
|
||||
<label class="control-label col-xs-7">978 MHz</label>
|
||||
<div class="col-xs-5">
|
||||
<ui-switch ng-model='UAT_Enabled' settings-change></ui-switch>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label col-xs-7">1090 MHz</label>
|
||||
<div class="col-xs-5">
|
||||
<ui-switch ng-model='ES_Enabled' settings-change></ui-switch>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label col-xs-7">Ping ADS-B</label>
|
||||
<div class="col-xs-5">
|
||||
<ui-switch ng-model='Ping_Enabled' settings-change></ui-switch>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label col-xs-7">GPS</label>
|
||||
<div class="col-xs-5">
|
||||
<ui-switch ng-model='GPS_Enabled' settings-change></ui-switch>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label col-xs-7">Attitude Sensor</label>
|
||||
<div class="col-xs-5">
|
||||
<ui-switch ng-model='IMU_Sensor_Enabled' settings-change></ui-switch>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label col-xs-7">Altitude Sensor</label>
|
||||
<div class="col-xs-5">
|
||||
<ui-switch ng-model='BMP_Sensor_Enabled' settings-change></ui-switch>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">Hardware</div>
|
||||
<div class="panel-body">
|
||||
<div class="form-group">
|
||||
<label class="control-label col-xs-7">978 MHz</label>
|
||||
<div class="col-xs-5">
|
||||
<ui-switch ng-model='UAT_Enabled' settings-change></ui-switch>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label col-xs-7">1090 MHz</label>
|
||||
<div class="col-xs-5">
|
||||
<ui-switch ng-model='ES_Enabled' settings-change></ui-switch>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label col-xs-7">Ping ADS-B</label>
|
||||
<div class="col-xs-5">
|
||||
<ui-switch ng-model='Ping_Enabled' settings-change></ui-switch>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label col-xs-7">GPS</label>
|
||||
<div class="col-xs-5">
|
||||
<ui-switch ng-model='GPS_Enabled' settings-change></ui-switch>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label col-xs-7">Attitude Sensor</label>
|
||||
<div class="col-xs-5">
|
||||
<ui-switch ng-model='IMU_Sensor_Enabled' settings-change></ui-switch>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label col-xs-7">Altitude Sensor</label>
|
||||
<div class="col-xs-5">
|
||||
<ui-switch ng-model='BMP_Sensor_Enabled' settings-change></ui-switch>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="panel-group col-sm-6">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">Diagnostics</div>
|
||||
<div class="panel-body">
|
||||
<div class="form-group">
|
||||
<label class="control-label col-xs-7">Show Traffic Source in Callsign</label>
|
||||
<div class="col-xs-5">
|
||||
<ui-switch ng-model='DisplayTrafficSource' settings-change></ui-switch>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label col-xs-7">Verbose Message Log</label>
|
||||
<div class="col-xs-5">
|
||||
<ui-switch ng-model='DEBUG' settings-change></ui-switch>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label col-xs-7">Record Replay Logs</label>
|
||||
<div class="col-xs-5">
|
||||
<ui-switch ng-model='ReplayLog' settings-change></ui-switch>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label col-xs-7">Record AHRS Logs</label>
|
||||
<div class="col-xs-5">
|
||||
<ui-switch ng-model='AHRSLog' settings-change></ui-switch>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="panel-group col-sm-6">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">Diagnostics</div>
|
||||
<div class="panel-body">
|
||||
<div class="form-group">
|
||||
<label class="control-label col-xs-7">Show Traffic Source in Callsign</label>
|
||||
<div class="col-xs-5">
|
||||
<ui-switch ng-model='DisplayTrafficSource' settings-change></ui-switch>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label col-xs-7">Verbose Message Log</label>
|
||||
<div class="col-xs-5">
|
||||
<ui-switch ng-model='DEBUG' settings-change></ui-switch>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label col-xs-7">Record Replay Logs</label>
|
||||
<div class="col-xs-5">
|
||||
<ui-switch ng-model='ReplayLog' settings-change></ui-switch>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label col-xs-7">Record AHRS Logs</label>
|
||||
<div class="col-xs-5">
|
||||
<ui-switch ng-model='AHRSLog' settings-change></ui-switch>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="panel-group col-sm-6">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">AHRS</div>
|
||||
<div class="panel-body">
|
||||
<div class="col-xs-12">
|
||||
<span style="position:relative; overflow: hidden;">
|
||||
<button class="btn btn-primary btn-block" ui-turn-on="modalCalibrateForward">
|
||||
Set AHRS Sensor Orientation
|
||||
</button>
|
||||
</span>
|
||||
<div class="form-group reset-flow">
|
||||
<label class="control-label col-xs-5">G Limits</label>
|
||||
<form name="GLimitForm" ng-submit="updateGLimits()" novalidate>
|
||||
<input class="col-xs-7" type="string" required ng-model="GLimits" placeholder="Space-separated negative and positive G meter limits" ng-blur="updateGLimits()" />
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-12">
|
||||
<div class="panel-group col-sm-6">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">Configuration</div>
|
||||
<div class="panel-body">
|
||||
<div class="form-group reset-flow">
|
||||
<label class="control-label col-xs-5">Mode S Code (Hex)</label>
|
||||
<form name="modeForm" ng-submit="updatemodes()" novalidate>
|
||||
<!-- type="number" not supported except on mobile -->
|
||||
<!-- RegEx for validation: ^[A-Fa-f0-9]{6}$ -->
|
||||
<input class="col-xs-7" type="string" required ng-model="OwnshipModeS" placeholder="FAA HEX code" ng-blur="updatemodes()" />
|
||||
</form>
|
||||
</div>
|
||||
<div class="form-group reset-flow">
|
||||
<label class="control-label col-xs-5">Watch List</label>
|
||||
<form name="watchForm" ng-submit="updatewatchlist()" novalidate>
|
||||
<!-- type="number" not supported except on mobile -->
|
||||
<input class="col-xs-7" type="string" required ng-model="WatchList" placeholder="space-delimited identifiers" ng-blur="updatewatchlist()" />
|
||||
</form>
|
||||
</div>
|
||||
<div class="form-group reset-flow">
|
||||
<label class="control-label col-xs-5">PPM Correction</label>
|
||||
<form name="ppmForm" ng-submit="updateppm()" novalidate>
|
||||
<!-- type="number" not supported except on mobile -->
|
||||
<input class="col-xs-7" type="number_format" required ng-model="PPM" placeholder="integer" ng-blur="updateppm()" />
|
||||
</form>
|
||||
</div>
|
||||
<div class="form-group reset-flow" ng-class="{ 'section_invisible': (!visible_serialout)}">
|
||||
<label class="control-label col-xs-5">Serial Output Baudrate</label>
|
||||
<form name="ppmForm" ng-submit="updateBaud()" novalidate>
|
||||
<!-- type="number" not supported except on mobile -->
|
||||
<input class="col-xs-7" type="number_format" required ng-model="Baud" placeholder="integer" ng-blur="updateBaud()" />
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="panel-group col-sm-6">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">Commands</div>
|
||||
<div class="panel-body">
|
||||
<!-- Upload. Temporary. -->
|
||||
<div class="col-xs-12">
|
||||
<span ng-show="update_files == ''">
|
||||
<span style="position:relative; overflow: hidden;">
|
||||
<span class="fake-btn fake-btn-block">Click to select System Update file</span>
|
||||
<input style="opacity:0.0; position: absolute; top: 0; right: 0;" class="col-xs-12" type="file" name="update_file" onchange="angular.element(this).scope().setUploadFile(this.files)"/>
|
||||
</span>
|
||||
</span>
|
||||
<span ng-hide="update_files == ''">
|
||||
<button class="btn btn-block" onclick="angular.element(this).scope().uploadFile()">Install {{update_files[0].name}}</button>
|
||||
</span>
|
||||
</div>
|
||||
<div class="form-group reset-flow">
|
||||
<div class="col-xs-12">
|
||||
<button class="btn btn-primary btn-block" ui-turn-on="modalReboot">Reboot</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group reset-flow">
|
||||
<div class="col-xs-12">
|
||||
<button class="btn btn-primary btn-block"ui-turn-on="modalShutdown">Shutdown</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="panel-group col-sm-6">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">AHRS</div>
|
||||
<div class="panel-body">
|
||||
<div class="col-xs-12">
|
||||
<span style="position:relative; overflow: hidden;">
|
||||
<button class="btn btn-primary btn-block" ui-turn-on="modalCalibrateForward"
|
||||
ng-disabled="!IMU_Sensor_Enabled">Set AHRS Sensor Orientation</button>
|
||||
</span>
|
||||
</div>
|
||||
<div class="form-group reset-flow">
|
||||
<div class="col-xs-12">
|
||||
<button class="btn btn-primary btn-block" ui-turn-on="modalCalibrateGyros"
|
||||
ng-disabled="!IMU_Sensor_Enabled">Calibrate Gyros</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group reset-flow">
|
||||
<label class="control-label col-xs-5">G Limits</label>
|
||||
<form name="GLimitForm" ng-submit="updateGLimits()" novalidate ng-disabled="!IMU_Sensor_Enabled">
|
||||
<input class="col-xs-7" type="string" required ng-model="GLimits" ng-blur="updateGLimits()"
|
||||
placeholder="Space-separated negative and positive G meter limits"/>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Developer mode area -->
|
||||
<div class="col-sm-12">
|
||||
<div ng-show="DeveloperMode" class="panel-group col-sm-6">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">Developer Options</div>
|
||||
<div class="panel-body">
|
||||
<div class="col-xs-12">
|
||||
<div class="form-group reset-flow">
|
||||
<label class="control-label col-xs-5">Static IPs</label>
|
||||
<form name="staticipForm" ng-submit="updatestaticips()" novalidate>
|
||||
<input class="col-xs-7" type="string" required ng-model="StaticIps" ng-list=" " ng-trim="false" placeholder="space-delimited ip's to send network data" ng-blur="updatestaticips()" />
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="panel-group col-sm-6">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">Configuration</div>
|
||||
<div class="panel-body">
|
||||
<div class="form-group reset-flow">
|
||||
<label class="control-label col-xs-5">Mode S Code (Hex)</label>
|
||||
<form name="modeForm" ng-submit="updatemodes()" novalidate>
|
||||
<!-- type="number" not supported except on mobile -->
|
||||
<!-- RegEx for validation: ^[A-Fa-f0-9]{6}$ -->
|
||||
<input class="col-xs-7" type="string" required ng-model="OwnshipModeS" placeholder="FAA HEX code" ng-blur="updatemodes()" />
|
||||
</form>
|
||||
</div>
|
||||
<div class="form-group reset-flow">
|
||||
<label class="control-label col-xs-5">Watch List</label>
|
||||
<form name="watchForm" ng-submit="updatewatchlist()" novalidate>
|
||||
<!-- type="number" not supported except on mobile -->
|
||||
<input class="col-xs-7" type="string" required ng-model="WatchList" placeholder="space-delimited identifiers" ng-blur="updatewatchlist()" />
|
||||
</form>
|
||||
</div>
|
||||
<div class="form-group reset-flow">
|
||||
<label class="control-label col-xs-5">PPM Correction</label>
|
||||
<form name="ppmForm" ng-submit="updateppm()" novalidate>
|
||||
<!-- type="number" not supported except on mobile -->
|
||||
<input class="col-xs-7" type="number_format" required ng-model="PPM" placeholder="integer" ng-blur="updateppm()" />
|
||||
</form>
|
||||
</div>
|
||||
<div class="form-group reset-flow" ng-class="{ 'section_invisible': (!visible_serialout)}">
|
||||
<label class="control-label col-xs-5">Serial Output Baudrate</label>
|
||||
<form name="ppmForm" ng-submit="updateBaud()" novalidate>
|
||||
<!-- type="number" not supported except on mobile -->
|
||||
<input class="col-xs-7" type="number_format" required ng-model="Baud" placeholder="integer" ng-blur="updateBaud()" />
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="panel-group col-sm-6">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">Commands</div>
|
||||
<div class="panel-body">
|
||||
<!-- Upload. Temporary. -->
|
||||
<div class="col-xs-12">
|
||||
<span ng-show="update_files == ''">
|
||||
<span style="position:relative; overflow: hidden;">
|
||||
<span class="fake-btn fake-btn-block">Click to select System Update file</span>
|
||||
<input style="opacity:0.0; position: absolute; top: 0; right: 0;" class="col-xs-12" type="file" name="update_file" onchange="angular.element(this).scope().setUploadFile(this.files)"/>
|
||||
</span>
|
||||
</span>
|
||||
<span ng-hide="update_files == ''">
|
||||
<button class="btn btn-block" onclick="angular.element(this).scope().uploadFile()">Install {{update_files[0].name}}</button>
|
||||
</span>
|
||||
</div>
|
||||
<div class="form-group reset-flow">
|
||||
<div class="col-xs-12">
|
||||
<button class="btn btn-primary btn-block" ui-turn-on="modalReboot">Reboot</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group reset-flow">
|
||||
<div class="col-xs-12">
|
||||
<button class="btn btn-primary btn-block"ui-turn-on="modalShutdown">Shutdown</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Developer mode area -->
|
||||
<div class="col-sm-12">
|
||||
<div ng-show="DeveloperMode" class="panel-group col-sm-6">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">Developer Options</div>
|
||||
<div class="panel-body">
|
||||
<div class="col-xs-12">
|
||||
<div class="form-group reset-flow">
|
||||
<label class="control-label col-xs-5">Static IPs</label>
|
||||
<form name="staticipForm" ng-submit="updatestaticips()" novalidate>
|
||||
<input class="col-xs-7" type="string" required ng-model="StaticIps" ng-list=" " ng-trim="false" placeholder="space-delimited ip's to send network data" ng-blur="updatestaticips()" />
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="col-sm-12" ng-show="DeveloperMode" >
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">Raw Configuration</div>
|
||||
<div class="panel-body">
|
||||
<p>stratux.conf:</p>
|
||||
<pre>{{rawSettings}}</pre>
|
||||
</div>
|
||||
</div>
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">Raw Configuration</div>
|
||||
<div class="panel-body">
|
||||
<p>stratux.conf:</p>
|
||||
<pre>{{rawSettings}}</pre>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="col-sm-12">
|
||||
<h3 ui-if="rebooting" ui-state="rebooting">Stratux is rebooting. You may need to reconnect WiFi once it reboots.</h3>
|
||||
<h3 ui-if="shuttingdown" ui-state="shuttingdown">Stratux is shutting down. You may disconnect power.</h3>
|
||||
<h3 ui-if="rebooting" ui-state="rebooting">Stratux is rebooting. You may need to reconnect WiFi once it reboots.</h3>
|
||||
<h3 ui-if="shuttingdown" ui-state="shuttingdown">Stratux is shutting down. You may disconnect power.</h3>
|
||||
</div>
|
||||
|
||||
<div ui-content-for="modals">
|
||||
<div class="modal" ui-if="modalReboot" ui-state="modalReboot">
|
||||
<div class="modal-overlay "></div>
|
||||
<div class="vertical-alignment-helper center-block">
|
||||
<div class="modal-dialog vertical-align-center">
|
||||
<div class="modal" ui-if="modalReboot" ui-state="modalReboot">
|
||||
<div class="modal-overlay "></div>
|
||||
<div class="vertical-alignment-helper center-block">
|
||||
<div class="modal-dialog vertical-align-center">
|
||||
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button class="close"
|
||||
ui-turn-off="modalReboot"></button>
|
||||
<h4 class="modal-title">Are you really sure?</h4>
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button class="close"
|
||||
ui-turn-off="modalReboot"></button>
|
||||
<h4 class="modal-title">Are you really sure?</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<p>Do you wish to reboot the Stratux?</p>
|
||||
<p>Note that the system will reboot immediately and it will stop responding during the reboot</p>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<a ui-turn-off="modalReboot" class="btn btn-default">Cancel</a>
|
||||
<a ng-click="postReboot()" ui-turn-off="modalReboot" ui-turn-on="rebooting" class="btn btn-primary">Reboot</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<p>Do you wish to reboot the Stratux?</p>
|
||||
<p>Note that the system will reboot immediately and it will stop responding during the reboot</p>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<a ui-turn-off="modalReboot" class="btn btn-default">Cancel</a>
|
||||
<a ng-click="postReboot()" ui-turn-off="modalReboot" ui-turn-on="rebooting" class="btn btn-primary">Reboot</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="modal" ui-if="modalShutdown" ui-state="modalShutdown">
|
||||
<div class="modal-overlay "></div>
|
||||
<div class="vertical-alignment-helper center-block">
|
||||
<div class="modal-dialog vertical-align-center">
|
||||
<div class="modal" ui-if="modalShutdown" ui-state="modalShutdown">
|
||||
<div class="modal-overlay "></div>
|
||||
<div class="vertical-alignment-helper center-block">
|
||||
<div class="modal-dialog vertical-align-center">
|
||||
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button class="close"
|
||||
ui-turn-off="modalShutdown"></button>
|
||||
<h4 class="modal-title">Are you really sure?</h4>
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button class="close"
|
||||
ui-turn-off="modalShutdown"></button>
|
||||
<h4 class="modal-title">Are you really sure?</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<p>Do you wish to shutdown the Stratux?</p>
|
||||
<p>Note that the system will shutdown immediately. Please disconnect the power after the shutdown.</p>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<a ui-turn-off="modalShutdown" class="btn btn-default">Cancel</a>
|
||||
<a ng-click="postShutdown()" ui-turn-off="modalShutdown" ui-turn-on="shuttingdown" class="btn btn-primary">Shutdown</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<p>Do you wish to shutdown the Stratux?</p>
|
||||
<p>Note that the system will shutdown immediately. Please disconnect the power after the shutdown.</p>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<a ui-turn-off="modalShutdown" class="btn btn-default">Cancel</a>
|
||||
<a ng-click="postShutdown()" ui-turn-off="modalShutdown" ui-turn-on="shuttingdown" class="btn btn-primary">Shutdown</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="modal" ui-if="modalCalibrateForward" ui-state="modalCalibrateForward">
|
||||
<div class="modal-overlay "></div>
|
||||
<div class="vertical-alignment-helper center-block">
|
||||
<div class="modal-dialog vertical-align-center">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button class="close" ui-turn-off="modalCalibrateForward"></button>
|
||||
<h4 class="modal-title">Set AHRS Sensor Orientation: Forward Direction</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<p>Point the Stratux/sensor box so that the end that will be pointing toward the <strong>nose</strong> of the airplane is pointing toward the sky and press the <strong>Set Forward Direction</strong> button.</p>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<a ui-turn-off="modalCalibrateForward" ui-turn-on="modalCalibrateCanceled" class="btn btn-default">Cancel</a>
|
||||
<a ng-click="setOrientation('forward')" ui-turn-off="modalCalibrateForward" ui-turn-on="modalCalibrateUp" class="btn btn-default btn-primary">Set Forward Direction</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal" ui-if="modalCalibrateUp" ui-state="modalCalibrateUp">
|
||||
<div class="modal-overlay "></div>
|
||||
<div class="vertical-alignment-helper center-block">
|
||||
<div class="modal-dialog vertical-align-center">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button class="close" ui-turn-off="modalCalibrateUp"></button>
|
||||
<h4 class="modal-title">Set AHRS Sensor Orientation: Up Direction</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<p>Place the Stratux/sensor box in the orientation it will be in during flight and press the <strong>Set Up Direction</strong> button.</p>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<a ui-turn-off="modalCalibrateUp" ui-turn-on="modalCalibrateCanceled" class="btn btn-default">Cancel</a>
|
||||
<a ng-click="setOrientation('up')" ui-turn-off="modalCalibrateUp" ui-turn-on="modalCalibrateDone" class="btn btn-default btn-primary">Set Up Direction</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal" ui-if="modalCalibrateDone" ui-state="modalCalibrateDone">
|
||||
<div class="modal-overlay "></div>
|
||||
<div class="vertical-alignment-helper center-block">
|
||||
<div class="modal-dialog vertical-align-center">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button class="close" ui-turn-off="modalCalibrateDone"></button>
|
||||
<h4 class="modal-title">Set AHRS Sensor Orientation: Finished</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<p>The sensors are calibrated. These settings will be saved for future flights.</p>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<a ui-turn-off="modalCalibrateDone" class="btn btn-default btn-primary">OK</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal" ui-if="modalCalibrateFailed" ui-state="modalCalibrateFailed">
|
||||
<div class="modal-overlay "></div>
|
||||
<div class="vertical-alignment-helper center-block">
|
||||
<div class="modal-dialog vertical-align-center">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button class="close" ui-turn-off="modalCalibrateFailed"></button>
|
||||
<h4 class="modal-title">Set AHRS Sensor Orientation: Failed!</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<p>There was an error: {{Orientation_Failure_Message}}</p>
|
||||
<p><div id="orientationFailureMessage"></div></p>
|
||||
<p>The calibration failed.</p>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<a ui-turn-off="modalCalibrateFailed" class="btn btn-default btn-primary">OK</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal" ui-if="modalCalibrateCanceled" ui-state="modalCalibrateCanceled">
|
||||
<div class="modal-overlay "></div>
|
||||
<div class="vertical-alignment-helper center-block">
|
||||
<div class="modal-dialog vertical-align-center">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button class="close" ui-turn-off="modalCalibrateCanceled"></button>
|
||||
<h4 class="modal-title">Set AHRS Sensor Orientation: Canceled</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<p>Calibration canceled.</p>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<a ui-turn-off="modalCalibrateCanceled" class="btn btn-default btn-primary">OK</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal" ui-if="modalCalibrateForward" ui-state="modalCalibrateForward">
|
||||
<div class="modal-overlay "></div>
|
||||
<div class="vertical-alignment-helper center-block">
|
||||
<div class="modal-dialog vertical-align-center">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button class="close" ui-turn-off="modalCalibrateForward"></button>
|
||||
<h4 class="modal-title">Set AHRS Sensor Orientation: Forward Direction</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<p>Point the Stratux so that the end that will be pointing toward the
|
||||
<strong>nose</strong> of the airplane is pointing toward the sky and press the
|
||||
<strong>Set Forward Direction</strong> button.</p>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<a ui-turn-off="modalCalibrateForward" class="btn btn-default">Cancel</a>
|
||||
<a ng-click="setOrientation('forward')" ui-turn-off="modalCalibrateForward"
|
||||
ui-turn-on="modalCalibrateDone" class="btn btn-default btn-primary">Set Forward Direction</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal" ui-if="modalCalibrateDone" ui-state="modalCalibrateDone">
|
||||
<div class="modal-overlay "></div>
|
||||
<div class="vertical-alignment-helper center-block">
|
||||
<div class="modal-dialog vertical-align-center">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button class="close" ui-turn-off="modalCalibrateDone"></button>
|
||||
<h4 class="modal-title">Set AHRS Sensor Orientation: Finished</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<p>The sensor orientation is set. These settings will be saved for future flights.
|
||||
Place the Stratux in its in-flight orientation and keep it stationary for 5 seconds
|
||||
after you press the <strong>Done</strong> button.</p>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<a ng-click="setOrientation('done')" ui-turn-off="modalCalibrateDone"
|
||||
class="btn btn-default btn-primary">Done</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal" ui-if="modalCalibrateFailed" ui-state="modalCalibrateFailed">
|
||||
<div class="modal-overlay "></div>
|
||||
<div class="vertical-alignment-helper center-block">
|
||||
<div class="modal-dialog vertical-align-center">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button class="close" ui-turn-off="modalCalibrateFailed"></button>
|
||||
<h4 class="modal-title">Set AHRS Sensor Orientation: Failed!</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<p>There was an error: {{Orientation_Failure_Message}}</p>
|
||||
<p><div id="orientationFailureMessage"></div></p>
|
||||
<p>The orientation failed. Please try again.</p>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<a ui-turn-off="modalCalibrateFailed" class="btn btn-default btn-primary">OK</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="modal" ui-if="modalCalibrateGyros" ui-state="modalCalibrateGyros">
|
||||
<div class="modal-overlay "></div>
|
||||
<div class="vertical-alignment-helper center-block">
|
||||
<div class="modal-dialog vertical-align-center">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button class="close" ui-turn-off="modalCalibrateGyros"></button>
|
||||
<h4 class="modal-title">Calibrate MPU Gyros</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<p>Press <b>Calibrate</b> and keep the Stratux as stationary as possible for the next second.
|
||||
You should only do this in calm air as turbulence will throw off the calibrations.</p>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<a ui-turn-off="modalCalibrateGyros" class="btn btn-default">Cancel</a>
|
||||
<a ng-click="calibrateGyros()" ui-turn-off="modalCalibrateGyros"
|
||||
class="btn btn-default btn-primary">Calibrate</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
Ładowanie…
Reference in New Issue