Browse Source

Merge branch 'master' of github.com:PX4/Firmware into paul_estimator_numeric

sbg
Lorenz Meier 11 years ago
parent
commit
15bab106b7
  1. 5
      ROMFS/px4fmu_common/init.d/2103_skyhunter_1800
  2. 2
      ROMFS/px4fmu_common/init.d/3033_wingwing
  3. 6
      ROMFS/px4fmu_common/init.d/rc.autostart
  4. 2
      Tools/.gitignore
  5. 4
      Tools/px4params/.gitignore
  6. 10
      Tools/px4params/README.md
  7. 1
      Tools/px4params/__init__.py
  8. 44
      Tools/px4params/dokuwikiout.py
  9. 16
      Tools/px4params/dokuwikirpc.py
  10. 31
      Tools/px4params/output_dokuwiki_listings.py
  11. 76
      Tools/px4params/output_dokuwiki_tables.py
  12. 67
      Tools/px4params/px_process_params.py
  13. 5
      Tools/px4params/srcparser.py
  14. 11
      Tools/px4params/srcscanner.py
  15. 0
      Tools/px4params/xmlout.py
  16. 5
      Tools/px4params/xmlrpc.sh
  17. 140
      Tools/px_process_params.py
  18. 2
      Tools/px_update_wiki.sh
  19. 34
      src/modules/dataman/dataman.c
  20. 2
      src/modules/dataman/module.mk
  21. 2
      src/modules/fw_pos_control_l1/fw_pos_control_l1_params.c

5
ROMFS/px4fmu_common/init.d/2103_skyhunter_1800

@ -0,0 +1,5 @@ @@ -0,0 +1,5 @@
#!nsh
sh /etc/init.d/rc.fw_defaults
set MIXER FMU_AET

2
ROMFS/px4fmu_common/init.d/3033_wingwing

@ -27,7 +27,7 @@ then @@ -27,7 +27,7 @@ then
param set FW_PR_IMAX 0.2
param set FW_PR_P 0.06
param set FW_RR_FF 0.6
param set FW_RR_IMA 0.2
param set FW_RR_IMAX 0.2
param set FW_RR_P 0.09
param set FW_THR_CRUISE 0.65
fi

6
ROMFS/px4fmu_common/init.d/rc.autostart

@ -68,6 +68,12 @@ then @@ -68,6 +68,12 @@ then
set MODE custom
fi
if param compare SYS_AUTOSTART 2103 103
then
sh /etc/init.d/2103_skyhunter_1800
set MODE custom
fi
#
# Flying wing
#

2
Tools/.gitignore vendored

@ -0,0 +1,2 @@ @@ -0,0 +1,2 @@
parameters.wiki
parameters.xml

4
Tools/px4params/.gitignore vendored

@ -1,4 +0,0 @@ @@ -1,4 +0,0 @@
parameters.wiki
parameters.xml
parameters.wikirpc.xml
cookies.txt

10
Tools/px4params/README.md

@ -1,9 +1 @@ @@ -1,9 +1 @@
h1. PX4 Parameters Processor
It's designed to scan PX4 source codes, find declarations of tunable parameters,
and generate the list in various formats.
Currently supported formats are:
* XML for the parametric UI generator
* Human-readable description in DokuWiki format
This folder contains a python library used by px_process_params.py

1
Tools/px4params/__init__.py

@ -0,0 +1 @@ @@ -0,0 +1 @@
__all__ = ["srcscanner", "srcparser", "xmlout", "dokuwikiout", "dokuwikirpc"]

44
Tools/px4params/dokuwikiout.py

@ -0,0 +1,44 @@ @@ -0,0 +1,44 @@
from xml.sax.saxutils import escape
import codecs
class DokuWikiTablesOutput():
def __init__(self, groups):
result = ("====== Parameter Reference ======\n"
"<note>**This list is auto-generated from the source code** and contains the most recent parameter documentation.</note>\n"
"\n")
for group in groups:
result += "==== %s ====\n\n" % group.GetName()
result += "|< 100% 25% 45% 10% 10% 10% >|\n"
result += "^ Name ^ Description ^ Min ^ Max ^ Default ^\n"
result += "^ ::: ^ Comment ^^^^\n"
for param in group.GetParams():
code = param.GetFieldValue("code")
name = param.GetFieldValue("short_desc")
min_val = param.GetFieldValue("min")
max_val = param.GetFieldValue("max")
def_val = param.GetFieldValue("default")
long_desc = param.GetFieldValue("long_desc")
if name == code:
name = ""
else:
name = name.replace("\n", " ")
name = name.replace("|", "%%|%%")
name = name.replace("^", "%%^%%")
result += "| **%s** |" % code
result += " %s |" % name
result += " %s |" % (min_val or "")
result += " %s |" % (max_val or "")
result += " %s |" % (def_val or "")
result += "\n"
if long_desc is not None:
result += "| ::: | <div>%s</div> ||||\n" % long_desc
result += "\n"
self.output = result;
def Save(self, filename):
with codecs.open(filename, 'w', 'utf-8') as f:
f.write(self.output)

16
Tools/px4params/dokuwikirpc.py

@ -0,0 +1,16 @@ @@ -0,0 +1,16 @@
try:
import xmlrpclib
except ImportError:
import xmlrpc.client as xmlrpclib
# See https://www.dokuwiki.org/devel:xmlrpc for a list of available functions!
# Usage example:
# xmlrpc = dokuwikirpc.get_xmlrpc(url, username, password)
# print(xmlrpc.dokuwiki.getVersion())
def get_xmlrpc(url, username, password):
#proto, url = url.split("://")
#url = proto + "://" + username + ":" + password + "@" + url + "/lib/exe/xmlrpc.php"
url += "/lib/exe/xmlrpc.php?u=" + username + "&p=" + password
return xmlrpclib.ServerProxy(url)

31
Tools/px4params/output_dokuwiki_listings.py

@ -1,31 +0,0 @@ @@ -1,31 +0,0 @@
import codecs
class DokuWikiListingsOutput():
def __init__(self, groups):
result = ""
for group in groups:
result += "==== %s ====\n\n" % group.GetName()
for param in group.GetParams():
code = param.GetFieldValue("code")
name = param.GetFieldValue("short_desc")
if code != name:
name = "%s (%s)" % (name, code)
result += "=== %s ===\n\n" % name
long_desc = param.GetFieldValue("long_desc")
if long_desc is not None:
result += "%s\n\n" % long_desc
min_val = param.GetFieldValue("min")
if min_val is not None:
result += "* Minimal value: %s\n" % min_val
max_val = param.GetFieldValue("max")
if max_val is not None:
result += "* Maximal value: %s\n" % max_val
def_val = param.GetFieldValue("default")
if def_val is not None:
result += "* Default value: %s\n" % def_val
result += "\n"
self.output = result
def Save(self, filename):
with codecs.open(filename, 'w', 'utf-8') as f:
f.write(self.output)

76
Tools/px4params/output_dokuwiki_tables.py

@ -1,76 +0,0 @@ @@ -1,76 +0,0 @@
from xml.sax.saxutils import escape
import codecs
class DokuWikiTablesOutput():
def __init__(self, groups):
result = "====== Parameter Reference ======\nThis list is auto-generated every few minutes and contains the most recent parameter names and default values.\n\n"
for group in groups:
result += "==== %s ====\n\n" % group.GetName()
result += "|< 100% 20% 20% 10% 10% 10% 30%>|\n"
result += "^ Name ^ Description ^ Min ^ Max ^ Default ^ Comment ^\n"
for param in group.GetParams():
code = param.GetFieldValue("code")
name = param.GetFieldValue("short_desc")
min_val = param.GetFieldValue("min")
max_val = param.GetFieldValue("max")
def_val = param.GetFieldValue("default")
long_desc = param.GetFieldValue("long_desc")
name = name.replace("\n", " ")
result += "| %s | %s |" % (code, name)
if min_val is not None:
result += " %s |" % min_val
else:
result += " |"
if max_val is not None:
result += " %s |" % max_val
else:
result += " |"
if def_val is not None:
result += " %s |" % def_val
else:
result += " |"
if long_desc is not None:
long_desc = long_desc.replace("\n", " ")
result += " %s |" % long_desc
else:
result += " |"
result += "\n"
result += "\n"
self.output = result;
def Save(self, filename):
with codecs.open(filename, 'w', 'utf-8') as f:
f.write(self.output)
def SaveRpc(self, filename):
with codecs.open(filename, 'w', 'utf-8') as f:
f.write("""<?xml version='1.0'?>
<methodCall>
<methodName>wiki.putPage</methodName>
<params>
<param>
<value>
<string>:firmware:parameters</string>
</value>
</param>
<param>
<value>
<string>""")
f.write(escape(self.output))
f.write("""</string>
</value>
</param>
<param>
<value>
<name>sum</name>
<string>Updated parameters automagically from code.</string>
</value>
</param>
</params>
</methodCall>""")

67
Tools/px4params/px_process_params.py

@ -1,67 +0,0 @@ @@ -1,67 +0,0 @@
#!/usr/bin/env python
############################################################################
#
# Copyright (C) 2013 PX4 Development Team. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in
# the documentation and/or other materials provided with the
# distribution.
# 3. Neither the name PX4 nor the names of its contributors may be
# used to endorse or promote products derived from this software
# without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
#
############################################################################
#
# PX4 paramers processor (main executable file)
#
# It scans src/ subdirectory of the project, collects all parameters
# definitions, and outputs list of parameters in XML and DokuWiki formats.
#
import scanner
import srcparser
import output_xml
import output_dokuwiki_tables
import output_dokuwiki_listings
# Initialize parser
prs = srcparser.Parser()
# Scan directories, and parse the files
sc = scanner.Scanner()
sc.ScanDir("../../src", prs)
groups = prs.GetParamGroups()
# Output into XML
out = output_xml.XMLOutput(groups)
out.Save("parameters.xml")
# Output to DokuWiki listings
#out = output_dokuwiki_listings.DokuWikiListingsOutput(groups)
#out.Save("parameters.wiki")
# Output to DokuWiki tables
out = output_dokuwiki_tables.DokuWikiTablesOutput(groups)
out.Save("parameters.wiki")
out.SaveRpc("parameters.wikirpc.xml")

5
Tools/px4params/srcparser.py

@ -44,6 +44,7 @@ class Parameter(object): @@ -44,6 +44,7 @@ class Parameter(object):
"default": 6,
"min": 5,
"max": 4,
"unit": 3,
# all others == 0 (sorted alphabetically)
}
@ -71,7 +72,7 @@ class Parameter(object): @@ -71,7 +72,7 @@ class Parameter(object):
"""
return self.fields.get(code)
class Parser(object):
class SourceParser(object):
"""
Parses provided data and stores all found parameters internally.
"""
@ -86,7 +87,7 @@ class Parser(object): @@ -86,7 +87,7 @@ class Parser(object):
re_is_a_number = re.compile(r'^-?[0-9\.]')
re_remove_dots = re.compile(r'\.+$')
valid_tags = set(["min", "max", "group"])
valid_tags = set(["group", "min", "max", "unit"])
# Order of parameter groups
priority = {

11
Tools/px4params/scanner.py → Tools/px4params/srcscanner.py

@ -2,26 +2,21 @@ import os @@ -2,26 +2,21 @@ import os
import re
import codecs
class Scanner(object):
class SourceScanner(object):
"""
Traverses directory tree, reads all source files, and passes their contents
to the Parser.
"""
re_file_extension = re.compile(r'\.([^\.]+)$')
def ScanDir(self, srcdir, parser):
"""
Scans provided path and passes all found contents to the parser using
parser.Parse method.
"""
extensions = set(parser.GetSupportedExtensions())
extensions = tuple(parser.GetSupportedExtensions())
for dirname, dirnames, filenames in os.walk(srcdir):
for filename in filenames:
m = self.re_file_extension.search(filename)
if m:
ext = m.group(1)
if ext in extensions:
if filename.endswith(extensions):
path = os.path.join(dirname, filename)
self.ScanFile(path, parser)

0
Tools/px4params/output_xml.py → Tools/px4params/xmlout.py

5
Tools/px4params/xmlrpc.sh

@ -1,5 +0,0 @@ @@ -1,5 +0,0 @@
python px_process_params.py
rm cookies.txt
curl --cookie cookies.txt --cookie-jar cookies.txt --user-agent Mozilla/4.0 --data "u=$XMLRPCUSER&p=$XMLRPCPASS" https://pixhawk.org/start?do=login
curl -k --cookie cookies.txt -H "Content-Type: application/xml" -X POST --data-binary @parameters.wikirpc.xml "https://pixhawk.org/lib/exe/xmlrpc.php"

140
Tools/px_process_params.py

@ -0,0 +1,140 @@ @@ -0,0 +1,140 @@
#!/usr/bin/env python
############################################################################
#
# Copyright (C) 2013-2014 PX4 Development Team. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in
# the documentation and/or other materials provided with the
# distribution.
# 3. Neither the name PX4 nor the names of its contributors may be
# used to endorse or promote products derived from this software
# without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
#
############################################################################
#
# PX4 paramers processor (main executable file)
#
# This tool scans the PX4 source code for declarations of tunable parameters
# and outputs the list in various formats.
#
# Currently supported formats are:
# * XML for the parametric UI generator
# * Human-readable description in DokuWiki page format
#
# This tool also allows to automatically upload the human-readable version
# to the DokuWiki installation via XML-RPC.
#
from __future__ import print_function
import sys
import os
import argparse
from px4params import srcscanner, srcparser, xmlout, dokuwikiout, dokuwikirpc
def main():
# Parse command line arguments
parser = argparse.ArgumentParser(description="Process parameter documentation.")
parser.add_argument("-s", "--src-path",
default="../src",
metavar="PATH",
help="path to source files to scan for parameters")
parser.add_argument("-x", "--xml",
nargs='?',
const="parameters.xml",
metavar="FILENAME",
help="Create XML file"
" (default FILENAME: parameters.xml)")
parser.add_argument("-w", "--wiki",
nargs='?',
const="parameters.wiki",
metavar="FILENAME",
help="Create DokuWiki file"
" (default FILENAME: parameters.wiki)")
parser.add_argument("-u", "--wiki-update",
nargs='?',
const="firmware:parameters",
metavar="PAGENAME",
help="Update DokuWiki page"
" (default PAGENAME: firmware:parameters)")
parser.add_argument("--wiki-url",
default="https://pixhawk.org",
metavar="URL",
help="DokuWiki URL"
" (default: https://pixhawk.org)")
parser.add_argument("--wiki-user",
default=os.environ.get('XMLRPCUSER', None),
metavar="USERNAME",
help="DokuWiki XML-RPC user name"
" (default: $XMLRPCUSER environment variable)")
parser.add_argument("--wiki-pass",
default=os.environ.get('XMLRPCPASS', None),
metavar="PASSWORD",
help="DokuWiki XML-RPC user password"
" (default: $XMLRPCUSER environment variable)")
parser.add_argument("--wiki-summary",
metavar="SUMMARY",
default="Automagically updated parameter documentation from code.",
help="DokuWiki page edit summary")
args = parser.parse_args()
# Check for valid command
if not (args.xml or args.wiki or args.wiki_update):
print("Error: You need to specify at least one output method!\n")
parser.print_usage()
sys.exit(1)
# Initialize source scanner and parser
scanner = srcscanner.SourceScanner()
parser = srcparser.SourceParser()
# Scan directories, and parse the files
print("Scanning source path " + args.src_path)
scanner.ScanDir(args.src_path, parser)
param_groups = parser.GetParamGroups()
# Output to XML file
if args.xml:
print("Creating XML file " + args.xml)
out = xmlout.XMLOutput(param_groups)
out.Save(args.xml)
# Output to DokuWiki tables
if args.wiki or args.wiki_update:
out = dokuwikiout.DokuWikiTablesOutput(param_groups)
if args.wiki:
print("Creating wiki file " + args.wiki)
out.Save(args.wiki)
if args.wiki_update:
if args.wiki_user and args.wiki_pass:
print("Updating wiki page " + args.wiki_update)
xmlrpc = dokuwikirpc.get_xmlrpc(args.wiki_url, args.wiki_user, args.wiki_pass)
xmlrpc.wiki.putPage(args.wiki_update, out.output, {'sum': args.wiki_summary})
else:
print("Error: You need to specify DokuWiki XML-RPC username and password!")
print("All done!")
if __name__ == "__main__":
main()

2
Tools/px_update_wiki.sh

@ -0,0 +1,2 @@ @@ -0,0 +1,2 @@
# Remember to set the XMLRPCUSER and XMLRPCPASS environment variables
python px_process_params.py --wiki-update

34
src/modules/dataman/dataman.c

@ -1,8 +1,10 @@ @@ -1,8 +1,10 @@
/****************************************************************************
*
* Copyright (c) 2013 PX4 Development Team. All rights reserved.
* Author: Lorenz Meier
* Jean Cyr
* Author: Jean Cyr
* Lorenz Meier
* Julian Oes
* Thomas Gubler
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@ -40,16 +42,8 @@ @@ -40,16 +42,8 @@
#include <nuttx/config.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <math.h>
#include <poll.h>
#include <time.h>
#include <sys/ioctl.h>
#include <systemlib/systemlib.h>
#include <systemlib/err.h>
#include <queue.h>
#include "dataman.h"
@ -175,8 +169,10 @@ create_work_item(void) @@ -175,8 +169,10 @@ create_work_item(void)
/* Try to reuse item from free item queue */
lock_queue(&g_free_q);
if ((item = (work_q_item_t *)sq_remfirst(&(g_free_q.q))))
g_free_q.size--;
unlock_queue(&g_free_q);
/* If we there weren't any free items then obtain memory for a new one */
@ -289,11 +285,11 @@ _write(dm_item_t item, unsigned char index, dm_persitence_t persistence, const v @@ -289,11 +285,11 @@ _write(dm_item_t item, unsigned char index, dm_persitence_t persistence, const v
offset = calculate_offset(item, index);
/* If item type or index out of range, return error */
if (offset < 0)
if (offset < 0)
return -1;
/* Make sure caller has not given us more data than we can handle */
if (count > DM_MAX_DATA_SIZE)
if (count > DM_MAX_DATA_SIZE)
return -1;
/* Write out the data, prefixed with length and persistence level */
@ -339,6 +335,7 @@ _read(dm_item_t item, unsigned char index, void *buf, size_t count) @@ -339,6 +335,7 @@ _read(dm_item_t item, unsigned char index, void *buf, size_t count)
/* Read the prefix and data */
len = -1;
if (lseek(g_task_fd, offset, SEEK_SET) == offset)
len = read(g_task_fd, buffer, count + DM_SECTOR_HDR_SIZE);
@ -492,7 +489,7 @@ dm_write(dm_item_t item, unsigned char index, dm_persitence_t persistence, const @@ -492,7 +489,7 @@ dm_write(dm_item_t item, unsigned char index, dm_persitence_t persistence, const
return -1;
/* get a work item and queue up a write request */
if ((work = create_work_item()) == NULL)
if ((work = create_work_item()) == NULL)
return -1;
work->func = dm_write_func;
@ -599,17 +596,20 @@ task_main(int argc, char *argv[]) @@ -599,17 +596,20 @@ task_main(int argc, char *argv[])
/* Open or create the data manager file */
g_task_fd = open(k_data_manager_device_path, O_RDWR | O_CREAT | O_BINARY);
if (g_task_fd < 0) {
warnx("Could not open data manager file %s", k_data_manager_device_path);
sem_post(&g_init_sema); /* Don't want to hang startup */
return -1;
}
if (lseek(g_task_fd, max_offset, SEEK_SET) != max_offset) {
close(g_task_fd);
warnx("Could not seek data manager file %s", k_data_manager_device_path);
sem_post(&g_init_sema); /* Don't want to hang startup */
return -1;
}
fsync(g_task_fd);
/* We use two file descriptors, one for the caller context and one for the worker thread */
@ -767,10 +767,10 @@ dataman_main(int argc, char *argv[]) @@ -767,10 +767,10 @@ dataman_main(int argc, char *argv[])
stop();
else if (!strcmp(argv[1], "status"))
status();
else if (!strcmp(argv[1], "poweronrestart"))
dm_restart(DM_INIT_REASON_POWER_ON);
else if (!strcmp(argv[1], "inflightrestart"))
dm_restart(DM_INIT_REASON_IN_FLIGHT);
else if (!strcmp(argv[1], "poweronrestart"))
dm_restart(DM_INIT_REASON_POWER_ON);
else if (!strcmp(argv[1], "inflightrestart"))
dm_restart(DM_INIT_REASON_IN_FLIGHT);
else
usage();

2
src/modules/dataman/module.mk

@ -38,5 +38,3 @@ @@ -38,5 +38,3 @@
MODULE_COMMAND = dataman
SRCS = dataman.c
INCLUDE_DIRS += $(MAVLINK_SRC)/include/mavlink

2
src/modules/fw_pos_control_l1/fw_pos_control_l1_params.c

@ -245,7 +245,7 @@ PARAM_DEFINE_FLOAT(FW_T_INTEG_GAIN, 0.1f); @@ -245,7 +245,7 @@ PARAM_DEFINE_FLOAT(FW_T_INTEG_GAIN, 0.1f);
/**
* Maximum vertical acceleration
*
* This is the maximum vertical acceleration (in metres/second^2)
* This is the maximum vertical acceleration (in metres/second square)
* either up or down that the controller will use to correct speed
* or height errors. The default value of 7 m/s/s (equivalent to +- 0.7 g)
* allows for reasonably aggressive pitch changes if required to recover

Loading…
Cancel
Save