From 01126ae9de38f4a16bf8823b14bb8747ca23a117 Mon Sep 17 00:00:00 2001 From: Michael Oborne Date: Thu, 26 Apr 2012 08:01:08 +0800 Subject: [PATCH] APM Planner - code only add yaw to config screen. intergrate adams changes this will force an update, but not the main exe --- .../ArdupilotMegaPlanner/ArduCopterConfig.xml | 66 ++++- .../ArdupilotMegaPlanner/ArdupilotMega.csproj | 1 + Tools/ArdupilotMegaPlanner/MainV2.cs | 14 +- Tools/ArdupilotMegaPlanner/Msi/wix.pdb | Bin 19968 -> 19968 bytes .../Utilities/CollectionExtensions.cs | 47 +++ .../Utilities/ParameterMetaDataConstants.cs | 16 +- .../Utilities/ParameterMetaDataParser.cs | 275 +++++++++++++----- .../Utilities/ParameterMetaDataRepository.cs | 15 +- Tools/ArdupilotMegaPlanner/app.config | 4 + .../bin/Release/ArduCopterConfig.xml | 66 ++++- .../bin/Release/version.txt | 2 +- 11 files changed, 428 insertions(+), 78 deletions(-) create mode 100644 Tools/ArdupilotMegaPlanner/Utilities/CollectionExtensions.cs diff --git a/Tools/ArdupilotMegaPlanner/ArduCopterConfig.xml b/Tools/ArdupilotMegaPlanner/ArduCopterConfig.xml index 2558e46e2c..fda38f6780 100644 --- a/Tools/ArdupilotMegaPlanner/ArduCopterConfig.xml +++ b/Tools/ArdupilotMegaPlanner/ArduCopterConfig.xml @@ -101,6 +101,70 @@ Too high = slow wobbles 0.001 + + Yaw Angular Rate Control: + How much throttle is applied to rotate the copter at the desired speed. + + + + P + RATE_YAW_P + 0.001 + 5 + 0.001 + + + I + RATE_YAW_I + 0 + 5 + 0.001 + + + D + RATE_YAW_D + 0 + 5 + 0.001 + + + IMAX + RATE_YAW_IMAX + 0 + 50 + 1 + + + + Yaw Stabilize Control: + + How fast the copter reacts to user or autopilot input. + Higher = more aggressive control. + Too high = slow wobbles + + + + P + STB_YAW_P + 0.001 + 10 + 0.001 + + + I + STB_YAW_I + 0 + 5 + 0.001 + + + IMAX + STB_YAW_IMAX + 0 + 50 + 1 + + @@ -140,7 +204,7 @@ How much angle is applied to make the copter accelerate to the desired speed. LOITER_LON_IMAX 0 50 - 0.1 + 1 Loiter Speed: diff --git a/Tools/ArdupilotMegaPlanner/ArdupilotMega.csproj b/Tools/ArdupilotMegaPlanner/ArdupilotMega.csproj index def4fc453c..b318087f83 100644 --- a/Tools/ArdupilotMegaPlanner/ArdupilotMega.csproj +++ b/Tools/ArdupilotMegaPlanner/ArdupilotMega.csproj @@ -226,6 +226,7 @@ + UserControl diff --git a/Tools/ArdupilotMegaPlanner/MainV2.cs b/Tools/ArdupilotMegaPlanner/MainV2.cs index f04826220b..907bb8c6ca 100644 --- a/Tools/ArdupilotMegaPlanner/MainV2.cs +++ b/Tools/ArdupilotMegaPlanner/MainV2.cs @@ -1733,8 +1733,18 @@ namespace ArdupilotMega static void DoUpdateWorker_DoWork(object sender, Controls.ProgressWorkerEventArgs e) { - ((ProgressReporterDialogue)sender).UpdateProgressAndStatus(-1, "Getting Base URL"); - MainV2.updateCheckMain((ProgressReporterDialogue)sender); + // TODO: Is this the right place? + #region Fetch Parameter Meta Data + + var progressReporterDialogue = ((ProgressReporterDialogue) sender); + progressReporterDialogue.UpdateProgressAndStatus(-1, "Getting Updated Parameters"); + + ParameterMetaDataParser.GetParameterInformation(); + + #endregion Fetch Parameter Meta Data + + progressReporterDialogue.UpdateProgressAndStatus(-1, "Getting Base URL"); + MainV2.updateCheckMain(progressReporterDialogue); } private static bool updateCheck(ProgressReporterDialogue frmProgressReporter, string baseurl, string subdir) diff --git a/Tools/ArdupilotMegaPlanner/Msi/wix.pdb b/Tools/ArdupilotMegaPlanner/Msi/wix.pdb index e2bd4a8c51e6596bf41da25015857ed84be7ef85..a5d459167772c92af2f5da9b7b52010c246af54a 100644 GIT binary patch delta 519 zcmZpe!`Lu~aRUpNgi-$te?|rdhBZrs_U{d9_u1F9(WYBUJ9)DV*Be2$vyyAL?Ugt4 z$+R#rs!pCPcbw_7$mAILEFkB&d^V%%W@ClvK$*>_mD)j6uxdIpQ>N(VJsNsUOc|n+ z-)N-)RR(J(1Ld}BNApdV7h_{d%quS6EMpbH!tz0KlhEV}y9Aa3c_8BsknuqZ$Z)V% ztLGC0x`}}eM1VoOD~ttlEJ$1wCcu!H4`YJlq=A?nD!|C#pNEjk&rg0FybRdBgvB==`CqyP=FhZ@FY4Rjc?#>FfQ3>I*WIY=4}8EymRK%NHyCZN8} OCmd{;@x-so6HWkYMOCH% delta 481 zcmZpe!`Lu~aRUpN#QD?H{TUe;7_zx|7hk*>;NAH0Y=W(xPUvPCt~Y{g0X+Mso>JP( zC)2{js4;o6+;Jv0(aACLSwPNl`D{jw&BhATfijy{GqmKpMs?*JJLtif`V z9qiTWV?sd+*+2vsq~^g`j0~(`aZ#86kPicl48bMRKn^=pfRQ0J86lTnq6Fj^!{vNa z5pt=;APZskF)}kG7f*g+uLd+I2`H{M+0a2$`KWvcklhQ_#Kdq^9?E0@1)(UAxC&Ai z&C2i!$gYB`Lv|knLkbfEgFO&~0F(l=8G+_4W?^7}h7nK>)%@E)IccEz!kaHRm@wms IIhQA#0DA&g(f|Me diff --git a/Tools/ArdupilotMegaPlanner/Utilities/CollectionExtensions.cs b/Tools/ArdupilotMegaPlanner/Utilities/CollectionExtensions.cs new file mode 100644 index 0000000000..6b435af402 --- /dev/null +++ b/Tools/ArdupilotMegaPlanner/Utilities/CollectionExtensions.cs @@ -0,0 +1,47 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace ArdupilotMega.Utilities +{ + public static class CollectionExtensions + { + /// + /// Performs the specified on each element of the . + /// + /// + /// An enumerable instance. + /// + public static void ForEach(this IEnumerable enumerable, Action action) + { + foreach (object obj in enumerable) + action(obj); + } + + /// + /// Performs the specified on each element of the . + /// + /// + /// An enumerable instance. + /// + public static void ForEach(this IEnumerable enumerable, Action action) + { + foreach (T obj in enumerable) + action(obj); + } + + /// + /// Performs the specified on each element of the . + /// + /// + /// The type contained in the . + /// + public static void ForEach(this IEnumerable enumerable, Action action) + { + foreach (T obj in enumerable) + action(obj); + } + } +} diff --git a/Tools/ArdupilotMegaPlanner/Utilities/ParameterMetaDataConstants.cs b/Tools/ArdupilotMegaPlanner/Utilities/ParameterMetaDataConstants.cs index 7f189aa066..fb29584b08 100644 --- a/Tools/ArdupilotMegaPlanner/Utilities/ParameterMetaDataConstants.cs +++ b/Tools/ArdupilotMegaPlanner/Utilities/ParameterMetaDataConstants.cs @@ -2,11 +2,23 @@ { public sealed class ParameterMetaDataConstants { - public const string Delimeter = "@"; + #region Markers + + public const string ParamDelimeter = "@"; + public const string PathDelimeter = ","; public const string Param = "Param"; + public const string Group = "Group"; + public const string Path = "Path"; + + #endregion + + #region Meta Keys + public const string DisplayName = "DisplayName"; public const string Description = "Description"; public const string Units = "Units"; public const string Range = "Range"; + + #endregion } -} +} \ No newline at end of file diff --git a/Tools/ArdupilotMegaPlanner/Utilities/ParameterMetaDataParser.cs b/Tools/ArdupilotMegaPlanner/Utilities/ParameterMetaDataParser.cs index 2c3d2c0e13..d4498f0f5f 100644 --- a/Tools/ArdupilotMegaPlanner/Utilities/ParameterMetaDataParser.cs +++ b/Tools/ArdupilotMegaPlanner/Utilities/ParameterMetaDataParser.cs @@ -7,13 +7,15 @@ using System.Net; using System.Text.RegularExpressions; using System.Windows.Forms; using System.Xml; +using ArdupilotMega.Utilities; using log4net; namespace ArdupilotMega.Utilities { public static class ParameterMetaDataParser { - private static readonly Regex _paramMetaRegex = new Regex(String.Format("{0}(?[^:]+):(?.+)", ParameterMetaDataConstants.Delimeter)); + private static readonly Regex _paramMetaRegex = new Regex(String.Format("{0}(?[^:]+):(?.+)", ParameterMetaDataConstants.ParamDelimeter)); + private static readonly Regex _parentDirectoryRegex = new Regex("(?[../]*)(?.+)"); private static readonly ILog log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); @@ -34,51 +36,16 @@ namespace ArdupilotMega.Utilities foreach (string parameterLocation in parameterLocations) { - log.Info(parameterLocation); + // Write the start element for this parameter location + objXmlTextWriter.WriteStartElement(parameterLocation.ToLower().Contains("arducopter") ? MainV2.Firmwares.ArduCopter2.ToString() : MainV2.Firmwares.ArduPlane.ToString()); - var request = WebRequest.Create(parameterLocation); + // Read and parse the content. + string dataFromAddress = ReadDataFromAddress(parameterLocation); + ParseGroupInformation(dataFromAddress, objXmlTextWriter, parameterLocation); + ParseParameterInformation(dataFromAddress, objXmlTextWriter); - // Plenty of timeout - request.Timeout = 10000; - - // Set the Method property of the request to GET. - request.Method = "GET"; - - // Get the response. - using (var response = request.GetResponse()) - { - // Display the status. - log.Info(((HttpWebResponse)response).StatusDescription); - - // Get the stream containing content returned by the server. - using (var dataStream = response.GetResponseStream()) - { - if (dataStream != null) - { - // Open the stream using a StreamReader for easy access. - using (var reader = new StreamReader(dataStream)) - { - // Write the start element for this parameter location - objXmlTextWriter.WriteStartElement(parameterLocation); - - // Read and parse the content. - ParseParameterInformation(reader.ReadToEnd(), objXmlTextWriter); - - // Write the end element for this parameter location - objXmlTextWriter.WriteEndElement(); - - // Close the reader - reader.Close(); - } - - // Close the datastream - dataStream.Close(); - } - } - - // Close the response - response.Close(); - } + // Write the end element for this parameter location + objXmlTextWriter.WriteEndElement(); } @@ -90,6 +57,67 @@ namespace ArdupilotMega.Utilities } } + /// + /// Parses the group parameter information. + /// + /// The file contents. + /// The obj XML text writer. + /// The parameter location. + private static void ParseGroupInformation(string fileContents, XmlTextWriter objXmlTextWriter, string parameterLocation) + { + var parsedInformation = ParseKeyValuePairs(fileContents, ParameterMetaDataConstants.Group); + if (parsedInformation != null && parsedInformation.Count > 0) + { + // node is the prefix of the parameter group here + parsedInformation.ForEach(node => + { + // node.Value is a nested dictionary containing the additional meta data + // In this case we are looking for the @Path key + if (node.Value != null && node.Value.Count > 0) + { + // Find the @Path key + node.Value + .Where(meta => meta.Key == ParameterMetaDataConstants.Path) + // We might have multiple paths to inspect, so break them out by the delimeter + .ForEach(path => path.Value.Split(new []{ ParameterMetaDataConstants.PathDelimeter }, StringSplitOptions.None) + .ForEach(separatedPath => + { + // Match based on the regex defined at the top of this class + Match pathMatch = _parentDirectoryRegex.Match(separatedPath); + if (pathMatch.Success && pathMatch.Groups["Path"] != null && !String.IsNullOrEmpty(pathMatch.Groups["Path"].Value)) + { + if (pathMatch.Groups["ParentDirectory"] != null && !String.IsNullOrEmpty(pathMatch.Groups["ParentDirectory"].Value)) + { + // How many directories from the original path do we have to move + int numberOfParentDirectoryMoves = pathMatch.Groups["ParentDirectory"].Value.Split(new string[] { "../" }, StringSplitOptions.None).Count(); + + // We need to remove the http:// or https:// prefix to build the new URL properly + string httpTest = parameterLocation.Substring(0, 7); + int trimHttpPrefixIdx = httpTest == "http://" ? 7 : 8; + + // Get the parts of the original URL + var parameterLocationParts = parameterLocation.Substring(trimHttpPrefixIdx, parameterLocation.Length - trimHttpPrefixIdx).Split(new char[] { '/' }); + + // Rebuild the new url taking into account the numberOfParentDirectoryMoves + string urlAfterParentDirectory = string.Empty; + for (int i = 0; i < parameterLocationParts.Length && i < parameterLocationParts.Length - numberOfParentDirectoryMoves; i++) + { + urlAfterParentDirectory += parameterLocationParts[i] + "/"; + } + + // This is the URL of the file we need to parse for comments + string newPath = String.Format("{0}{1}{2}", parameterLocation.Substring(0, trimHttpPrefixIdx), urlAfterParentDirectory, pathMatch.Groups["Path"].Value); + + // Parse the param info from the newly constructed URL + ParseParameterInformation(ReadDataFromAddress(newPath), objXmlTextWriter, node.Key); + } + } + })); + } + }); + } + } + /// /// Parses the parameter information. /// @@ -97,8 +125,50 @@ namespace ArdupilotMega.Utilities /// The obj XML text writer. private static void ParseParameterInformation(string fileContents, XmlTextWriter objXmlTextWriter) { + ParseParameterInformation(fileContents, objXmlTextWriter, string.Empty); + } + + /// + /// Parses the parameter information. + /// + /// The file contents. + /// The obj XML text writer. + /// The parameter prefix. + private static void ParseParameterInformation(string fileContents, XmlTextWriter objXmlTextWriter, string parameterPrefix) + { + var parsedInformation = ParseKeyValuePairs(fileContents, ParameterMetaDataConstants.Param); + if(parsedInformation != null && parsedInformation.Count > 0) + { + parsedInformation.ForEach(node => + { + objXmlTextWriter.WriteStartElement(String.Format("{0}{1}", parameterPrefix, node.Key)); + if (node.Value != null && node.Value.Count > 0) + { + node.Value.ForEach(meta => + { + // Write the key value pair to XML + objXmlTextWriter.WriteStartElement(meta.Key); + objXmlTextWriter.WriteString(meta.Value); + objXmlTextWriter.WriteEndElement(); + }); + } + objXmlTextWriter.WriteEndElement(); + }); + } + } + + /// + /// Parses the parameter information. + /// + /// The file contents. + /// The node key. + /// + private static Dictionary> ParseKeyValuePairs(string fileContents, string nodeKey) + { + var returnDict = new Dictionary>(); + var indicies = new List(); - GetIndexOfMarkers(ref indicies, fileContents, ParameterMetaDataConstants.Delimeter + ParameterMetaDataConstants.Param, 0); + GetIndexOfMarkers(ref indicies, fileContents, ParameterMetaDataConstants.ParamDelimeter + nodeKey, 0); if(indicies.Count > 0) { @@ -113,7 +183,7 @@ namespace ArdupilotMega.Utilities if(!String.IsNullOrEmpty(subStringToSearch)) { var metaIndicies = new List(); - GetIndexOfMarkers(ref metaIndicies, subStringToSearch, ParameterMetaDataConstants.Delimeter, 0); + GetIndexOfMarkers(ref metaIndicies, subStringToSearch, ParameterMetaDataConstants.ParamDelimeter, 0); if(metaIndicies.Count > 0) { @@ -123,40 +193,43 @@ namespace ArdupilotMega.Utilities // Match based on the regex defined at the top of this class Match paramNameKeyMatch = _paramMetaRegex.Match(paramNameKey); - if (paramNameKeyMatch.Success && paramNameKeyMatch.Groups["MetaKey"].Value == ParameterMetaDataConstants.Param) + if (paramNameKeyMatch.Success && paramNameKeyMatch.Groups["MetaKey"].Value == nodeKey) { - objXmlTextWriter.WriteStartElement(paramNameKeyMatch.Groups["MetaValue"].Value.Trim(new char[] { ' ' })); - - // Loop through the indicies of the meta data found - for (int x = 1; x < metaIndicies.Count; x++) + string key = paramNameKeyMatch.Groups["MetaValue"].Value.Trim(new char[] {' '}); + var metaDict = new Dictionary(); + if(!returnDict.ContainsKey(key)) { - // This is the end index for a substring to search for parameter attributes - // If we are on the last index in our collection, we will search to the end of the file - var stopMetaIdx = (x == metaIndicies.Count - 1) ? subStringToSearch.Length : metaIndicies[x + 1]; - - // This meta param string - var metaString = subStringToSearch.Substring(metaIndicies[x], (stopMetaIdx - metaIndicies[x])); - - // Match based on the regex defined at the top of this class - Match metaMatch = _paramMetaRegex.Match(metaString); - - // Test for success - if (metaMatch.Success) + // Loop through the indicies of the meta data found + for (int x = 1; x < metaIndicies.Count; x++) { - // Write the key value pair to XML - objXmlTextWriter.WriteStartElement(metaMatch.Groups["MetaKey"].Value.Trim(new char[] { ' ' })); - objXmlTextWriter.WriteString(metaMatch.Groups["MetaValue"].Value.Trim(new char[] { ' ' })); - objXmlTextWriter.WriteEndElement(); + // This is the end index for a substring to search for parameter attributes + // If we are on the last index in our collection, we will search to the end of the file + var stopMetaIdx = (x == metaIndicies.Count - 1) ? subStringToSearch.Length : metaIndicies[x + 1]; + + // This meta param string + var metaString = subStringToSearch.Substring(metaIndicies[x], (stopMetaIdx - metaIndicies[x])); + + // Match based on the regex defined at the top of this class + Match metaMatch = _paramMetaRegex.Match(metaString); + + // Test for success + if (metaMatch.Success) + { + string metaKey = metaMatch.Groups["MetaKey"].Value.Trim(new char[] {' '}); + if(!metaDict.ContainsKey(metaKey)) + { + metaDict.Add(metaKey, metaMatch.Groups["MetaValue"].Value.Trim(new char[] { ' ' })); + } + } } } - - // End this parameter node - objXmlTextWriter.WriteEndElement(); + returnDict.Add(key, metaDict); } } } } } + return returnDict; } /// @@ -188,5 +261,67 @@ namespace ArdupilotMega.Utilities } } } + + /// + /// Reads the data from address. + /// + /// The address. + /// + private static string ReadDataFromAddress(string address) + { + string data = string.Empty; + + log.Info(address); + + // Make sure we don't blow up if the user is not connected or the endpoint is not available + try + { + var request = WebRequest.Create(address); + + // Plenty of timeout + request.Timeout = 10000; + + // Set the Method property of the request to GET. + request.Method = "GET"; + + // Get the response. + using (var response = request.GetResponse()) + { + // Display the status. + log.Info(((HttpWebResponse)response).StatusDescription); + + // Get the stream containing content returned by the server. + using (var dataStream = response.GetResponseStream()) + { + if (dataStream != null) + { + // Open the stream using a StreamReader for easy access. + using (var reader = new StreamReader(dataStream)) + { + // Store the data to return + data = reader.ReadToEnd(); + + // Close the reader + reader.Close(); + } + + // Close the datastream + dataStream.Close(); + } + } + + // Close the response + response.Close(); + } + + // Return the data + return data; + } + catch (WebException ex) + { + log.Error(String.Format("The request to {0} failed.", address), ex); + } + return string.Empty; + } } } diff --git a/Tools/ArdupilotMegaPlanner/Utilities/ParameterMetaDataRepository.cs b/Tools/ArdupilotMegaPlanner/Utilities/ParameterMetaDataRepository.cs index 0697a76c07..738e684880 100644 --- a/Tools/ArdupilotMegaPlanner/Utilities/ParameterMetaDataRepository.cs +++ b/Tools/ArdupilotMegaPlanner/Utilities/ParameterMetaDataRepository.cs @@ -3,6 +3,7 @@ using System.Configuration; using System.IO; using System.Windows.Forms; using System.Xml.Linq; +using System.Linq; namespace ArdupilotMega.Utilities { @@ -32,7 +33,19 @@ namespace ArdupilotMega.Utilities { // Use this to find the endpoint node we are looking for // Either it will be pulled from a file in the ArduPlane hierarchy or the ArduCopter hierarchy - string endpointSearchString = (MainV2.cs.firmware == MainV2.Firmwares.ArduPlane) ? "arduplane" : "arducopter"; + var element = _parameterMetaDataXML.Element(MainV2.cs.firmware.ToString()); + if(element != null && element.HasElements) + { + var node = element.Element(nodeKey); + if(node != null && node.HasElements) + { + var metaValue = node.Element(metaKey); + if(metaValue != null) + { + return metaValue.Value; + } + } + } } return string.Empty; } diff --git a/Tools/ArdupilotMegaPlanner/app.config b/Tools/ArdupilotMegaPlanner/app.config index 063dfdef78..9bb4229ef3 100644 --- a/Tools/ArdupilotMegaPlanner/app.config +++ b/Tools/ArdupilotMegaPlanner/app.config @@ -8,6 +8,10 @@ + + diff --git a/Tools/ArdupilotMegaPlanner/bin/Release/ArduCopterConfig.xml b/Tools/ArdupilotMegaPlanner/bin/Release/ArduCopterConfig.xml index 2558e46e2c..fda38f6780 100644 --- a/Tools/ArdupilotMegaPlanner/bin/Release/ArduCopterConfig.xml +++ b/Tools/ArdupilotMegaPlanner/bin/Release/ArduCopterConfig.xml @@ -101,6 +101,70 @@ Too high = slow wobbles 0.001 + + Yaw Angular Rate Control: + How much throttle is applied to rotate the copter at the desired speed. + + + + P + RATE_YAW_P + 0.001 + 5 + 0.001 + + + I + RATE_YAW_I + 0 + 5 + 0.001 + + + D + RATE_YAW_D + 0 + 5 + 0.001 + + + IMAX + RATE_YAW_IMAX + 0 + 50 + 1 + + + + Yaw Stabilize Control: + + How fast the copter reacts to user or autopilot input. + Higher = more aggressive control. + Too high = slow wobbles + + + + P + STB_YAW_P + 0.001 + 10 + 0.001 + + + I + STB_YAW_I + 0 + 5 + 0.001 + + + IMAX + STB_YAW_IMAX + 0 + 50 + 1 + + @@ -140,7 +204,7 @@ How much angle is applied to make the copter accelerate to the desired speed. LOITER_LON_IMAX 0 50 - 0.1 + 1 Loiter Speed: diff --git a/Tools/ArdupilotMegaPlanner/bin/Release/version.txt b/Tools/ArdupilotMegaPlanner/bin/Release/version.txt index cf279dbac7..b68b098b7a 100644 --- a/Tools/ArdupilotMegaPlanner/bin/Release/version.txt +++ b/Tools/ArdupilotMegaPlanner/bin/Release/version.txt @@ -1 +1 @@ -1.1.4498.32482 \ No newline at end of file +1.1.4499.14296 \ No newline at end of file