diff --git a/Tools/ArdupilotMegaPlanner/ArdupilotMega.csproj b/Tools/ArdupilotMegaPlanner/ArdupilotMega.csproj
index 1e1da846984a0deb0a6269dfe253cacf53019a27..b59c4d3ae9ec3e5d8b2bed08d3335bd05039bdb9 100644
--- a/Tools/ArdupilotMegaPlanner/ArdupilotMega.csproj
+++ b/Tools/ArdupilotMegaPlanner/ArdupilotMega.csproj
@@ -226,7 +226,8 @@
     <Compile Include="Attributes\DisplayTextAttribute.cs" />
     <Compile Include="Attributes\PrivateAttribute.cs" />
     <Compile Include="CodeGen.cs" />
-    <Compile Include="Constants\ParameterMetaDataConstants.cs" />
+    <Compile Include="Utilities\CollectionExtensions.cs" />
+    <Compile Include="Utilities\Constants\ParameterMetaDataConstants.cs" />
     <Compile Include="Controls\BackstageView\BackstageView.cs">
       <SubType>UserControl</SubType>
     </Compile>
diff --git a/Tools/ArdupilotMegaPlanner/Constants/ParameterMetaDataConstants.cs b/Tools/ArdupilotMegaPlanner/Constants/ParameterMetaDataConstants.cs
deleted file mode 100644
index 73a226920b9d22142c11a136f3cc30910e3a57cb..0000000000000000000000000000000000000000
--- a/Tools/ArdupilotMegaPlanner/Constants/ParameterMetaDataConstants.cs
+++ /dev/null
@@ -1,12 +0,0 @@
-namespace ArdupilotMega.Constants
-{
-   public sealed class ParameterMetaDataConstants
-   {
-      public const string Delimeter = "@";
-      public const string Param = "Param";
-      public const string DisplayName = "DisplayName";
-      public const string Description = "Description";
-      public const string Units = "Units";
-      public const string Range = "Range";
-   }
-}
diff --git a/Tools/ArdupilotMegaPlanner/GCSViews/ConfigurationView/ConfigRawParams.cs b/Tools/ArdupilotMegaPlanner/GCSViews/ConfigurationView/ConfigRawParams.cs
index 2ee33bf48ac4c85c03387a3e49ab1591135799ab..e49bf42a85da52f2e6959b72f3c6abc85500ea5d 100644
--- a/Tools/ArdupilotMegaPlanner/GCSViews/ConfigurationView/ConfigRawParams.cs
+++ b/Tools/ArdupilotMegaPlanner/GCSViews/ConfigurationView/ConfigRawParams.cs
@@ -1,20 +1,14 @@
 using System;
 using System.Collections;
-using System.Collections.Generic;
 using System.ComponentModel;
-using System.Configuration;
 using System.Drawing;
-using System.Data;
 using System.IO;
-using System.Linq;
 using System.Text;
-using System.Xml.Linq;
 using System.Windows.Forms;
-using ArdupilotMega.Constants;
 using ArdupilotMega.Utilities;
+using ArdupilotMega.Utilities.Constants;
 using log4net;
 using ArdupilotMega.Controls.BackstageView;
-using ArdupilotMega.Controls;
 
 namespace ArdupilotMega.GCSViews.ConfigurationView
 {
diff --git a/Tools/ArdupilotMegaPlanner/Utilities/CollectionExtensions.cs b/Tools/ArdupilotMegaPlanner/Utilities/CollectionExtensions.cs
new file mode 100644
index 0000000000000000000000000000000000000000..6b435af4025aabf2f92bf0bf975914ca637f78f5
--- /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
+   {
+      /// <summary>
+      /// Performs the specified <paramref name="action"/> on each element of the <paramref name="enumerable"/>.
+      /// 
+      /// </summary>
+      /// <param name="enumerable">An enumerable instance.
+      ///             </param><param name="action"/>
+      public static void ForEach(this IEnumerable enumerable, Action<object> action)
+      {
+         foreach (object obj in enumerable)
+            action(obj);
+      }
+
+      /// <summary>
+      /// Performs the specified <paramref name="action"/> on each element of the <paramref name="enumerable"/>.
+      /// 
+      /// </summary>
+      /// <param name="enumerable">An enumerable instance.
+      ///             </param><param name="action"/>
+      public static void ForEach<T>(this IEnumerable enumerable, Action<T> action)
+      {
+         foreach (T obj in enumerable)
+            action(obj);
+      }
+
+      /// <summary>
+      /// Performs the specified <paramref name="action"/> on each element of the <paramref name="enumerable"/>.
+      /// 
+      /// </summary>
+      /// <typeparam name="T">The type contained in the <paramref name="enumerable"/>.
+      ///             </typeparam><param name="enumerable"/><param name="action"/>
+      public static void ForEach<T>(this IEnumerable<T> enumerable, Action<T> action)
+      {
+         foreach (T obj in enumerable)
+            action(obj);
+      }
+   }
+}
diff --git a/Tools/ArdupilotMegaPlanner/Utilities/Constants/ParameterMetaDataConstants.cs b/Tools/ArdupilotMegaPlanner/Utilities/Constants/ParameterMetaDataConstants.cs
new file mode 100644
index 0000000000000000000000000000000000000000..b8764f9a737d2d170fab3d31f90f0d6eccfc5a0f
--- /dev/null
+++ b/Tools/ArdupilotMegaPlanner/Utilities/Constants/ParameterMetaDataConstants.cs
@@ -0,0 +1,24 @@
+namespace ArdupilotMega.Utilities.Constants
+{
+   public sealed class ParameterMetaDataConstants
+   {
+      #region Markers
+
+      public const string ParamDelimeter = "@";
+      public const string PathDelimeter = ",";
+      public const string Param = "Param";
+      public const string Lib = "Lib";
+      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
+   }
+}
diff --git a/Tools/ArdupilotMegaPlanner/Utilities/ParameterMetaDataParser.cs b/Tools/ArdupilotMegaPlanner/Utilities/ParameterMetaDataParser.cs
index a737da4f5397ca983ab3ca956e5c5bd627f99771..1d6882537163edad19e94dd92d1771dc3f585d1b 100644
--- a/Tools/ArdupilotMegaPlanner/Utilities/ParameterMetaDataParser.cs
+++ b/Tools/ArdupilotMegaPlanner/Utilities/ParameterMetaDataParser.cs
@@ -7,14 +7,15 @@ using System.Net;
 using System.Text.RegularExpressions;
 using System.Windows.Forms;
 using System.Xml;
-using ArdupilotMega.Constants;
+using ArdupilotMega.Utilities.Constants;
 using log4net;
 
 namespace ArdupilotMega.Utilities
 {
    public static class ParameterMetaDataParser
    {
-      private static readonly Regex _paramMetaRegex = new Regex(String.Format("{0}(?<MetaKey>[^:]+):(?<MetaValue>.+)", ParameterMetaDataConstants.Delimeter));
+      private static readonly Regex _paramMetaRegex = new Regex(String.Format("{0}(?<MetaKey>[^:]+):(?<MetaValue>.+)", ParameterMetaDataConstants.ParamDelimeter));
+      private static readonly Regex _parentDirectoryRegex = new Regex("(?<ParentDirectory>[../]*)(?<Path>.+)");
       private static readonly ILog log =
          LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
 
@@ -35,59 +36,85 @@ namespace ArdupilotMega.Utilities
 
                foreach (string parameterLocation in parameterLocations)
                {
-                  log.Info(parameterLocation);
+                  // Write the start element for this parameter location
+                  objXmlTextWriter.WriteStartElement(parameterLocation);
 
-                  var request = WebRequest.Create(parameterLocation);
+                  // Read and parse the content.
+                  string dataFromAddress = ReadDataFromAddress(parameterLocation);
+                  ParseLibInformation(dataFromAddress, objXmlTextWriter, parameterLocation);
+                  ParseParameterInformation(dataFromAddress, objXmlTextWriter);
 
-                  // Plenty of timeout
-                  request.Timeout = 10000;
+                  // Write the end element for this parameter location
+                  objXmlTextWriter.WriteEndElement();
 
-                  // 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);
+               }
+               
+               // Clear the stream
+               objXmlTextWriter.WriteEndDocument();
+               objXmlTextWriter.Flush();
+               objXmlTextWriter.Close();
+            }
+         }
+      }
 
-                     // Get the stream containing content returned by the server.
-                     using (var dataStream = response.GetResponseStream())
-                     {
-                        if (dataStream != null)
+      /// <summary>
+      /// Parses the lib information.
+      /// </summary>
+      /// <param name="fileContents">The file contents.</param>
+      /// <param name="objXmlTextWriter">The obj XML text writer.</param>
+      /// <param name="parameterLocation">The parameter location.</param>
+      private static void ParseLibInformation(string fileContents, XmlTextWriter objXmlTextWriter, string parameterLocation)
+      {
+         var parsedInformation = ParseKeyValuePairs(fileContents, ParameterMetaDataConstants.Lib);
+         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 =>
                         {
-                           // Open the stream using a StreamReader for easy access.
-                           using (var reader = new StreamReader(dataStream))
+                           // 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))
                            {
-                              // Write the start element for this parameter location
-                              objXmlTextWriter.WriteStartElement(parameterLocation);
+                              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();
 
-                              // Read and parse the content.
-                              ParseParameterInformation(reader.ReadToEnd(), objXmlTextWriter);
+                                 // 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;
 
-                              // Write the end element for this parameter location
-                              objXmlTextWriter.WriteEndElement();
+                                 // Get the parts of the original URL
+                                 var parameterLocationParts = parameterLocation.Substring(trimHttpPrefixIdx, parameterLocation.Length - trimHttpPrefixIdx).Split(new char[] { '/' });
 
-                              // Close the reader
-                              reader.Close();
-                           }
+                                 // 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] + "/";
+                                 }
 
-                           // Close the datastream
-                           dataStream.Close();
-                        }
-                     }
-
-                     // Close the response
-                     response.Close();
-                  }
+                                 // 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);
+                              }
+                           }                                         
+                        }));
                }
-               
-               // Clear the stream
-               objXmlTextWriter.WriteEndDocument();
-               objXmlTextWriter.Flush();
-               objXmlTextWriter.Close();
-            }
+            });
          }
       }
 
@@ -98,8 +125,50 @@ namespace ArdupilotMega.Utilities
       /// <param name="objXmlTextWriter">The obj XML text writer.</param>
       private static void ParseParameterInformation(string fileContents, XmlTextWriter objXmlTextWriter)
       {
+         ParseParameterInformation(fileContents, objXmlTextWriter, string.Empty);
+      }
+
+      /// <summary>
+      /// Parses the parameter information.
+      /// </summary>
+      /// <param name="fileContents">The file contents.</param>
+      /// <param name="objXmlTextWriter">The obj XML text writer.</param>
+      /// <param name="parameterPrefix">The parameter prefix.</param>
+      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();
+            });
+         }
+      }
+
+      /// <summary>
+      /// Parses the parameter information.
+      /// </summary>
+      /// <param name="fileContents">The file contents.</param>
+      /// <param name="nodeKey">The node key.</param>
+      /// <returns></returns>
+      private static Dictionary<string, Dictionary<string, string>> ParseKeyValuePairs(string fileContents, string nodeKey)
+      {
+         var returnDict = new Dictionary<string, Dictionary<string, string>>();
+
          var indicies = new List<int>();
-         GetIndexOfMarkers(ref indicies, fileContents, ParameterMetaDataConstants.Delimeter + ParameterMetaDataConstants.Param, 0);
+         GetIndexOfMarkers(ref indicies, fileContents, ParameterMetaDataConstants.ParamDelimeter + nodeKey, 0);
 
          if(indicies.Count > 0)
          {
@@ -114,7 +183,7 @@ namespace ArdupilotMega.Utilities
                if(!String.IsNullOrEmpty(subStringToSearch))
                {
                   var metaIndicies = new List<int>();
-                  GetIndexOfMarkers(ref metaIndicies, subStringToSearch, ParameterMetaDataConstants.Delimeter, 0);
+                  GetIndexOfMarkers(ref metaIndicies, subStringToSearch, ParameterMetaDataConstants.ParamDelimeter, 0);
 
                   if(metaIndicies.Count > 0)
                   {
@@ -124,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<string, string>();
+                        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];
+                           // Loop through the indicies of the meta data found
+                           for (int x = 1; x < metaIndicies.Count; x++)
+                           {
+                              // 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]));
+                              // 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);
+                              // Match based on the regex defined at the top of this class
+                              Match metaMatch = _paramMetaRegex.Match(metaString);
 
-                           // Test for success
-                           if (metaMatch.Success)
-                           {
-                              // 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();
+                              // 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;
       }
 
       /// <summary>
@@ -189,5 +261,58 @@ namespace ArdupilotMega.Utilities
             }
          }
       }
+
+      /// <summary>
+      /// Reads the data from address.
+      /// </summary>
+      /// <param name="address">The address.</param>
+      /// <returns></returns>
+      private static string ReadDataFromAddress(string address)
+      {
+         string data = string.Empty;
+
+         log.Info(address);
+
+         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;
+      }
    }
 }