using concurrent::AtomicRef
** Drone config in the Session category.
** Session config relates to the current flight and encapsulates user and application data.
** That is, should the session be changed / reset, the user and application config changes also.
**
** Create a new session by means of:
**
** syntax: fantom
** drone.config.session("My Session Name")
**
** Future code may then access the same session by **not** passing a session name:
**
** syntax: fantom
** drone.config.session.hoveringRange = 1000
**
const class DroneSessionConfig {
private const Log log := Drone#.pod.log
internal const DroneConfig _config
** Internal because we need to keep track of the multi-config IDs
** Creates a wrapper around the given drone.
internal new make(DroneConfig config, Bool reReadConfig := true) {
this._config = config
if (reReadConfig)
config.drone.configMap(true)
}
** The wrapped drone instance
Drone drone() {
_config.drone
}
// ---- Identity ----
** The current session ID.
**
** Corresponds to the 'CUSTOM:profile_id' configuration key.
Str id {
get { getConfig("CUSTOM:session_id") }
private set { }
}
** The current session name.
**
** Corresponds to the 'CUSTOM:profile_desc' configuration key.
Str name {
get { getConfig("CUSTOM:session_desc") }
private set { }
}
** Deletes this session data from the drone.
Void deleteMe() {
id := id
if (id == "00000000") {
log.warn("Will not delete default data!") // don't know what might happen if we try this!?
return
}
_config._delSess("-${id}")
}
** Deletes **ALL** session data from the drone.
** Use with caution.
Void deleteAll() {
log.warn("Deleting ALL session data!")
_config._delSess("-all")
}
// ---- Config ----
** Gets or makes user config.
DroneUserConfig user(Str? userName := null) {
_config._userConfig(userName, true)
}
** Gets or makes application config.
** If 'null' is passed, this just returns the current config.
DroneAppConfig app(Str? appicationName := null) {
_config._appConfig(appicationName, true)
}
// ---- Other Cmds ----
** Enables free flight or a semi-autonomous hover on top of a roundel picture.
** If orientated then the drone will always face the same direction.
**
** 0 = FREE_FLIGHT // Normal mode, commands are enabled
** 1 = HOVER_ON_ROUNDEL // Commands are disabled, drone hovers on a roundel
** 2 = HOVER_ON_ORIENTED_ROUNDEL // Commands are disabled, drone hovers on an oriented roundel
**
** Hover modes **MUST** be activated by the 'detect_type' configuration.
**
** For all modes, progressive commands are possible.
**
** Note 'HOVER_ON_ROUNDEL' was developed for 2011 CES autonomous demonstration.
**
** Corresponds to the 'CONTROL:flying_mode' configuration key.
Int hoverMode { // TODO rename to hoverOnRoundel
get { getConfig("CONTROL:flying_mode").toInt }
set { setConfig("CONTROL:flying_mode", it.toStr) }
}
** The maximum distance (in millimetres) the drone should hover.
** Used when 'flyingMode' is set to 'HOVER_ON_(ORIENTED_)ROUNDEL'
**
** Corresponds to the 'CONTROL:hovering_range' configuration key.
Int hoverMaxHeight {
get { getConfig("CONTROL:hovering_range").toInt }
set { setConfig("CONTROL:hovering_range", it.toStr) }
}
** Current FPS of the live video codec. Maximum value is 30.
**
** Corresponds to the 'VIDEO:codec_fps' configuration key.
Int videoCodecFps {
get { getConfig("VIDEO:codec_fps").toInt }
set { setConfig("VIDEO:codec_fps", it.toStr) }
}
** Current video codec of the AR.Drone.
** Also controls the start/stop of the record stream.
**
** Main values:
**
** H264_360P_CODEC = 0x81 // Live stream with 360p H264 hardware encoder. No record stream.
** H264_720P_CODEC = 0x83 // Live stream with 720p H264 hardware encoder. No record stream.
**
** MP4_360P_CODEC = 0x80 // Live stream with MPEG4.2 soft encoder. No record stream.
** MP4_360P_H264_360P_CODEC = 0x88 // Live stream with MPEG4.2 soft encoder. Record stream with 360p H264 hardware encoder.
** MP4_360P_H264_720P_CODEC = 0x82 // Live stream with MPEG4.2 soft encoder. Record stream with 720p H264 hardware encoder.
**
** Other values:
**
** NULL_CODEC = 0,
** UVLC_CODEC = 0x20 // codec_type value is used for START_CODE
** P264_CODEC = 0x40
** MP4_360P_SLRS_CODEC = 0x84
** H264_360P_SLRS_CODEC = 0x85
** H264_720P_SLRS_CODEC = 0x86
** H264_AUTO_RESIZE_CODEC = 0x87 // resolution is automatically adjusted according to bitrate
**
** Corresponds to the 'VIDEO:codec' configuration key.
Int videoCodec {
get { getConfig("VIDEO:codec", false)?.toInt ?: 0 }
set { setConfig("VIDEO:codec", it.toStr) }
}
** Maximum bitrate (kilobits per second) the device can decode. This is set as the upper bound for drone bitrate values.
**
** Typical values for Apple iOS Device are:
** - iPhone 4S : 4000 kbps
** - iPhone 4 : 1500 kbps
** - iPhone 3GS : 500 kbps
**
** When using the bitrate control mode in 'VBC_MANUAL', this maximum bitrate is ignored.
**
** When using the bitrate control mode in 'VBC_MODE_DISABLED', the bitrate is fixed to this maximum bitrate.
**
** Corresponds to the 'VIDEO:max_bitrate' configuration key.
Int videoMaxBitrate {
get { getConfig("VIDEO:max_bitrate").toInt }
set { setConfig("VIDEO:max_bitrate", it.toStr) }
}
** The video channel that will be sent to the controller.
**
** 0 = ZAP_CHANNEL_HORI
** 1 = ZAP_CHANNEL_VERT
**
** Corresponds to the 'VIDEO:videol_channel' configuration key.
Int videoChannel {
get { getConfig("VIDEO:videol_channel", false)?.toInt ?: 0 }
set { setConfig("VIDEO:videol_channel", it.toStr) }
}
// TODO bool -> hover on roundel (what does the detect hori do for us? play with vision tags)
// TODO roundel detect - none / hori / vert, set fps 30 / 60
// TODO userbox
** Active tag detection.
**
** 3 = CAD_TYPE_NONE : No detections
** 10 = CAD_TYPE_MULTIPLE_DETECTION_MODE : See following note
** 12 = CAD_TYPE_ORIENTED_COCARDE_BW : Black & White oriented roundel detected on bottom facing camera
** 13 = CAD_TYPE_VISION_V2 : Standard tag detection
**
** It is preferred to enable multiple detection mode and configure each camera.
**
** Note you should **NEVER** enable detection on both cameras, as this will cause failures in the algorithms.
**
** Corresponds to the 'DETECT:detect_type' configuration key.
@Deprecated
Int detectType {
get { getConfig("DETECT:detect_type").toInt }
set { setConfig("DETECT:detect_type", it.toStr) }
}
** Horizontal camera detection.
**
** 0 = TAG_TYPE_NONE : No tag to detect
** 3 = TAG_TYPE_ORIENTED_ROUNDEL (???)
** 6 = TAG_TYPE_SHELL_TAG_V2 : Standard hulls (both indoor and outdoor) tags
** 8 = TAG_TYPE_BLACK_ROUNDEL : Black&While oriented roundel
**
** Note you should **NEVER** enable detection on both cameras, as this will cause failures in the algorithms.
**
** Corresponds to the 'DETECT:detections_select_h' configuration key.
Int detectTypeHori {
get { getConfig("DETECT:detections_select_h").toInt }
set { setConfig("DETECT:detections_select_h", it.toStr) }
}
** Vertical camera detection.
**
** 0 = TAG_TYPE_NONE : No tag to detect
** 3 = TAG_TYPE_ORIENTED_ROUNDEL (???)
** 6 = TAG_TYPE_SHELL_TAG_V2 : Standard hulls (both indoor and outdoor) tags
** 8 = TAG_TYPE_BLACK_ROUNDEL : Black&While oriented roundel
**
** Note you should **NEVER** enable detection on both cameras, as this will cause failures in the algorithms.
**
** Corresponds to the 'DETECT:detections_select_v' configuration key.
Int detectTypeVert {
get { getConfig("DETECT:detections_select_v").toInt }
set { setConfig("DETECT:detections_select_v", it.toStr) }
}
** Detection defaults to 60 fps, but may be reduced to 30 fps to reduce the CPU load when you don’t need a 60Hz detection.
**
** Corresponds to the 'DETECT:detections_select_v_hsync' configuration key.
Int detectTypeVertFps {
get { getConfig("DETECT:detections_select_v_hsync").toInt }
set { setConfig("DETECT:detections_select_v_hsync", it.toStr) }
}
** The GPS position used for media tagging and userbox recording.
**
** When setting values, all unknown values are ignored.
** To change, pass in a map with just the values you wish to update.
**
** Corresponds to the configuration keys:
** - 'GPS:longitude'
** - 'GPS:latitude'
** - 'GPS:altitude'
Str:Float gpsPosition {
get {
[
"longitude" : getConfig("GPS:longitude").toFloat,
"latitude" : getConfig("GPS:latitude").toFloat,
"altitude" : getConfig("GPS:altitude").toFloat
]
}
set {
setConfig("GPS:longitude" , it["longitude"]?.toStr)
setConfig("GPS:latitude" , it["latitude" ]?.toStr)
setConfig("GPS:altitude" , it["altitude" ]?.toStr)
}
}
//USERBOX:userbox_cmd
//CAT_SESSION | Read/Write
//Description :
//The USERBOX:userbox_cmd provide a feature to save navigation data from drone during a time period and to take
//pictures. When the USERBOX:userbox_cmd is sent with parameter USERBOX_CMD_START, the AR.Drone create
//directory /data/video/boxes/tmp_flight_YYYYMMDD_hhmmss in AR.Drone flash memory and save a binary file
//containingnavigationdataandnamed/data/video/boxes/tmp_flight_YYYYMMDD_hhmmss/userbox_<timestamp>.
//<timestamp> represent the time since the AR.Drone booted.
//When the USERBOX:userbox_cmd is sent with parameter USERBOX_CMD_STOP, the AR.Drone finish saving of
///data/video/boxes/tmp_flight_YYYYMMDD_hhmmss/userbox_<timestamp>. and rename directory from
///data/video/boxes/tmp_flight_YYYYMMDD_hhmmss to /data/video/boxes/flight_YYYYMMDD_hhmmss.
//When the USERBOX:userbox_cmd is sent with parameter USERBOX_CMD_CANCEL, the AR.Drone stop the user-
//box like sending USERBOX_CMD_STOP and delete file
///data/video/boxes/tmp_flight_YYYYMMDD_hhmmss/userbox_<timestamp>.
//When the USERBOX:userbox_cmd is sent with parameter USERBOX_CMD_SCREENSHOT, the AR.Drone takes pic-
//ture of frontal camera and saves it as JPEG image named
///data/video/boxes/tmp_flight_YYYYMMDD_hhmmss/picture_YYMMDD_hhmmss.jpg.
//Note : If the userbox is started, the picture is saved in userbox directory. Note : After stopping userbox or taking
//picture, you MUST call academy_download_resume function to download flight directory by ftp protocol.
//Typical values are :
//• USERBOX_CMD_STOP : Command to stop userbox. This command takes no parameters.
//• USERBOX_CMD_CANCEL : Command to cancel userbox. If the userbox is started, stop the userbox and
//delete its content.
//• USERBOX_CMD_START : Command to start userbox. This command takes the current date as string pa-
//rameter with format YYYYMMDD_hhmmss
//• USERBOX_CMD_SCREENSHOT : Command to take a picture from AR.Drone . This command takes 3
//parameters.
//– 1 - delay : This value is an unsigned integer representing the delay (in seconds) between each screen-
//shot.
//– 1 - number of burst : This value is an unsigned integer representing the number of screenshot to take.
//– 1 - current date : This value is the current date as string parameter with format YYYYMMDD_hhmmss.
//Note : The file /data/video/boxes/tmp_flight_YYYYMMDD_hhmmss/userbox_<timestamp> will be used for future
//feature. (AR.Drone Academy ).
//
** Dumps all fields to debug string.
Str dump(Bool dumpToStdOut := true) {
fields := typeof.fields.findAll { it.isPublic && it.parent == this.typeof }
names := (Str[]) fields.map { it.name.toDisplayName }
width := names.max |p1, p2| { p1.size <=> p2.size }.size
values := fields.map |field, i| { names[i].padr(width, '.') + "..." + field.get(this).toStr }
dump := values.join("\n")
dump = "SESSION CONFIG\n==============\n" + dump + "\n\n"
dump += user.dump(false)
dump += app.dump(false)
if (dumpToStdOut)
echo(dump)
return dump
}
@NoDoc
override Str toStr() { dump }
private Str? getConfig(Str key, Bool checked := true) {
_config.drone.configMap[key] ?: (checked ? throw UnknownKeyErr(key) : null)
}
private Void setConfig(Str key, Str? val) {
if (val != null) { // for GPS position
_config.sendMultiConfig(key, val)
_config.drone._updateConfig(key, val)
}
}
}