sourceafParrotSdk2::NavOption.fan


** Data options returned from the drone, see `NavData`.
** Unfortunately, NavOption data is not really documented in the Drone SDK so make of it what you may. 
** 
** To tell the drone what data to return, see `DroneAppConfig.navDataOptions`.
enum class NavOption {
    demo            (#parseDemo),
    time            (#parseTime),
    rawMeasures     (#parseRawMeasures),
    physMeasures    (#parsePhysMeasures), 
    gyrosOffsets    (#parseGyrosOffsets),
    eulerAngles     (#parseEulerAngles),
    references      (#parseReferences), 
    trims           (#parseTrims), 
    rcReferences    (#parseRcReferences), 
    pwm             (#parsePwm), 
    altitude        (#parseAltitude), 
    visionRaw       (#parseVisionRaw), 
    visionOf        (#parseVisionOf), 
    vision          (#parseVision), 
    visionPerf      (#parseVisionPerf), 
    trackersSend    (#parseTrackersSend),
    visionDetect    (#parseVisionDetect),
    watchdog        (#parseWatchdog), 
    adcDataFrame    (#parseAdcDataFrame), 
    videoStream     (#parseVideoStream), 
    games           (#parseGames), 
    pressureRaw     (#parsePressureRaw), 
    magneto         (#parseMagneto), 
    windSpeed       (#parseWindSpeed), 
    kalmanPressure  (#parseKalmanPressure), 
    hdvideoStream   (#parseHdVideoStream), 
    wifi            (#parseWifi), 
    gps             (#parseGps),
    unknown1        (#parseUnknown),
    unknown2        (#parseUnknown);
    
    internal const Method parseMethod
    
    private new make(Method parseMethod) {
        this.parseMethod = parseMethod
    }
    
    Int flag() {
        1.shiftl(this.ordinal)
    }
    
    static internal NavOptionDemo parseDemo(InStream in) {
        NavOptionDemo {
            it.droneState           = DroneState.vals.getSafe(uint16(in), DroneState.unknown)
            it.flightState          = FlightState.vals[uint16(in)]
            it.batteryPercentage    = uint32 (in)
            it.theta                = float32(in) / 1000
            it.phi                  = float32(in) / 1000
            it.psi                  = float32(in) / 1000
            it.altitude             = int32  (in) / 1000f
            it.velocityX            = float32(in)
            it.velocityY            = float32(in)
            it.velocityZ            = float32(in)
            it.frameIndex           = uint32 (in)
            detection               := Str:Obj[
                "camera"            : Str:Obj[
                    "rotation"      : matrix3x3(in),
                    "translation"   : vector3x1(in)
                ],
                "tagIndex"          : uint32(in)
            ]
            detection["camera"]->set("type", uint32(in))
            it.cameraDetectionParams= detection
            it.cameraDroneParams    = Str:Obj[
                "camera"            : Str:Obj[
                    "rotation"      : matrix3x3(in),
                    "translation"   : vector3x1(in)
                ]
            ]
        }
    }
    
    static internal Duration parseTime(InStream in) {
        droneTime(in.readU4)
    }
    
    static internal Str:Obj parseRawMeasures(InStream in) {
        Str:Obj[
            "accelerometers"        : ["x": uint16(in), "y": uint16(in), "z": uint16(in)],  // [LSB] filtered accelerometers
            "gyroscopes"            : ["x": uint16(in), "y": uint16(in), "z": uint16(in)],  // [LSB] filtered gyrometers
            "gyroscopes110"         : ["x": uint16(in), "y": uint16(in)],                   // [LSB] x/y 110 deg/s
            "batteryMilliVolt"      : uint32(in),           // [mV] battery voltage raw
            "usEcho"                : Str:Int[
                "start"             : uint16(in),           // [LSB]
                "end"               : uint16(in),           // [LSB]
                "association"       : uint16(in),           // [LSB?]
                "distance"          : uint16(in),           // [LSB]
            ],
            "usCurve"               : Str:Int[
                "time"              : uint16(in),           // [LSB]
                "value"             : uint16(in),           // [LSB]
                "ref"               : uint16(in),           // [LSB]
            ],
            "echo"                  : Str:Int[
                "flagIni"           : uint16(in),           // [LSB]
                "num"               : uint16(in),           // [LSB] (is key 'num' OR 'name'?)
                "sum"               : uint32(in),           // [LSB]
            ],
            "altTemp"               : uint32(in),           // [mm]
            "gradient"              : uint16(in)
        ]
    }
    
    static internal Str:Obj parsePhysMeasures(InStream in) {
        Str:Obj[
            "temperature"           : Str:Num[
                "accelerometer"     : float32(in),          // [K]
                "gyroscope"         : uint16(in),           // [LSB]
            ],
            "accelerometers"        : vector3x1(in),        // [mg]
            "gyroscopes"            : vector3x1(in),        // [deg/s]
            "alim3V3"               : uint32(in),           // 3.3volt alim [LSB]
            "vrefEpson"             : uint32(in),           // ref volt Epson gyro [LSB]
            "vrefIDG"               : uint32(in)            // ref volt IDG gyro [LSB]
        ]
    }
    
    static internal Str:Float parseGyrosOffsets(InStream in) {
        vector3x1(in)
    }
    
    static internal Str:Float parseEulerAngles(InStream in) {
        Str:Float[
            "theta"                 : float32(in),          // [mdeg?]
            "phi"                   : float32(in)           // [mdeg?]
        ]
    }

    static internal Str:Obj parseReferences(InStream in) {
        Str:Obj[
            "theta"                 : uint32(in),           // [mdeg]
            "phi"                   : uint32(in),           // [mdeg]
            "thetaI"                : uint32(in),           // [mdeg]
            "phiI"                  : uint32(in),           // [mdeg]
            "pitch"                 : uint32(in),           // [mdeg]
            "roll"                  : uint32(in),           // [mdeg]
            "yaw"                   : uint32(in),           // [mdeg/s]
            "psi"                   : uint32(in),           // [mdeg]

            "vx"                    : float32(in),
            "vy"                    : float32(in),
            "thetaMod"              : float32(in),
            "phiMod"                : float32(in),
            
            "kVX"                   : float32(in),
            "kVY"                   : float32(in),
            "kMode"                 : uint16(in),
            
            "ui"                    : Str:Num[
                "time"              : float32(in),
                "theta"             : float32(in),
                "phi"               : float32(in),
                "psi"               : float32(in),
                "psiAccuracy"       : float32(in),
                "seq"               : uint32(in),
            ]
        ]
    }

    static internal Str:Obj parseTrims(InStream in) {
        Str:Obj[
            "angularRates"          : Str:Float[
                "r"                 : float32(in)
            ],
            "eulerAngles"           : Str:Float[
                "theta"             : float32(in),          // [mdeg?]
                "phi"               : float32(in)           // [mdeg?]
            ]
        ]
    }
    
    static internal Str:Int parseRcReferences(InStream in) {
        Str:Int[
            "pitch"                 : int32(in),            // [mdeg?]
            "roll"                  : int32(in),            // [mdeg?]
            "yaw"                   : int32(in),            // [mdeg/s?]
            "gaz"                   : int32(in),            // [mdeg?]
            "ag"                    : int32(in)
        ]
    }
    
    static internal Str:Obj parsePwm(InStream in) {
        Str:Obj[
            "motors"                : x(4) { uint8(in) },   // [PWM]
            "satMotors"             : x(4) { uint8(in) },   // [PWM]
            "gazFeedForward"        : float32(in),          // [PWM]
            "gazAltitude"           : float32(in),          // [PWM]
            "altitudeIntegral"      : float32(in),          // [mm/s]
            "vzRef"                 : float32(in),          // [mm/s]
            "uPitch"                : int32(in),            // [PWM]
            "uRoll"                 : int32(in),            // [PWM]
            "uYaw"                  : int32(in),            // [PWM]
            "yawUI"                 : float32(in),          // [PWM] yaw_u_I
            "uPitchPlanif"          : int32(in),            // [PWM]
            "uRollPlanif"           : int32(in),            // [PWM]
            "uYawPlanif"            : int32(in),            // [PWM]
            "uGazPlanif"            : float32(in),          // [PWM]
            "motorCurrents"         : x(4) { uint16(in) },  // [mA]
            "altitudeProp"          : float32(in),          // [PWM]
            "altitudeDer"           : float32(in)           // [PWM]
        ]
    }

    static internal Str:Obj parseAltitude(InStream in) {
        Str:Obj[
            "vision"                : int32(in),            // [mm]
            "vz"                    : float32(in),          // [mm/s]
            "ref"                   : int32(in),            // [mm]
            "raw"                   : int32(in),            // [mm]
            "observer"              : Str:Obj[
                "acceleration"      : float32(in),          // [m/s2]
                "altitude"          : float32(in),          // [m]
                "x"                 : vector3x1(in),
                "state"             : uint32(in)
            ],
            "estimated"             : Str:Obj[
                "vb"                : vector2x1(in),
                "state"             : uint32(in)
            ]
        ]
    }
    
    static internal Str:Obj parseVisionRaw(InStream in) {
        Str:Obj[
            "tx"                    : float32(in),
            "ty"                    : float32(in),
            "tz"                    : float32(in)
        ]       
    }
    
    static internal Str:Obj parseVisionOf(InStream in) {
        Str:Obj[
            "dx"                    : x(5) { float32(in) },
            "dy"                    : x(5) { float32(in) }
        ]       
    }
    
    static internal Str:Obj parseVision(InStream in) {
        Str:Obj[
            "state"                 : uint32(in),
            "misc"                  : int32(in),
            "phi"                   : Str:Float[
                "trim"              : float32(in),          // [rad]
                "refProp"           : float32(in)           // [rad]
            ],
            "theta"                 : Str:Float[
                "trim"              : float32(in),          // [rad]
                "refProp"           : float32(in)           // [rad]
            ],
            "newRawPicture"         : int32(in),
            "capture"               : Str:Obj[
                "theta"             : float32(in),
                "phi"               : float32(in),
                "psi"               : float32(in),
                "altitude"          : int32(in),
                "time"              : droneTime(uint32(in))
            ],
            "bodyV"                 : vector3x1(in),
            "delta"                 : Str:Float[
                "theta"             : float32(in),
                "phi"               : float32(in),
                "psi"               : float32(in),
            ],
            "gold"                  : Str:Num[
                "defined"           : uint32(in),
                "reset"             : uint32(in),
                "phi"               : float32(in),
                "psi"               : float32(in),
            ]           
        ]       
    }
    
    static internal Str:Obj parseVisionPerf(InStream in) {
        Str:Obj[
            "szo"                   : float32(in),
            "corners"               : float32(in),
            "compute"               : float32(in),
            "tracking"              : float32(in),
            "trans"                 : float32(in),
            "update"                : float32(in),
            "custom"                : x(20) { float32(in) }
        ]       
    }

    static internal Str:Obj parseTrackersSend(InStream in) {
        Str:Obj[
            "locked"                : x(30) { int32(in) },
            "point"                 : x(30) { screenPoint(in) }
        ]       
    }

    static internal Str:Obj parseVisionDetect(InStream in) {
        Str:Obj[
            "nbDetected"            : uint32(in),           // number of detected tags or oriented roundel
            "type"                  : x(4) { uint32(in) },  // Type of the detected tag or oriented roundel; see the CAD_TYPE enumeration
            "xc"                    : x(4) { uint32(in) },  // X and Y coordinates of detected tag or oriented roundel inside the picture, 
            "yc"                    : x(4) { uint32(in) },  // with (0,0) being the top-left corner, and (1000,1000) the right-bottom corner regardless the picture resolution or the source camera
            "width"                 : x(4) { uint32(in) },  // Width and height of the detection bounding-box (tag or oriented roundel), when applicable
            "height"                : x(4) { uint32(in) },
            "dist"                  : x(4) { uint32(in) },  // Distance from camera to detected tag or oriented roundel in centimeters, when applicable
            "orientationAngle"      : x(4) { float32(in) }, // Angle of the oriented roundel in degrees in the screen, when applicable
            "rotation"              : x(4) { matrix3x3(in) },   //  Reserved for future use
            "translation"           : x(4) { vector3x1(in) },   //  Reserved for future use
            "cameraSource"          : x(4) { uint32(in) }   // Camera Source which detected tag or oriented roundel
        ]
    }
    
    static internal Int parseWatchdog(InStream in) {
        uint32(in)
    }
    
    static internal Str:Obj parseAdcDataFrame(InStream in) {
        Str:Obj[
            "version"               : uint32(in),
            "dataFrame"             : x(32) { uint8(in) }
        ]
    }
    
    static internal Str:Obj parseVideoStream(InStream in) {
        Str:Obj[
            "quant"                 : uint8(in),            // quantizer reference used to encode frame [1:31]
            "frame"                 : Str:Int[
                "size"              : uint32(in),           // frame size (bytes)
                "number"            : uint32(in)            // frame index
            ],
            "atcmd"                 : Str:Num[
                "sequence"          : uint32(in),           // atmcd ref sequence number
                "meanGap"           : uint32(in),           // mean time between two consecutive atcmd_ref (ms)
                "varGap"            : float32(in),
                "quality"           : uint32(in)            // estimator of atcmd link quality
            ],
            "bitrate"               : Str:Int[
                "out"               : uint32(in),           // measured out throughput from the video tcp socket
                "desired"           : uint32(in)            // last frame size generated by the video encoder
            ],
            "data"                  : x(5) { int32(in) },   // misc temporary data
            "tcpQueueLevel"         : uint32(in),
            "fifoQueueLevel"        : uint32(in)
        ]
    }
    
    static internal Str:Obj parseGames(InStream in) {
        Str:Obj[
            "doubleTap"             : uint32(in),
            "finishLine"            : uint32(in)
        ]
    }

    static internal Str:Obj parsePressureRaw(InStream in) {
        Str:Obj[
            "up"                : int32(in),            // [LSB] (UP?)
            "ut"                : int16(in),            // [LSB] (UT?)
            "temperature"       : int32(in),            // [0_1C]
            "pressure"          : int32(in)             // [Pa]
        ]
    }

    static internal Str:Obj parseMagneto(InStream in) {
        Str:Obj[
            "mx"                : int16(in),            // [LSB]
            "my"                : int16(in),            // [LSB]
            "mz"                : int16(in),            // [LSB]
            "raw"               : vector3x1(in),        // [mG] magneto in the body frame, in mG
            "rectified"         : vector3x1(in),        // [mG]
            "offset"            : vector3x1(in),        // [mG]
            "heading"           : Str:Float[
                "unwrapped"     : float32(in),          // [deg]
                "gyroUnwrapped" : float32(in),          // [deg]
                "fusionUnwrapped": float32(in)          // [mdeg]
            ],
            "ok"                : uint8(in),
            "state"             : uint32(in),           // [SU]
            "radius"            : float32(in),          // [mG]
            "error"             : Str:Float[
                "mean"          : float32(in),          // [mG]
                "variance"      : float32(in)           // [mG2]
            ]
        ]
    }
    
    static internal Str:Obj parseWindSpeed(InStream in) {
        Str:Obj[
            "speed"             : float32(in),          // [m/s] estimated wind speed
            "angle"             : float32(in),          // [rad] estimated wind direction in North-East frame, e.g. if wind_angle is pi/4, wind is from South-West to North-East
            "compensation"      : Str:Float[
                "theta"         : float32(in),          // [rad]
                "phi"           : float32(in)           // [mG2]
            ],
            "stateX"            : x(6) { float32(in) }, // [SU]
            "debug"             : x(3) { float32(in) }
        ]
    }


    static internal Str:Obj parseKalmanPressure(InStream in) {
        Str:Obj[
            "offsetPressure"    : float32(in),          // [Pa]
            "estimated"         : Str:Obj[
                "altitude"      : float32(in),          // [mm]
                "velocity"      : float32(in),          // [m/s]
                "angle"         : Str:Float[
                    "pwm"       : float32(in),          // [m/s2]
                    "pressure"  : float32(in)           // [Pa]
                ],
                "us"            : Str:Float[
                    "offset"    : float32(in),          // [m]
                    "prediction": float32(in)           // [mm]
                ],
                "covariance"    : Str:Float[
                    "alt"       : float32(in),          // [m]
                    "pwm"       : float32(in),
                    "velocity"  : float32(in)           // [m/s]
                ],
                "groundEffect"  : bool(in),             // [SU]
                "sum"           : float32(in),          // [mm]
                "reject"        : bool(in),             // [SU]
                "uMultisinus"   : float32(in),
                "gazAltitude"   : float32(in),
                "flagMultisinus": bool(in),
                "flagMultisinusStart": bool(in)
            ]
        ]
    }
    
    static internal Str:Obj parseHdVideoStream(InStream in) {
        val := Str:Obj[
            "hdvideoState"      : uint32(in),
            "storageFifo"       : Str:Int[
                "nbPackets"     : uint32(in),
                "size"          : uint32(in)
            ],
            "usbkey"            : Str:Int[
                "size"          : uint32(in),           // [KB] USB key in kbytes - 0 if no key present
                "freespace"     : uint32(in),           // [KB] USB key free space in kbytes - 0 if no key present
            ],
            "frameNumber"       : uint32(in),           // 'frame_number' PaVE field of the frame starting to be encoded for the HD stream 
        ]
        val["usbkey"]->set("remainingTime", uint32(in)) // [sec] time in seconds
        return val
    }

    static internal Str:Float parseWifi(InStream in) {
        Str:Float[
            // from ARDrone_SDK_2_0/ControlEngine/iPhone/Classes/Controllers/MainViewController.m
            "linkQuality"       : 1 - (float32(in))
        ]
    }

    static internal Str:Obj parseGps(InStream in) {
        Str:Obj[
            "latitude"          : double64(in), 
            "longitude"         : double64(in), 
            "elevation"         : double64(in), 
            "hdop"              : double64(in), 
            "dataAvailable"     : int32(in), 
            "zeroValidated"     : int32(in), 
            "wptValidated"      : int32(in), 
            "lat0"              : double64(in), 
            "lon0"              : double64(in), 
            "latFuse"           : double64(in), 
            "lonFuse"           : double64(in), 
            "gpsState"          : uint32(in), 
            "xTraj"             : float32(in), 
            "xRef"              : float32(in), 
            "yTraj"             : float32(in), 
            "yRef"              : float32(in), 
            "thetaP"            : float32(in), 
            "phiP"              : float32(in), 
            "thetaI"            : float32(in), 
            "phiI"              : float32(in), 
            "thetaD"            : float32(in), 
            "phiD"              : float32(in), 
            "vdop"              : double64(in), 
            "pdop"              : double64(in), 
            "speed"             : float32(in), 
            "lastFrameTimestamp": droneTime(uint32(in)), 
            "degree"            : float32(in), 
            "degreeMag"         : float32(in), 
            "ehpe"              : float32(in), 
            "ehve"              : float32(in), 
            "c_n0"              : float32(in), 
            "nbSatellites"      : uint32(in), 
            "channels"          : x(12) { satChannel(in) }, 
            "gpsPlugged"        : int32(in), 
            "ephemerisStatus"   : uint32(in), 
            "vxTraj"            : float32(in), 
            "vyTraj"            : float32(in), 
            "firmwareStatus"    : uint32(in) 
        ]
    }

    static internal Buf parseUnknown(InStream in) {
        in.readAllBuf
    }

    private static Bool     bool    (InStream in) { in.readU1 != 0 }
    private static Int      uint8   (InStream in) { in.readU1 }
    private static Int      uint16  (InStream in) { in.readU2 }
    private static Int      uint32  (InStream in) { in.readU4 }
    private static Int      int16   (InStream in) { in.readS2 }
    private static Int      int32   (InStream in) { in.readS4 }
    private static Float    float32 (InStream in) { Float.makeBits32(in.readU4) }
    private static Float    double64(InStream in) { Float.makeBits(in.readS8) }
    
    private static List x(Int num, |Int->Obj| f) {
        (0..<num).toList.map { f(it) }
    }
    
    private static Str:Int satChannel(InStream in) {
        Str:Int["sat": uint8(in), "cn0": uint8(in)]
    }

    private static Str:Int screenPoint(InStream in) {
        Str:Int["x": int32(in), "y": int32(in)]
    }

    private static Str:Float vector2x1(InStream in) {
        Str:Float["x": float32(in), "y": float32(in)]
    }

    private static Str:Float vector3x1(InStream in) {
        Str:Float["x": float32(in), "y": float32(in), "z": float32(in)]
    }

    private static Float[] matrix3x3(InStream in) {
        x(9) { Float.makeBits32(in.readU4) }
    }
    
    private static Duration droneTime(Int time) {
        // first 11 bits are seconds
        seconds := time.shiftr(21)
        // last 21 bits are microseconds
        microseconds := time.shiftl(11).shiftr(11)
        return Duration((seconds * 1sec.ticks) + (microseconds * 1000))
    }
}