From 0087d0533a0ea10ffddd3a38805aa18a5717ca0f Mon Sep 17 00:00:00 2001 From: Michael Oborne Date: Sat, 3 Mar 2012 15:42:41 +0800 Subject: [PATCH 001/178] APM Planner 1.1.47 fix Updater --- .../ArdupilotMegaPlanner/ArdupilotMega.csproj | 6 +- Tools/ArdupilotMegaPlanner/MagCalib.cs | 131 ++++++++------- Tools/ArdupilotMegaPlanner/MainV2.cs | 149 ++++++++++-------- .../MavlinkLog.Designer.cs | 10 ++ Tools/ArdupilotMegaPlanner/MavlinkLog.cs | 83 ++++++++++ Tools/ArdupilotMegaPlanner/MavlinkLog.resx | 39 ++++- Tools/ArdupilotMegaPlanner/Program.cs | 11 +- .../Properties/AssemblyInfo.cs | 2 +- Tools/ArdupilotMegaPlanner/Script.cs | 28 +++- Tools/ArdupilotMegaPlanner/Updater/Program.cs | 16 +- Tools/ArdupilotMegaPlanner/app.config | 2 +- .../bin/Release/.gitignore | 3 +- .../Release/ArdupilotMegaPlanner.exe.config | 2 +- .../bin/Release/ArdupilotMegaPlanner.pdb | Bin 972288 -> 974336 bytes 14 files changed, 331 insertions(+), 151 deletions(-) diff --git a/Tools/ArdupilotMegaPlanner/ArdupilotMega.csproj b/Tools/ArdupilotMegaPlanner/ArdupilotMega.csproj index c76303df54..f14a442d90 100644 --- a/Tools/ArdupilotMegaPlanner/ArdupilotMega.csproj +++ b/Tools/ArdupilotMegaPlanner/ArdupilotMega.csproj @@ -86,7 +86,7 @@ false - true + false @@ -118,6 +118,10 @@ Properties\app.manifest + + False + Lib\alglibnet2.dll + ..\..\..\..\..\Desktop\DIYDrones\myquad\greatmaps_e1bb830a18a3\Demo.WindowsForms\bin\Debug\BSE.Windows.Forms.dll diff --git a/Tools/ArdupilotMegaPlanner/MagCalib.cs b/Tools/ArdupilotMegaPlanner/MagCalib.cs index 5edd807b18..3db2921682 100644 --- a/Tools/ArdupilotMegaPlanner/MagCalib.cs +++ b/Tools/ArdupilotMegaPlanner/MagCalib.cs @@ -4,6 +4,7 @@ using System.Linq; using System.Text; using System.Windows.Forms; using System.IO; +using System.Collections; namespace ArdupilotMega { @@ -14,34 +15,12 @@ namespace ArdupilotMega public static void doWork() { - /* - double[,] x = new double[,] { { -1 }, { -0.8 }, { -0.6 }, { -0.4 }, { -0.2 }, { 0 }, { 0.2 }, { 0.4 }, { 0.6 }, { 0.8 }, { 1.0 } }; - double[] y = new double[] { 0.223130, 0.382893, 0.582748, 0.786628, 0.941765, 1.000000, 0.941765, 0.786628, 0.582748, 0.382893, 0.223130 }; - double[] c = new double[] { 0.3 }; - double epsf = 0; - double epsx = 0.000001; - int maxits = 0; - int info; - alglib.lsfitstate state; - alglib.lsfitreport rep; - double diffstep = 0.0001; - - // - // Fitting without weights - // - alglib.lsfitcreatef(x, y, c, diffstep, out state); - alglib.lsfitsetcond(state, epsf, epsx, maxits); - alglib.lsfitfit(state, function_cx_1_func, null, null); - alglib.lsfitresults(state, out info, out c, out rep); - System.Console.WriteLine("{0}", info); // EXPECTED: 2 - System.Console.WriteLine("{0}", alglib.ap.format(c, 1)); // EXPECTED: [1.5] - */ - // based of tridge's work Tuple offset = new Tuple(0, 0, 0); List> data = new List>(); + Hashtable filter = new Hashtable(); OpenFileDialog openFileDialog1 = new OpenFileDialog(); openFileDialog1.Filter = "*.tlog|*.tlog"; @@ -54,6 +33,8 @@ namespace ArdupilotMega } catch { } // incase dir doesnt exist + openFileDialog1.FileName = @"C:\Users\hog\Downloads\2012-02-05.log"; + if (openFileDialog1.ShowDialog() == DialogResult.OK) { foreach (string logfile in openFileDialog1.FileNames) @@ -74,65 +55,97 @@ namespace ArdupilotMega //progressBar1.Refresh(); //Application.DoEvents(); - byte[] packet = mine.readPacket(); + byte[] packetraw = mine.readPacket(); - var pack = mine.DebugPacket(packet); + var packet = mine.DebugPacket(packetraw); - if (pack.GetType() == typeof(MAVLink.__mavlink_sensor_offsets_t)) + if (packet == null) + continue; + + if (packet.GetType() == typeof(MAVLink.__mavlink_sensor_offsets_t)) { offset = new Tuple( - ((MAVLink.__mavlink_sensor_offsets_t)pack).mag_ofs_x, - ((MAVLink.__mavlink_sensor_offsets_t)pack).mag_ofs_y, - ((MAVLink.__mavlink_sensor_offsets_t)pack).mag_ofs_z); + ((MAVLink.__mavlink_sensor_offsets_t)packet).mag_ofs_x, + ((MAVLink.__mavlink_sensor_offsets_t)packet).mag_ofs_y, + ((MAVLink.__mavlink_sensor_offsets_t)packet).mag_ofs_z); } - else if (pack.GetType() == typeof(MAVLink.__mavlink_raw_imu_t)) + else if (packet.GetType() == typeof(MAVLink.__mavlink_raw_imu_t)) { + int div = 20; + + string item = (int)(((MAVLink.__mavlink_raw_imu_t)packet).xmag / div) + "," + + (int)(((MAVLink.__mavlink_raw_imu_t)packet).ymag / div) + "," + + (int)(((MAVLink.__mavlink_raw_imu_t)packet).zmag / div); + + if (filter.ContainsKey(item)) + { + filter[item] = (int)filter[item] + 1; + + if ((int)filter[item] > 3) + continue; + } + else + { + filter[item] = 1; + } + + data.Add(new Tuple( - ((MAVLink.__mavlink_raw_imu_t)pack).xmag - offset.Item1, - ((MAVLink.__mavlink_raw_imu_t)pack).ymag - offset.Item2, - ((MAVLink.__mavlink_raw_imu_t)pack).zmag - offset.Item3)); + ((MAVLink.__mavlink_raw_imu_t)packet).xmag - offset.Item1, + ((MAVLink.__mavlink_raw_imu_t)packet).ymag - offset.Item2, + ((MAVLink.__mavlink_raw_imu_t)packet).zmag - offset.Item3)); } } - - - - - - //progressBar1.Value = 100; + Console.WriteLine("Extracted " + data.Count + " data points"); + Console.WriteLine("Current offset: " + offset); mine.logreadmode = false; mine.logplaybackfile.Close(); mine.logplaybackfile = null; + double[] x = new double[] { 0, 0, 0, 0 }; + double epsg = 0.0000000001; + double epsf = 0; + double epsx = 0; + int maxits = 0; + alglib.minlmstate state; + alglib.minlmreport rep; + + alglib.minlmcreatev(data.Count, x, 100, out state); + alglib.minlmsetcond(state, epsg, epsf, epsx, maxits); + alglib.minlmoptimize(state, sphere_error, null, data); + alglib.minlmresults(state, out x, out rep); + + System.Console.WriteLine("{0}", rep.terminationtype); // EXPECTED: 4 + System.Console.WriteLine("{0}", alglib.ap.format(x, 2)); // EXPECTED: [-3,+3] + //System.Console.ReadLine(); + + + // return; + + } } } - public static List sphere_error(double[,] p, double[] data) + public static void sphere_error(double[] xi, double[] fi, object obj) { - double xofs = p[0, 0]; - double yofs = p[0, 1]; - double zofs = p[0, 2]; - double r = p[0, 3]; - List ret = new List(); - foreach (var d in data) + double xofs = xi[0]; + double yofs = xi[1]; + double zofs = xi[2]; + double r = xi[3]; + int a = 0; + foreach (var d in (List>)obj) { - //double x, y, z = d; - //double err = r - Math.Sqrt(Math.Pow((x + xofs), 2) + Math.Pow((y + yofs), 2) + Math.Pow((z + zofs), 2)); - //ret.Add(err); + double x = d.Item1; + double y = d.Item2; + double z = d.Item3; + double err = r - Math.Sqrt(Math.Pow((x + xofs), 2) + Math.Pow((y + yofs), 2) + Math.Pow((z + zofs), 2)); + fi[a] = err; + a++; } - return ret; } - - public static void function_cx_1_func(double[] c, double[] x, ref double func, object obj) - { - // this callback calculates f(c,x)=exp(-c0*sqr(x0)) - // where x is a position on X-axis and c is adjustable parameter - func = System.Math.Exp(-c[0] * x[0] * x[0]); - } - - } } \ No newline at end of file diff --git a/Tools/ArdupilotMegaPlanner/MainV2.cs b/Tools/ArdupilotMegaPlanner/MainV2.cs index 3ab2c80f11..4e66490df6 100644 --- a/Tools/ArdupilotMegaPlanner/MainV2.cs +++ b/Tools/ArdupilotMegaPlanner/MainV2.cs @@ -22,6 +22,7 @@ using System.Threading; using System.Net.Sockets; using IronPython.Hosting; using log4net; +using ArdupilotMega.Controls; namespace ArdupilotMega { @@ -1629,12 +1630,12 @@ namespace ArdupilotMega } - public static void updatecheck(Label loadinglabel) + public static void updatecheck(ProgressReporterDialogue frmProgressReporter) { var baseurl = ConfigurationManager.AppSettings["UpdateLocation"]; try { - bool update = updatecheck(loadinglabel, baseurl, ""); + bool update = updatecheck(frmProgressReporter, baseurl, ""); var process = new Process(); string exePath = Path.GetDirectoryName(Application.ExecutablePath); if (MONO) @@ -1659,17 +1660,20 @@ namespace ArdupilotMega log.Error("Exception during update", ex); } } - if (loadinglabel != null) - UpdateLabel(loadinglabel, "Starting Updater"); + if (frmProgressReporter != null) + frmProgressReporter.UpdateProgressAndStatus(-1, "Starting Updater"); log.Info("Starting new process: " + process.StartInfo.FileName + " with " + process.StartInfo.Arguments); process.Start(); log.Info("Quitting existing process"); try { - Application.Exit(); + MainV2.instance.BeginInvoke((MethodInvoker)delegate() { + Application.Exit(); + }); } catch { + Application.Exit(); } } catch (Exception ex) @@ -1719,10 +1723,25 @@ namespace ArdupilotMega { var fi = new FileInfo(path); - log.Info(response.Headers[HttpResponseHeader.ETag]); + string CurrentEtag = ""; - if (fi.Length != response.ContentLength) // && response.Headers[HttpResponseHeader.ETag] != "0") + if (File.Exists(path + ".etag")) { + using (Stream fs = File.OpenRead(path + ".etag")) + { + using (StreamReader sr = new StreamReader(fs)) + { + CurrentEtag = sr.ReadLine(); + sr.Close(); + } + fs.Close(); + } + } + + if (fi.Length != response.ContentLength && response.Headers[HttpResponseHeader.ETag] != CurrentEtag) + { + log.Debug("New file Check: " + fi.Length + " vs " + response.ContentLength + " " + response.Headers[HttpResponseHeader.ETag] + " vs " + CurrentEtag); + using (var sw = new StreamWriter(path + ".etag")) { sw.WriteLine(response.Headers[HttpResponseHeader.ETag]); @@ -1757,46 +1776,28 @@ namespace ArdupilotMega public static void DoUpdate() { - var loading = new Form + ProgressReporterDialogue frmProgressReporter = new ProgressReporterDialogue() { - - Width = 400, - Height = 150, - StartPosition = FormStartPosition.CenterScreen, - TopMost = true, - MinimizeBox = false, - MaximizeBox = false + Text = "Check for Updates", + StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen }; - var resources = new ComponentResourceManager(typeof(MainV2)); - loading.Icon = ((Icon)(resources.GetObject("$this.Icon"))); - var loadinglabel = new Label - { - Location = new System.Drawing.Point(50, 40), - Name = "load", - AutoSize = true, - Text = "Checking...", - Size = new System.Drawing.Size(100, 20) - }; + MainV2.fixtheme(frmProgressReporter); - loading.Controls.Add(loadinglabel); - loading.Show(); + frmProgressReporter.DoWork += new Controls.ProgressReporterDialogue.DoWorkEventHandler(frmProgressReporter_DoWork); - try - { - MainV2.updatecheck(loadinglabel); - } - catch (Exception ex) - { - log.Error("Error in updatecheck", ex); - } - //); - //t12.Name = "Update check thread"; - //t12.Start(); - //MainV2.threads.Add(t12); + frmProgressReporter.UpdateProgressAndStatus(-1, "Checking for Updates"); + + frmProgressReporter.RunBackgroundOperationAsync(); } - private static bool updatecheck(Label loadinglabel, string baseurl, string subdir) + static void frmProgressReporter_DoWork(object sender, Controls.ProgressWorkerEventArgs e) + { + ((ProgressReporterDialogue)sender).UpdateProgressAndStatus(-1, "Getting Base URL"); + MainV2.updatecheck((ProgressReporterDialogue)sender); + } + + private static bool updatecheck(ProgressReporterDialogue frmProgressReporter, string baseurl, string subdir) { bool update = false; List files = new List(); @@ -1845,17 +1846,23 @@ namespace ArdupilotMega Directory.CreateDirectory(dir); foreach (string file in files) { + if (frmProgressReporter.doWorkArgs.CancelRequested) + { + frmProgressReporter.doWorkArgs.CancelAcknowledged = true; + throw new Exception("Cancel"); + } + if (file.Equals("/")) { continue; } if (file.EndsWith("/")) { - update = updatecheck(loadinglabel, baseurl + file, subdir.Replace('/', Path.DirectorySeparatorChar) + file) && update; + update = updatecheck(frmProgressReporter, baseurl + file, subdir.Replace('/', Path.DirectorySeparatorChar) + file) && update; continue; } - if (loadinglabel != null) - UpdateLabel(loadinglabel, "Checking " + file); + if (frmProgressReporter != null) + frmProgressReporter.UpdateProgressAndStatus(-1, "Checking " + file); string path = Path.GetDirectoryName(Application.ExecutablePath) + Path.DirectorySeparatorChar + subdir + file; @@ -1876,26 +1883,44 @@ namespace ArdupilotMega //dataStream = response.GetResponseStream(); // Open the stream using a StreamReader for easy access. - bool getfile = false; + bool updateThisFile = false; if (File.Exists(path)) { FileInfo fi = new FileInfo(path); - log.Info(response.Headers[HttpResponseHeader.ETag]); + //log.Info(response.Headers[HttpResponseHeader.ETag]); + string CurrentEtag = ""; - if (fi.Length != response.ContentLength) // && response.Headers[HttpResponseHeader.ETag] != "0") + if (File.Exists(path + ".etag")) { - StreamWriter sw = new StreamWriter(path + ".etag"); - sw.WriteLine(response.Headers[HttpResponseHeader.ETag]); - sw.Close(); - getfile = true; + using (Stream fs = File.OpenRead(path + ".etag")) + { + using (StreamReader sr = new StreamReader(fs)) + { + CurrentEtag = sr.ReadLine(); + sr.Close(); + } + fs.Close(); + } + } + + if (fi.Length != response.ContentLength && response.Headers[HttpResponseHeader.ETag] != CurrentEtag) + { + log.Debug("New file Check: " + fi.Length + " vs " + response.ContentLength + " " + response.Headers[HttpResponseHeader.ETag] + " vs " + CurrentEtag); + + using (StreamWriter sw = new StreamWriter(path + ".etag")) + { + sw.WriteLine(response.Headers[HttpResponseHeader.ETag]); + sw.Close(); + } + updateThisFile = true; log.Info("NEW FILE " + file); } } else { - getfile = true; + updateThisFile = true; log.Info("NEW FILE " + file); // get it } @@ -1904,7 +1929,7 @@ namespace ArdupilotMega //dataStream.Close(); response.Close(); - if (getfile) + if (updateThisFile) { if (!update) { @@ -1918,16 +1943,21 @@ namespace ArdupilotMega // return; } } - if (loadinglabel != null) - UpdateLabel(loadinglabel, "Getting " + file); + if (frmProgressReporter != null) + frmProgressReporter.UpdateProgressAndStatus(-1, "Getting " + file); // from head long bytes = response.ContentLength; // Create a request using a URL that can receive a post. - request = WebRequest.Create(baseurl + file); + request = HttpWebRequest.Create(baseurl + file); // Set the Method property of the request to POST. request.Method = "GET"; + + ((HttpWebRequest)request).AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate; + + request.Headers.Add("Accept-Encoding", "gzip,deflate"); + // Get the response. response = request.GetResponse(); // Display the status. @@ -1951,8 +1981,8 @@ namespace ArdupilotMega { if (dt.Second != DateTime.Now.Second) { - if (loadinglabel != null) - UpdateLabel(loadinglabel, "Getting " + file + ": " + (((double)(contlen - bytes) / (double)contlen) * 100).ToString("0.0") + "%"); //+ Math.Abs(bytes) + " bytes"); + if (frmProgressReporter != null) + frmProgressReporter.UpdateProgressAndStatus((int)(((double)(contlen - bytes) / (double)contlen) * 100), "Getting " + file + ": " + (((double)(contlen - bytes) / (double)contlen) * 100).ToString("0.0") + "%"); //+ Math.Abs(bytes) + " bytes"); dt = DateTime.Now; } } @@ -1978,11 +2008,6 @@ namespace ArdupilotMega return update; - } - - private void toolStripMenuItem3_Click(object sender, EventArgs e) - { - } protected override bool ProcessCmdKey(ref Message msg, Keys keyData) diff --git a/Tools/ArdupilotMegaPlanner/MavlinkLog.Designer.cs b/Tools/ArdupilotMegaPlanner/MavlinkLog.Designer.cs index 29e1be3f92..38356beb49 100644 --- a/Tools/ArdupilotMegaPlanner/MavlinkLog.Designer.cs +++ b/Tools/ArdupilotMegaPlanner/MavlinkLog.Designer.cs @@ -32,6 +32,7 @@ this.BUT_redokml = new ArdupilotMega.MyButton(); this.progressBar1 = new System.Windows.Forms.ProgressBar(); this.BUT_humanreadable = new ArdupilotMega.MyButton(); + this.BUT_graphmavlog = new ArdupilotMega.MyButton(); this.SuspendLayout(); // // BUT_redokml @@ -53,10 +54,18 @@ this.BUT_humanreadable.UseVisualStyleBackColor = true; this.BUT_humanreadable.Click += new System.EventHandler(this.BUT_humanreadable_Click); // + // BUT_graphmavlog + // + resources.ApplyResources(this.BUT_graphmavlog, "BUT_graphmavlog"); + this.BUT_graphmavlog.Name = "BUT_graphmavlog"; + this.BUT_graphmavlog.UseVisualStyleBackColor = true; + this.BUT_graphmavlog.Click += new System.EventHandler(this.BUT_graphmavlog_Click); + // // MavlinkLog // resources.ApplyResources(this, "$this"); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.Controls.Add(this.BUT_graphmavlog); this.Controls.Add(this.BUT_humanreadable); this.Controls.Add(this.progressBar1); this.Controls.Add(this.BUT_redokml); @@ -71,5 +80,6 @@ private MyButton BUT_redokml; private System.Windows.Forms.ProgressBar progressBar1; private MyButton BUT_humanreadable; + private MyButton BUT_graphmavlog; } } \ No newline at end of file diff --git a/Tools/ArdupilotMegaPlanner/MavlinkLog.cs b/Tools/ArdupilotMegaPlanner/MavlinkLog.cs index 21963759d9..381a0a0463 100644 --- a/Tools/ArdupilotMegaPlanner/MavlinkLog.cs +++ b/Tools/ArdupilotMegaPlanner/MavlinkLog.cs @@ -512,5 +512,88 @@ namespace ArdupilotMega } } + private void BUT_graphmavlog_Click(object sender, EventArgs e) + { + OpenFileDialog openFileDialog1 = new OpenFileDialog(); + openFileDialog1.Filter = "*.tlog|*.tlog"; + openFileDialog1.FilterIndex = 2; + openFileDialog1.RestoreDirectory = true; + openFileDialog1.Multiselect = true; + try + { + openFileDialog1.InitialDirectory = Path.GetDirectoryName(Application.ExecutablePath) + Path.DirectorySeparatorChar + @"logs" + Path.DirectorySeparatorChar; + } + catch { } // incase dir doesnt exist + + if (openFileDialog1.ShowDialog() == DialogResult.OK) + { + foreach (string logfile in openFileDialog1.FileNames) + { + + MAVLink mine = new MAVLink(); + mine.logplaybackfile = new BinaryReader(File.Open(logfile, FileMode.Open, FileAccess.Read, FileShare.Read)); + mine.logreadmode = true; + + mine.packets.Initialize(); // clear + + CurrentState cs = new CurrentState(); + + float oldlatlngalt = 0; + + DateTime appui = DateTime.Now; + + while (mine.logplaybackfile.BaseStream.Position < mine.logplaybackfile.BaseStream.Length) + { + // bar moves to 50 % in this step + progressBar1.Value = (int)((float)mine.logplaybackfile.BaseStream.Position / (float)mine.logplaybackfile.BaseStream.Length * 100.0f / 2.0f); + progressBar1.Invalidate(); + progressBar1.Refresh(); + + byte[] packet = mine.readPacket(); + + cs.datetime = mine.lastlogread; + + cs.UpdateCurrentSettings(null, true, mine); + + if (appui != DateTime.Now) + { + // cant do entire app as mixes with flightdata timer + this.Refresh(); + appui = DateTime.Now; + } + + try + { + if (MainV2.talk != null) + MainV2.talk.SpeakAsyncCancelAll(); + } + catch { } // ignore because of this Exception System.PlatformNotSupportedException: No voice installed on the system or none available with the current security setting. + + if ((float)(cs.lat + cs.lng) != oldlatlngalt + && cs.lat != 0 && cs.lng != 0) + { + Console.WriteLine(cs.lat + " " + cs.lng + " " + cs.alt + " lah " + (float)(cs.lat + cs.lng) + "!=" + oldlatlngalt); + CurrentState cs2 = (CurrentState)cs.Clone(); + + flightdata.Add(cs2); + + oldlatlngalt = (cs.lat + cs.lng); + } + } + + mine.logreadmode = false; + mine.logplaybackfile.Close(); + mine.logplaybackfile = null; + + Application.DoEvents(); + + //writeKML(logfile + ".kml"); + + progressBar1.Value = 100; + + } + } + } + } } \ No newline at end of file diff --git a/Tools/ArdupilotMegaPlanner/MavlinkLog.resx b/Tools/ArdupilotMegaPlanner/MavlinkLog.resx index 9067a963f6..7aadc69694 100644 --- a/Tools/ArdupilotMegaPlanner/MavlinkLog.resx +++ b/Tools/ArdupilotMegaPlanner/MavlinkLog.resx @@ -135,19 +135,19 @@ BUT_redokml - ArdupilotMega.MyButton, ArdupilotMegaPlanner, Version=1.0.0.0, Culture=neutral, PublicKeyToken=ff91852278f5092c + ArdupilotMega.MyButton, ArdupilotMegaPlanner, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null $this - 2 + 3 10, 42 - 313, 26 + 432, 26 9 @@ -162,7 +162,7 @@ $this - 1 + 2 @@ -184,12 +184,39 @@ BUT_humanreadable - ArdupilotMega.MyButton, ArdupilotMegaPlanner, Version=1.0.0.0, Culture=neutral, PublicKeyToken=ff91852278f5092c + ArdupilotMega.MyButton, ArdupilotMegaPlanner, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null $this + 1 + + + NoControl + + + 289, 13 + + + 116, 23 + + + 11 + + + Graph Log + + + BUT_graphmavlog + + + ArdupilotMega.MyButton, ArdupilotMegaPlanner, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + + + $this + + 0 @@ -199,7 +226,7 @@ 6, 13 - 335, 82 + 456, 82 diff --git a/Tools/ArdupilotMegaPlanner/Program.cs b/Tools/ArdupilotMegaPlanner/Program.cs index a0792ca57c..fb7e6f2e71 100644 --- a/Tools/ArdupilotMegaPlanner/Program.cs +++ b/Tools/ArdupilotMegaPlanner/Program.cs @@ -21,8 +21,11 @@ namespace ArdupilotMega [STAThread] static void Main() { - //System.Threading.Thread.CurrentThread.CurrentUICulture = new System.Globalization.CultureInfo("en-US"); - //System.Threading.Thread.CurrentThread.CurrentCulture = new System.Globalization.CultureInfo("en-US"); + + Application.EnableVisualStyles(); + XmlConfigurator.Configure(); + log.Info("******************* Logging Configured *******************"); + Application.SetCompatibleTextRenderingDefault(false); Application.ThreadException += Application_ThreadException; @@ -36,10 +39,6 @@ namespace ArdupilotMega //Common.linearRegression(); - Application.EnableVisualStyles(); - XmlConfigurator.Configure(); - log.Info("******************* Logging Configured *******************"); - Application.SetCompatibleTextRenderingDefault(false); try { Thread.CurrentThread.Name = "Base Thread"; diff --git a/Tools/ArdupilotMegaPlanner/Properties/AssemblyInfo.cs b/Tools/ArdupilotMegaPlanner/Properties/AssemblyInfo.cs index 798018a819..d6bbc81952 100644 --- a/Tools/ArdupilotMegaPlanner/Properties/AssemblyInfo.cs +++ b/Tools/ArdupilotMegaPlanner/Properties/AssemblyInfo.cs @@ -34,5 +34,5 @@ using System.Resources; // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.1.46")] +[assembly: AssemblyFileVersion("1.1.47")] [assembly: NeutralResourcesLanguageAttribute("")] diff --git a/Tools/ArdupilotMegaPlanner/Script.cs b/Tools/ArdupilotMegaPlanner/Script.cs index 617c49ef31..82b7c9346e 100644 --- a/Tools/ArdupilotMegaPlanner/Script.cs +++ b/Tools/ArdupilotMegaPlanner/Script.cs @@ -24,11 +24,12 @@ namespace ArdupilotMega if (engine != null) engine.Runtime.Shutdown(); - engine = Python.CreateEngine(options); + engine = Python.CreateEngine(options); scope = engine.CreateScope(); scope.SetVariable("cs", MainV2.cs); scope.SetVariable("Script", this); + scope.SetVariable("mavutil", this); engine.CreateScriptSourceFromString("print 'hello world from python'").Execute(scope); engine.CreateScriptSourceFromString("print cs.roll").Execute(scope); @@ -54,8 +55,22 @@ namespace ArdupilotMega } } + public object mavlink_connection(string device, int baud = 115200, int source_system = 255, + bool write = false, bool append = false, + bool robust_parsing = true, bool notimestamps = false, bool input = true) + { - public void Sleep(int ms) { + return null; + } + + public object recv_match(string condition = null, string type = null, bool blocking = false) + { + + return null; + } + + public void Sleep(int ms) + { System.Threading.Thread.Sleep(ms); } @@ -104,7 +119,8 @@ namespace ArdupilotMega public bool WaitFor(string message, int timeout) { int timein = 0; - while (!MainV2.cs.message.Contains(message)) { + while (!MainV2.cs.message.Contains(message)) + { System.Threading.Thread.Sleep(5); timein += 5; if (timein > timeout) @@ -113,8 +129,8 @@ namespace ArdupilotMega return true; } - - public bool SendRC(int channel, ushort pwm,bool sendnow) + + public bool SendRC(int channel, ushort pwm, bool sendnow) { switch (channel) { @@ -166,4 +182,4 @@ namespace ArdupilotMega return true; } } -} +} \ No newline at end of file diff --git a/Tools/ArdupilotMegaPlanner/Updater/Program.cs b/Tools/ArdupilotMegaPlanner/Updater/Program.cs index be5c260020..ef47cba3ec 100644 --- a/Tools/ArdupilotMegaPlanner/Updater/Program.cs +++ b/Tools/ArdupilotMegaPlanner/Updater/Program.cs @@ -26,16 +26,18 @@ namespace Updater string path = Path.GetDirectoryName(Application.ExecutablePath); - UpdateFiles(path); + // give 4 seconds grace + System.Threading.Thread.Sleep(5000); - //if (!UpdateFiles(path)) + //UpdateFiles(path); + + if (!UpdateFiles(path)) { - // this fails on mac - //Console.WriteLine("Update failed, please try it later."); - //Console.WriteLine("Press any key to continue."); - //Console.ReadKey(); + Console.WriteLine("Update failed, please try it later."); + Console.WriteLine("Press any key to continue."); + Console.ReadKey(); } - //else + else { try { diff --git a/Tools/ArdupilotMegaPlanner/app.config b/Tools/ArdupilotMegaPlanner/app.config index 6368d93fef..063dfdef78 100644 --- a/Tools/ArdupilotMegaPlanner/app.config +++ b/Tools/ArdupilotMegaPlanner/app.config @@ -19,7 +19,7 @@ - + diff --git a/Tools/ArdupilotMegaPlanner/bin/Release/.gitignore b/Tools/ArdupilotMegaPlanner/bin/Release/.gitignore index b09e38ab43..f792876120 100644 --- a/Tools/ArdupilotMegaPlanner/bin/Release/.gitignore +++ b/Tools/ArdupilotMegaPlanner/bin/Release/.gitignore @@ -1 +1,2 @@ -*.pdb \ No newline at end of file +*.pdb +*.etag \ No newline at end of file diff --git a/Tools/ArdupilotMegaPlanner/bin/Release/ArdupilotMegaPlanner.exe.config b/Tools/ArdupilotMegaPlanner/bin/Release/ArdupilotMegaPlanner.exe.config index 6368d93fef..063dfdef78 100644 --- a/Tools/ArdupilotMegaPlanner/bin/Release/ArdupilotMegaPlanner.exe.config +++ b/Tools/ArdupilotMegaPlanner/bin/Release/ArdupilotMegaPlanner.exe.config @@ -19,7 +19,7 @@ - + diff --git a/Tools/ArdupilotMegaPlanner/bin/Release/ArdupilotMegaPlanner.pdb b/Tools/ArdupilotMegaPlanner/bin/Release/ArdupilotMegaPlanner.pdb index 55b77aa8312582e870d5ec5997310ad613dcd35e..b5e4392f1ecc3da666804ebced2b469df070f5e0 100644 GIT binary patch delta 158586 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 z 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 delta 155293 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 U2g5-o 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 Date: Sat, 3 Mar 2012 08:14:06 -0500 Subject: [PATCH 002/178] Added support for TradHeli H1 swashplate type. Added new param heli_h1_swash_enabled. Signed-off-by: Robert Lefebvre --- ArduCopter/Parameters.h | 31 +++++++------- ArduCopter/Parameters.pde | 21 +++++----- ArduCopter/heli.pde | 88 ++++++++++++++++++++++++++++++--------- 3 files changed, 97 insertions(+), 43 deletions(-) diff --git a/ArduCopter/Parameters.h b/ArduCopter/Parameters.h index f2e6ccfe88..beb92f70b0 100644 --- a/ArduCopter/Parameters.h +++ b/ArduCopter/Parameters.h @@ -78,7 +78,8 @@ public: k_param_heli_servo_averaging, k_param_heli_servo_manual, k_param_heli_phase_angle, - k_param_heli_collective_yaw_effect, // 97 + k_param_heli_collective_yaw_effect, + k_param_heli_h1_swash_enabled, //98 #endif // 110: Telemetry control @@ -281,6 +282,7 @@ public: AP_Int8 heli_servo_manual; // 0 = normal mode, 1 = radio inputs directly control swash. required for swash set-up AP_Int16 heli_phase_angle; // 0 to 360 degrees. specifies mixing between roll and pitch for helis AP_Float heli_collective_yaw_effect; // -5.0 ~ 5.0. Feed forward control from collective to yaw. 1.0 = move rudder right 1% for every 1% of collective above the mid point + AP_Int8 heli_h1_swash_enabled; // 0 = CCPM swashplate, 1 = H1 swashplate (no servo mixing) #endif // RC channels @@ -387,20 +389,21 @@ public: auto_slew_rate (AUTO_SLEW_RATE), #if FRAME_CONFIG == HELI_FRAME - heli_servo1_pos (-60), - heli_servo2_pos (60), - heli_servo3_pos (180), - heli_roll_max (4500), - heli_pitch_max (4500), - heli_collective_min (1250), - heli_collective_max (1750), - heli_collective_mid (1500), - heli_ext_gyro_enabled (0), - heli_ext_gyro_gain (1350), - heli_servo_averaging (0), - heli_servo_manual (0), - heli_phase_angle (0), + heli_servo1_pos (-60), + heli_servo2_pos (60), + heli_servo3_pos (180), + heli_roll_max (4500), + heli_pitch_max (4500), + heli_collective_min (1250), + heli_collective_max (1750), + heli_collective_mid (1500), + heli_ext_gyro_enabled (0), + heli_ext_gyro_gain (1350), + heli_servo_averaging (0), + heli_servo_manual (0), + heli_phase_angle (0), heli_collective_yaw_effect (0), + heli_h1_swash_enabled (0), #endif rc_speed(RC_FAST_SPEED), diff --git a/ArduCopter/Parameters.pde b/ArduCopter/Parameters.pde index cfe4170285..4855031e41 100644 --- a/ArduCopter/Parameters.pde +++ b/ArduCopter/Parameters.pde @@ -76,16 +76,17 @@ static const AP_Param::Info var_info[] PROGMEM = { GGROUP(heli_servo_2, "HS2_", RC_Channel), GGROUP(heli_servo_3, "HS3_", RC_Channel), GGROUP(heli_servo_4, "HS4_", RC_Channel), - GSCALAR(heli_servo1_pos, "SV1_POS_"), - GSCALAR(heli_servo2_pos, "SV2_POS_"), - GSCALAR(heli_servo3_pos, "SV3_POS_"), - GSCALAR(heli_roll_max, "ROL_MAX_"), - GSCALAR(heli_pitch_max, "PIT_MAX_"), - GSCALAR(heli_collective_min, "COL_MIN_"), - GSCALAR(heli_collective_max, "COL_MAX_"), - GSCALAR(heli_collective_mid, "COL_MID_"), - GSCALAR(heli_ext_gyro_enabled, "GYR_ENABLE_"), - GSCALAR(heli_ext_gyro_gain, "GYR_GAIN_"), + GSCALAR(heli_servo1_pos, "SV1_POS"), + GSCALAR(heli_servo2_pos, "SV2_POS"), + GSCALAR(heli_servo3_pos, "SV3_POS"), + GSCALAR(heli_roll_max, "ROL_MAX"), + GSCALAR(heli_pitch_max, "PIT_MAX"), + GSCALAR(heli_collective_min, "COL_MIN"), + GSCALAR(heli_collective_max, "COL_MAX"), + GSCALAR(heli_collective_mid, "COL_MID"), + GSCALAR(heli_ext_gyro_enabled, "GYR_ENABLE"), + GSCALAR(heli_h1_swash_enabled, "H1_ENABLE"), + GSCALAR(heli_ext_gyro_gain, "GYR_GAIN"), GSCALAR(heli_servo_averaging, "SV_AVG"), GSCALAR(heli_servo_manual, "HSV_MAN"), GSCALAR(heli_phase_angle, "H_PHANG"), diff --git a/ArduCopter/heli.pde b/ArduCopter/heli.pde index 6e5a0a621b..4ce6a81d7a 100644 --- a/ArduCopter/heli.pde +++ b/ArduCopter/heli.pde @@ -28,15 +28,40 @@ static void heli_reset_swash() g.heli_servo_3.radio_min = 1000; g.heli_servo_3.radio_max = 2000; - // pitch factors - heli_pitchFactor[CH_1] = cos(radians(g.heli_servo1_pos - g.heli_phase_angle)); - heli_pitchFactor[CH_2] = cos(radians(g.heli_servo2_pos - g.heli_phase_angle)); - heli_pitchFactor[CH_3] = cos(radians(g.heli_servo3_pos - g.heli_phase_angle)); + if (!g.heli_h1_swash_enabled){ //CCPM Swashplate, perform servo control mixing + + // roll factors + heli_rollFactor[CH_1] = cos(radians(g.heli_servo1_pos + 90 - g.heli_phase_angle)); + heli_rollFactor[CH_2] = cos(radians(g.heli_servo2_pos + 90 - g.heli_phase_angle)); + heli_rollFactor[CH_3] = cos(radians(g.heli_servo3_pos + 90 - g.heli_phase_angle)); + + // pitch factors + heli_pitchFactor[CH_1] = cos(radians(g.heli_servo1_pos - g.heli_phase_angle)); + heli_pitchFactor[CH_2] = cos(radians(g.heli_servo2_pos - g.heli_phase_angle)); + heli_pitchFactor[CH_3] = cos(radians(g.heli_servo3_pos - g.heli_phase_angle)); + + // collective factors + heli_collectiveFactor[CH_1] = 1; + heli_collectiveFactor[CH_2] = 1; + heli_collectiveFactor[CH_3] = 1; + + }else{ //H1 Swashplate, keep servo outputs seperated - // roll factors - heli_rollFactor[CH_1] = cos(radians(g.heli_servo1_pos + 90 - g.heli_phase_angle)); - heli_rollFactor[CH_2] = cos(radians(g.heli_servo2_pos + 90 - g.heli_phase_angle)); - heli_rollFactor[CH_3] = cos(radians(g.heli_servo3_pos + 90 - g.heli_phase_angle)); + // roll factors + heli_rollFactor[CH_1] = 1; + heli_rollFactor[CH_2] = 0; + heli_rollFactor[CH_3] = 0; + + // pitch factors + heli_pitchFactor[CH_1] = 0; + heli_pitchFactor[CH_2] = 1; + heli_pitchFactor[CH_3] = 0; + + // collective factors + heli_collectiveFactor[CH_1] = 0; + heli_collectiveFactor[CH_2] = 0; + heli_collectiveFactor[CH_3] = 1; + } // set throttle scaling heli_collective_scalar = ((float)(g.rc_3.radio_max - g.rc_3.radio_min))/1000.0; @@ -69,15 +94,40 @@ static void heli_init_swash() // determine scalar throttle input heli_collective_scalar = ((float)(g.heli_collective_max-g.heli_collective_min))/1000.0; - // pitch factors - heli_pitchFactor[CH_1] = cos(radians(g.heli_servo1_pos - g.heli_phase_angle)); - heli_pitchFactor[CH_2] = cos(radians(g.heli_servo2_pos - g.heli_phase_angle)); - heli_pitchFactor[CH_3] = cos(radians(g.heli_servo3_pos - g.heli_phase_angle)); + if (!g.heli_h1_swash_enabled){ //CCPM Swashplate, perform control mixing + + // roll factors + heli_rollFactor[CH_1] = cos(radians(g.heli_servo1_pos + 90 - g.heli_phase_angle)); + heli_rollFactor[CH_2] = cos(radians(g.heli_servo2_pos + 90 - g.heli_phase_angle)); + heli_rollFactor[CH_3] = cos(radians(g.heli_servo3_pos + 90 - g.heli_phase_angle)); + + // pitch factors + heli_pitchFactor[CH_1] = cos(radians(g.heli_servo1_pos - g.heli_phase_angle)); + heli_pitchFactor[CH_2] = cos(radians(g.heli_servo2_pos - g.heli_phase_angle)); + heli_pitchFactor[CH_3] = cos(radians(g.heli_servo3_pos - g.heli_phase_angle)); + + // collective factors + heli_collectiveFactor[CH_1] = 1; + heli_collectiveFactor[CH_2] = 1; + heli_collectiveFactor[CH_3] = 1; + + }else{ //H1 Swashplate, keep servo outputs seperated - // roll factors - heli_rollFactor[CH_1] = cos(radians(g.heli_servo1_pos + 90 - g.heli_phase_angle)); - heli_rollFactor[CH_2] = cos(radians(g.heli_servo2_pos + 90 - g.heli_phase_angle)); - heli_rollFactor[CH_3] = cos(radians(g.heli_servo3_pos + 90 - g.heli_phase_angle)); + // roll factors + heli_rollFactor[CH_1] = 1; + heli_rollFactor[CH_2] = 0; + heli_rollFactor[CH_3] = 0; + + // pitch factors + heli_pitchFactor[CH_1] = 0; + heli_pitchFactor[CH_2] = 1; + heli_pitchFactor[CH_3] = 0; + + // collective factors + heli_collectiveFactor[CH_1] = 0; + heli_collectiveFactor[CH_2] = 0; + heli_collectiveFactor[CH_3] = 1; + } // servo min/max values g.heli_servo_1.radio_min = 1000; @@ -160,9 +210,9 @@ static void heli_move_swash(int roll_out, int pitch_out, int coll_out, int yaw_o } // swashplate servos - g.heli_servo_1.servo_out = (heli_rollFactor[CH_1] * roll_out + heli_pitchFactor[CH_1] * pitch_out)/10 + coll_out_scaled + (g.heli_servo_1.radio_trim-1500); - g.heli_servo_2.servo_out = (heli_rollFactor[CH_2] * roll_out + heli_pitchFactor[CH_2] * pitch_out)/10 + coll_out_scaled + (g.heli_servo_2.radio_trim-1500); - g.heli_servo_3.servo_out = (heli_rollFactor[CH_3] * roll_out + heli_pitchFactor[CH_3] * pitch_out)/10 + coll_out_scaled + (g.heli_servo_3.radio_trim-1500); + g.heli_servo_1.servo_out = (heli_rollFactor[CH_1] * roll_out + heli_pitchFactor[CH_1] * pitch_out)/10 + heli_collectiveFactor[CH_1] * coll_out_scaled + (g.heli_servo_1.radio_trim-1500) + g.heli_h1_swash_enabled * 500; + g.heli_servo_2.servo_out = (heli_rollFactor[CH_2] * roll_out + heli_pitchFactor[CH_2] * pitch_out)/10 + heli_collectiveFactor[CH_2] * coll_out_scaled + (g.heli_servo_2.radio_trim-1500) + g.heli_h1_swash_enabled * 500; + g.heli_servo_3.servo_out = (heli_rollFactor[CH_3] * roll_out + heli_pitchFactor[CH_3] * pitch_out)/10 + heli_collectiveFactor[CH_3] * coll_out_scaled + (g.heli_servo_3.radio_trim-1500); g.heli_servo_4.servo_out = yaw_out + yaw_offset; // use servo_out to calculate pwm_out and radio_out From ba3ffb3b8b6d50e68ab4d10f020df323bc0e0de2 Mon Sep 17 00:00:00 2001 From: Michael Oborne Date: Sun, 4 Mar 2012 08:42:42 +0800 Subject: [PATCH 003/178] APM Planner 1.1.48 Add ThemeManager - re andrew Add CustomMessageBox - re andrew and me few mono fixs mono tts working (speech) --- Tools/ArdupilotMegaPlanner/Antenna/Tracker.cs | 2 +- .../ArdupilotMegaPlanner/ArdupilotMega.csproj | 2 + Tools/ArdupilotMegaPlanner/Common.cs | 6 +- Tools/ArdupilotMegaPlanner/CommsUdpSerial.cs | 2 +- .../Controls/MessageBox.cs | 237 ++++++++++++++++++ .../Controls/ProgressReporterDialogue.cs | 12 +- .../ArdupilotMegaPlanner/CustomMessageBox.cs | 132 ++++++++++ .../GCSViews/Configuration.cs | 6 +- .../ArdupilotMegaPlanner/GCSViews/Firmware.cs | 4 +- .../GCSViews/FlightData.cs | 12 +- .../GCSViews/FlightPlanner.cs | 8 +- .../ArdupilotMegaPlanner/GCSViews/Terminal.cs | 4 +- Tools/ArdupilotMegaPlanner/JoystickSetup.cs | 2 +- Tools/ArdupilotMegaPlanner/MAVLink.cs | 4 +- Tools/ArdupilotMegaPlanner/MainV2.cs | 193 +------------- Tools/ArdupilotMegaPlanner/Program.cs | 1 + .../Properties/AssemblyInfo.cs | 2 +- Tools/ArdupilotMegaPlanner/Setup/Setup.cs | 9 +- Tools/ArdupilotMegaPlanner/Speech.cs | 31 ++- Tools/ArdupilotMegaPlanner/ThemeManager.cs | 221 ++++++++++++++++ .../bin/Release/ArdupilotMegaPlanner.pdb | Bin 974336 -> 984576 bytes Tools/ArdupilotMegaPlanner/srtm.cs | 1 + Tools/ArdupilotMegaPlanner/temp.cs | 2 +- 23 files changed, 678 insertions(+), 215 deletions(-) create mode 100644 Tools/ArdupilotMegaPlanner/Controls/MessageBox.cs create mode 100644 Tools/ArdupilotMegaPlanner/CustomMessageBox.cs create mode 100644 Tools/ArdupilotMegaPlanner/ThemeManager.cs diff --git a/Tools/ArdupilotMegaPlanner/Antenna/Tracker.cs b/Tools/ArdupilotMegaPlanner/Antenna/Tracker.cs index ad65cecda1..80114f674e 100644 --- a/Tools/ArdupilotMegaPlanner/Antenna/Tracker.cs +++ b/Tools/ArdupilotMegaPlanner/Antenna/Tracker.cs @@ -19,7 +19,7 @@ namespace ArdupilotMega.Antenna { InitializeComponent(); - MainV2.fixtheme(this); + ThemeManager.ApplyThemeTo(this); CMB_serialport.DataSource = SerialPort.GetPortNames(); diff --git a/Tools/ArdupilotMegaPlanner/ArdupilotMega.csproj b/Tools/ArdupilotMegaPlanner/ArdupilotMega.csproj index f14a442d90..d059812cba 100644 --- a/Tools/ArdupilotMegaPlanner/ArdupilotMega.csproj +++ b/Tools/ArdupilotMegaPlanner/ArdupilotMega.csproj @@ -241,6 +241,7 @@ Tracker.cs + Form @@ -464,6 +465,7 @@ + Tracker.cs diff --git a/Tools/ArdupilotMegaPlanner/Common.cs b/Tools/ArdupilotMegaPlanner/Common.cs index 2e16ee37a8..74f101f290 100644 --- a/Tools/ArdupilotMegaPlanner/Common.cs +++ b/Tools/ArdupilotMegaPlanner/Common.cs @@ -652,7 +652,7 @@ namespace ArdupilotMega form.MinimizeBox = false; form.MaximizeBox = false; - MainV2.fixtheme(form); + ThemeManager.ApplyThemeTo(form); form.Show(); form.Refresh(); @@ -706,7 +706,7 @@ namespace ArdupilotMega form.MinimizeBox = false; form.MaximizeBox = false; - MainV2.fixtheme(form); + ThemeManager.ApplyThemeTo(form); DialogResult dialogResult =form.ShowDialog(); @@ -760,7 +760,7 @@ namespace ArdupilotMega form.AcceptButton = buttonOk; form.CancelButton = buttonCancel; - MainV2.fixtheme(form); + ThemeManager.ApplyThemeTo(form); DialogResult dialogResult = DialogResult.Cancel; diff --git a/Tools/ArdupilotMegaPlanner/CommsUdpSerial.cs b/Tools/ArdupilotMegaPlanner/CommsUdpSerial.cs index a5ac6dbf51..628a3616ec 100644 --- a/Tools/ArdupilotMegaPlanner/CommsUdpSerial.cs +++ b/Tools/ArdupilotMegaPlanner/CommsUdpSerial.cs @@ -86,7 +86,7 @@ namespace System.IO.Ports frmProgressReporter.UpdateProgressAndStatus(-1, "Connecting Mavlink UDP"); - ArdupilotMega.MainV2.fixtheme(frmProgressReporter); + ArdupilotMega.ThemeManager.ApplyThemeTo(frmProgressReporter); frmProgressReporter.RunBackgroundOperationAsync(); diff --git a/Tools/ArdupilotMegaPlanner/Controls/MessageBox.cs b/Tools/ArdupilotMegaPlanner/Controls/MessageBox.cs new file mode 100644 index 0000000000..53cd628146 --- /dev/null +++ b/Tools/ArdupilotMegaPlanner/Controls/MessageBox.cs @@ -0,0 +1,237 @@ +using System; +using System.Drawing; +using System.Windows.Forms; +using ArdupilotMega.Controls; +using System.Text; +using ArdupilotMega; + +namespace System.Windows.Forms +{ + public static class MessageBox + { + const int FORM_Y_MARGIN = 10; + const int FORM_X_MARGIN = 16; + + static DialogResult _state = DialogResult.None; + + public static DialogResult Show(string text) + { + return Show(text, string.Empty, MessageBoxButtons.OK, MessageBoxIcon.None); + } + + public static DialogResult Show(string text, string caption) + { + return Show(text, caption, MessageBoxButtons.OK, MessageBoxIcon.None); + } + + public static DialogResult Show(string text, string caption, MessageBoxButtons buttons) + { + return Show(text, caption, buttons, MessageBoxIcon.None); + } + + public static DialogResult Show(string text, string caption, MessageBoxButtons buttons, MessageBoxIcon icon) + { + if (text == null) + text = ""; + + if (caption == null) + caption = ""; + + // ensure we are always in a known state + _state = DialogResult.None; + + // convert to nice wrapped lines. + text = AddNewLinesToText(text); + // get pixel width and height + Size textSize = TextRenderer.MeasureText(text, SystemFonts.DefaultFont); + // allow for icon + if (icon != MessageBoxIcon.None) + textSize.Width += SystemIcons.Question.Width; + + var msgBoxFrm = new Form + { + FormBorderStyle = FormBorderStyle.FixedDialog, + ShowInTaskbar = false, + StartPosition = FormStartPosition.CenterScreen, + Text = caption, + MaximizeBox = false, + MinimizeBox = false, + Width = textSize.Width + 50, + Height = textSize.Height + 100, + TopMost = true, + }; + + Rectangle screenRectangle = msgBoxFrm.RectangleToScreen(msgBoxFrm.ClientRectangle); + int titleHeight = screenRectangle.Top - msgBoxFrm.Top; + + var lblMessage = new Label + { + Left = 58, + Top = 15, + Width = textSize.Width + 10, + Height = textSize.Height + 10, + Text = text + }; + + msgBoxFrm.Controls.Add(lblMessage); + + var actualIcon = getMessageBoxIcon(icon); + + if (actualIcon == null) + { + lblMessage.Location = new Point(FORM_X_MARGIN, FORM_Y_MARGIN); + } + else + { + var iconPbox = new PictureBox + { + Image = actualIcon.ToBitmap(), + Location = new Point(FORM_X_MARGIN, FORM_Y_MARGIN) + }; + msgBoxFrm.Controls.Add(iconPbox); + } + + + AddButtonsToForm(msgBoxFrm, buttons); + + ThemeManager.ApplyThemeTo(msgBoxFrm); + + if (System.Windows.Forms.Application.OpenForms.Count > 0) + { + msgBoxFrm.StartPosition = FormStartPosition.Manual; + Form parentForm = System.Windows.Forms.Application.OpenForms[0]; + // center of first form + msgBoxFrm.Location = new Point(parentForm.Location.X + parentForm.Width / 2 - msgBoxFrm.Width / 2, + parentForm.Location.Y + parentForm.Height / 2 - msgBoxFrm.Height / 2); + DialogResult test = msgBoxFrm.ShowDialog(); + } + else + { + DialogResult test = msgBoxFrm.ShowDialog(); + } + + DialogResult answer = _state; + + return answer; + } + + static void msgBoxFrm_FormClosing(object sender, FormClosingEventArgs e) + { + throw new NotImplementedException(); + } + + // from http://stackoverflow.com/questions/2512781/winforms-big-paragraph-tooltip/2512895#2512895 + private static int maximumSingleLineTooltipLength = 85; + + private static string AddNewLinesToText(string text) + { + if (text.Length < maximumSingleLineTooltipLength) + return text; + int lineLength = maximumSingleLineTooltipLength; + StringBuilder sb = new StringBuilder(); + int currentLinePosition = 0; + for (int textIndex = 0; textIndex < text.Length; textIndex++) + { + // If we have reached the target line length and the next + // character is whitespace then begin a new line. + if (currentLinePosition >= lineLength && + char.IsWhiteSpace(text[textIndex])) + { + sb.Append(Environment.NewLine); + currentLinePosition = 0; + } + // If we have just started a new line, skip all the whitespace. + if (currentLinePosition == 0) + while (textIndex < text.Length && char.IsWhiteSpace(text[textIndex])) + textIndex++; + // Append the next character. + if (textIndex < text.Length) sb.Append(text[textIndex]); + currentLinePosition++; + } + return sb.ToString(); + } + + private static void AddButtonsToForm(Form msgBoxFrm, MessageBoxButtons buttons) + { + Rectangle screenRectangle = msgBoxFrm.RectangleToScreen(msgBoxFrm.ClientRectangle); + int titleHeight = screenRectangle.Top - msgBoxFrm.Top; + + var t = Type.GetType("Mono.Runtime"); + if ((t != null)) + titleHeight = 25; + + switch (buttons) + { + case MessageBoxButtons.OK: + var but = new MyButton + { + Size = new Size(75, 23), + Text = "OK", + Left = msgBoxFrm.Width - 75 - FORM_X_MARGIN, + Top = msgBoxFrm.Height - 23 - FORM_Y_MARGIN - titleHeight + }; + + but.Click += delegate { _state = DialogResult.OK; msgBoxFrm.Close(); }; + msgBoxFrm.Controls.Add(but); + msgBoxFrm.AcceptButton = but; + break; + + case MessageBoxButtons.YesNo: + + if (msgBoxFrm.Width < (75 * 2 + FORM_X_MARGIN * 3)) + msgBoxFrm.Width = (75 * 2 + FORM_X_MARGIN * 3); + + var butyes = new MyButton + { + Size = new Size(75, 23), + Text = "Yes", + Left = msgBoxFrm.Width - 75 * 2 - FORM_X_MARGIN * 2, + Top = msgBoxFrm.Height - 23 - FORM_Y_MARGIN - titleHeight + }; + + butyes.Click += delegate { _state = DialogResult.Yes; msgBoxFrm.Close(); }; + msgBoxFrm.Controls.Add(butyes); + msgBoxFrm.AcceptButton = butyes; + + var butno = new MyButton + { + Size = new Size(75, 23), + Text = "No", + Left = msgBoxFrm.Width - 75 - FORM_X_MARGIN, + Top = msgBoxFrm.Height - 23 - FORM_Y_MARGIN - titleHeight + }; + + butno.Click += delegate { _state = DialogResult.No; msgBoxFrm.Close(); }; + msgBoxFrm.Controls.Add(butno); + msgBoxFrm.CancelButton = butno; + break; + + default: + throw new NotImplementedException("Only MessageBoxButtons.OK and YesNo supported at this time"); + } + } + + /// + /// Get system icon for MessageBoxIcon. + /// + /// The MessageBoxIcon value. + /// SystemIcon type Icon. + private static Icon getMessageBoxIcon(MessageBoxIcon icon) + { + switch (icon) + { + case MessageBoxIcon.Asterisk: + return SystemIcons.Asterisk; + case MessageBoxIcon.Error: + return SystemIcons.Error; + case MessageBoxIcon.Exclamation: + return SystemIcons.Exclamation; + case MessageBoxIcon.Question: + return SystemIcons.Question; + default: + return null; + } + } + + } +} \ No newline at end of file diff --git a/Tools/ArdupilotMegaPlanner/Controls/ProgressReporterDialogue.cs b/Tools/ArdupilotMegaPlanner/Controls/ProgressReporterDialogue.cs index 4a055197cd..85757abd5e 100644 --- a/Tools/ArdupilotMegaPlanner/Controls/ProgressReporterDialogue.cs +++ b/Tools/ArdupilotMegaPlanner/Controls/ProgressReporterDialogue.cs @@ -42,7 +42,16 @@ namespace ArdupilotMega.Controls private void RunBackgroundOperation(object o) { - Thread.CurrentThread.Name = "ProgressReporterDialogue Background thread"; + try + { + Thread.CurrentThread.Name = "ProgressReporterDialogue Background thread"; + } + catch { } // ok on windows - fails on mono + + // mono fix - ensure the dialog is running + while (this.IsHandleCreated == false) + System.Threading.Thread.Sleep(5); + try { if (this.DoWork != null) this.DoWork(this, doWorkArgs); @@ -56,6 +65,7 @@ namespace ArdupilotMega.Controls return; } + if (doWorkArgs.CancelRequested && doWorkArgs.CancelAcknowledged) { ShowDoneCancelled(); diff --git a/Tools/ArdupilotMegaPlanner/CustomMessageBox.cs b/Tools/ArdupilotMegaPlanner/CustomMessageBox.cs new file mode 100644 index 0000000000..592263567f --- /dev/null +++ b/Tools/ArdupilotMegaPlanner/CustomMessageBox.cs @@ -0,0 +1,132 @@ +using System; +using System.Drawing; +using System.Windows.Forms; +using ArdupilotMega.Controls; + +namespace ArdupilotMega +{ + public static class CustomMessageBox + { + const int FORM_Y_MARGIN = 10; + const int FORM_X_MARGIN = 16; + + public static DialogResult Show(string text) + { + return Show(text, string.Empty, MessageBoxButtons.OK, MessageBoxIcon.None); + } + + public static DialogResult Show(string text, string caption) + { + return Show(text, caption, MessageBoxButtons.OK, MessageBoxIcon.None); + } + + public static DialogResult Show(string text, string caption, MessageBoxButtons buttons) + { + return Show(text, caption, buttons, MessageBoxIcon.None); + } + + public static DialogResult Show(string text, string caption, MessageBoxButtons buttons, MessageBoxIcon icon) + { + var msgBoxFrm = new Form + { + FormBorderStyle = FormBorderStyle.FixedDialog, + ShowInTaskbar = false, + StartPosition = FormStartPosition.CenterScreen, + Text = caption, + MaximizeBox = false, + MinimizeBox = false, + Width = 400, + Height = 170 + }; + + Rectangle screenRectangle = msgBoxFrm.RectangleToScreen(msgBoxFrm.ClientRectangle); + int titleHeight = screenRectangle.Top - msgBoxFrm.Top; + + var lblMessage = new Label + { + Left = 58, + Top = 15, + Width = 300, + Text = text, + AutoSize = true, + }; + + + + msgBoxFrm.Controls.Add(lblMessage); + + var actualIcon = getMessageBoxIcon(icon); + + if (actualIcon == null) + { + lblMessage.Location = new Point(FORM_X_MARGIN, FORM_Y_MARGIN); + } + else + { + var iconPbox = new PictureBox + { + Image = actualIcon.ToBitmap(), + Location = new Point(FORM_X_MARGIN, FORM_Y_MARGIN) + }; + msgBoxFrm.Controls.Add(iconPbox); + } + + + AddButtonsToForm(msgBoxFrm, buttons); + + ThemeManager.ApplyThemeTo(msgBoxFrm); + + msgBoxFrm.ShowDialog(); + + return DialogResult.OK; + } + + private static void AddButtonsToForm(Form msgBoxFrm, MessageBoxButtons buttons) + { + Rectangle screenRectangle = msgBoxFrm.RectangleToScreen(msgBoxFrm.ClientRectangle); + int titleHeight = screenRectangle.Top - msgBoxFrm.Top; + + switch (buttons) + { + case MessageBoxButtons.OK: + var but = new CustomButton + { + Size = new Size(75, 23), + Text = "OK", + Left = msgBoxFrm.Width - 75 - FORM_X_MARGIN, + Top = msgBoxFrm.Height - 23 - FORM_Y_MARGIN - titleHeight + }; + + but.Click += delegate { msgBoxFrm.Close(); }; + msgBoxFrm.Controls.Add(but); + break; + + default: + throw new NotImplementedException("Only MessageBoxButtons.OK supported at this time"); + } + } + + /// + /// Get system icon for MessageBoxIcon. + /// + /// The MessageBoxIcon value. + /// SystemIcon type Icon. + private static Icon getMessageBoxIcon(MessageBoxIcon icon) + { + switch (icon) + { + case MessageBoxIcon.Asterisk: + return SystemIcons.Asterisk; + case MessageBoxIcon.Error: + return SystemIcons.Error; + case MessageBoxIcon.Exclamation: + return SystemIcons.Exclamation; + case MessageBoxIcon.Question: + return SystemIcons.Question; + default: + return null; + } + } + + } +} \ No newline at end of file diff --git a/Tools/ArdupilotMegaPlanner/GCSViews/Configuration.cs b/Tools/ArdupilotMegaPlanner/GCSViews/Configuration.cs index 6ef519fefa..04287df16e 100644 --- a/Tools/ArdupilotMegaPlanner/GCSViews/Configuration.cs +++ b/Tools/ArdupilotMegaPlanner/GCSViews/Configuration.cs @@ -734,7 +734,7 @@ namespace ArdupilotMega.GCSViews temp.Configuration = this; - MainV2.fixtheme(temp); + ThemeManager.ApplyThemeTo(temp); temp.ShowDialog(); @@ -985,7 +985,7 @@ namespace ArdupilotMega.GCSViews private void BUT_Joystick_Click(object sender, EventArgs e) { Form joy = new JoystickSetup(); - MainV2.fixtheme(joy); + ThemeManager.ApplyThemeTo(joy); joy.Show(); } @@ -1146,7 +1146,7 @@ namespace ArdupilotMega.GCSViews sr.Close(); ParamCompare temp = new ParamCompare(this, param, param2); - MainV2.fixtheme(temp); + ThemeManager.ApplyThemeTo(temp); temp.ShowDialog(); } } diff --git a/Tools/ArdupilotMegaPlanner/GCSViews/Firmware.cs b/Tools/ArdupilotMegaPlanner/GCSViews/Firmware.cs index b2ae277080..ab5651f73a 100644 --- a/Tools/ArdupilotMegaPlanner/GCSViews/Firmware.cs +++ b/Tools/ArdupilotMegaPlanner/GCSViews/Firmware.cs @@ -226,7 +226,7 @@ namespace ArdupilotMega.GCSViews else if (items.Count == 2 && false) { XorPlus select = new XorPlus(); - MainV2.fixtheme(select); + ThemeManager.ApplyThemeTo(select); select.ShowDialog(); int a = 0; @@ -685,7 +685,7 @@ namespace ArdupilotMega.GCSViews private void BUT_setup_Click(object sender, EventArgs e) { Form temp = new Setup.Setup(); - MainV2.fixtheme(temp); + ThemeManager.ApplyThemeTo(temp); temp.ShowDialog(); } diff --git a/Tools/ArdupilotMegaPlanner/GCSViews/FlightData.cs b/Tools/ArdupilotMegaPlanner/GCSViews/FlightData.cs index 0d98ff5403..2e55ef0f2f 100644 --- a/Tools/ArdupilotMegaPlanner/GCSViews/FlightData.cs +++ b/Tools/ArdupilotMegaPlanner/GCSViews/FlightData.cs @@ -280,7 +280,7 @@ namespace ArdupilotMega.GCSViews comPort.requestDatastream((byte)ArdupilotMega.MAVLink.MAV_DATA_STREAM.MAV_DATA_STREAM_RC_CHANNELS, MainV2.cs.raterc); // request rc info } catch { } - lastdata = DateTime.Now; // prevent flooding + lastdata = DateTime.Now.AddSeconds(12); // prevent flooding } if (!MainV2.comPort.logreadmode) @@ -852,7 +852,7 @@ namespace ArdupilotMega.GCSViews private void BUT_RAWSensor_Click(object sender, EventArgs e) { Form temp = new RAW_Sensor(); - MainV2.fixtheme(temp); + ThemeManager.ApplyThemeTo(temp); temp.Show(); } @@ -1185,14 +1185,14 @@ namespace ArdupilotMega.GCSViews } Form frm = new MavlinkLog(); - MainV2.fixtheme(frm); + ThemeManager.ApplyThemeTo(frm); frm.ShowDialog(); } private void BUT_joystick_Click(object sender, EventArgs e) { Form joy = new JoystickSetup(); - MainV2.fixtheme(joy); + ThemeManager.ApplyThemeTo(joy); joy.Show(); } @@ -1480,7 +1480,7 @@ namespace ArdupilotMega.GCSViews selectform.Width = x + 100; } } - MainV2.fixtheme(selectform); + ThemeManager.ApplyThemeTo(selectform); selectform.Show(); } @@ -1555,7 +1555,7 @@ namespace ArdupilotMega.GCSViews MessageBox.Show("Max 10 at a time."); ((CheckBox)sender).Checked = false; } - MainV2.fixtheme(this); + ThemeManager.ApplyThemeTo(this); string selected = ""; try diff --git a/Tools/ArdupilotMegaPlanner/GCSViews/FlightPlanner.cs b/Tools/ArdupilotMegaPlanner/GCSViews/FlightPlanner.cs index 04e5e0de87..d615283bad 100644 --- a/Tools/ArdupilotMegaPlanner/GCSViews/FlightPlanner.cs +++ b/Tools/ArdupilotMegaPlanner/GCSViews/FlightPlanner.cs @@ -1205,7 +1205,7 @@ namespace ArdupilotMega.GCSViews frmProgressReporter.DoWork += getWPs; frmProgressReporter.UpdateProgressAndStatus(-1, "Receiving WP's"); - MainV2.fixtheme(frmProgressReporter); + ThemeManager.ApplyThemeTo(frmProgressReporter); frmProgressReporter.RunBackgroundOperationAsync(); } @@ -1314,7 +1314,7 @@ namespace ArdupilotMega.GCSViews frmProgressReporter.DoWork += saveWPs; frmProgressReporter.UpdateProgressAndStatus(-1, "Sending WP's"); - MainV2.fixtheme(frmProgressReporter); + ThemeManager.ApplyThemeTo(frmProgressReporter); frmProgressReporter.RunBackgroundOperationAsync(); @@ -2332,7 +2332,7 @@ namespace ArdupilotMega.GCSViews double homealt; double.TryParse(TXT_homealt.Text, out homealt); Form temp = new ElevationProfile(pointlist, homealt); - MainV2.fixtheme(temp); + ThemeManager.ApplyThemeTo(temp); temp.ShowDialog(); } @@ -2952,7 +2952,7 @@ namespace ArdupilotMega.GCSViews private void BUT_Camera_Click(object sender, EventArgs e) { Camera form = new Camera(); - MainV2.fixtheme(form); + ThemeManager.ApplyThemeTo(form); form.Show(); } diff --git a/Tools/ArdupilotMegaPlanner/GCSViews/Terminal.cs b/Tools/ArdupilotMegaPlanner/GCSViews/Terminal.cs index 4ff9bd2f27..fb5d258c30 100644 --- a/Tools/ArdupilotMegaPlanner/GCSViews/Terminal.cs +++ b/Tools/ArdupilotMegaPlanner/GCSViews/Terminal.cs @@ -293,7 +293,7 @@ namespace ArdupilotMega.GCSViews private void Logs_Click(object sender, EventArgs e) { Form Log = new Log(); - MainV2.fixtheme(Log); + ThemeManager.ApplyThemeTo(Log); inlogview = true; Log.ShowDialog(); inlogview = false; @@ -302,7 +302,7 @@ namespace ArdupilotMega.GCSViews private void BUT_logbrowse_Click(object sender, EventArgs e) { Form logbrowse = new LogBrowse(); - MainV2.fixtheme(logbrowse); + ThemeManager.ApplyThemeTo(logbrowse); logbrowse.ShowDialog(); } } diff --git a/Tools/ArdupilotMegaPlanner/JoystickSetup.cs b/Tools/ArdupilotMegaPlanner/JoystickSetup.cs index ce492aa7ae..012475894d 100644 --- a/Tools/ArdupilotMegaPlanner/JoystickSetup.cs +++ b/Tools/ArdupilotMegaPlanner/JoystickSetup.cs @@ -256,7 +256,7 @@ namespace ArdupilotMega MainV2.joystick = joy; - MainV2.fixtheme(this); + ThemeManager.ApplyThemeTo(this); CMB_joysticks.SelectedIndex = CMB_joysticks.Items.IndexOf(joy.name); } diff --git a/Tools/ArdupilotMegaPlanner/MAVLink.cs b/Tools/ArdupilotMegaPlanner/MAVLink.cs index 36b70180b2..0f66e80614 100644 --- a/Tools/ArdupilotMegaPlanner/MAVLink.cs +++ b/Tools/ArdupilotMegaPlanner/MAVLink.cs @@ -146,7 +146,7 @@ namespace ArdupilotMega frmProgressReporter.DoWork += FrmProgressReporterDoWorkNOParams; } frmProgressReporter.UpdateProgressAndStatus(-1, "Mavlink Connecting..."); - MainV2.fixtheme(frmProgressReporter); + ThemeManager.ApplyThemeTo(frmProgressReporter); frmProgressReporter.RunBackgroundOperationAsync(); } @@ -582,7 +582,7 @@ namespace ArdupilotMega frmProgressReporter.DoWork += FrmProgressReporterGetParams; frmProgressReporter.UpdateProgressAndStatus(-1, "Getting Params..."); - MainV2.fixtheme(frmProgressReporter); + ThemeManager.ApplyThemeTo(frmProgressReporter); frmProgressReporter.RunBackgroundOperationAsync(); } diff --git a/Tools/ArdupilotMegaPlanner/MainV2.cs b/Tools/ArdupilotMegaPlanner/MainV2.cs index 4e66490df6..0a1d312b20 100644 --- a/Tools/ArdupilotMegaPlanner/MainV2.cs +++ b/Tools/ArdupilotMegaPlanner/MainV2.cs @@ -106,8 +106,7 @@ namespace ArdupilotMega var t = Type.GetType("Mono.Runtime"); MONO = (t != null); - if (!MONO) - talk = new Speech(); + talk = new Speech(); //talk.SpeakAsync("Welcome to APM Planner"); @@ -313,174 +312,6 @@ namespace ArdupilotMega CMB_serialport.Text = oldport; } - public static void fixtheme(Control temp) - { - fixtheme(temp, 0); - } - - public static void fixtheme(Control temp, int level) - { - if (level == 0) - { - temp.BackColor = Color.FromArgb(0x26, 0x27, 0x28); - temp.ForeColor = Color.White;// Color.FromArgb(0xe6, 0xe8, 0xea); - } - //Console.WriteLine(temp.GetType()); - - //temp.Font = new Font("Lucida Console", 8.25f); - - foreach (Control ctl in temp.Controls) - { - if (((Type)ctl.GetType()) == typeof(System.Windows.Forms.Button)) - { - ctl.ForeColor = Color.Black; - System.Windows.Forms.Button but = (System.Windows.Forms.Button)ctl; - } - else if (((Type)ctl.GetType()) == typeof(TextBox)) - { - ctl.BackColor = Color.FromArgb(0x43, 0x44, 0x45); - ctl.ForeColor = Color.White;// Color.FromArgb(0xe6, 0xe8, 0xea); - TextBox txt = (TextBox)ctl; - txt.BorderStyle = BorderStyle.None; - } - else if (((Type)ctl.GetType()) == typeof(DomainUpDown)) - { - ctl.BackColor = Color.FromArgb(0x43, 0x44, 0x45); - ctl.ForeColor = Color.White;// Color.FromArgb(0xe6, 0xe8, 0xea); - DomainUpDown txt = (DomainUpDown)ctl; - txt.BorderStyle = BorderStyle.None; - } - else if (((Type)ctl.GetType()) == typeof(GroupBox)) - { - ctl.BackColor = Color.FromArgb(0x26, 0x27, 0x28); - ctl.ForeColor = Color.White;// Color.FromArgb(0xe6, 0xe8, 0xea); - } - else if (((Type)ctl.GetType()) == typeof(ZedGraph.ZedGraphControl)) - { - ZedGraph.ZedGraphControl zg1 = (ZedGraph.ZedGraphControl)ctl; - zg1.GraphPane.Chart.Fill = new ZedGraph.Fill(Color.FromArgb(0x1f, 0x1f, 0x20)); - zg1.GraphPane.Fill = new ZedGraph.Fill(Color.FromArgb(0x37, 0x37, 0x38)); - - foreach (ZedGraph.LineItem li in zg1.GraphPane.CurveList) - { - li.Line.Width = 4; - } - - zg1.GraphPane.Title.FontSpec.FontColor = Color.White; - - zg1.GraphPane.XAxis.MajorTic.Color = Color.White; - zg1.GraphPane.XAxis.MinorTic.Color = Color.White; - zg1.GraphPane.YAxis.MajorTic.Color = Color.White; - zg1.GraphPane.YAxis.MinorTic.Color = Color.White; - - zg1.GraphPane.XAxis.MajorGrid.Color = Color.White; - zg1.GraphPane.YAxis.MajorGrid.Color = Color.White; - - zg1.GraphPane.YAxis.Scale.FontSpec.FontColor = Color.White; - zg1.GraphPane.YAxis.Title.FontSpec.FontColor = Color.White; - - zg1.GraphPane.XAxis.Scale.FontSpec.FontColor = Color.White; - zg1.GraphPane.XAxis.Title.FontSpec.FontColor = Color.White; - - zg1.GraphPane.Legend.Fill = new ZedGraph.Fill(Color.FromArgb(0x85, 0x84, 0x83)); - zg1.GraphPane.Legend.FontSpec.FontColor = Color.White; - } - else if (((Type)ctl.GetType()) == typeof(BSE.Windows.Forms.Panel) || ((Type)ctl.GetType()) == typeof(System.Windows.Forms.SplitterPanel)) - { - ctl.BackColor = Color.FromArgb(0x26, 0x27, 0x28); - ctl.ForeColor = Color.White;// Color.FromArgb(0xe6, 0xe8, 0xea); - } - else if (((Type)ctl.GetType()) == typeof(Form)) - { - ctl.BackColor = Color.FromArgb(0x26, 0x27, 0x28); - ctl.ForeColor = Color.White;// Color.FromArgb(0xe6, 0xe8, 0xea); - } - else if (((Type)ctl.GetType()) == typeof(RichTextBox)) - { - ctl.BackColor = Color.FromArgb(0x43, 0x44, 0x45); - ctl.ForeColor = Color.White; - RichTextBox txtr = (RichTextBox)ctl; - txtr.BorderStyle = BorderStyle.None; - } - else if (((Type)ctl.GetType()) == typeof(CheckedListBox)) - { - ctl.BackColor = Color.FromArgb(0x43, 0x44, 0x45); - ctl.ForeColor = Color.White; - CheckedListBox txtr = (CheckedListBox)ctl; - txtr.BorderStyle = BorderStyle.None; - } - else if (((Type)ctl.GetType()) == typeof(TabPage)) - { - ctl.BackColor = Color.FromArgb(0x26, 0x27, 0x28); //Color.FromArgb(0x43, 0x44, 0x45); - ctl.ForeColor = Color.White; - TabPage txtr = (TabPage)ctl; - txtr.BorderStyle = BorderStyle.None; - } - else if (((Type)ctl.GetType()) == typeof(TabControl)) - { - ctl.BackColor = Color.FromArgb(0x26, 0x27, 0x28); //Color.FromArgb(0x43, 0x44, 0x45); - ctl.ForeColor = Color.White; - TabControl txtr = (TabControl)ctl; - - } - else if (((Type)ctl.GetType()) == typeof(DataGridView)) - { - ctl.ForeColor = Color.White; - DataGridView dgv = (DataGridView)ctl; - dgv.EnableHeadersVisualStyles = false; - dgv.BorderStyle = BorderStyle.None; - dgv.BackgroundColor = Color.FromArgb(0x26, 0x27, 0x28); - DataGridViewCellStyle rs = new DataGridViewCellStyle(); - rs.BackColor = Color.FromArgb(0x43, 0x44, 0x45); - rs.ForeColor = Color.White; - dgv.RowsDefaultCellStyle = rs; - - DataGridViewCellStyle hs = new DataGridViewCellStyle(dgv.ColumnHeadersDefaultCellStyle); - hs.BackColor = Color.FromArgb(0x26, 0x27, 0x28); - hs.ForeColor = Color.White; - - dgv.ColumnHeadersDefaultCellStyle = hs; - - dgv.RowHeadersDefaultCellStyle = hs; - } - else if (((Type)ctl.GetType()) == typeof(ComboBox)) - { - ctl.BackColor = Color.FromArgb(0x43, 0x44, 0x45); - ctl.ForeColor = Color.White; - ComboBox CMB = (ComboBox)ctl; - CMB.FlatStyle = FlatStyle.Flat; - } - else if (((Type)ctl.GetType()) == typeof(NumericUpDown)) - { - ctl.BackColor = Color.FromArgb(0x43, 0x44, 0x45); - ctl.ForeColor = Color.White; - } - else if (((Type)ctl.GetType()) == typeof(TrackBar)) - { - ctl.BackColor = Color.FromArgb(0x26, 0x27, 0x28); - ctl.ForeColor = Color.White; - } - else if (((Type)ctl.GetType()) == typeof(LinkLabel)) - { - ctl.BackColor = Color.FromArgb(0x26, 0x27, 0x28); - ctl.ForeColor = Color.White; - LinkLabel LNK = (LinkLabel)ctl; - LNK.ActiveLinkColor = Color.White; - LNK.LinkColor = Color.White; - LNK.VisitedLinkColor = Color.White; - - } - else if (((Type)ctl.GetType()) == typeof(HorizontalProgressBar2) || - ((Type)ctl.GetType()) == typeof(VerticalProgressBar2)) - { - ((HorizontalProgressBar2)ctl).BackgroundColor = Color.FromArgb(0x43, 0x44, 0x45); - ((HorizontalProgressBar2)ctl).ValueColor = Color.FromArgb(148, 193, 31); - } - - if (ctl.Controls.Count > 0) - fixtheme(ctl, 1); - } - } private void MenuFlightData_Click(object sender, EventArgs e) { @@ -490,7 +321,7 @@ namespace ArdupilotMega UserControl temp = FlightData; - fixtheme(temp); + ThemeManager.ApplyThemeTo(temp); temp.Anchor = AnchorStyles.Bottom | AnchorStyles.Left | AnchorStyles.Right | AnchorStyles.Top; @@ -516,7 +347,7 @@ namespace ArdupilotMega UserControl temp = FlightPlanner; - fixtheme(temp); + ThemeManager.ApplyThemeTo(temp); temp.Anchor = AnchorStyles.Bottom | AnchorStyles.Left | AnchorStyles.Right | AnchorStyles.Top; @@ -551,7 +382,7 @@ namespace ArdupilotMega UserControl temp = Configuration; - fixtheme(temp); + ThemeManager.ApplyThemeTo(temp); //temp.Anchor = AnchorStyles.Bottom | AnchorStyles.Left | AnchorStyles.Right | AnchorStyles.Top; @@ -578,7 +409,7 @@ namespace ArdupilotMega UserControl temp = Simulation; - fixtheme(temp); + ThemeManager.ApplyThemeTo(temp); temp.Anchor = AnchorStyles.Bottom | AnchorStyles.Left | AnchorStyles.Right | AnchorStyles.Top; @@ -601,7 +432,7 @@ namespace ArdupilotMega UserControl temp = Firmware; - fixtheme(temp); + ThemeManager.ApplyThemeTo(temp); temp.Anchor = AnchorStyles.Bottom | AnchorStyles.Left | AnchorStyles.Right | AnchorStyles.Top; @@ -641,7 +472,7 @@ namespace ArdupilotMega UserControl temp = Terminal; - fixtheme(temp); + ThemeManager.ApplyThemeTo(temp); temp.Anchor = AnchorStyles.Bottom | AnchorStyles.Left | AnchorStyles.Right | AnchorStyles.Top; @@ -1616,7 +1447,7 @@ namespace ArdupilotMega UserControl temp = new GCSViews.Help(); - fixtheme(temp); + ThemeManager.ApplyThemeTo(temp); temp.Anchor = AnchorStyles.Bottom | AnchorStyles.Left | AnchorStyles.Right | AnchorStyles.Top; @@ -1782,7 +1613,7 @@ namespace ArdupilotMega StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen }; - MainV2.fixtheme(frmProgressReporter); + ThemeManager.ApplyThemeTo(frmProgressReporter); frmProgressReporter.DoWork += new Controls.ProgressReporterDialogue.DoWorkEventHandler(frmProgressReporter_DoWork); @@ -2015,7 +1846,7 @@ namespace ArdupilotMega if (keyData == (Keys.Control | Keys.F)) { Form frm = new temp(); - fixtheme(frm); + ThemeManager.ApplyThemeTo(frm); frm.Show(); return true; } @@ -2027,14 +1858,14 @@ namespace ArdupilotMega if (keyData == (Keys.Control | Keys.G)) // test { Form frm = new SerialOutput(); - fixtheme(frm); + ThemeManager.ApplyThemeTo(frm); frm.Show(); return true; } if (keyData == (Keys.Control | Keys.A)) // test { Form frm = new _3DRradio(); - fixtheme(frm); + ThemeManager.ApplyThemeTo(frm); frm.Show(); return true; } diff --git a/Tools/ArdupilotMegaPlanner/Program.cs b/Tools/ArdupilotMegaPlanner/Program.cs index fb7e6f2e71..e1f808f6c2 100644 --- a/Tools/ArdupilotMegaPlanner/Program.cs +++ b/Tools/ArdupilotMegaPlanner/Program.cs @@ -31,6 +31,7 @@ namespace ArdupilotMega Application.Idle += Application_Idle; + //MagCalib.doWork(); //return; diff --git a/Tools/ArdupilotMegaPlanner/Properties/AssemblyInfo.cs b/Tools/ArdupilotMegaPlanner/Properties/AssemblyInfo.cs index d6bbc81952..951e78d73e 100644 --- a/Tools/ArdupilotMegaPlanner/Properties/AssemblyInfo.cs +++ b/Tools/ArdupilotMegaPlanner/Properties/AssemblyInfo.cs @@ -34,5 +34,5 @@ using System.Resources; // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.1.47")] +[assembly: AssemblyFileVersion("1.1.48")] [assembly: NeutralResourcesLanguageAttribute("")] diff --git a/Tools/ArdupilotMegaPlanner/Setup/Setup.cs b/Tools/ArdupilotMegaPlanner/Setup/Setup.cs index 6c3feb616d..57a374d2c2 100644 --- a/Tools/ArdupilotMegaPlanner/Setup/Setup.cs +++ b/Tools/ArdupilotMegaPlanner/Setup/Setup.cs @@ -986,8 +986,10 @@ namespace ArdupilotMega.Setup MessageBox.Show("Please Connect First"); this.Close(); } - - tabControl1_SelectedIndexChanged(null, new EventArgs()); + else + { + tabControl1_SelectedIndexChanged(null, new EventArgs()); + } } private void TXT_srvpos1_Validating(object sender, CancelEventArgs e) @@ -1407,6 +1409,9 @@ namespace ArdupilotMega.Setup timer.Dispose(); tabControl1.SelectedIndex = 0; + + // mono runs validation on all controls on exit. try and skip it + startup = true; } private void CHK_enableoptflow_CheckedChanged(object sender, EventArgs e) diff --git a/Tools/ArdupilotMegaPlanner/Speech.cs b/Tools/ArdupilotMegaPlanner/Speech.cs index baa8cd0b0e..0da3155cae 100644 --- a/Tools/ArdupilotMegaPlanner/Speech.cs +++ b/Tools/ArdupilotMegaPlanner/Speech.cs @@ -3,11 +3,14 @@ using System.Collections.Generic; using System.Linq; using System.Text; using System.Speech.Synthesis; +using log4net; namespace ArdupilotMega { public class Speech { + private static readonly ILog log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + SpeechSynthesizer _speechwindows; System.Diagnostics.Process _speechlinux; @@ -15,8 +18,10 @@ namespace ArdupilotMega bool MONO = false; - public SynthesizerState State { - get { + public SynthesizerState State + { + get + { if (MONO) { return _state; @@ -33,6 +38,8 @@ namespace ArdupilotMega var t = Type.GetType("Mono.Runtime"); MONO = (t != null); + log.Info("TTS: init, mono = " + MONO); + if (MONO) { _state = SynthesizerState.Ready; @@ -47,23 +54,39 @@ namespace ArdupilotMega { if (MONO) { - if (_speechlinux == null || _speechlinux.HasExited) + //if (_speechlinux == null) { _state = SynthesizerState.Speaking; _speechlinux = new System.Diagnostics.Process(); - _speechlinux.StartInfo.FileName = "echo " + text + " | festival --tts"; + _speechlinux.StartInfo.RedirectStandardInput = true; + _speechlinux.StartInfo.UseShellExecute = false; + _speechlinux.StartInfo.FileName = "festival"; _speechlinux.Start(); _speechlinux.Exited += new EventHandler(_speechlinux_Exited); + + log.Info("TTS: start " + _speechlinux.StartTime); + } + + _state = SynthesizerState.Speaking; + _speechlinux.StandardInput.WriteLine("(SayText \"" + text + "\")"); + _speechlinux.StandardInput.WriteLine("(quit)"); + + _speechlinux.Close(); + + _state = SynthesizerState.Ready; } else { _speechwindows.SpeakAsync(text); } + + log.Info("TTS: say " + text); } void _speechlinux_Exited(object sender, EventArgs e) { + log.Info("TTS: exit " + _speechlinux.ExitTime); _state = SynthesizerState.Ready; } diff --git a/Tools/ArdupilotMegaPlanner/ThemeManager.cs b/Tools/ArdupilotMegaPlanner/ThemeManager.cs new file mode 100644 index 0000000000..7723eb9dd3 --- /dev/null +++ b/Tools/ArdupilotMegaPlanner/ThemeManager.cs @@ -0,0 +1,221 @@ +using System; +using System.Drawing; +using System.Windows.Forms; +using log4net; + +namespace ArdupilotMega +{ + /// + /// Helper class for the stylng 'theming' of forms and controls, and provides MessageBox + /// replacements which are also styled + /// + public class ThemeManager + { + private static readonly ILog log = + LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + private static Themes _currentTheme = Themes.BurntKermit; + + public enum Themes + { + /// + /// no theme - standard Winforms appearance + /// + None, + + /// + /// Standard Planner Charcoal & Green colours + /// + BurntKermit, + } + + /// + /// Change the current theme. Existing controls are not affected + /// + /// + public static void SetTheme(Themes theme) + { + log.Debug("Theme set to " + Enum.GetName(typeof(Themes), theme)); + _currentTheme = theme; + } + + /// + /// Will recursively apply the current theme to 'control' + /// + /// + public static void ApplyThemeTo(Control control) + { + switch (_currentTheme) + { + case Themes.BurntKermit: ApplyBurntKermitTheme(control, 0); + break; + + // More themes go here + + default: + break; + } + + + } + + private static void ApplyBurntKermitTheme(Control temp, int level) + { + if (level == 0) + { + temp.BackColor = Color.FromArgb(0x26, 0x27, 0x28); + temp.ForeColor = Color.White;// Color.FromArgb(0xe6, 0xe8, 0xea); + } + + //temp.Font = new Font("Lucida Console", 8.25f); + + foreach (Control ctl in temp.Controls) + { + if (ctl.GetType() == typeof(Button)) + { + ctl.ForeColor = Color.Black; + } + else if (ctl.GetType() == typeof(TextBox)) + { + ctl.BackColor = Color.FromArgb(0x43, 0x44, 0x45); + ctl.ForeColor = Color.White;// Color.FromArgb(0xe6, 0xe8, 0xea); + TextBox txt = (TextBox)ctl; + txt.BorderStyle = BorderStyle.None; + } + else if (ctl.GetType() == typeof(DomainUpDown)) + { + ctl.BackColor = Color.FromArgb(0x43, 0x44, 0x45); + ctl.ForeColor = Color.White;// Color.FromArgb(0xe6, 0xe8, 0xea); + DomainUpDown txt = (DomainUpDown)ctl; + txt.BorderStyle = BorderStyle.None; + } + else if (ctl.GetType() == typeof(GroupBox)) + { + ctl.BackColor = Color.FromArgb(0x26, 0x27, 0x28); + ctl.ForeColor = Color.White;// Color.FromArgb(0xe6, 0xe8, 0xea); + } + else if (ctl.GetType() == typeof(ZedGraph.ZedGraphControl)) + { + var zg1 = (ZedGraph.ZedGraphControl)ctl; + zg1.GraphPane.Chart.Fill = new ZedGraph.Fill(Color.FromArgb(0x1f, 0x1f, 0x20)); + zg1.GraphPane.Fill = new ZedGraph.Fill(Color.FromArgb(0x37, 0x37, 0x38)); + + foreach (ZedGraph.LineItem li in zg1.GraphPane.CurveList) + li.Line.Width = 4; + + zg1.GraphPane.Title.FontSpec.FontColor = Color.White; + + zg1.GraphPane.XAxis.MajorTic.Color = Color.White; + zg1.GraphPane.XAxis.MinorTic.Color = Color.White; + zg1.GraphPane.YAxis.MajorTic.Color = Color.White; + zg1.GraphPane.YAxis.MinorTic.Color = Color.White; + + zg1.GraphPane.XAxis.MajorGrid.Color = Color.White; + zg1.GraphPane.YAxis.MajorGrid.Color = Color.White; + + zg1.GraphPane.YAxis.Scale.FontSpec.FontColor = Color.White; + zg1.GraphPane.YAxis.Title.FontSpec.FontColor = Color.White; + + zg1.GraphPane.XAxis.Scale.FontSpec.FontColor = Color.White; + zg1.GraphPane.XAxis.Title.FontSpec.FontColor = Color.White; + + zg1.GraphPane.Legend.Fill = new ZedGraph.Fill(Color.FromArgb(0x85, 0x84, 0x83)); + zg1.GraphPane.Legend.FontSpec.FontColor = Color.White; + } + else if (ctl.GetType() == typeof(BSE.Windows.Forms.Panel) || ctl.GetType() == typeof(SplitterPanel)) + { + ctl.BackColor = Color.FromArgb(0x26, 0x27, 0x28); + ctl.ForeColor = Color.White;// Color.FromArgb(0xe6, 0xe8, 0xea); + } + else if (ctl.GetType() == typeof(Form)) + { + ctl.BackColor = Color.FromArgb(0x26, 0x27, 0x28); + ctl.ForeColor = Color.White;// Color.FromArgb(0xe6, 0xe8, 0xea); + } + else if (ctl.GetType() == typeof(RichTextBox)) + { + ctl.BackColor = Color.FromArgb(0x43, 0x44, 0x45); + ctl.ForeColor = Color.White; + RichTextBox txtr = (RichTextBox)ctl; + txtr.BorderStyle = BorderStyle.None; + } + else if (ctl.GetType() == typeof(CheckedListBox)) + { + ctl.BackColor = Color.FromArgb(0x43, 0x44, 0x45); + ctl.ForeColor = Color.White; + CheckedListBox txtr = (CheckedListBox)ctl; + txtr.BorderStyle = BorderStyle.None; + } + else if (ctl.GetType() == typeof(TabPage)) + { + ctl.BackColor = Color.FromArgb(0x26, 0x27, 0x28); //Color.FromArgb(0x43, 0x44, 0x45); + ctl.ForeColor = Color.White; + TabPage txtr = (TabPage)ctl; + txtr.BorderStyle = BorderStyle.None; + } + else if (ctl.GetType() == typeof(TabControl)) + { + ctl.BackColor = Color.FromArgb(0x26, 0x27, 0x28); //Color.FromArgb(0x43, 0x44, 0x45); + ctl.ForeColor = Color.White; + TabControl txtr = (TabControl)ctl; + + } + else if (ctl.GetType() == typeof(DataGridView)) + { + ctl.ForeColor = Color.White; + DataGridView dgv = (DataGridView)ctl; + dgv.EnableHeadersVisualStyles = false; + dgv.BorderStyle = BorderStyle.None; + dgv.BackgroundColor = Color.FromArgb(0x26, 0x27, 0x28); + DataGridViewCellStyle rs = new DataGridViewCellStyle(); + rs.BackColor = Color.FromArgb(0x43, 0x44, 0x45); + rs.ForeColor = Color.White; + dgv.RowsDefaultCellStyle = rs; + + DataGridViewCellStyle hs = new DataGridViewCellStyle(dgv.ColumnHeadersDefaultCellStyle); + hs.BackColor = Color.FromArgb(0x26, 0x27, 0x28); + hs.ForeColor = Color.White; + + dgv.ColumnHeadersDefaultCellStyle = hs; + dgv.RowHeadersDefaultCellStyle = hs; + } + else if (ctl.GetType() == typeof(ComboBox)) + { + ctl.BackColor = Color.FromArgb(0x43, 0x44, 0x45); + ctl.ForeColor = Color.White; + ComboBox CMB = (ComboBox)ctl; + CMB.FlatStyle = FlatStyle.Flat; + } + else if (ctl.GetType() == typeof(NumericUpDown)) + { + ctl.BackColor = Color.FromArgb(0x43, 0x44, 0x45); + ctl.ForeColor = Color.White; + } + else if (ctl.GetType() == typeof(TrackBar)) + { + ctl.BackColor = Color.FromArgb(0x26, 0x27, 0x28); + ctl.ForeColor = Color.White; + } + else if (ctl.GetType() == typeof(LinkLabel)) + { + ctl.BackColor = Color.FromArgb(0x26, 0x27, 0x28); + ctl.ForeColor = Color.White; + LinkLabel LNK = (LinkLabel)ctl; + LNK.ActiveLinkColor = Color.White; + LNK.LinkColor = Color.White; + LNK.VisitedLinkColor = Color.White; + + } + else if (ctl.GetType() == typeof(HorizontalProgressBar2) || ctl.GetType() == typeof(VerticalProgressBar2)) + { + ((HorizontalProgressBar2)ctl).BackgroundColor = Color.FromArgb(0x43, 0x44, 0x45); + ((HorizontalProgressBar2)ctl).ValueColor = Color.FromArgb(148, 193, 31); + } + + if (ctl.Controls.Count > 0) + ApplyBurntKermitTheme(ctl, 1); + } + } + + } +} \ No newline at end of file diff --git a/Tools/ArdupilotMegaPlanner/bin/Release/ArdupilotMegaPlanner.pdb b/Tools/ArdupilotMegaPlanner/bin/Release/ArdupilotMegaPlanner.pdb index b5e4392f1ecc3da666804ebced2b469df070f5e0..ae1895b403c936d8e5fe53069f471c0fd129fc26 100644 GIT binary patch delta 165393 zcma&P2Y405`uM-IC!HiDCLyF3dI%7Dkrp~gZ=%uygc^D%DwqQz(n%;8M0yhil%_!i zK}1Cb1TS7u5kV0F0fCENP{9A^-QANM{od#K|IWk9XJ_V}UUznOn}07+(l|=@DFNtfR9;rUs3li z3d^+fg<-9SE@{22aNDB9^iqL);)BwC!j4^9yz5@@ciYa7xD!>aeA=2_nOoJ8&~_W! zg_)&)xfOhD#*ph(KO5b6->>g%(V2sT4;FO2x+JlE>69t=NA~Sqc7WNj@46SS+^~H0 zZoj8}nZHz6)8k9Oz16GB^H**T8U4fd((}Y|cWk@Juqq*C;(GTP@rU2RdYQl7Uh{$F zkkKwa%!u55vuE^yiz_yNkk)V7!tItr=XPe;r+<|>c5VML{}A`@XA+0Iw^;E=>beJn z?RfFnzpm|FeC5N-uT4m}@<*EGsc*ZWuyya09s5J|JBuc%pu=4nPibm7498(fi}eqG zAL#S#ttTI!Q|I%aey|*J+l7TKtRB#NM9yM{75tVLz z?0)s9gGW@{IC<)|DbqUY@Wtxag0AoF@i}%stmw?i&;aGTi-xj$Psq70N_YKN=*}Xa z)1iG-(ZDZ5XQ`;`zJ_rF`4zc|+(K?^^;Ky7K;>r`CgNI}`D2m_*^~9-Q$D^GXq*-G zPw$03uA3hWOEEI%?>8<~g9!u$eqjqCp)KIAqSDUV$xqzN(vnT@=N z%t7Y*8%52|hQ3d=lrI&x5?}nFbi?av$+ZBV{0@ep)%egJ+C3pOV9&5?+uG?$&xCdf z?m0Yrbatn#FZ6XfbxGPDxb#0&U|U zjG=W^x}RTr!^m!5)V!{G#PmCYA+1AEpZaQxsXi#koKo0W`GiD<8%CQot%KLxJEl}Y zW(}34GaIWiK8eF#`ESuvjnxj*=ljfQ-E?p>)zhbR??wIf5V;CFwz^W${${GL@~OPB z{Dh+TOy#3|QhGdgO_y(hd+n#9KiAV*sO>&sEgvo|N^hw$luw!LI-B*tR;pcMHfgCW zW${CX%DGhJ+lOmO>{Bqiy-bkv6VXGllgA%l%hke)n4WERrSVY_0+a1 zJ~54w^91oA^I>zw_45TE74>bef=!=^Z`Hi7a~@NbeclMDx?Hb# zOu2n7bci~o<2z!PUpM^|-A=CRzPhJPQEo?7M-_HfKd44UKXz74RPaQ9!!O0($B-dY z_Zt!%ty^|gm6946!C18NG5k!!&$!KXJH%F0MuJ|St0Ib4byc&Jzb_#SnBlAcDrMI8 zxBXq#S>07RKR;Y%&d~F^s|LjmpNNA$4s&Pd+uc>FYc5`sOjnG~=%K3n59ulKUe?(? zPzylq=NWoY57oHX|0!_@#NoyaU44kF#Gy$~9D;BdIa9Cnc6b#B|57-NpXsY>d>iy= zaad8kR5?Acr}8n~Gj-EmUa6dpi(d$SUYx1F$##__|0i(>#bNbK9ok!^`mUboYbZV5 z9gw6C4N?I*f2hkxuW|=O>YX*r0KF5V+M#FkR!LyjRSWOirVBPQd#ecT9*p0v!z|^L z$1SbQ$5o|p{XD@_BC$p?4VoUV-@gnRD-fkb@`Q4b5A@En4#A^>l3Rt^-;}DD)9A@ zuGqpSR9GN&MQW7MU+?PWiqPp#sO=^dB<}i-DBN%qrs-QDC?r3r)|u3YrEvC16=sf~ zsc$@~T1bIgmKh6u{DPCL2G*FEDenGH;kh z7iz=$zbZMJzRWHtqsQ>EQ?M;#xWXCnjAMxCPG6?mtWdS|_Mm_${q~ts(K^4giqsjG z`S0YJQcYDO{ntAGs0ve^@PqK<`K1&7eDCmeW>;0^QM>RYa_J+U1fKmL0aQb0`Tq%E z!2b@Qxg?vPztp4it4;uGy#v5ra(JG|g3%XUk9#6bpcL+VG%YJmyFd5$QG4|Ij%J)* zx6)UxuP;&2d7>ss-Q(4YMo%2ZklSX$XzWv+mgMa|aqxuf>@nT52j|k$a+lnAhmkcncT!eP`_RE-$Jos}KooRlT&ajai8IhLo~m!gl*+IYAvLi_ z&luqwmnm5eBdf=Vv>w)9Ew?LO(jk+OcRVAAper*5)>be~X#^wTHm+qzg?R!CAcZ+N zRw^tBj5+RafsM?@ghR6X02UW;OCXp}`CS-0lf5bI6d+*;6`>7?VA*=h&Xv zQ*-TRv5$mo#jp57S3g!5IHL3&EH_~(dHn>-4+;aH$o6Ex6XPcV zMT{*b<>rnZLxhqEbghO+zyt9s{ye%;DH7)QQ5=W-`vq}guOJJy;{{XGjyj3zW%<_ZftXKmaQSZ!m$}-Hwvl6z52Vh zW=!4?D2TS4%__!WO1U8y?>;7zOUbp9mYw3>f!qn`0@lM}1=fXw>P zFJz^!&imP?cFfokdGCk%>Q0yaRE&CqD_RDSi zyada>jb*=pwqg%^s(83eA`G{*A%3Y`O3jsn(i|#Sep$T3NX%7WEKG;!GKL#&#K?d( zA>wWiYm=-UusO?W_d8r<;_wM<$&^)^$U0(u{uzXSnZhAp!ml$Dr^4j)y+9S(+ZDnMelAoZ;4aH9)ZGtjGu)WXgqZH(|LMk_44Ax|MP zXNzKEl+uv6;_BK`sBhGB#YQmxxPsrLX9D#OvQIe{^GZp(pu!O}R+gi-K$7zbxT z>e_e#N}WoMQ{Y^@P#?wu?3=-bFcUJ?xm!WeYXg^H?f?s57F-5LIwVn*jpbNO!$Kl( zJ0x&JV-BH+!i@xS)I|SyG_ZY$RGvMqDPxGfH90UMPa>j`8mrKk#A>R;+NfefcwjG~`J8GVtONG&7|X=lVB zQARW}5UEjz|LQsx{b6lH>_mBzRo?@N#2!$TQD5KsTt#&Lj<}^(&%<)?2UrDOgf-wL zSQlP~A&jtg8mc=%OL|hQprzr3tkkRxV|7MZpMX4S5)XFu2O15GK%+S(!?=UU@F}-Y z@@t1|r4aTbr;*Eu;WCU!Bpqpv^g*T}%aFZ@EH|zpK0b_HNMocY;`P&GUsMJ9{6YWn z+NZyY_v4n|@3^0?*k84C2EbNc_fpa3j(Km_ID4Lb4@*n9WTL6cU zGssOOz?bwQjgh`cF2W+x*p3`SE+W>gz8~d+3`C|P`N&?`L|I!nN0oQAj5PIM2Lk)) zS#wlb?xR=FQF1$de2(fSiAtWU($!(zX)bpyhxO>W>NnCoc8-eDQ|F=oKo`tYt+D!Q zo~mZL%4om&%+avveAN}}#q(7)RZ$<9uNp?%Q^iSEXWn<6Ep^BO)kS3$^;@7GSLWd; zeeN^ASbcJ#>O<&N7ODDyt}-TFM;YaG%|+ZzO=)mxx zVfRA4VTnquvU{O@S1wcZURtRSEwCyH``NMgOwl>Ao^S0xAu<@pINfk5x4X%N6SK%i zKiWstFOGV>xTN4R9hbEON;NBX313FsskrP|q#G?$4V)$`IrmgVc>9Xo-h^A5_bn`;h zJdhMwb{W>jf?idq>bQ20%0D}+7=5i!b!=LePFx4+hzv*Eh%8pOBS(<4$Q?u$GUbuR zNM9ruSrAx|Ij^w03f93ZRHWZIvbCs^uDC)anu{tGaa$O#s7ty1(^Fqkk)6Ir;Xoy4 z(NukK?$`{RV}BD zozv}Ct8&eLMtxKjryV4@p9^t!9)Sw^mhjdcrxq8fU+&I6s!AKU%9&10PGXb67?ftWgmm z!)XeV8fx3f*VKHH%GWh*bX!OC6C8a}VhBcQF0L{8is{w)jfE9)4z--$#}{E-5zn_B z&$8RY7=`DQ^(qe6CN`b`3En}Cn9RN3DEoFp7P$Gkz}DQcUL}QxRCUr$a56ZM;0^S+ zo9k6rcs(ySnKv!B$J9C9Zv!Rpi?-@+NY_I*s_G#(((U9}ds+I_1{EDBl_W*EM8CgLH7xe3 zHsO_BdA~=i>9kF%V)&!gN^*j_u~cVmQqeI>y;9>TRY}QGU9d^DFAna41jh!y-|}iY zXtPR-U0xiVE4)0p&q1WT_f*rJH>-~RLA$bTj)>Fm#J56Mn%7 zz_Ts4OxNAQKASxTpVQN~;EyK>e(kD@zl!?U7FEmHQ}y)g+r&2zS!4|u%BW#2kaWf? zs-thEv+BN!+ap1KU-%0~w|>!wC4~ZZ#)Q zZV&e%Cy|TDeI$~mnvS$W`Xaf=0%R+42sw+~L4vtqFOM`px*|i6X~+s>CvptAh{#@b zS)>lq5y?dsAlrjktsddxB61(8Lp^syW`*b*dsHpIFQ}px%mjOB=CJc#)l@Ce3-_vC zp84SJUKJVsFVs4D=7S!&Src^TKvxxK%=kigdQ+7PKaI|lB|2lrS$l-VI=j&E`x2dD zmGn1n7Vl?&p%dO>JmNWx-?U2h{c^FF8RGJ9yu65uY_2;END}Rtl{3hE3#S2<((A7T zMeE2SRo3iONmnmonf0VaYYh}{67`xQm1a(>q(2qM7c1HACw`xbufB?6*@v7&E+Y4l zFh;1#NGqf-l8Y=r)`jlMT&W7*QOW+BNla{*uO2(BRFrP~jtX{Jrn#!7p7xIV$Wx4c z-c^zQThOh8uGfQt&3ebX6wE8Qj0w~Kez$l^+N`7Y0ef_+s_;@r?!8v&N<3r^I3grKLh5o`ucu$zcI1hrxOpTN5YqiZ%Rvg ztPBy)>dXVGt=g>T9w44qiKkV#-hF_vrWIR>qA4Rdg zWJz%G2UT#)H1Dx&&`2wx%$5Y0d5|nk)BS8beULe4nhvi`UGKzW$Y3YEk~5cXa)3SG ziw9NMBY%43gN2bXP3it4RT&+Bh$fx?NJ%E?X%fpJE8MI@s@x;*dAZVUioI?>q#96U zKcVCI8b$VMq~;-DTKKDxC80@F)1{c=^tg}NdY-O#-403ulvcD}_dd@#j=rb*6dvZH zGU?axwS#zadYDn`XrzAcpi0wyFod*>Dhbn9Hz9R8|1b~Zrt9U0Rk^??9p^H7{6UIv z#XVP;9`}h)I>`(FfaGl>dE29OqYu2A)YCXba`WSN(D7_c%+Af6I%1-3-c_YJ9dEO~ zApUot_C=HqI>H*@i{iM}zfS=^c0^Tm=9bNR`Vo|0M>({N-hy&?Xc;@*GAmLPMxM2G zt?wKm277AUtSfwor#JA_u#E2fVex3NSr>@IP8>Rx(eHRWJix(!7Y?~)e07)ZzI3*a zRB$+^;~S<>^{FG2*Zz-G7;48qV%70kSvwHV zipi~gKW6n{#FS)27GG{_pHz4LSjC1ncHG2^ta9ACV61OT%KpH|WMDVx%#P8QKBj48 zJDQ#)+ze?NNot19v_S_br;m{reRjVJ(kqXu(D2EQA5ULJ+3u_A6ICvF520UmH1zvZ zf+KXxPgJGi+8d9K-(GZnkI^eXp+Eob6&gu3X6jR)(4l7P^__wu3O{A>=c$%zpW^jR zyq1sEy>SRHA6rtq;`RBG-O%Frz7$Vy;i*Bae)uWFD}3%#m7v$&4hqy=Kl5r>Gd@GL z2-P03`ZXL}J!07e?NTa6-~5c#wI>->j-j>>wZ*Zz`!ULJv6BobZAr!p|2OH!#n0RL ziHOs`A0z1z+`M^4F@|howw?6gU9JGV;26c-=QxATY*n%>9i26`cyyetryr+`W*0wg z^wB$yE1v{!{V8K7j2ba!nB_-qm}l!#wx8?AS(dcrjNqJ_>9Er%93zQM7*Z-TK@;_I7%sOHE>gQ@`;26g(Kwo$Qx15tKv?hlYJ$F); zW39rA7M)TzO!L*qqUTPl*OY5}6!%Bxf?{;5f2(*GXV%Id2~=<|J|%xsODaW=|YxhxA2qk$hw;auhj_+(#mr z4AYTT$UtN&l8V z6FG`pMD8Pz`qWJ|jNAK2UA9VSu>TF7W}lnzw`B(B5q_Y5{EAD$M4fn*L44g044(-T zOFD@x3O4Di9~nM3>F{VD!Kn;0T5tVDh3RXL2YEW^W!>*b+8JkQ{8r@tt({%=dXCN( zvq37XT4<&(jAT80?MF4lB>wIf)ww{tT5d^p&361rRgOxJph%ED$T(yUvQBb0rSK9P zQ4)N;F}mUc{YFO4DGQG=P_NgeOrq>vWDF9Z%v3k}u6(4A4RvE+X z`>g%fxX&UpLD$tgiTfz%lgMSnh~#DhNk>{CeIpAp6AN#s^6Fz<;Rg5WAL~vx)F|-w z4b_iAAFz>4g!Eroeg2|b|BAvddi1Xnp#imgrQwsdQ*A5iCQt zBS#~5WmZ>KJKpzINU;Bply+sRS(eMrL5;Rpc?L2GtnwIp2YkV8Rmbl zSe@7FBSIt6IKt&uZlPVzMvv@V>--g7Wk*KpZ55J%lv`+@kBGnNiqbDt4rs=iAo`%$ zNGH7#P$pBR5`I!Xo?m4`?%@eJbKJO`r>(GijzvL2zX*HcPyF;)s5=Cg>N?im;FUB< zHaySGWv^O(vM=lTRY7Oy-$HLOX~LM?$Fe7k9^uJ^#3GLX_v2sudh|Uj_ubYq)RzIw zur8g2`)*ycaZpU2EBqLK>36n21JVMlpf&7)>Z zVIb^`!vu(<`+3+6E`r@5k3)?fPzD4EQ0lN3<~@+dm+m955BwZH0sjr3ggnu+^nZYT zG2emxp)b8+fIO}a<3a+Af>}7E!NIU590I$+Y?uRw!RMgpyB+f)I2?PPd0OsU9rt~3 zB=%px9C!_mh72v%WAS7-HV=zNT#Sc3A-Q*tfw^!YoCLSSDeyDMwC%nMpMepS`LnPZ zlmyj+(=qpk67DeQ=HCRzeF~h3c`lpihc&98r?0RJjL$eLpoP*(I1PK;83^{j)CG~ zBBZ|EFTgdh5X$50^>7{B3Pn%O6>r3R7;c8g;THHMd2S0&z;HR(| z{0uS^ThG~hz~h()z!Pv36#t{)DX}l$;$K|60#Cya;8*YzJOj@_>9_J+Qat_%zrh@0 z#4`c4M5^;Rz80NI#>y1T^31)aV}4X84K<^yHOH!rWgW#)s3;zP+v<&r?QOFRIZgE7 zq2^O5lm6k<;2-8@`g=l-X;Ew)Wi;cuVR6Kzhndk)O}(7!J5J5@qr=Q*c_ne%X9(&z z&Y8tt>@=0=+2$t2?)Gtl`k3Xpzb8-6ay=C3M^U6hIWkq=3fp@W9u%-l<_5VdlF_?+ zD5pju(F&(%W1$pvAj46h466L@AOVP9dodYCG7=oc_A}BL>4S_zmLc1bBT>6DH>kop zEDLAq3U^eJYvu-}yWCJs^!aR_NUd8CS9RCPVj*RQNza98z~C21!Xad+>sB(1N*@2O5=bx$RPA0lkeuP+PJZsMA#x7|}A zzK3w=rVrdx(XRXtOxq9TX?z@Biec zW9J{LY(OKA^ZIG*%KW&LwQwU{>Q7b0w=14I>xO@F;=GZb@+bLs>&<_vhPL-=>M0#^ zUsVMS@2dhiRB--JZs*S5CkGq!z56QD6HnI%#PjusPBL~)Cm#O=z7o&22ZY*CfBit! z1|bjaaMnHKa6+Lz{*WUJh5Erm)k#9{_?Jp|9s9`CdD-lw<^RQU`Iuh)mwJJ4M;BVhW! z%Ip+qw*X~Su{IXMv+y5`)*u)U2kY^sSSNlA7C(xfP^P7xslG^bXW$ zf~N>D{0q9cB$G9ib=v7G{lLeJwpwHt%@d0ZU$c(7T9oZ;KIr(w?DYKm4a(qszW*wJt?sp}A&;9OJ{E?Op z!RG5G;r|hA4h@`Sg|Cc9bhiaQk$QTFS*c84vXP4{K(-=>kke$VO<|~+>^GAT*KoQZ z)J$}(sbb~GGh(L(*7J2)1GIG#t>RlHB|%+xhYlh#={oc)Kxa&cfO<>!<3 zcOUn}VKxq}(sXK=>3L^mrp^w-;YA!Krs+jt6!OG0AKmt7P+Mm&c&1k2Xv{(5>olDf z?&Wo~ILyT%xT-GncKBKx=Hbw+sx}`nn>!oTGj;n%%yK$E-1IT~Rn_Mn@e1orT>KW` zCI24|DG@j<#9>!eofzrmW1%>3X2&lwUC)a&J@3cN)W3RJGu69G4>>zx@XInbzEm{Q%&6}+KdnMNt4tmqq)9t zohNYaXfq?Qm19@K-ZMTHZHAfD=(%W`=+};0ZQE^NSu-p!m<79p;n*#}&ZM^1lr__& zZa#&9`HoJC?zSu_CZdIPe<|ynU5>+GJHW;vreF0SjBdYW6kDy*XS>daYk7r9chL1LB=7okX6V&Kd*CHJ{XVjpXlN)C-ge$^8uxTi`K=P!%g3pu>VSjB$=bs3H@}ESz8Uz zI|SSG1wj=Zm25t$e$w5N%{M)RS$qm>fbqI+idhNtOEHJ3v--mnvlFI>RI{3j*O{pd z>G3){)$E}v>9QQ~&MoKyJdGoXB`dl@$jNV_)EbIDgx=a7{kn?Oe%bB%g6*91o z8JT=0z|P!q8`l2`=YykDtzDiBR5u}_>T#Am9PtyYv(n5a_3VZ%8 zO`n8(i4}EG^*I0UP-E|e*nvg(76)o@hwnFjhE7Z;f$}u>5IW*MeukYu+36JZI6b4g zZxWB(t)2V)bkiqF4#CKomoS`zXWHszw5lqH5Yo-y5#qj|;C$#!c`rEb1Sg$~R~f8U zB?-x%YR})S2dx7l=dfGk=u1w_f9Oxno-lC)?{>{Ra5kq!fUnnIv}4j2 zUf_nM(hjqd*~rk+9+C%^wu2w#i3L`~%NrgqDYKoM80WN8#*oW(IR zUbhig)A6tX5BxLA%`b`9-|~=&ij}k@xHDTA-MmzI7Ar|xH`cd~ZeHIENbTTM!8H30 zg$GOBE^ZB}&hrIT9*1+^CKphIP4@O4Lu-c)Bh#D$&$s@=Ube z*9)#y@&=z}Q$L|6DU}Z$nsw1_+`!~0M_vBIS7=h5;%tbY)A(UkWxQDIXT124 z;Xgs#<*rYwlcZl$f|R^qa9%|Ivu4Gm>!9(Gm9jDW~dFwvX$ergylLCfH9d+tCb`C9=q-F)rk_CTX)0pG-xmde=->6lw0s!aERU~$yx#gOC?eq|9_QduswJ$jq)jr_pxLCUSuQ~`5}C|h5GD1DqauMx!P0%2 zo6){9KvR*g25>&Isp<2#QX4fo$4V`I9G&A$|4|J&V+UJvA)|@}(Tojn@4QYNoMri@ zTj5-@nU(TR;BQ(vS#)}mByBfU&uC^<;(A+I`gEoG#hp}gb0*n(DrGc%sidSR1H4+f zNwO}jgD4rzttPsDmMhvf#j@^3eiOFMu)AxW%XMSY_yy%QAb#V0j zsx!9auF@S^nmwJlICgt^+p)l-18bnRb(KER(u|F{OfXZ?5%;Z5oYG1RUGq^hNhh~5 zeRQ2i%}9OdimL7e+O4azuzA8OP#*I6HC$~c+US%$W>UNCoN)tM=CFLR7A`x9Bp!d_ z$D=28B|+GCiE?*k-4Y#gf|oJG^Bd0ax@5I()Y@$B$=ZIYW_}-0S)N}_Qn6ySeyufG zJ3=sX&=L0)PRb-}ep>yM8Qt(c9=qc4MLceGJW5g}p7P3? znymQ7O&B|vF92C}Yl@pLz=SLn5+NI-(-EFLYF7u`A06 zlGK()B#D@XiZs;PYfBn~ucgAV)+XloNWHG58QE>P=6qEjyTGC@eo1R!Jqi?=%tbZajzgJYFk^?A;FiGrp@m~$)oeDP4MeI!M7ZqJ$Mu! zU9h9Eg3lr7i}V`t*5Rgz&c@=P0?r@2)B0eSZ zidwa2kycSxX-{q8>uCnlf$hxzu18>1cN5WWC)!u3swV473Qby)cfdnO*khr;73hKX zW?ZL332;!WOM~t>gmN^-dFjj4RZ)M}g({RFx1!P*tIq37QWIpU z^y^^8B}#(NqryOFl-f|DA}foE9E{KK<6!)1Rk4@->d!y#^)5SA(;9WpuMSmH*$K*M zHP)#VJJIpz??pr(9sNrszb<<6V`h5I|Gm%|=rk!Nz~WzB!XJ&_H@+>EqVGIbyzGyi zTGQ5%Z&i4H^-!L-!Rn6*LkO%DI^sUhNuace7?dmN86Bz8O0voq%#hW)6iOw1!M5QE znK-2M;0-%I#}=$Rb~3}T=+}wi6fIeeEa=3ijViatG3V(3-e(YFyY^;TeN3)~;}AZ< zx$lrBCF!iBZ*`(cRnjq?Sz-0HH-nQVwDdZgOBzn7Uf-U1Vq6!-?fvb|_?W3E zrlZ&ezmIzy!>eBfbaX+yv)#TS}sNL_dLZf~2AWX?}-P zoN%0_h$5_n&Y*kx%95s%9?{i|qnLHm6aHm5r;{?{e4KT-AsoQV;zD$ zi~GV?N@A4-4iy%~G30fB1qA5y87}M2J1j21xe@pk4bQJWZEwp~mwx%Me@xwJ1b3R5 zSQN0dmI^Ws?#2E-BFTKc*xnuoE9+g|7|%r|1Fxd;jh6~}Hf)tBQ5oW>{O(cF<2%V+ zO*igp#C-+s!FWl2)f2ltB@je96(K4oQQ@EQq@yB5>BA-z!Q^*mbJjE9=hQ`sUw27@ z^J_qEmplH9!NcXdTRHqUiOODk;yHSV->At zy137_uW#|Tk@fMKDso~rS|92`yKY6ObqKW{q3-lbwIr&FzR-idSw&tniLFSL+Le1B zFAM5W4w%bx^hoj`85LI1O?sMfQKFJTs1vao>`~F--OY&D$s@9-U~6S5pHR|K>xX&V zYr1K7Gq!?!`A6#Y2yT^eOTlffCkQD{%vJQ)J)TFjtQG$rMeX!9{b_GAHuNIFw@-wBQxxCb;nI2UnEhiL*&zhTDC+#0;r=!5Yv-txgk{9k5hYQ;(rRi_ZBn4s z^r=ktm8#k8-TDF<*UtuII#Z!UBo8Y*r!_A+kxlW$1V^zby|9nOa9XqK-|PA|&ZlW? z_H!X+Jp&S-QanfXCr_Hs=gH_co@e7fLt47~zi<+K04Ku;k|`%G6W~->!!gUZ zU&Or&d=~pba2k{k_&f)nfo}fELB*MH6MP=N181?h?v{I^7qIvdz6gJXbKswFK2+4* z0!TR+i(xD*fGKb(>;#v=99Re^!WD26Tn*)Bcny39Zh{<-u}(7ZAq|e_aRgI7KDrf$ zOK>~91|>%~;Om%gI`n7hEang>?xo>Q%*k*UYy6h2--92+ zgLzzB;^GkeFMJ=Cp~enF_REbAU@!O~lmm(%K^|;d$M06cqnHms#sv2X_$j;vKZB;P zeGIPxJb}3${2a=W-_tM~=6%Tpr?stPcXCkh4CasEH}EU?E&K~gj^!NScbH8mW+n%{1Ga)U;Xpq&5^r%a8;k$IrSLcS8oUSJfcN2>@PWS9 z&&*UQMa}w~{S@7J^#C(2Pbup=uJWM9U4|y>2NNJ)Q?d>u2SJ8Sc~;kW4kD5cmQR>7PD(;$u8s0ueY?zB0hy1qA%2dJOvYFTDn z!&8gY^6inqP0bU=F-k5k3he!oE-<><=Zvflwl3II$ue0wuzsuqPZ2rT$oXx+lX?uq49j zR)ldQ%nE__GgM`~q-z$M5qV?LlZ=js5^pX{gi~P^C>0{{GHkii9dmU!9ka|Bd9XR0 z0o%YAU=PS$x>XQ!p`>d*lyohGjA}*!WK?n)OO!r0!mP}Y??00A;90Fz9)-9|x>i6* z*Geemu?k9gtbvlQbxpPO1!(E#JdMdyl+B@w+KoTdmA=^@50XT02~0{gC*r(#VY@{qs$cZL$@9|%8boB zj6yhyM_>&67)p=$1lE9`!DjFTYzx1D-Jw*7Wbia*>9}Hk9Dap)5d0dBfZsytxZlAk z@O$_iyZ{%=Ln-DL_ev~&g4^KFN|(vuBw026SPtprLGqX!()kO{j5Y=zl(P=KF&$ZF z*KWba*#8DQL8d1wUH75%HA&Y%_z-iJV;&6I&a~3SG-joTw^ppT3Va|9!ty7{VtRAG zO#8AfBz+R#4j6#L0mu9v495H=422A`mfj`E8poQnBOs%kWgiNoG0UXQ$Isl29s8y* z0dq6QoCy;#cT;&h;NaqEERx}RmTm;;49Fy$ zfqApTosRu(SPT1Our~Y()`d6oxZv|_?kE?-6|4s(pa$?!%>7^!$l(kl6Y@OIXbFp8 zYxpB<3x9#_;9d9_l<$~II3bV~gF6&i zE`_Jza`+q6usm%>{8fZ2F*6sIvMiVcjh9WmXuR3o#n}Y?SFS7Ok@aYJj+7>&@WzWe zbOI@+MOpoH3zWHVD~y2KVR^U%%D^o#WxzKu*L2LaAuZ6#p}054%tyrBnT~r)ScF*y zIC1X^-^Sd{F*D#-m2c$zt>eFkIm=NP3=d%*3EwyM7Zc1udG;X(WgU3H+S-qkSJUM8 z5xO$U(jBZpVBeJA)| z%;O#NWca7aLVG$F4{`VbDi^O3K^HVB1s@m&{a^wNfD9x?AY@=Lf?y*U3|qiZNH;WC zguCe-2K(CXsgQBQJsn0v8m&x-{GbzwMVxf$AI_pag&No9V2-lXd9Bd7x^|XaDMYV%6MRkC( zIC~6^g4~!`2jDxwxtKe{Lf8eq0=vS!up9gkk`4D4um}7Rk{$O=IUe7O3u!&Qp-eH4 zLmt=5rys>7vL_V z5reyR+9mnl~2vQ2dXB zrQvuei=By3)*_Q&GMo&h_@~0k@EIs$$TV07N}G^H;7rWT;PbE_oDIjoIgqu6{E>>; zuR+nLd*&I-aX5~J#zDH_I?OlVM%ae}*a8Q@SDd>tNvyn<>?!FwR< z8RIQjiblH+@{vd5UDy;JfW6>BIG(O&9O7aM7Kh;s_#tF0H;zK-4WB{=Fyk|L5}tr` zMdKuV1fGIbq2#CZqV?t-taR_SZxdz zzFf#0EID`v`eT09G3P-R6z+L2sOYz6*dsPMsggL2d4@eI>kh67ls1zI6CvvWx6C7L ze2iI7z>b&)KnXt!cE&sic7+oliTc}&+0(~(VK??qV!sdeC7d5&7UrvPFuWx%x3HkF zzI-bIOQ&OD;r4@K4uGRE2f?v0&aqE`6MXdTY34|i!zlfyo3UwA#2*2ZdFwTs>98#3 z=U^I~0i}~Y@1r+N=d}Igr7rzhk%~#&f`be<5@C$B2T%22KJAaErTQU(=Pg2~l%o>@ zIm>SKIHBB52vZ@e9xIZUpxj2h471>RC==WUD698PKF0IQA@5jPujaf4H(}lmrDwek z--0_KLsg!!i;I6_u^avX_rmM&E%+zoEqH5H{2q*VO{~p!;NqP+zThd498Su4z_?Zq5KJh=iyK|3r>Wyp?o!W4tx>Lg#~aPTmuI{Ij+W5se3P61P{W+@WX&~ zUODIDGb|)0C*d;8UpTz(*x!bQzD13mH`kbfxvT7*!aCMFxM?fVFHfg=8Opq}3WgXX z*hr~f{7RiH?l>}&INOY^x(;_)9 zK>LJ?GCtBZ=LAILy@MZ#^8l1-;5}Fl9)z;6It1&&!>~2{07{~z5M_n>G3Hm{QTR6e z41VOef99A^!QUqQLcJOjJH zuVHWa4a|n$`5H49LP_9acmex-_#>1Bo7leuFJXRJ#k1bwVmlUB;0KO^Ob5UC>L=%z zD+BFQFN%j#@+P(po67-ihKd)YCVs;YptMU~4wa3U^=oybxlFqEaF^2k1IEDzP)he9 zYyjD|x0b1fpZ&3a7wm<-FB}R3pe$R1;38NW7C??9SntI~z)hIh&bM~VqTvC|G4OLK z-8e4JV37bXz(jZ%N-6vflQBPV%%w3Kk3&sBxSPipe zxH@d@Oj&I17_~8XFzF=>if%Srj0SKhYy?Nb#&8;J0%f_&hY76ZZX5l=Jo6Q^@&;Xf zz8PD)gP--%meCdGWYXCk)`C5u?0)oyt>EJ@#3)TgG}h0~H)8@hd1A;ee}dh2pTa#H zy}pn-H~Lxn1JQ3$+!yOG-g5@!8{*B&!kttZgCIkKkqsl@P#6n`!3uB$%z%6^!K%=) zurucIus56tWmjer90sSrTsRfZgwMc*@L8A-rCeE6Yh*FM!NJ?v=7yTFS*{ zEDGUUa3z!*oK^5TTn%r-wU8ZGV;u~j$Tq;{a0~1VnZ(=!;j2)#0k%Q8{by3MZvS_} zmof7I$-M>^!PjK9#4P9D1NXys;Cql=7vm5-4-dmD@CdvOKZLSMlAQUoSos)pC=|17 z2YiOPJvmT7iUhhK zt75|!vdT65;W5aclXJ5;HA=y2Fa)wjG)hCy9wSRTBMNgYjD`u2^?{pN(uje}q2ye{ zcz;$)D;$fJFad=kmoG&)?JI77(()aDNZO;Z?{w!+i@@g#U$=AVZ$j*ci&J zh+-jsT#8i_KS5o_zpES%-1x14cPyCv8oB_3$e_leLU>AJY&< zVr~Sbhdv6Wr}Ot8t;w?)l$)sLki~$}0?Lj-E7%COhRtCc*ao)srxx0A(H@Jg@G&S| zn!mW;I|0ed<;ZQ90V!_c?_q%WeJPt>~i;&X=?n`hql&L?QLt5c{_NmJfGbt*AOZgIu z{4E%9O1GSzUt;z$m%pmNS;APypYpUOr(9T(aQI`M*7KC9a5`rGaHq9rA_ZYc^C}E90eud zbT|vMOimI(reog?&hgi8Ej7mk+9z%lfB0(s8!F<-1*l0&VAX2X^di^;b3U933*c(F z9Bze$P|8`u51>T*A$$q5uBp%T=oGtd=tBz0)G{EnT)o<4)Ap-8x(KAr{FF)5*ESd;M-6Vv>$!}55Uv#Ap8*? zfFU3GY34 z0kcecVt$|T&iKJ!e^h98cJ1b*&VaXEF^QMZkd*ukeHfgHK9)&NsDWaZCMz_sSlyn$r1RRSBK$T(yHvI#kaoI&m*kyK&>q$@HNk(WyL zAt#YL2!HU=$Uxd5Imj$z6S5zIsU#NZi_Ah+A^VZjNC1OjGSV37iR2;+knPA3j#6$&4(@-)xRl{PiClwiQ#@E9OI&nxIQ>GbhUXP+{A6 zhhW7vvwyK6c)OQ@kDc}B+}rot&9R`%4hsiu)Og)8t$p2mR*uHK&Sxz%-Y|!HuD5$# zSKevaFWzbHk>l%Dq`tMP6#Rf%cf9v;FG;U05}jVPV7*Br$4=X*=y8Th6r zyfXT`H_dEMoPFN1><_+WrL0Dgoj@C<_gSXAeO?(4c-t$l)4UBgF;J9U-r*Hs(p5Bd zzxjKhYFIS(BXfFuUIyjf3h9eXMe>oI$Wi1nB5wyIBMp$Ah#b4mN46rzkc&t_6?BkR zNMA$_TdY9#At#ZWNI)7vA#ds42RQ-znz@~#fet+Rssk*G_&y*OO2zGT(_$1j=V zr5QB;*-SU%TIn%An~B0jKbv={U0k8XIC@aF3gSIzkWrQ6E5#6;6X2Pf&cU(9f`bX#5h7qhpS+*Z&2#q1bU+4_sO zY_GHNSn~IaC6T2UsP?`*V>5;qHN0j<@bREly7RB*JoQA;*T0%BMU>y&H0Mi*BX60r ztM?_NxyS-!Cvp@yi`+pXYf@WCM`Q?+U(^0W^o4iKW z*Ug{=9sDycG&wq5yd)6l`^6pXc z1$xIlvuaF%m-0~*48_{Rh?bP`~sCeYuKr?)sCItkC!Vqy|^$l>6wf&@bKhL>#5>-#5z!oaT|Mq*1@Wg7d!_ z4|vVsw9b5Bz90>TTaie8_5tBE)xSL;-ljU`q2;tZnHcsz#N~DU3 zSEZQ6j(;ipJArhiAf_|&`HJ{|mOruclIigir7xQV^D`g2a#aG~xi|;j%H^s~5m>Rz zak~)73QupPz^wE1rI>4xk(hBm=W=zFIbo+ih11-JFn8-GeE3^QyYI$wBt(W{3_ z8MVBsL!0{Y$>u;;JZ*V>plf5G-8_{s+Wy-#1A|=a)WafG%C$|=tab#u@@O~JLR{}s zLsvlH>pa7kewS|lfty32u5mPmnx$P`sQVeET~AT#`dn$(lYBO>VVFx(jiGT8 z;jTB#b2oJVxA=?JK97)wpLNP3uDn3I=oNqC$ok9I`yX*_r)WbWsjgWOt~q9zn>sYo zwL!`$k|bZdX{TUvJ#H1nfT#HW%f%>HWlABWjH^rDWjea`S_GRi=}0R? zUT~O(tU~r8^0vZdMBXeYkF-MuB2$rkWGiwAIg8vu!s;+bAnlNW$W%m*@b5&9BIl92 zNMv0@|JuyuTdNftlzkC7eLn|Th3rL+BIl7iNN_#FNJbhUUF*r;#w$ztF^eAv&bX{TNTE;lKn#Xcy)(bx?;R5(S&W{T^;db{h`3E@vca} zP~5xK(ud<+)vI)?<@vI&EBrjoLhfFYVSmRy);TNxk`6EM&2&B^7NWBfT;=@Os;V#xYobFXV0FIkdP3UxW-)>!L@ zK@bGdh6X_p1VLyJMC;zrXvsql8ZD=^F403bswyolZK$@WwzTxnYLB+GPFp?N^M2RN z-pS_t`|eMEd1kHWvM#gMnl;bNtc5I&Mf0?eY*jf~Pp{%U{g7;U7_uSA-tdv7dosj1 zZ#*RXp^~kNtj5zBYuqFcArev_S*_iJ`JGoE*=oqv@yf2-%4#OB*C)Sq9+IuofV#o) zX?AWWeHw6bpbr#&S_unXl{C-;OrGGF!`sOh4fG~X=mS#28|n=urh)Eq&TJ=(8tTmz zRT6&oCvSnKwA$lWO@bO>2mB5*HCTD9b)LLU&=r3CPDn^oH@fogKICGC;G15yJckP1gCvc1fW@adR` z6{9(fKJDeJ2nq>(Ky!F21n`=hEJ6<%_!?PPG@+Cd-WWN>C{=;r!rFE^?qT!!3Z z(Oh*iRDdzn3T#&a22Cq)Sp^sstw2a80t|arAVCEf*Q~%&6<`dr0_VCLE;-(bNfhIi z6?0dy8Jes>%gzKCfUH283NYAMfz2wwz+wf?s{n(D6$t1;fC0k_v`H!NlK3vzXN0g~ zaul1x^Vt==qvOAh982t!N2i09HiJ)#s&^20hBU1GQRoA&HlGeUeMbfCP$lEHC z23)Z_k+f4QGPOIAw8=#(lBQ=xo>P&uvL93=ZOMv^=|LpzW^@lCX&zQ&Q4hV@;uFjW zE`i%1q$3w~5D!v84p;%Wb zC2$)Ab>SwvSr?3fWRL~&z)o-+Tn2YRKvyPNAQ~ir46qawfuv>*l~gKUrwc7o&JGPnx@dSDPl zgCvmAV_ob=)~+Gh_1OL9HeJxowlqGQ?6LbzPi8qhJ~8h+%sHtzJWw$!&Ur{Dyce9G z;q-o(vqo|5!pVD>a|e#eV;S?t9H|+ndv`s)DZ}Gn`~u_GIkG5DuWS4|hdGSg`HJsb z55?(aTkG6Wg1;j8=v=AUyYxcAo;$r^@TA9le6B3-&FJ>{T=(AI+^zf{d%$Ef^tiKR z^owj2c&m?|=1;MiF{y`{*4mfnX1ZLG*;jAlPpK`2y*s%a?W-r~s=UvSEEg&piG1L~>vjxve;xCJBITl;YlBA4&=(+m16q&XZAiYX>uE&bH8RZ>%^%}BTUfPjg8Xp!+(6Lh97{tx< zN>NMv$jw1|K=2VC5i}7Q`=s7iJ0b%IlhPZc^pz*2vo8gdlZ}J*py023GR^(8W0l$p zxR$kQ-YQ|YyHI&;klsqd5_Laqm4qj9Ke|fRZ7^yXE=zj<27}dF6RDV0vMf<=9b7Za zt_5`~VOk=0`Z3SFoJa;+dw8mb%2~XH`KSjCv5bcf(OU;T;}NNbh(E77b3*dp)tY#2 zMUKdpA#@U61~Fd`V`J7FmTw#$6!}f$z73PDL-h{9-}
1<*?Sg#~MF3|%eOa(8g;M0$2ffA#FzYW#{*kRiUl2n4)YFV;SufpY^ zej+#ddBbSS@sv&ShO$IM(J;1wOIN{jiMkI(3zV zwPD%ak$STZjbiCWAQj|+?cfx+3IcjEV1js%3i7~qaJ1*T*u4cQdYF+ymVc7i!T$B7 zPYU-0F98PBWD@a6K;IK6=$ zj_L<1nVPj3uZQS^2tBVtspA=p!!76OP1!UarBIZvEtj>!O1G)JDMlKMnlNrImsV*$ zqx4M0s0E|R3VF_#aRo-X+Atzk7}EOl@?Fc>P2;BYn}A9kIMFMl`*5Eu?^g_-n47&; z$Y&FD?;6uLC3GT;dN4-tq0A$=u97FxXGg3k8`V^o=krvx(bzuwyK`$pvVHc3Wc%z5 z$@bYBlI>F~7%Dl$eK#cAXKzTh&)$%1pRgfWEh(Br&)O&Jnz&d2&OYAX#8q8xO=5@| z%$s!@DSMq0B=9vuURXN)YM+Fs>$U3a(|D-q`OTV;mdGM*mN;W486KO?D0owLrBl8} zl<$>1>5{B<^6XFK+c@Hp=j2=0F3&|Rda@qn+tAwuPKNVw*cT zTc1tQ7dbgOmQ>bMq#{ssE;xYe)5Hy2Dx#08YIueQakQaai9k@r0su*P~G+fQ!v~ zhX~i0^)eW)FYCnu^^|l0{0?$BOCO_kmC!kQi^W`=bJdv7$e~u#=kdDz*(_PLo`RD# z>xI6)P~hkX9SZFa9R^K+PJs@BE`tt+E{Ae$w4RP5V|_O^9Qsejtpo;C`~N4HZ&93 z5IPIm0-6PlhR%hmSI?L=@xsvn-cR7*Q6h4nqoIqS6QGNs8PHt*W*5eGFFj;vO$q#Ii0I_bOsI-=MsH6-|4Pef@Xw!{}R2cYVhAbfzVm0|D@hp zTO>oC)E7G|CCW!nGX1TT=>Gjly{3kZs>@(6l-|p5gm0IV%k+-gcK094^r@P*UnZ}> z#1z@0$U^y0kriUB)CXu=WynfG-^j9+=>IMUSL#peZw>Q2#@oJ%@?MoUR_U#sSBJ^j zubr97v!A+J5AmnEtdS?fc82G##u#p%(8p7TcX#NIst4=tu$S~WXWbKMTmrX&A459qrWP|Xf;oHSq}+_aXHN7 z!=5Lnql(n?$d~ot`rartkEa$KYG}Cuo#qj(DR)M&E>hmhdX3EMUZW`Rx6RoDox)t5{6@981OMZqOk%CwB7|-;FmjX+tKlc$# zJ}f`HqSstp*=4^Uq-Y57s`jcvs}gPrtp@D{tqxTKK6b26cxyt{5Ks&HEVLf95E=%3 z8CoBD5UT9Cp-l*%fHs3(gz^=Z8lo#ZT5_PqXeIbNG*UM0=84X*BlZ`(S_cW-qt~jq zluF+XPJruF{(A*`8Dny!@m{^5&f5qw_<+{l%_=D`tIll=D=|fMvwRs*WIYjlwn&fA zPDybQgUl(pQKYX?eJ*Ri-crkyZTt21sC}{@nR#Noip)HB_^Z06-e-`O2lSTCRd31{ zITad6&H+6@1u8DAknP!rw5Lx)jiv}W5_(YYMbe`V>XZCW@$Ij=LEdSNwQ}{Ko(?=7u@*QtVLGU9cs3Z6d6v)Y|1s*e=EuE!!}Mb$V;)IfK2z}c{6buZ$uO`n2wMu#nvr+>$gbkwv2kKOt=Gba>mFU{zU396M=kd)w0d@@?$YmcSEbc2Z9u&|K#EM3tzh7IMQU zs?$lLI?IrgmLl~S!G0`noV04YM7-nWRh8U#c#J;tW!0j1yuZ%PW2yu1=xW_^ ztK7F?Yiq>+-LhwL9|=kKq3ME*0fr z7s1v(P#Pg}<&++2$46)vrQ2!Ch?V-r(^QlHEAr}TE~C)TPU|~W4=Os28t*N!dE0w> z5Sy>Vuu-_R63S^tRekS@HqX3cr2w z+6Ve0+7A+V4xvWUTak;h@EjNI#7?{dsSs>k}gPs7RKP|AYte2W8+V3|Qx7-6zQX zh}`phx+&L@(_OnTHJ0VlgD&BGrq8vy#O+Q!i`JB^OE~M=?ozE$Q_C8vuTTmvai2dz zPG91&|80rA-`XN$Glq7zp*Or*i@UhhR3?EMOmpR)k+@PX@ z=qSjypmQKvOEx0vA8WNx%~4aX-SAg?qH~oRTDpPHV{%O?%#^^-A#0@b=M?L(EF`2K z!Suc6u1f0txy=~ z1d>4}SP2TjA#e`d0xoWq!aygGG??3s3=Z&8=xqiE zz&UUe+y^0edpdzckOlHUAvgrigImBQvB9o4_a_Euul=CcwWo4FGWnZ$_wuKdkpIUiw21N9Dsm)b+<*;ZObF`fH}^a`}n1 zxv`7_2_O@!1e?JDa1PuAH6G!98zh5FkPmi(bKoX$QTE!P6G#MEAP?*YC&1-L*To*g zhZQ1+ZUhE2T+YZ4&4&+aw0A_urls|qla)1N`s}0`ELJ?N`?xV-&()a6r4Gxaa6$mqfTEj?3rZ#I5XnO3m0 z)Mj$le$RV3%_h-`21C`{FT&Bs(brm8+x|XWso7aBRXgrcQ`D>02Is&4YxT@BH9L=9 zwf-d@HATH@tsU`r7jOgcy9@k)n(wP$4RDt;Q9GHl4N^cB*qpqd(WjuYE6i+)7xKtj zX;Rr$S3k0r9nI9lE4#9*Kh4H^U+_|8S4jJ2NR{wyyLIj|W{ge4u(}mE2TfxVpA5sx zR}*-mc@e9A6<2j_nslz>Y8vc(+Sc~Y`lrdvDy~{^$KolL!YVF5=QK_JY{$DF$E&zp zFiuu+H4J~!qo$0idY+~^EaNJHalq?)pC-W}q_WXRTvY_oFK7d_rm`W##j6FBqEWsa z3vqd$IW?7giqRZKmwahZ)zu)l3!mt#VtR`)U9E8I-AWEaRgrIj{7?)j`Jw-R`N(R> z^C7i4C0|BXb9w!fO=S~|_7O0$Jq8?;r_Y`+E6b|aLKj1U!B|92ynIzuq8&4Am*ot5 zvF;fXS)F>EAp@&Z{%1V4ytO<--l&e_adUN7P;dmFfUANjp1Q%Zc(L_tH?C?1UZ1jR zuQUaOy$w&=)NnO(maKJ;tl?U&>5cMTV!fkwKh)LC->xvtQNzAw#?(ZV%9&Er)ze9# z_ttbZcV_3iKdb5Lu5~y->pKOmg1aDKgu@XAI)NmR0ak)Sa0r|OH%IJ`eO0qv>2+Np zW?%f@bEBn6T~`z5+-Ucpx~>{(T(mZq%&CV!JObI#Qc%z3-9)jkd|J=dP{QiET+VsX z;tccQ^bUiQUk}cLXqoQI*$>AYfU%rt`OKG5r#_4X7>lB%PkkR-s}y4(jK$INsxRZ; zFeIivi7bhhx($3(#x_7@Fe*<(%W7Z78O2D1u_{`A@nv*w=xSJX2#l@Kp3!vDgsd@r zW=zkL*hDSd<1_Co+mMsn4M=lGw7l1_wC(j3|3XwqoCeAR|&U5@ANReGPdSLr3BR_P_g z=0VnzxaZ|VJLZl}EU$a&WHSJv$R?KT5Su86yHVaYX~*DdSGLwQaj}N|M4sW^Y~pHO zTCC8f)aoN-`Erc(Z0b`dOBCZ#7&l_%Wnad(ijfTCevDLZ=A$vB8H^Dyj96aY@?jiS zjFB*E$I4f}jQZg)9)r<1R{DqgXsl9<6d2L5yv60ixT6@OVDyfan$3L}Bbvh)4I?Gi z_Zd!KDOQXzFs8)Hcg(vTcx&kVWg&Wz^)5vDa-WH_;XI~lK67_Ki^zSK)TKY8TV#OE_V{A|P&X*Ap z0V54YQBQd!!bf8hjEWOrxXaQS9pRIf(F)Cp2)x--TD9`goT(U-V4UeG&-pU0C`LMr z^1Z}t?W57JHH^tHf_urV)~+VCf_vHJQLy0q~*Vc#mv31r}RcU7&Bpf&`Vmi^I^E8j(Yy@VvgTNbc@{_M-=T2xYgmI!w^LJm(T?m+q z5cn!ij&$KM?X6C(R;A6RerLFg;eHz@-T#NXNpYE9ngP9S-OHU_ZA*2lc7eMDZk66j zH=&fVPBET<5oxKFF#@~7coIe@OQRy;ZMt$b8Rb!a zfISbkxg6yMy=8t6ig`5JNBNH8u7LYQZ~3$P!`#W;;I4#Q=+WKX%}4i|;;w@Gl1KLe z?uhPiSHpeJqr17gPmwMt?o)6-v~XsMMk&M3wj7{7Q@3ySfv*DnU{ zTDT#7>{8~%_~f)0uH5cH71iov7xMvj=U9~UQSRJFM)srP%pdK=NZ-G^;~TxGdjr5KxF{OU=rq_8R|8?9D*`L~%2&Rc;qhob598@F&F_3QHz8maA|QR`t$3eY8vS5wgRz${%li2+W-7)D zF#hN(&-L@kIOIJW0M7;FF0x2n4)@z+{hr6raZ#x_E%kG_QUF)^{Q^GhX^9_~d7uV(fykI9`tU zGPHp(UWV~*yfh!^qcKx4UV(8oUY_%1TvLqQFfLN&K|VzrJ_yDh7}w)vkuT#kjDWo` zYWK5?CZjHr^Gbt#a^7t)#ovcaLyrts+%Xpesy-;SA1Sj4sTTd@v%x-TH%^4HA4cbX zGAPl9u?a@Nt1xDI(;oNt;0e)94VpCtaR z7zbgj=qGiD`Y2fvUq%l1VeCMuPX^{J?3ict(>L4Von%ebQ$Z^2mKUuq`%XpBmR z@ivSX`pa@(#%aYk0po0c`6=0_!FL|P**Xd1f~O3$z~7U7Mx0#;nC~EPrN4YM!bdZ7 zB%1HS_*a?cXCqvlJX@6Xg`@7qyLdMdR=4E*xT7llokFJi0C{z!kJ)?5>}eQv2b2zh zM@IT&X!2uZ=sg6Q43K9Y^U?eiM#cAGM3rei_n41nzZ5h}5J(*$vr>FC55uT<2F9c^ z&G{)ln&G3+Jd41L0Wx%ykLD&A6+eKnyi9ZCC?8G#(P*AS;Pe1#JK9Hc9*l|~!Z=r^ z*=4kk=C?}oBLprDkji6xG)Ig<^J5ramuc1<R0rNZpl@sJAU(L>`XkLI3nowG| zzx!(LLcqL;K>Y;yDAgy;(6MNK0;6@A=4YusX|6)RyoA7{1bKC=kLEoX0iVK{?$MMX zS9wZSGS;UfO&*8xXUNP=kY~oZnuO2w$a)=Eg+4B`@sYM;OZkBc<=Qy>bA@tmoU2}_ zuat7EDQ)F#DwN3amQ=s-+*TLLWSguS@9N7vimh)Q zUQ>q+tV7E!kU7B>z_+IL*-F@GWJM487l)0lL(4tT#5%+wP|Ij)9pWOWWi<1~T5bYm z!g3iTPPEKf$C*CI`98-*KF8;Lj&J)M2Tii<)R{!JZIf;`8D*1&HrZm6H*9jnCV$wZ zPP(mUlTkKVXp=1vIW^A3cD`pcK37h6`H{q@={Nu@4zg=moj!Gvw@L71SM}g+K5bx9 zCQAuP?0DQG36mLA)5l{dlOt@bnrx-I%Ou?#m#~_m^sz|_8 zSB>B=e0Y_-yy}uL)fEu@wTGu#Qjo=)Jk`qfs;SgKKh|orasjup#VwwSgLIo*vB^D1 z9pCyGH*3!9^meviw3?+5nPDjm%&@FZvqP(Fvcrx%nc*5n`wyLlEA9%d{Ma-*Rmb4z zLnq9hJb%K2uDB)0nO`7xX_~w|&8O>s3nTbT7+-n~%*K}|!C}5v_30>IMdq7nGJm?y z73&SfxCY~gY4Wu%BYXzk@+%m>Oru*qr}y%_I^(^rsD~M$V0o(OhDv&VC73I7b?S5jGYl_o} z1Mi0{OyjRxJD0nus5x-)(Gkg);d4kFznsM>QXG77ic>Hb2JSbD(Q+;fTyB<1j^f~E zgEPp9SM7_r7{_^5{&CkAPJComzFpa5%XW!rj!@g<-6k84H(szWo+aTd1e|!j&aNa- znC(h%;_dn&n>xd}Wj}t7n&+ymzo|m%xpu}p6mVZHn&+D6#9O73DVR?xwqwfjtAD_= z=$7-bh1bbSWjzAUm|k`&#}x;!QpE+Nf)mM3C24`HwiAz$mF>I*$m1p2y1+G3KZVGc z*ZgWq)f`tPC!V0aIpj4a#}(tm`_pPQZ!K?896Ua7MmllrSVkHx#7K)cWdzT`Ld0?1 zSe)I8Gdxa?Ekqozj1?KRh}M87#(JbLsf&=u?P9Tx!g4+zCubKSk4MFdj9ZL6UKCqC zb20L`Oe|IjEGHh4FBT(@FT{#W%0<3PZ;yO#F7o(0EY@XMPJA3c2aiI1|EFAaX8le=BZcH%0mxZ*ucF=v&lHt!b>nMcby0LRIl?6K7}qN}SgKQ3Oi zx#l`IsdmfFT8;QjTYUFw#JK}Se4>*ZPRn}CQ&>Oi70-AI@r$2}J4!=0j?L|PtQu!Rb#F1Q( zzk+!6qKX_}QbCbwsykM zxu38r;`}pIToV;i6&LUKw;8Y8t-TYf!pI`;y${PAZQg_!u$RGK@N50LWfkvwfn z=B`JQ8N8CLDSOttYU!7}maoHeer;Li(}E3ThX?LYlAVkVFhUb#(FSr~Kf#lcbHwUQ zukG`Ge*@=zk}aQB0Eg+b-E!9z&~oP{xc3&g&T7tg2g;(2}b+-~cEA zH-TdsRS2R$6375~U^_SgE`$3ZWI8e+0c3!sU^_SpE`z(E#tcpwNCFu%IRE(^>;xs? zI&g94Q5!^qB#;gA!2wVLZUeuWlm^6sbfEU_+YXL`tKc_Kdls1i$siM~2fM*}a0`UY z#>Qg)C4zL22eyL}a2*6>QKcXWWPr`!0JskBgO+p10LTDK!ESH@Tm`>@kh#c!1ds-n zg3aJ4I1lcE#Q~2a1mZv%$N`(d0dOAN0s+}%1jK<9kOS6(1E2)l0a^!Ka8=L^w!F>?6fB^)gfGn^c>;@&^I=Bx)a>zJ{11TU2 z~*Iqvj^760@bW!eG9EbTGJ%AzjYQLW#!^8UO{Djl~%i*54b@v_7+i^~dhxwtIj z32&7hAN4tI`L-2rorleDmu1xNgmpaTM49QUc9bQWaMEI1MLu-0tZ}%*-f>lQG7)Qi z%EiYl^89ktP=xXPu7Sb$wjh34IMVaQ!FI=Xkg}Z42&-Zw7wTIN5#asAO@aXh^#4dj50pa_(J z>p*>6R|B*JaUca`fjqDs90!-cT@b*)+XzI1B#;4CfcMxya&R zJ=hISfXm=62w1|quOJ4bfGn^c>;@&^I#6Ht)c{c-0c3!sU^_SpE`z%upra2xooW>5x;JMk|Oqyx2L^+r$xPJydHeact^bOMPW3*>>F;5fJp z?t-8^Y7fML6p#(_!ESH@Tm`>@pf$*W7?8Y%H&3%U$OpT@32+_U2O(>zJ`fL5K@M0C z4uBGH3%H)9WVgJFBkfUX+`y=(KRQ{L!Jn0%QxIVU6}U`Xh7m@9`+5VT z86PE0k&2Csw$9Kg(zB8A1GhYpjg4X2NmJy*6x81*2<5yr3DT=(Ht#$=6^a~rlXB3M~;NE<_aXCf-} zjGSy^3?x(~lF%lJjWpC}sZXg;p&YhDdRsy-Nn~3?t+Mf?3h`YA_47<=H#zqdn6v03GI!B z+T-q3?TttIm{P8FFgmjAW@tyqcp1{sXvYoYG8Ot--cX^R(BwW3nH6ICb+Rn$v%6bm-hrXIgnQ3vg)m>xtOl~Fy2dfSdFQc+Y_592B7WJHWH zN%yC04&`w%)?YVkO9_%-QYa91wx*oSAk@Z2@1g>a1PuAe$O&4 zfM}2eGM;smb1dax=d=4`k7xyn^sn{OIFbIfewzJVa={QoO}2&&p(UJ>B}0rBkUc|; z>e|2M0SMt4H-XkoMt3n@4tT02hkbp;xX64d&yPnSNv!rAeayh#eTXDTc z+Q;gdl^nN^)jObLF>zP&JM3;lrZ~vlsb;Fj~A-rRQq^~I?lC^-%!Ve_VE>U zeB3_%LmgkWk9iVSt6-dMoVwks&c{o;Ga>f~cRPM5I4CSq5hfPk} zo+T?~!j5J%%CcSMk!6wUWvTcE1bvc@5W#LYm5ypbQ zW(D%W@hH02;0Z>!8Ao&5^NTE+U^LM8{K5tD2d$g?>IB1D!os>79iL=`n7tAE@fZ1Q zl2JGCNA`a7wnu*%JKCrxZQ7T2X>CO7Lt9L=kL&kwR+rRtBPiJYt1Yiy_-7PjuZkt< zM#JD=e4>dZnlCY`s~rqD{7^|W{H;vUX+;OSSlPeEWQ<07cnvVBIt3~nxl;Tv#3(N* zlZ}wzG#>$%C9q^NgN;Y-*kq%;=eR;UhcZ&G%!oO~=%U3*>=dJ6xjq!U=YMpWI>m?x z=D;esDhc9zS-oot*NOv_QqE7I^V(OKIPsrqGz{pA>IIL64EYa>e?Q*K>3y+1PL?54 zE*_aXnBO0i}GG9%$O);tjW<^F?Ia4*#Rp=l+K818gu4-88p3;4zFq*TBFMKsjAwh86hO` z?KE0*JMo`x)T+bAMxFxkWN>oYtO?_7E9xwg-RVZX(5pcVuGGu>?AYUNiiX9Wr`Wz0 z#*SB?ve@UBqL4t%8kqkOwFpPqmnf=Xw$tRf`4wsw%rIP`iO9?(ZmC`-qpG)^)R{pF zd9c-nOzT}XTa~iB#U4JxXc&4Nb~S>Z^A&;0pUOZ5i@k1!(W|-Ybm|25^qj!V%JBHr zw~6(iUHMFZQ~sP`#CzVx@oIVB#<}XzQnl;-^~Z8^Q|4wGF%N0=@uZbf#gc2S z1t*2tX+Gyo8k&d}*Z0wLjk--!YB(HW$SA(c&)co^;ElxBCVssgFD+`BYl6MG@ET8+ z*vE}30Yk92)uSu1H3O?Ouu7ARdZU`mb!mEDw(8L8n$uAj$*Rll$9ak5P!^5w_~S-M zo%Lvhq0s?}W2Kp~Uv*)1#>b6bExcLqp3nP;tDo9=$NL*fe*W(7;=ZMP&5H0(0mWBw zEq>PrL_T<;yrzO`+Xl{g?LdcNs+iSXd+ccAt);w~Q$8HQ;}v8zf`4(! zPt>vP?)EYN2wEi-{ z5!hSV&FWjmtOjQvvH2pF-wl*wi~i@53ok78RZPDAz@35CJ%KKZv_=KvNiE=mHx(J;6^1?L7`IQ3^eMitBu+gO6~Zh1aEk( zt5T{Na+k8(M!C7z2$9=g@iIiSTq7VnbH?Q9S%@eT2QZP1iFCr{gX~hO`L3$vE)xC( z_0dIoKVignuy?I_xbrk?j37VXlR1vO&i2@nD^6PHq#|e2hYIT*-PU^ys41!UHy#7) zf~3`xM)X6S!rSs(O>Eg%uL?8`t*zc zPT~WflqRC(2$n@ljRqBS$cY~^7C%__E;Z5~y5M^AyxU_*Q+4b4O~TR#yz#1{M01hn z$CeonSC!X5ZO?4Pw_&AY;9O;Sb=m)nKi&eUEuhqIpiQj*lhNv0#gptz7u~T{Jg&@SYGL|%v1JpiDM^Ch#X_ToTy~1 zNfJrKpsVy&lFV`=!Q-s+wk~f9xLsFpmZoBKONh*0VZ{8!u%E>0aR_E0_>U0z?ym*o zC3Yo((-6EH!XCgz-6qM+@r$*<{Z01nvKOc-jmqYF;)96qMYv5>9E_ap-NXeDr+Vn% zs=R$Gthdas=T%8FUQhC zkCty*nP^?BDs5LAaevW!;v(!6JPpzc%tWgOiP)zqqQX?Z4EInQiHB zHui>AlOLY?pPKO2pV}Kt{kGV|`k#eXdNmoHXVk5jg4GhB_{4E(OZbcQGd-3(#IiI8 zODwW%t}$XJJ=ht%<5*f7JK@7NvHs6RE2_F(r;fB)Gcsq)$@2CEYy2jOHs~oGubkJ} z&{g)V!P(I42?p$mtW=VYjMCYSPD^xD3w+jNTitJ}*=tw%V~x?PbUNJMb8nF&L)J1U zdYs&R@6nJU!vh=I)8TZC#kb=@4;H*^brGq6!DuxdR_~DE2aC3SkGJh(d_Ps>>PCM* z33}RM;sB~ru!(RRPZ*DY zeV!E5sZl9)Q%#|Yq^~!kN=I(*7}Bh>l`%&vHG%T{a>(W7TJp|%?oiYw5qCSWb|n1E z9=j@Qs;hJtZ3FFxo#1Q|Ym>1o?H<})D{D>O*6p%%SOi|_umF552rkQ-O*r#*PgfTZ zwY|h6ghOkWH87RA?h;sF)CyH1YNv^L^rxjhBCHd(p1O)j(p{l(@Na=cWHx(bRHn-* znGkz9$rtr6CROlqp3{aXtb@9ft6;+DE^M7b_T5GMYxBWGgp^@{oE7uuFQ}Qo@YqUF>J@k zj^{Y#F>(?T8ROGTv&PwtFb#uo7*x*3>8v@bx{$ius74qgRsUvmi?o;W@s4$^Jmb<; zPfqI~=>4(zw7Dc42gob37~Ban8v7w~YiHf4dAgVYK)7(ltk}&D?y#Nbt9P-P_@2RXJ{M3T|8m6Jat>bBcV~y zu^u`O+JW$7DC^bcE`WB{*l&C}2VIGH2HG9E1*!}`52fmJ3q9c%pgjrigvLQx;MdUy z`Z2UG^dht$^iya8^bSNd<9b-7O z3G`8DH|PjxFX%{UKjZ%hc1L3hAx6$fhxNSBsQVzy)unamGx*WO&x(d1*`V{mKRF&)q^l8G!p=+RLpwB>mhT>Al zZN!YB0NNfZ(8r)#p{!Wq*alq)eF3@-s_d~`!eYlxB3O~Y@pmZS&pT*{xqP1P*aPLu zV8=h8e2(cj2>lg$2wJWji()~mK$W4Yo-kVvIF1tE2YL+3cI}oNyQo`o>!HQOKL>pq zx~&{J~Jfi{GG0F8lu1WkaRhdu>W39f-&BK#Kgb7&wlpexX-(5ukS z(66Ae(0@YvLFqxc!=c|nQ=#8OC$`~08BB+=B7E)?56$(&KLP!d)3^ru6MT^+r+JGb z+Wqrs(@HQ3-_tDn2#Iis!S{JX#O{LuK$SzO-T>LbIc z`LDB_oElH~XP%`@2_G9VPF$#KKPDfx15|VD7VSF|lOG$I{Pwt0{WXJZQX^!<0e8{Zgj`_q`s`=XvEzL32PW$R5@?*Q9 zG{;&y->IJ(nL5588T_Ij_l=(#&GdDIo_>kkwfT%{+8QK-J~Kw@UlLpIQ({l3SVyq? ztIt&BeGu&a>2sr|=ETQQ@rp6g-}YK)j)8Wah3458yB5UZU;twL!+~2@S4LdGw)F9bKe-r z`odZ+`LU2MgyL>eFZS$Nb3{pOIX<2(ylLb(FV}L{{g(O(X-A&xmF6sooH2>3dCM5- z>|M`2_m;6;XGO+Zw~f>O_AE(r+>*$TDpV=BV;pj>YbHnT(3Y5X{CS7WEeV(Jelq4S zPTRo58x(>=;2gLP?t`!bu7@BEG_~uyZqG>~Rim0_A6D3F1HoSPFK76W|tbZKX7z6G#S`U_ICk z&Vif2?|EcE3`hn!U_CehO294PDx}sxG)P&@zbvp36oK>L76{tLoEOA{RIn6m21mhp za2Eu;K#4#+NC&x~2%G}9fa^sv3lc#t*a!}RbKo}c+wO2QZ^OTMkO@|TtD)Yu|J4pX_M7nmuVuHmXZ!>5 ziwA*O+pOwmUd1w6Zy*$X_|wz|Hu;4WD}0=@|tP3a#rXrUz=tIxgS=}RIg_)DQC9R zUUDBS$9p>387cNd^)tEShw7ga>yN5`jLh{nJFxr49)emYx#o{dj0BfA`|`T#i1Ow@ zRVS6qs&ceE+5K8Bls6mdU-xp#)H%jr_2I+SN@j?pR)D!q=2b8oLbg;e|KZg8$j|_@ zl@=vS0?aoxx5NgTO(By5&5ll^pS%!gW~p7fZ_h%%WkvMQN$-kgdu7v#%O_4B-=E5= z;A|&#+nUwnE>X^kgQa36v$>*ODw#tWM%Gj^huGPS(9$I^h)kqQWRN+46{Z&kQLgo} zUy-|VBgp(*n;^x(W(&yo!RWE{aAj)iq)e-9s@3T$#gkBRWwSaKKdnrbXNp$EoTpv` zEDR;9`Blh6`C;;M6*CU;AFH6uf;Ax|THPHRf}Zw~jHpT>Df&xS2d<`>*4VG@yARYFR3gtZC zl76A)lQfhwD)f^45en}UiL6QJ3mIDzUbbATW!8{CYMNCz4z5L(vn9Ni>DB{AIAzRS zqng|!vL+#i=I}TcYBL0Y$%F$&Nb}m}bd)yLw(}QLnUdYFZH5?qxm|los@9>7pOS8M z%*P=I>yY*{a-$Au&yvY?snuETHFeE@XqvcV!)TS-Vp&xmp%rqtKH2?BzOQdi<;&C& z4PbVaZ4IdEh4N_w^L_0#*};yjoc${e%^un=snf_O3rwrpxfAR@0!Nus=gn^cF~QQ}hV(XRAgL4XZ4u_v8ikE)O{RX539V^Jd2+BddiUhtt<6U%`oK2iyQwT| zV_UJxd9w{xwulxMk*rFsRwufn6km)e`b&eVA_zpa^Xow(7Q)3F_B*PCTt2eY-l`C%jX zJ1``_E#Vz0-`g^(BcjnVrz6!;D0@0m+V6SIoN=;?Ea=2oFiLiHGSwUNKdaEwQopkm zn%bFAv23zK&xexgZ=I=+pC!19sb0RfqB6P=byt>kAtQGe@c#BvV|;1-wdo3Tko4DGIzu`_v#?q)C%-MUk-gA&@qd`ybEn_+B#giLFQ)&tIM#aV!}enStlU1+VvWo__K z56(gix9*S?a;=A*bPTC{Bco!->o>A0#{80vm?p=Xv6S@7iWL5MEQR?(K8;1-3o&|{ zKWhncuP1%wBN^Ds{2N;+jE!TY_@kG7NodmzrG9bbBwsOFL)OL7CRO8#Gn*Ox8B9({ zU~lV0Jl31kFUYFioU#k@MsKs9k_#Guz1n>kc?KYSTM6@iX&*-DF0!JJ8R4%jvrFZW z|JDesDWCMAsc6gOSZ_1FR6o8i`K~Qv`U|+;*N>_Xm)`xT*?v;2NH6Ku-yDw3|8}InJNskhMJeuY6|2$! zlIbkn2AEw#JFhG|1L*^p(18rjz(`p)fZ7=?#RC{ZOQd%KLuiRiPB3Ti$^NGaL@t+6 z1Fc*=KM;GHt@${SeBu7-V5@=GOC+@(GBB~Mk_r>4lGN3nDhaMbm3*A2 z`sZp{+s#b$+DRCKopmx{h-JraJ}Qd+NrupTo)KdxC;BDntjKwpHq>nGbUekDqD+eX zo|3ae%_nGmLxxc=Q)J07^Fvh%>pGO4gc-gnNMbNQ<=&NKmQy>E>>o~bHzw>p^#?HWl3ERfER5g+CL{xMV6*bw7R3OQ;abw-)%$o{@j znAjm#Mqy%y7^BT^RnoUdQ-Rr1XABw2mVsj!O5Cz+j5$YbbYQj8pj7g8K*CdLWd~$J zsyV@GfcoB3z2c*%AYYYB`>$V(C4eG>cj6$V#)I6G`5OQUAj&{*D{gmQnm;49WCoeYeU zA?cilQSOE540;s$gUOtTWcgzo$p)19@A<&M`&JHs?^BmePK%xsT7QZp`KMn0ut!<7Qi}hV*-!^1L8R9!KMV9DJP2 z43*B=j3Yy3R5rY!vLTy{CdISn$v2IZ>0Vn z+&D%1%-u{zM-`b34Q7l>4st8O1Zk9;v$R0Axy|8KqH%ikD0O;lWS|dr`yVo&*R)CQ zU59C_)oqDDN1alsLr$h{?hlWcZ#tQht$V}#m#%GbFD&L%GJ$&IE%Pxhb)j!F&$yyO zd>`<(8RKuyel*tZw!AYzC(L9ut2y?T$tqDN5MUZ()l^g4*K_rR8Rh@BC$72dui&cU zZgY~hN89f94)r!lw0AMS^BpspNejob83e4T{CBba^8#7)F}7W&n2z0*s;4+NgWQKt znSGs1EwuN|NotsT9}7$0$HG;0Je%3VkP^<`H*W0=9frX-{4B9wxVM~Dor5d$ z34|L03HK2ofq+2>1PJ$G!XXF&!XW}81Vu#_6cq9af(Ate`IH-e zObR}8cQIBzVfz$k56ABR%w3I@WM@Bf_phqPJIhDC(kc4i1e9yp1HSpE-SwT}i)7Jh z_Yk9!_2$zYDV9eipW{y_ss1^4XTK9QmV{WNfJL8kcgtkY=iJZJ{>z`+iRt^7`)yuc z$NxpqUFKhL#vSeE&9mWalK5q*{tXZMOnK`Y_wPK!n=W8@U20w=d5+457v1w*-j$rm zC(Pk4{MOxqYG&=XHRVylS*>xK&YWj{n#LsaL;uXHa3J{ebU>{ab%f&qPP*^CR(T@7I2E zk9BD${P$g>;vy=a|3db0komufL!$q{zm;iYf7-9Ay67vHf8$=Bl;OX-C(lcIl~E(e zh3T*u*28|d1djDgu!I)S6GlTZJPT!T1kS*9h}pnM4rD_2; z0Vm-)L~JE>APWj%0j!_Lzx{9lZbI!h@C1gzbXX1>;TT+ih&R!JY{-YjunvyF1&G;3 zATS7upcHn%DYybrZ;@({4f!x{IsZ1o8MqF$w-W)#gF;vg>);Tafg2FzM+fqt5Ej6C z*bnF62E^}Rv=RnE5iEy|a1t&-*iOpTPVzsUA9*knmO>dEfh!QUi@bxLumD!WNw@^n z-o_5bK{1rU5x5Q!yNMv=!2(zfC*cz4d&p|YfI)lm2$&yBp$v||1-J>Rdr2lJhG*d< zTmr{F?hbmwXjl##;SijG>-&~vervBQzv+%~59S1&%PXYrO?M5~sdBG2D)*Ya&CQ6E9U2)t~RTdKA71upca+)8;n(Su^Rx>-6}1 zL8BUkTmh%ktSQ*x6|JAvV!J5or}nU`YPgEqG&%5%nYiMZCqi~OJ@Lk}7Xx9hIM2ez zD;W7oU$KqU-KbQZCb2G0J>R_7Y~xxOyDZ}zm#3+3=%#XQm8a8WiOZAhn-pTK?ul@f z@tYyWDut)XhpEoEaF6wqwU_mL*F!Y)+ZvJ|<_XiL2`Y&R$1qRFs^#YLpj9peJo5%U zOH4>2pPF&`ScqnXWqmEoQ`Pp5wH>9bhN=Ie)`G+y9`50^84|m6i#!(YspTu(Vh5s9 zSfvKr(*0sq4Ob~JT}@SFz;2|bhpStkE@|mzLNqIe2zDkhYK`GW6z+hkVZd13yo&7o@(IQXOsKH5l;-F$V{ad{b-zR!o*u+zu))2IB(Q4%4j6x@On;o{ysu!6grSYENhU|l-ze%J=qqAk3%r!l^w;g|?EXH6_ z?=AT&)S|x^i+iz{@s`Z>dRjS=ccepj1PWtOc=j!65s@GDO{GBu<#v;g0jm!;u7rydyB90{1u`g|_~{J>J(K zvYK34Wt89Je01Cs(0R!(uT{Vkg?Iciq@t%)m3IQ3S+h2yc|FE3nTCk{ z3lA!K$~^WOk-<_Bg+uo1b1&Z^i=sSDoX9(THhd^dLSeh5P(^zBJi!B`NDyT^8QY|t z@`}&XOiPjvJ)Z8jOH_kO*cV~n*|M)8MU_HauT{2Fu-&**-owJTktsC6%3l?n84@1N z^B%J+n96n$n_;bUxqT1wqw!`c-W=P-=M_&4-?4yxu&#YTe9f6$c_o^#?Zs?V|1l){ zG#n+o9Z2@`n>pB^-lp4&qX)|}bUf41x%=%fd4IL5OJMS;db_E9YH;auQG$vrFHc)o z|L;fV!MCMJtS5NN-C&s*OGIa2@%r0R5=&wuYsAqL4n``WG71l%(0{jdu8acm4uyA6 zkfpJnFz4U9ih}s4Qk<;o2(|;zKM3$9s~a9>gMj zubmQ(?0(Hk5qRW4C?IpA01y+0+^4^Gy9}n)sT=MRTd9pacG}x zu1W$S??|AuYWV&L3f}#J7))tO3?8WF@j1Qw@6kTw=_Xf4x9@-HK2aUr zN73CL)VF2?6|APyLK`SQm9P1YjDtNUiG;BY^+TrR!`tE_h8^|&!_S^4`A}Ib#Ul9~`LmX%mJ?Yc z*;9181g}U&VHpZ9yd!&)Q9$0IFt|1fPoq%vusmEl#OrsI#WTw5!}3$8MOqy!mSfTA zunega;$n@mSb;_J!*V#(f(ku3rUZ-jhwZ%JL2GeOPWN6?l;aMbg2ihZHQ8T>XS~Z{ zdA@Fl&*!mmKZ^%F4vSeY#3H927AvvncUWeGTI^I7tFRb)SiY|3sp~|(7fmC#u%WZr z?P_OueNSAah9Q;LbGTS@SRSh%lK98#lXI)FcsCGxiER1b@9Uff1h)pAPVdT$1|jd_ z<5$`z+xVGhgKOJ2g;`#+#H#j1b8d5C=U%LmekgE+yk+nxS#xKO*%tl0N zElv`S2E3ipN=0hBQQn9+fR6h`be0{J?;CkK`<4ZCRf~mJqhprcAm$CpPpd&3YyGrZ z@#?9XWgor}XZ@rVUo|}5`gvY$V-r)K=DVKaspi`h@K?Qd)LU$pXiYqE;i^SAOZueH zn4BdOQ#^@?CAQdP8x}OB<##T{6XmP?o_!n23)SGYyio3N9%uC^EHCUs9xZRGhO4&h zEWxWdS=xja@GJ@XrzcErZh!7y5aMrS(BHUl)g7??E@^7HBzo*AWB(?O>?vdaR=$T< zvb6C$^LF*Jp(*v&OQh|S?}u5lQzSLj6XRKj$wo}9?Sl$aJrO>xZok=8+RT;@GtES8 zw%u(iVh=NZ`#Lk(YjKLllwIHR0jSJ2?SmT@EU=SF!2re8=yf+RIZ{Q_W0Ebz5&#XpQA0*z=Q#Lj+GA1M?Jk*UCSXk;b~^)OF(fZZy!VpItY zl|0c%6(iQMS}}@6su;x~Rq|9psu;Ef8 z4W;N4cbKtZk6kL5>M-6F-IkRo#j2u6LDoSwMRrH3Oz443g{5bjh)@(zU@VafEOJDUUUk0 zk@5fW;{H2hk%g*?MOUPXMK`31#a+n%D;A6eIyMKq=xZIkP_swCi=F{5aspoTLiRzu zw{#fnNp#Y*A2HZdC81wHJujf%ADN2U09iKJQ`MOkP#Y3Z8yZj>7El{*tBnk(6$I2q z2Gm9c)JEHCH21AQ#|6~x3#g3`s7;XhLkN^c|MNpURnjJ7tjZsYkFD~@a$>9eu@KlQ zf76kw{5^o|hMXzGhtgUopb+MtbblT}kNP87?^%i^$sbZxxog$lsEL(iz@`A>I5tEs>ofEHr$hJ z*xeM(5hpcI8PW47X2mXS=^zzXL>@q@z~~ATXCjsBE=U@f#l4X<6^q9pk09qGX+so0 zfjov>gglPikNgm+MqNHaonx%#^MI@bEI3d9q7n^acu-- zOu)P{@{BYX;hEsfJt!wec&gMmhgvn9pGQVIdftAbRjHq7>liHlv2?zbYa=|-&P4&I z-v^9;u$<=J;q=vj)1L!6SEb+{Pqbn8l+-ud^Hsv4=lzCleFD0H?2h~cIUe~Zavt(O z$fuCEkk29iLaHkAZ{(XuN4TSy0edSg4j{w0{!kes&m-N)-;f@pN*e=N327p0XpDJy z`Oy%A2xKdyO6@ktid?r1$gF^QH)ND#=6l9E>CC;B&l|HcYAXKmNEQDCq>6tPq>6u4 zq>6uaq>6tHWM~y%i)+4;IFgY^k+qRuBI_W@WJi7EpU4Kt(7bKTHF;afp?-vBZi@6T z@CkCNZ9UmA1lmqr_`)sxc}sh-<*$U(^V$QekL9LiY- zu4e_VA4GPPl##qNUU=sY-?GqBzI8<^-#7xt^6f5UsBhi54)yJB*@SPds)zZuQs7KT zRQon!_Cy@P*Qlp^Kpn%d~OR44^J~a<24G$O z<1{j$G|E!CGfrKCN({4F5oc8Oe|+i@R4NQ8F;MwG5$_jJs>48{{y(2p_JY`jc z3_%rF#`+OtEhK|G#SM^*!f_w3P>$`UB%TQC^Z$+xuZ$qls zZ%3+%JQ(|3T!+Sf57#R8N`}UMuY`}qd;0&XFVg2A*2?>TB9-@tk;?lc$WZT(aUJUY z2V5)fl??U%q+A>4X)eX%?2!a3j8o{SFg`)5Fis;?7+)Ym!}yZx&@j$(t-??;G>or9 z!bmu3-^aJ;s4%`msxZDssxYn~L&Lbrb!Zs>=30fJWM~-IRT!{OxV4mc_y-$uqDPa$KGKO&WfKO^I~{x>oKsjBEINKK>4N2=Fv zHDpC(4P-TBBC-LpCbBcK7IG-EE^;ig9&(yCiaMVkthjYFK(b)g(HNK(<4&8r0Dqc@x<|ULNn+=Td_lY9DMVn?MQL_`ZMp z1kco_^CI@sQGqs)2ZgW@O5q5cgQx?<5;9;A%z@>wA5MegAa6v-hJ08G>)|w9g`|Jt zKa7Ssupaiq^?#E75r?pZT$lsP;Sihw{T&=bHsr$sSPe(u9O#F!hYT15g|GnD!+y8` zHzEFAzHh)FD1v993{Jm0j~MbJ<_PHyc~A(;VI!P^D-d%Od&q@xuo%|C5jY27?@<6C z0|vnySPnbjB;16U_qkEXg_*Dv%I5L!2wVmI7_o$GD1wDh21np3=*P(h$bexm9Tvkn z*bS%PIz*fxvXBL%VGgW@ZEzAULD&aG7)G|?UoI5F0$2yT;S5}d+9&DgK@lv3ZEy^3 zKom`{3>X9pp%hNTRnR{oYar{RWtk&Op7$iVW0*7f)1y-Nc~3**C%!dk6r9R3WgsIN zh0lAMB-o=#mpJP(IGU7>2AVQ&JPTcqJ@0AZ9)^!|@bS-*UhKRUaoVf5u8LCd?|p`% z2GN#MUOUEe{AR!D>?mrl&S0y7L3{OGgG~gijq>_pJ}clZ`0bg8+!yqkd4$hs zX{p1aA}~?W5B)UP!fC5j2t-I-9Y^O_9r=2#CwRnk&{c425VgmF`fF?p>;DN{eNk8L ze$f-$N%Fs4RddWJ)wITWj=Rt7R3nTb?wnl8xakarmys&2KOp;XeS@uG9e7$CNdf4uB;Uzm9c`d1bcZbH3=N?#bfajs zfIP^6y1;Gor(`60!G@g5hcD{dhut-{^MOKawIqiiNkhj_D@ZkcH|4goe9S2mo7d5y zz6X1q>jGpnawM_}Qr!c2N#xl8136Bvt@Bj%s@zWnRXASw-o-S^E8Ys(#h6glfbz<% zqQ#%mTmBK1FdTx@a1|mxrb>cr$cF{68n%7BHSLPc&C&s^ftEZCX-^n*T^*yaA>dQMitfG#;FPt`G{n>ANUeTFn{`1?Ofm$>FUAsNM zI_DiDis#@4RHGJZ0X<`iq#Skt4PSlMyZGa~rA@q6XJOYPr(zvr2zmdX?#CJh(9Zza6t z?#BC;ZpBaVqwtt#B>sMI%+r)(qWpiK@OjrX=1)6+?~gpKUAKK&{fXyk zl^dy_dem_*c1%7k554hc<-beq-+zDRQO9!;2q(jwW?EVYS##Q>&TIPYw5NgL*Y1t@ zTk}WV8*x=zmh0R8wdZM{mg0Zr-=6u}JoSt|3uSN$u7G};R~xi|o-huIp%iw&DYybr zpYy(kTo?z7VI3TSa}f3gg#j{P5X^z)up3Unl`q(*D(qhb25le@3Slv-(|ORw%#pd@g|#5t znkMLDB7E!deK(wftDwu2`}F9Bi@zdq;0T<9uydp`q(dIegr%_l+_KCXC3W@Mt|zVq z&b?VsSC401#G1Oq=(70g>51B9e_B0#lZy0L_4O3(H;HVZQ*z|423-9v_cuW2cUjRu z{~6TP95dzx{ zWY-TaPEY9VO^~ECy_w1b%kOb%_#F`@52xWba&wyA%NZRef1#vha}1K++!+%t_cqge zswXzJ5%D?Fj09{U=bLelEyQR}I`)-^n(O;WqYf=_5apJsE%YYNShu{`LSMw0G$}37 z-7NiEqI*n^w&Y&Fky|bG2~3s0uN7B4WlbyYqmLYKr9Y*eVlk@T2=PQ~?8b8R5n?_^ zA0ZA)oi?OVs@&fuB#lnDAx=Z(S{s}VmFjI#JScsXI3tfLQCoJl)kkTMNcDE)Ni7-N zF2wcjc6z+t%WI#JAj`5@RDQLc9>rQztvznvl9oz*Aon4hu@Ulodwrx@9FnfLcSc7_ z$8q5~wk|qnKK}VwXlq~5; z2#4fAM=RqhcG6RvH7iQTP9!68QYZa2z9uJRptM+WlvpG4GxYB$K=)s?hP8`X(;4C+EWzK|(hLd=dSvx{=E3$ec_ zv01vczLXnl%!2+US-M)!`*D`uz%zhn)m6zpGbpgN?DHW9M$rIrJRvz<$*EWUYr5+9 z=sat;a`Y}dT$#Pdq~HA$d+85qoH=#5w|YOY}*dhds8O; ziw5f3H5MXf4pt5}`}YjdSvGOXpE693b818VT}S8>oUGZ|ny+LhfAvv1YcLkdp3(Z- zB%Xiv82x#T6iOINY%=A(u{<{)NX>D2RS6rXS0f4d-P(20=d#y*OdqG$idN02xZCX^ z)lj)%J2`|Cm%8(P*IDF!bDW+&Z$A~yX}Ah8=V_Be1`L8CSO}|O8=Qno5J7XWHe|st zm=23!BOHQra0BAMp_v4EPzXz5Jsg7zpkJWTnRJ1g5At9pEQO752(CcbMXGGbfYC4q zN?`|_f$I?Qt^9SLUduh6j2-cU)E%#91a_KB2)nbhhV9((dKL2;gEp#*^Y3tZalGCz zy!N-;j$|&;_sLSx=14@L9^<(}Pj5|8xV6IFr-I35f z=2E;P7S!CDqpxIg4!vBNsLyc{{`g7y_XbWayF~fWPfxXIvR*%S7`Iad3!xNtz)5v` z{k9j;jpRY_Owr#|k6hAJo~DyisN6YkbgJHfvnL$xk5&d>WRFbMuW2#La6T)}~&V%XTvFz1`^nuwz zmt@RrV)_>`UGktjIa?1-jJ+hsmBrs!?0ryvo2}RK?G1RO;-(UGgEd9VK5cA+U1T@N zk~u_hgM2tww{Jof>kYzrQ<;I8ZI|TogLq8a-TmqusWeA#=zEoEtiiNVckr6MeB(9C zPZ{^1o+`WN=z79y8oj;1->7jDtlUr$c}>pF(G#WgK|S86MdVZ&c}=Q6q<6g?=6w(8 z$q^c1&Y5e6C1-P(G`i&>-RHtcI{icIefwcem`enmD8DvWI?vT>IguUb=yPSxySlEu zE``0&dzbu=kiFM8^__3>Q~8qfgh4|`&U`99-NTK-Y>;^vgZ*(xO=``2L!6F z&^kbU@Eh=ef5?2D2}V6<`d@iif7t09Jlo&!QT;K^SYqX;wJ@w^b99?UEy*4 zCYuO(7wXlWug>u|T&VBR;?-ivc2Es!S_2pA1uSOru6Yd`+F`@ zub&k8;U9WUCn->2vHqe<#nb8?N2wzWPcGJL_u589a0;$~e#zlTf(#f0MX(Uo!EQJM z*CC$4gjC3ed{Bc6&qCSdWtn?R7Bbg8=}G-B>L`EGQ+gBXEPwB%`XA29N6FgmMo{KeCjvSbC1;@h%m zh5jq`-b*DkHGh>4OL({cDz{2#1Pzr~p*30}{e`wjo;;z%0@)+_j!t(L~9m3o8l{$y((S+-Jd8E9ur_^)=xDLK26H~TOClvVmm zZld&IsXmwlZ?slV(0=uIU8|Z6r{%zl`aiT-S@sf@&A6BJ`UJ!8E=C`=1y%0_k6e3~ zB~4df($hQSlO8i+DQtsda1L%jJOekWkPZ2;09M0(I1N|*%XZU1S(aPBx>ylh&pCnG*wukTcEo#OR8BBdMjc-Q^IIgc*Vh?SEY=!D!aXEzZ3BFTA; zhR!iL{+ixawfV}nqF?QGa`anyas5qtW7oqYTvD}?ksw8z2;*USXcO)9XC-noMdJnOuvveEEvXJ{#=j+UakIWe zIkZAtxJ8ezm6UI{tvQUTaB{(DUQR9_gL96JCf{s$E|c5vD7KUpmYo^*fGUVUyD$?h*bsLxf+ zlf*-IXZz40{Wp~zyWi2jRrc!+)9+RWVMp}w=uJMtowbv1j!<0M$*7~Gc02j*sO8wd z_&xndgW(GZYBg+w({L5Se&+U|4dg;0EP!>e8_vLWh`GwGK`xAgXQ2!(f#Vu^@6Sv! zdTS-W=`k$pj{S{FVy3_QZ+c2N(Xh@FUi=>lZ6A60KRg@s5dTA_^^rO^iSE1d@=Xli zmE$)lj(^GUTXfL$QhEB8&dvyO^cMFrO>+LCrkW-b|H2_%?7wus_K7_7H}3P~*54G_ zycIQ#e%g=~_Zu&;GgYi+G-sEH?wT>r-H9?a>P4$1*T^nXOSSUW@a`}s=&V$ghvuM7 zWc`ief0;kUX}s+mUIVj()XGfwu!c(;A`f%j8hHfS75N@=0P=n0NTeE8orGizv3PPo zGH<{#pN3>yu$YxQj!*p^!j0h?opf;>E1?(S2D*v8VTW_lXo(mYfj*OD7x}gfe8lA+7!`6do z0BE;1zCb@iu@N+xo68T1RO_x0tj6}rQ3dUXRs#2$- z@r+hQc2>k?6**hcn5;H=i{e?HD)Xa^d2|#spHUCdz-LT$>MzSGpOMSU;|CwUWk^CL zEHfmtlCg#D3a?c%nzD6B&1mBh8Zs|Oq|7mNiffUPhav-qEWy9II?CAEQgJ72+qKD(Em;LK^w@0LRbK$umeuP6$rad z^$)3#4f!&qgYlIAR3)Ji{1QI&6oX+jTnDYT`bf)tf-zb$@+1wzR}KlnPntnpV|w`N4t#mi-sqqsh3p{TcfYG8bvqh0T;J6SSB=oilG@2IiAVcRMguoe2aB2Uv*7~;1rn|jyC7DJ61w`m`mlJ zm@Kn1L*jP;3(rw39>;s@IQ#6*MvUh@OkT$1g;lQZm6UaGl0hE%KqBnzYz%R7uT{Dj zot@m;h%QD$XNzQ6q^@(4<%GJvobk#t?%_7KxVNm?X*34d7Nw!hj8DB~2 zW|Ld-j51FC*|mp*;^QUbpPndx(h)h zBrzHg%Y8@3&^>rr>meh?8K<`_*~^su-ZM&Qr4VKm~i-iA-x z!tgLPs;c$^%TMG$A1c7B@@pTX3!5*s?Q2E<@xDZ4fxOk1h%At^eW?W( z$o>7${8cveGg?PRRu85SBaBir&q$PrJVR%kKQ<4oA<{jM%JzU9%_DIR_G0VwV&7N7hZ}0MUMp1w z4JXm>A+h?&l;MUNd;cn*#5y*dC=|%W;k*k9#5cm|=PYa_PZk(G$-_5C;7zHVA7Ru> zC~XwHUzbmvcbgGs?_FCeHSaMVbefIj`Fo5eN}jmKsO&Nu(|uVOo=}o+#JDPO@c|c- zns4NX=M#xFvLfHgF(Q$|cx+^W(a5z9wThcO9c5O55zWV~B?Y7v^|)1Nt`?B1-!u;9 z>PT|cvpBpS_tASKUNn}6Msf>{Wy470IqhXO=p)s3$gELhLVNjR6n5>U&S>L(`UTfU z8!OblvX;NA$KdY?4in;mbjXrX`1|n~O3MkkI0m0`Wd6PQL`hI$yIj84nCIk+(fG04 ztd{CuHP-k|;~l^3KCFL{ckUxU9+2?yygk2@CF6|;T;VNLN@z8u{sbe!y82+D)?2;$ z7fvwhdkRR6wAOY{GcfsOdq_`{5qAgAu2oO0k|~oIXRTIfoYda%|5#{L)OhS}O{BH( zhisZ;Ok+2%nv-eeERrdcjiK6ma(uGU+W0osb{=65NGBB;)p!;<6dBW8+5-R9X+~=o z1@!U^VooV+Fw^*l+n_92LDskC|H{d^Mh4}{H;-iOCmrS)t(^spWbb^VmOML;hEJ(n zo@cykkm;7IXXILc5940N#tzpSm8l)c`_lP@yH57ZC!XI(+QW#({+A!7F-Xqbdc^qM zuya9UZcRZvJFi7OY7}ZJjpsgQyytX&*Iasu^KSP>s-y50{#8#HZ#WqO$ysdlnD;D| z-bOeC7vLtu&>n3J*^mzlU^VQ3lW-Ga{zE~AK`;lFLm3=_b8rKq=xNl4Y{*x=4tN%J z!zs9alTBSCZV?z{!8j;}^{^k#!40VP7qvO$K_M)Lb#MgEK^R?`YS03DLJ=&4(!ZBw zF53R2DrfEdzdvRC>|)}>ch9iqm%?B1IpYCqL}oKhmetQ0&D4%SAG~Tfe2J*%usZp=@il(z+et-mWTT-v@Ye6_P36CjY%;!Ox3Mjojo+OO zqGkV1-0j|Ce5)=jPj-~i6bd*@-D+Euu0pHv8^)7Xz{<(VH*7E8B&ggsX>j4 z@kbvp`c>9i`p14|L^EB-|KL}~&*55{f5JuM|q#8hvl#lPQoRKqHkLtdb+fEj?w&B2&HfgEwDXfQMZ~@}!G^fI7m;+^=d79%0 zKW;({{l9F;ho!I{PQevOVo6FHD1-&D9`?f(2&2E)26CYY7Q!|-1~(ywZe%KCLq5!e z)vyhYIlbD}%qdz)HD{zmHa4T(WqfF?J3#6-Hfy-*4qzhlPmKO?Mu2|jaA|~pU1M{k zY6e;Ti)u~G7#{~5xtk48>sI*dT{LD=Xgjh@rZh2=-EW}NZh)+6V%G4r3+UG31Br5S zw|v;znIJ#)33p4+t**L(Zx>|}+Z2~?;_~1C>Dbf^?%h)+E0o1HEZ!d=dqXW^Q?X!m zvO960bWA0z#DR9a)R!WiuzJeGR5Ot&4_kk+#D})1`LIhFT8sBpx4)-#`lHlNGoyUn z16~Bbi}jSXot!+&{Y@Pw1!-nggqC561AW*?W@DOV!?}2g%%NAFS*P0nl4e%&)g5BT zM|~n=01La=W@bHK+o9#gYE-1BTuW48w01TOd>$*4WzD#^?cCdELuFSpv##&6fFpHp z)bT8OKEIy9wj8ycO>*SffUSzQCYfnwoJ3vV@bzKM%~Up)T!N09^?L5f!(@ANvzBi% zD=t+I2EVEGk^>KtD81zTgRX=`JEs`EuyPDF$JF~LS>HL8n_iOH!c6o{3wWV!PDQAf zOle_uA+Wbv5ZDd^J26bYY(dmdgapR0Giyd!xL;LLTbf~7Z_&Cr*+Sd?JwL`GWUB87HAsf5%ugGU8AFj0|J9>*RmygX!tt?Lu^y7TM z^j4-`y?4l6jGAyy0pVLyid0_pX4iHz+1GV=d4AB6$9RP@z7;T5X{55Lw@m40R+S5_ z%&1D!N0d8JC5`CzYNJ<{YOT%2BtiGqW^z5&L%R0{^c(}H-WQxXo$KW_3$<~Fy*$;y z9sCAZCYN#P-i6DrM@XeMW-TX@(}$}_ZkyX*;>+ZTHfX(#mir!g1FcB+J>~hSi;o1c zjtER(^u0U}$4s&AT;*Y|y^os8w_Lk8=ZdczrKYg08R7dT;F~q|%2Mf*!Hj@XWj8Lr z{LUF1#rdALW}GiHplQ?jC@u$D@pRm1Yo?PPE!z=a#&F%&@?}Ijio~^mFXgp@Ru~@q zY+5GgmHr;|dl#s>po%;(Ez&DZ+nYXL?}GC13Et61`m{IO-mXQKwa4XNT+S_!UF`{J zZa`n#O!*Q$~H#%{bMN>qgAyr1M<&l}Bxxmk|kl|Bu8} zNq~#yW_-1ZG+IdP_9W_;fk0IPs)B|_2Q#_BFC)w2u1Zv>heZWbt=v(ii9M1#P^A0H zk8RDnNWKF&j@ZXdO&V=`AlIg;7Jf%IezC{ON#c&&_kI-7AYSR7m&A-cIIJNy;RR2S|fVtKOKH z$z2{oZU5NdT~23%?k$<*deBJaqAI@w?JYwFhHM!!(AqLY8))s%V(%9+P^|qz2HN|D z3{=%lV80Nw)D|Lm(>bK@__`3$cZfmWcxl(g4DKmZCJ!l#!&n?1FRyel>qZ_P|Nl?i z>RC8o$+Elp1nHJVgBewNusYIo!9b}679e6RSmX|ZUoA9Htw~PV?22iR#?u zB-@~7@Z9E%5QRb6W(3O0PG<7k_NI80MjHk-`?6GBrtW4#nIZB{Hm}}Yfq19{P~~Wd z93TO#ZFvZIFcn~GcQY(uh*n;0P773;z12K1!R9t>!z`&1=un9T1Rp2+8SYunV^&Q!_6OE_cq(JY{@y)dI+f$+Anc60kgvcRuHV1HDoGz7mnGM4)vd@Di zfAl0D@2C%#^rHGXf#R6^ZLj3o462_GdYL}wnERz;uaK%Stv8;2fUb9j4CzgchMe2m zteoPVQJx6I!f{VXDo-kyF>&(fF}L5r_sD_XW^ntYGBI-T^CW(*m?6z_sWMgs{8GuJ z@;2XoW{PuZ9_4HD*MDeltj?td&A0ZLmHk-oTWvBc=j`7HXlIr5v5e2FCRdXEn>r#| ztVbooHt5=i$}pePF)YERNpZ5ekL9zq-Kr`#`HTcon)9U~k7m|Y+x8FJK|){JgCiff zGY5!CU$bh$;<^q;67IE`<<=_G^Hrlau6kB&h5=BSkI}eU2pyRs&ty zV`4F>Sj+*$Vp51EijGmd5O|#9@kK@tFynpu0}3iNRr8N;jRVN_QLX+*gK4-@d8Oh%TFwt7E$z=oWm0Dlp?yMV$LCA0L1q&tvfDtjmXr=MbvZPU zs;IahzxJ!kh3fM3AVOQuugLo*O}D&NNj64R;Z-@Aq59yExBBqG_&$^2iv17EV}t4O z?teJ6$9rY4sTN0AJ>2{uW{mq&BJ#<@GJ6PB)h7>^XDR{E60+W}`-hmR3ChdhSC3Te z=txt;YL382Vzr@WH5WZ)YyShu*vG!>W!Bu3+pM$u$XFKb; zQiqw*K=NR)Z&9EEW>QGi|pQ~zP&2}+&2CF{W(9|A3)*RxTTi`!D)_le3oWx0H z;|YicE8GUrb_Eij#H|TMfKu*v%tN zHPh72T*IcAMb7FI{3oWE9X02wLVty6<`p}A)!>(&J$0B} zsu_f_@A>806*JpbJbOulCFu(P+TfJ zVRm+Y^02?}6J{-K-UY@|Za@^XAZkN8u4cp)X+=LiD=QoCI$cH(w9JawRI0rW% zip8k)Ap-`%bXW{K;3QlHy&`^9WE3llAH!feEQWQkA5OznVDhq~K4ic!m<~%}Jsg5F za20ggKD8ko20;-lhIOz5PQq2tE8!nxz@SQ*DDq=5tb;>v25vx9G%R|B8o>XtnEl$l)h)?hW(u39_n zu1&>y4)`qNs652_LRUp{{&1!-7F=;DZkkGmrKb86^q{&*mkmoT-@j2;p zDfNTQf6i=#*z_Fj(Rc}8ZBB6xsV*~D^BE++j4$kc!#oHYo&xXTRM~y+8p_{)O^Hs20QDc_UW}e`+v%{wPsU9 z%@>I+qvXq9H0y`=A`VeZYBht?V%vpeYCeU^FOe^qW3?ar_rGLvCQZJ-?aSr_r(wsN zr_lbgwEtD|XN;VE)oksWMX+jrAxT|NPR^Fh_2#=)T-4X^@CXX)pZ>uc%xD)&FeYv^ zAMEX@OqBwSp(l)nIj|gd!zs7{QOvYz1G!KL3t%;DgVS&onBuoA^JvLtv$pg4K3TPe z;gyWdq|9~6*=&k4a=(1L*=(gvkm_3~s_SLt7E{gTIk1I{JRk{WW}mqF(W*h(JtQ42 zaDAN#q~;H(PTXq#qheA#u#)W$7MDll&$>WCTPNymC<>u`B0iV>bRm^g>FmTpJP?7*BK zln1Q$)N*$~uUZ?~d&CURTxlb>j^KYsEV9~2-J@n*Bdd))gQc?gs?!`8ca-l4gMwx> z2~|zKN|qdD0BM!He3X`9L#u$bk;_NTWKSo&`lU^{4E;U4{O)qzBajSiqT0%g_d-H{ zOIc)Mk=$0ke9x@mMD{vLA&-BbLjIi8JVtvs{e3g|<)Mw-_r952vokJMwGGU)={wol z=t8|cSj*%fF<4A;zBX}>c%RniN&fjZ2b3!ZZeX=sd*4iqd@EqAn!3z^){K4YY;ZNdMz#WucYRUTM{BkkdYpcz8%UIo4?9 z9rp*g4u-!*3RZ;2C4^ef3RtV2#TvPF+`Q9zz)ahguEsLhI`F@( zA82M&Vdio-H+xn<;@EP}HLoY^JMru6mrlsz}{?@&hx&;Hj}1?M>}Z`HfGS8BU&; zNhfJYtHnJv1U;qBK> zUblol`mC9wrR3vs4lIW$ zMCzV1>pGFW&Y8;z!kVOh;~bqdMy1_5n@FYeW_qCd`a4_(oTty2bdK?ncbmxE^JYf5 z)nTmMP8@yMM1H!%rq$QjxUl)EiH!J~KHpbO><3QukX6mJLekFiS!(^)bi|uBz4KvQ zVVypq+b3uc1M?fRR?9Fv>l;vX^cyq%{vuUcUA`!u!zlWxe0z2T?StL$5_<_|i9H6k z^jugN%X!wSRhcE$2|S4N-_W-$k!3mF4uMLT06SkG_I!AB_h;741+z{09lxe*+}J#x zDj(fpQ|Tf$9&BDqm39}o#DAnQV>EJ}cUHRHm0M(({k{)@)Xu1|z@YehfnUHBAt%sSj#j zHltiSn}o}jFR4~?FVkzM{9)D5^$x)NuL0=}eHGKTr>maZmn0kDP4!{s(iBVJDX6c-rpMF1vSP=HF&>XX0r2=-*~vt+Uj*ZmQ{Ho37In z`%XT*ZuX&ONdA>}e?#f>EAAW0tY2xPeJ7WHWeE7Hr2R&daDa^Y&1_H0aP4pQxbSaO zVe_Q_@3aB^W2M)tdX>l>l*)4qF|H+Z{i5A4-*!filf5@cXHL~EzRq`wq(97f=b&-2 zc|DQN{eu?8AQ}FLX{{5B|C8RrD0&N5r0btNAXj9}pEQ>3)|H!4rC{Mv8&N&zKmMo5 zX`(0m#x3(RC$T;Mw<%h~w`O@0U7Fv&(&c6D*C7A3FfYx`D^lS0_HLa)$_|6+uoTwA zemD)+A)+R^1X+*|Ght~>aw0)1(Y>|R+YZS2b*50xSlYMz&W^~!qPN*H?atBjJpo0v2U@| zjquir+{gZwsy?m3bIn@RdtFs!>HXmi1Jn9K7m%vgw5_cMa5QU`XoRRJ~ueBMMv1E05%FScp9qH2tFkug4RvTsC)v8w&L$V#8Lp6`W#v1;L{>bQ#( zJmR{Gsz0F;5m-e8&NY?JmAt`8rcWK1-U*Pzpx`X<^NJSC_^K35jcV=+2aoH5=ezR>|sR1T`97kd!IaFbb5U<;;i zsH?TMP#+({)u2n3oVQJGe|NCX%*c|Ov6glkc_M^@kUF}s@^E6@8hh$YL&h5z6L>CVy6;0OVZqo#tf_Mjd0%0o5APhz^Z+G z5L{f@8|9lC&{p@N5;;pYRVMA<3h_jZ;%BMj>Eh%jp7<_>I8lw_EJ=v-HucSIX2(kT zMCF0;;5cu4UsCh(JXdXG6052=E?mt)$dUtbqCAeOO`Ro2LRL|x0hhdvFujf>ZUarW+qhotgGIk0p{*gFISGpiAii*Pw!38cE-!B>NvW~GPNT{cY9+DuIhwY zS9}n)zNmGV4{eicwy=s}KKmTtBrVx{S0xp8@Ex6xhrC=CC428RE?ch$@=C6K>SAVH zZHgGLjvBSS_d4q|@jq7EyVvQYPTpLfDki_4x2KbOcym4PTxYFRX;L3a)r#f4&e5s< z$_>1WT+Tr){Vz85PIVb}@z9uEW_>D2P4yNTc1CKBOna*L?o=;Ry~&z}&AcBuN$kIx zd0RQJSdxih&Aru}B;usz-c~M^a%v1wt~U3EIoqWBe{1f2zT&(LUYvPQ2n(SUw!tyD z0%6I#SRn)QVJ0kxjc^LCKum4g7LW_$U?G&k4mb&yKrPrzf;KP+iePCSEy}T;AN%1n z+^nO$S@Zj|T1hwF;SbP2IK@oVZr-}SQ`QHx@~5DO{iH07bcZqJf+sVmP*)B#QPY{a zc{|4kzF3CjoN7Jb<)7WW_j+RL($%a>2X>|1CdsBe(c^dDToxvi$9iKWJ=+`MvaX(B zE@gf=+g}Vj?d4d>+uH`5%=WILMPYp(EbdN=f;GkN=%?i`uQNEL)=EC2NpYoE_WUy`C2Hi`x%LD`9n3vioi<#y>5e-tDdB8jn-<1F0ro_4EeE zxmcRt1GOB~7CbGpd(c){@U&g(Ri(h4I*R1lzo@2m_n_5LB=7XN{eZR-qbF{A;db3K z(yV7l*t4*x+Z&6M&)A+h`i?0Wjc2Nx$_HY{C1}p|$!FBrmGSaLPj7I1uazX^;B79h zUCX6&j<=TKS{{g!6r3e0$NH#G!DqcbS(8IM!~V)k8YyReaF)GX{>lmQuR|{^`eM<0 zxitBTN2s_L516|6l8f6jJ!RwnbJ_(ntf1lr+*vNl7CqCNt8ANl7Cm^*`5r zUR#;}`#x{S@$1~z`u@D`weF431xHkL+T!?)M4@U>=Uj-KTXv|6r-u}o@-QOstL=wZ z?oitv#;;3(?tj?g`0I+H%Dey*7LNpf-QleMo$h*lz*7)29RE&y_}9p~z%teC>;LZE z?k=1`)!ez|VT zBFi|l+a6~}g*s=j*Ma-V%Jw(>Ht5fp(v;4nA=E(7Zw@L^y!SOivsBCrP>0>{C5V48wA zP#^%z1IZv8>;QW~BRByr0IMI~*n?Sq@L`MaVHME7hJ2?Vd`jFaOK_+9PWdjeOmzCL zQLQP&KQ?ntv;;UgHL1`<%a8iES1h%Jncr8bTE0~kOD!pmTi5s}EMqOteIVa$J-kN! zveo4-M6P|p;*Z~+SN4QOf8lvrTbq?_nMHp=2@C(~W0_^FI=2i9s$iLAx+C-$Lh-v4 zx|wid60+5(xFn1Io^&g$VT~W)J14x%fc^#bvqWb@MPZfj^?qxB_Rf->A+N zmOItFWE{LFC0nMb?fTOy{pp1Mv=5(9a7nU0{NS@utg!^fA2N@6Xs$l*CnoYvjBolYD=m|TJzH;<-;uKtJuFpaD=l|H zT31?(ujpn!X_V3*`FTO4Cf7)U(s>?!{5gnuLU-a5-{;~)R5MW#{d=*cb0FCE3-QWuwQdB$vhsIGaveuuD7d1YAe zQ^`H*@eIpM{6fCc47^f!Qn_SWW|+6C2rXZzv`lonRW)T=o;LrY{5L?F@Eg!9Y5Lz7 zUfO~>#y@KrZJh%LboNJST%NLes`zIuejHGL^Y^OyS&ZfPs`FV(s}sIJHG0&z5k30t zPm(F_cj(dg8!hhm?#?C4@)LfIka?5kVe<|Zw+Wl%*Q!vUQkn`&San)j9Rf6j6@ zegi@3b4a;B)oaU3^*@KWua#f6WrmaUNVPQE@;rXwWM?*-aJ#bQSh92z&TK{7cjsVy z7O2`BODx(t?0Kw?I2HK3MZY@wb_`Pq#;Mo&#KNHw%d%qQSHd#nu{D&$|u*zu{IaAG^?^)i~eHT{xpibq7wuv_dH`;8bQnQ z5ENwuU7O9LI_weEm1n`1wAy@RUy z1xtmD_cXk3%lVDrJpS?qq zcc)UDn*QYQTUFxoE`hr6+^13fl6)+`5jUs}`FO^SxS{UVd@NxdYpjt|FQTZd8>Ofm zg+Cpu|NbWWfA33Z%O;if5+-MpDtie_aJI4)U>{(8eIAyrslxy$L$DD~P) zmL+OTq2(s0RCjel0iF_ChS&RmyJ*i!z!~v;`@?RFzwd*~A3v z-|FPG)nR$4?5#*}UX?NkbL$W9Y%4+$j%~QE$TAxLBEdBL2US>PiMlp7XNq+HZ&p7R zSth&Tk2x8xWv1$TU^s5)#g<3(P;4*8nAlZAv9S&;+bn(~9zaP`M&pMK@GFxr8f&*% zJPglc%Hl-@}L&I;b%dNC*HoMW4nelhk z&EKFt@3$@M%-MA%Z(Dxr1n=bY4z{`ZSY6^i3x3b%H>zPj?((yg=N~Pn@e5A}{%E;h z`;B`JSVG|=G7ng8vkt>nR`<3I_f!WC!}))&S`Wi>{I)Kt!SbXV_E6P_Fc&DVk1TgO z#f?=ZnTmATR7 z=2u!Q^YlMSZ9(EFRi)*TI+u?vx0=ld>wNxZ8D@5S&RB%__DThA!^vUxG2@ApcnqGP zNI`DJccut}_djOYs#o9Rt(JGpPFXjyY2JTF(>B!w{@sG#&T*)&{edNfD@K%%xCop4CEA5+-_N6 zpN)sqVz3VE0Q_0gJ$DuoD~rr@&?49e^ttNCw%U92^42!Fiy6 zU(Q$%4CaAVAQ$Wbhrvm335*Itr@*|RR1}5}*-hw$`NeGSsRgOPSF?z&lT=P~GIIeCdaZ6ZHpdLJFIf5;9 zV~53W_!%VFR50{zc3Ne1;NaYah=a&EcZjJi7V5!#P^73D^Q!h zymqfRt?ChR#}A0;E8zLv_$QD!T-SbV`pKbx>Hf4zJ%wVfpqS%ZhFS#!x4C-^3D(V7 zrFM1V#)47oL_>Z=eJ^cQBfr9R@Fht(?*DNeJgv&ULbjif?bz0#*TK`ur8{lbVJe5o8W2Xe+CghBf_spJ$eQ=LFka1;Az!@1S5Vyf?pN= z*G&*vyO7m{>s3;bz6nn72*!KdMi7DSCl$%0v6KIOE4+z!UcFrP)hx&~)&0MJExyMq zXYnS%jIv)XQsd6zQ40NEuZ#F;{Iht8d)QGW7Q~P{<7s978Vz+qVa~-v?~JEa3L-{i z;nDM8G4G7>O{Sw^_$@@HWdOVA%dc@Y+@x3S-*HP@a?UbunBFhOMe)cv%cxljVjbXqIZkEtSmwFi zU<}5!OXjH_Tr&MIgT^Iu+BdjlVm^&0=r~?7v%kR+0yFu^)A-8voHj7zLI1{0Q;*sO z%j3iJAUXb!#uR%7{7(_s0}g@X;5;yeqSqiCECQ>6{@aH;!4Yr@Tm_@U;4Hyxuo$cZ z1)v-p1}DG;;2aL;3j)9#umog>o5z}V;KM#}1e^qy0DhBaNmRuv7cJf{37FPe<$KW* zCEqX({lyrwFsZdF=c47|5#AAKLj=B;^T)Tb7FT=jSwc!Sy>jenGZWIZoY(`u-R z-aM$+OrTaEjZWv&C-JS+)>LXVehx^-yL?NH{2jFi|4K}UNBoVN2Db>?ZfZv5IwJZG zYD^)u^?#@xq0}U}Q=M+tDT!Z2&A*#k`44LGL)6H3sXbj(8y+S)f4=1F`#^`=5dhH< zty7qA*A{ALE!C@(ni5VOI8JR&qb5p)m0~x@$aLb3nJ%{wZ&bCmeL}nPX==k7DC#%$ zOl3e;5w)w1T91DprZYy(qz1|q`QsUHgnLsxA7y-}G#~=YO~>2tdP8fzt_WH?joMvI z&8o-v>xfiu2DB`uR>+Y0Ny|%LXL!$aD*lF#QDFa{sgV<@S&`HzxFcPz3ml5pvfHW6 z_z^N~SIX43hoS#EAO$a1v=&Q(VkuC2Rvli8FKV>bG*J5|QH$}SM~8RbLpugPPNeNF z{Du&%>0_zY?Nqn7sUBmPu4gjFUnguB$AGeb(Qf%YwbF}PD03cvj&|p()GmB`rt?R9 zL3KGp?YM>I`Mg5gLmE~qi!f0}s>l8w6O{dd+Kb|Jf$b-05BShd-$gtA*Hru>A|qXX zzT}%vt&&BY@)z1svS<_VgBZHp)@=;;{fuhw7|n>X0tO^BQ7eB#jg^K}oSb_^5xmr=`>QloyN zc1Xk0@!f&0pcIEptv+yaT3d(HPLR28dyU~$f2Eq2QR95HV*ab7!p!lEu!;6RM%zFf9-v+OlI(wfDWJrgE$k9s-*brx z%fzRb$jB6nukX0X__W_q>&H>E{zmnGl3FEGl2jq_cThbGG5)$`9$^d!bfPxM!^2;C z>Mn~bK|ELWb4(YB)0fVlnMW;&rN;e-S}ox%65gN8a5q0{>K57mr7|=XvR!gMWrA26 zwg0!&Hks3w5ZZD0mP@FxJv1URLUY85MN(i%=pN9$>&XNznf|=kqUh8VnClWwOTwB zejk=ma3a3u*A=)+MGd#n?vM)8zNVf3J+-8l>hce2mbmb&2HJkUhT2U@;=^tCG9qvU zd(tC5yW=f}CoZ7&iK|ZSq}_(wkZxF673~512&=Z6MLTX~c%^8<>$H2zwPOA=-(f&k z54GhqwM=|?io=J?W4BlKcf(4i^EI==3JI^5$8O=T8Q&le8@E>4>FcR^`kaCKO%3@B z81SZsNP@zVEVybE!!xDAHgUmG;(|jKGCoCiNyP7I+r$MAE}>l=Lk)3ZxzVR&|K~I@ zqID^C@JDKoRMd}`26{+q;~C!j0M%2b%4aNXHyPR#akU}K7#>?nEt7If&Qc>Cq3{NVgwjH3x%eKQWQ!wi35l&xOk8r+?--vyj#~dQwO3rS*J9ds z-x7Z4k>`KKLE1Uu@nXa^H_u{t^@>&0(?G~!((Uxe)cLFquggh$=P zbgiGW+~U)+|DzvbK)pDMfj@}-J+)aLCjGMQDsl1F4eG?JRjnSPS@JB2lET?1@D+kdE$qJ6T>TEAg2?FppaB8xHb4%*RP)O2w`(W0KBy`DzA z-PFVnrid}j&^4OsDe8YS?VcN`#iDI)v@1pPjQxzO*a(JK%QnOAG^RLH9%el+)AlzS zZig|20liOAQ)Q0QWsx-OWO%VW*Bj)yo+Nj=yg7`|!$Q()DMB7%rC-vnaGV=tk^A1q z@RsRN)Nk^Y)gFI93iu;c|CE|8(8rJ3EZeBmaha5gYo%iUgG`qxyQ5lmMU3oq9IB~CekXqNi_94rgytQ?G#U# z^9k+daP(jIFkVh7_44%VmglwCWhV5yCe){1aXg$vyQTb6 zS-j@|==s-EkU@=+n@Y26la8?rPk4>$Bc3gF8SQ*=-SM(JYQJH4V!6aOQ)8D?qu!x< z?WIQAf5i`J(tzqiv}@&nVB1c+zk=%d5w&>*HBja@p@DW^Ag91X)>4A3_P{-ik87c} zrcmuAve?oR7?3ZE(cg!5@l90!VN|ndyA$my(S~T+kuOPj4K+%JybYtQN7^=n>Nnm{ zyU9;ZE;g)2BY}9PYMG-1aTtRiGrn4OLE>WC?Xo5kWcAmGXRHlk{6IQ2{tVT3I5ovs z6PW*)9~saf2}|ywT_S$LZHr`lm)f<1>J~w*xSv`g$8H~KcsqVdQg^8KIO7M?sD*vh ztYE0#|5f4v%Vb;hKFtJCqgX)YRN9`hHnJwrE_J0Q$F#a&@=5y3c zIk-f@H5&WBrk)Xj-qfgB)SBtkNGZT=BJCboD>m?0}6uWr=3y77gRP|)qaoJn9ce|@|RO%#O21wRAgo|+~+(seiOCI zXb4&xyO#lO;)-q3(rC%p`a0wL!l_jT;zm<0S zF>389YV%py|84Ub&>)Vd^IO{f8X}if&tzJ$@nOhm&{4O<8c1une z?YK~Cskr9OzsqXvk&3;(WP&~qYK`{M=s~6@wZD~G`jpsrQriwuo4ly0uA+0Oed5Za z2WXdWqqf`k^MlJf)MkHbtt7~Qk9OK^)XteyPb<|&4lEsa(ROQ~_WMxl6R45W(TWkY zlm3Tlw@F0Ob_RsVYK@hB>+u%D+r)EuOrq_654BgG0qyy;o90nVKBo@Kevc3bW}eLO z&c_V3n_S8z;0U$kMrxT9SSSV7%eIM^DZF4Cah5{Ab-LG6|omC=vT z9>A&Fc>cSIt1Om9;U(LxTPmu@PaWx9&~=&_2j$#vmY#V?1+8-62$8juF1sQ^wq4xc znZG%cTBv^)yDm8X9}FlRP4#${nj=rIKDlyv{KRlKS@kuy&<>P`RZAo7{2!@h71T6& zPuTty?Ez^(Lm>LE8xUQ?h-x`Fq{u-d@ZSuteTC{PbFcrsqs|v2PrbnrQjYkEUU_Vn z$U`hpMyNtYG+mw_pR{pI20FKZ$W4>4o^cYn#}C(r*%nX_W;5|Pk$H?>uIR{SvSw!_ru+o^>K)XrJdgvr!q z*##{!B{ANT{sgtFlA8BE#$Q($D^Im3d8*Y8W4ON@x%x-auI{AzoTi4vQ3u3dL`eez zWxFQIE-00?Q|)l+^O!HqEwfCw4Vl;6_!m&N6G1MTQR$#|cnm#K)60@HRgys(jK zUP>L5^6O=)Dx_g4#_quU=g6Tl#+5xujbTPNPpZ#r)R+&bDNj(Vq(QB+R*KIueAixT zmmD;F%V{^u0Vgtvc8z|9png-S%xQ|~pp^}YmY31~vUn=w@meh}s}nwCK{4Xf8!Bk0 zNqFsY+7&NT``)CM9;H?$%l_XbzB~FxR-Atu6XeM1ZOrq4Ddh|A9FVLJ1_s8!;+ zi^X+Er!qWC8l1VAwu>zKv~Okqmn~$3zwFDF7TUclsTDUoc^IWEXU9#`qiCO@_wiK|9)yYSum)QxsW8ZT}s$H;h^$6^EqJ_UNMe ziK~v6aG&oaK7=|jo?2{gm58UQ>334Qil`kC)V4X);u|%$p7 zaF&`T{-I3jiFnQk$M^qNnZQjldN|%_e#!8zMsHe&xmJ98p6>mF+A1Jo+HeENP) zyYDM%qPXO$Gqih*24Vht|8+GN4BTC-rlI+lqBc!IPuvHk1(O1yhQ4KTndt&`%j`>yNqg+9{S2u*rFJo zB~#WZyP`+Zdx$4&8Y%lfGm9BYH&Wfjr}xSfRPAE8r}*+XnX0lM7@i{skAYLP;~S|V zOR47jscyTe4YGaHUzYtJDGf-J26W5$K0@wzak33Nd{{t=OpSjG?X)tg`2*^%C#WT| z7JB7fQO*&DXC_f?3gd6a6!d;i9q6Tc1W|psN=@~PXs7V0WeV(}-S-x?OfH?a658$+ z)F_$jp5?SNQJ1bS{UR!R9tk9xafRw z(J|7{C~?t&Qr_Sy=Ch}y@I!O~=)S?&}e#;M+61sZttXljn5JJ4{gPD+%QkoaaZoWeauSU8-#d)i0cyEOPfimSyHyVNth*o*2ulUg>1+O?S4^BT29 zMx@>0s{157n3|_uH0n2bh>vc2j}d{lQGMO0X?Ih7_EX~~P)nPrWwOr`U1&!&P@8qBL#{_Yk!D#_k+|famD>| z9&nL0(jt%V(w{K?#%dH7?A}2;P|k$Winh8_tDOjZ5t_5QS~UptG=ct z$=TA=m3E8VhGXsGY8%AWwv1+iE^)a%@(d_hA_YD`E&De$LKan%xZs9U4DY#x+V^{E z>QbtUj9~m&Zb!S1e2A5nd49lzCDKB(xZw2H7+xc;w{I@(>N0AREXLL+Xs2DI#{H2R zAqSHfX?X4HM!4Nnox}v5vR$HIq@5{WNF>an9fyh1Qxzi)DN$UrP15(v5z8ztJX1!p zT}CK&HOpz0({fCOwlV*1A2Pyg1+}J}nj{{~?RT{E-lTe@P~#q>nx&#*slZ*{mc?2b z-@1_+gYBj}Q2!RSxgCo7P5$z*$$Xj-T`g2MS-pvpp;fkBSwG_ogy9Qoi zo<&GQa-^J^KQlgS6xF%aW@$i+r1O+?c=v3itC4gi z!L;M`+#-L!c*y3z(C(D?izTwCQ|;n#@?{aa#V}!|WNel1bSoAyyse9xAltI-2HGWS zsU40ArJ`1GKqb=i%5qr_ZPM z$jJ1_$he6kYx84#|8JQ)PGL%ULk-5uFb6@87}6|2-(Yxs%LD^5WIgf_>6Go$F3$*?%w1c76f8YY z$)Vjgg4!8CO_KKr(Kpbp-b5|4$^I{q)mkIlqW4!!Q13=9&Zg!BQR9A3EiIu|C~Bf; zrSz~=4x_$)+_t4Mwb8Lm@Ar=E|2}y^V6!lyWCFEWTxjAx+VK~t-4dRDGi{r=*0N^W zZ40R>(%`_gwDTUIw)9h*r^EkYp_=@}g?h-VmNs`LD1L^T{~xMZ&l%F!{6xD?JfuxL zWK=7|lm1QZUqiJ`qo&nK{5Gn;T|ShF3vE5l2y+^><}D&e+KQ=)zqx1RI~W{ zRB3R3B*U9_Qv>BZQ7Z?L`umM=yQyAU&q_gb*I4Q_Ov|Y5UiwR5QVH5o+?N-@N#g}OhIG$=> z(@v6yjrmU6W#gzN>!=AIQ+-a!{*QIxw(7+4)I%5_K~4NYY{}>*bDVyV;eMN`_4BE2 z`>9#I)Q;KI+PkP#atv?d<C&ph_=qZb;Kc9Bw0ST8y6F-smKpnN|ZECmU?YG4H z6*0VjE7jd!)QcJ+ms9sP+Hv+H{E#34W=XIshv8;dYE1yOOctlR%wf0q^7^|OA1@Wg zOUF9JrB{keZ+}G6l~Cud7 zhZvvvCu-A7vGt`F^_%*n;5OMNe&Qe^zGuP?dFc2L(k>C--YLGlVFSbcZlSix$fW;5 zJ3(A|?MB*B)2UtthnIj0mkP^zB~ypX<&GzrDrmzo#Kf@5aWjue;cBKiDZ zl=R|9qR!K<9!>4GOOJiFFu+rudTp|8d|qdGy}Y34ksc+b zxI}G|i$}DaH`4XCME#~TnX4*U)p4>G^xsI-t2SDC7$^7rY8jCn@obSdNky{le8q7E z%5LzLeV_gj)44rJt-y8P*#E`ixzfawRmv_%lLjS;N2}V(jA=5*Z6DJ%%ZPa{qrFRZ zMd>8k#f8+EXi+C>VVCUx*5wRH63^%MJ#BYcoc&j6H;d=1mc`b;f#KaxP-~=z71F?} z4;b$97&Sr;x%r>b?%gN}1N#}!@ONsKxX9jZv}uN53RD868^;sdSnfh%Gs`Y6vI=~scBQFo|CC5BdET2OFWjYUc7Fy zy$i+jdC6klM5QNJlcE|KQv8Br)hSuO7cDr9am#r3+$l*CBE{!(BA3e!WLx0l-O zMoko#+acSrc_PC@ewOEdrV9gd?zFI!CYtED#W zq9$}vi#;X2gPQMHgm=mP-$T~GfZX}~WU(czXNJ6m)I@1mh`7*7Ihw^pF}^H=nj=$` z=S|!HC^a&I8Zw9KYoEanwX3Q5nUWx$TJb$KLi|7r=1h-7q8vVB#RK-pnn{(LO@w$n z9|_MJV7_R17P!mZ(jF}pdj6gXvSv|BJ*Y9Vs>|M^-O)r%YNqDALUofhGnC3&h!TfnmNn2WKPBTY6(;6M zh4ZPlKTzvsgzDw^9X*oaf%5FIm;8+ZG2)x!#5adjGu&*YCWR9qo08s!@! z<-dv=?@V?1HMLe;Zs%R>c{Lr9-Q;U!z`!UbEL~5{x=f9fi%Gf%?KIi{dE#i?Wf69Z z>uuB93R9LTuGTzoluS1697R-SrU@(hUmg&7mYb=F>_T_US_poezf z8EWcjYRwl^4^bbP!Z?}glv2hI?0}+vQ@(5qo6JdUJQGyRrG|(W2hjErZI+{#k0-+i zhf_;LGgs4Ylew>yHRCph;T|{%;rWMO8Y2!RT`EqKRhuafo#LOFp;#U|`5S0wK1NNK z5loO>lOqqASb1iYoMXB+Su@r0j7jj2=YN)5F6(b*!YXm4Jz`hB%WzNeT#2!?Yh*FG z$cu(nnYu3d!of`%+$VFMd6xO=#NpK%eh2fPcn2dA?x7aTP?qM=?vb?+D=xKATxySOE02*( z*DoHjM9TA%@6H;j> z<3r@66eF%VN?dbG6ysxeQH!O%%;#nQ$Gyo2KWSm=650(ihrRNX&k@qY7TJcyR;DWx z$K`Ta^2vLH_@8Mvi68K~Lc1%InxBmEH)9H_q{8aQX#30D;xFYH@x|iVIvkHLj~9@OKx#L<{#jWmfTYu(2J z>tz>Y%C@YQf1KX$&4%=#LcMl6r_=VjRrY_MqhNVF*2weQUG{x^9Ww?NQoH3@kQGfk z(UWSEr)icGZQuV;@EFQC5I^8=NKUhP}i=pOxM@#o~>FOgKZ-dv`YheZR+wK?K0Ul4dNgCW->gIYr}3Tm2FZg9?K>k%SYa9cC;}=ns}_P5ZbNcfP5A0 zRBXmSDP|f$! zZvP`SC!AU@`@KQdl)sdl|1INdv_sPSKUG$H${!d}xQkl6h-xmNddLe!Uzw6_7lubo zqgKikwTee<_!Ywk2dFu(Q~Uo)tIQ&~U^Cbb z_JT%m44eehobfjk!5mNob^`pBM$-Xs7#syBz<4aPU@#jLfPLT)I0BA?Q{X(npU5@^ zfbGLEtGn@GFSrD*0@o2}EAR%ZKnBm`$N)uPC)fk7fGMNV8892n1B*d2*ayyo%fRG;PJv1KRzC|L^dIJ2 z1XhEC;3V+&#L$5y;4nA}PJk<5{5TX2)`4tr2pj=pZ^cxAMsO9lj>m|Aa4-if0DHgz zZ~=_+dJ=`<3A+wtg92~}90A9{DR3D~nt+i2yTM6t4qOGUw_(_UH<$+IfCXR)H~`Lo zDc%?XmA=q=v;7o4j`cxtAOOq)bHQ$K5}X5CU4p;zIfm~1oj)D`w zc{0WfOaaND9P9%}fawmD4VHn`U?bQL_JYPc>{v$l;5r2}0_K2Ra2T8bXTSw;1vT*Hmj_F6oJFwC^!QyfGfZmkKV`US z#ztTi!7Q*DG=gK`Bsd2yfvdoEChD@|f8HPi>;xx(^WB&?Fdj?+!C*Eh0OepGI0P;O z>nv0R=7QDWAZP?vfomix0N!942nTaO5!eY10Q+J5Z`3`g3`_yRU>;ZulEFHV4GO>x za2%WhlkP>uU@lk$mVwn^BiIa%fvdoKHYx|RfyH1Q zC;&S^x&9T3`@m&jnv06TGO!wK1e?Kja1b zfZzvFIamkwfkWU3uph_&PJ#2_GMM`i8UdDp-C!>`2pYjLa1OZ6L*>95%mGWlDo_M= zg2Uh_H~~h*Vr_wWU@=Gr>p%f0kH!2S!iVGFJh%)@^D)<8F4zb*gYDoTXavW=NpJ~V z1+EWcfq`%^2P^@rKnBPKMc^nn11^9oz_j0B67j;QRzuI2aG6 zfM75i%mX_>IoJozgUi6Q45I;VVB1#ks8r=W6BpgIz*x7yF+W57!E7iG=h`h z9JmCo0`DhL9S8?=z!IPoXj}2P^@rKnBPKC%_pn>Sc zccXHAmEl<^%naTd~{xeHh?K$9#{<4fgPY6 z90A9{DR3TK2Bx(b05BFz0s&waSOk`V)nFqy2pYjLa0z&?!+3xNV97cRU@krsft}z0 zI1EOmV?e+ZkPOy=0#FY2fy=Bs!Jq=?4CDnnKsne44uRv~6gUqq zXV_6tCJF)pU@lk$mVw=%5gY^Ofa?aVSTGHQgE?RcSOqdbE;tO%fD7OXaDEn@0pr0G z5DaF6d0;U}w&Q=O%0ImS%O=uYK8;}1bgMHu-I0BA?Q{X(f48}f(hN!$GTClN5Khj28_?ejDTP;8x(*Ypd9Q2$HA;T z)C2Z{MlkvXWb}Rky$0c60ayYKfWzPf82=j-4CaAkunuH{9bg|g1TF*XX7miq1&hEk zuo`Rxo56Ol8=M5^z$Gx+o{t8AaIgR@0U00{>;!wj0dN=`1sA{-;QS(n9E=CaU>(Q? z`@kV^1RMwF!DV222@M2e!D_G(Yz8&=?=!!WY%Ng9S=Lc%XR_7H9HQP$w%%n9RsYly zrpBaLXPCp)gIXfg^AHu2VzsElDfnyg%j^D`Vx8tRa;iJ(Fl9uUOm*W|SqIGK6>7{= z$eyeoc*;86DIi5{fT@2L@FtV5k=7aMpD-<4wHBLWj7k4EB6?+n1%w6!1cU`Gzn*ri z`TtDIFiE@OdfM#&OIn5ngxZaQldmT}^M6UqFey02WV&4%tluI&VM=@E$@|uBd|-Xr z6A!FipLYN1wa=ukdGcBZm`3uhG?^wy-a|&-D0_19{FG6cnZC!PGNy{|9r~&`Y`iy_2L?=ffee# zHP$;Zv;SO!nGH-)W7cY2sUBF12@g;k)>^~xXOH)5D@c8{);iTGIYo_Jr*)+YU1ua( zsU=Xoq9sUuxDMscP(Nx3R@2iF7^0S@qn1#$MN61^Hyv@|>KiQ)YQlP~!k%=j!X@kV zDpW77$Ghqk>cjP@J6Zj_-WuwZlA=PNvCel&S*c!p#`-W?_W3i&9Hd5Opu`y}R7N_1Bu5RB1iBOMhLc^2P^V(Xj_HVK(y%Wa_*@;U{3sW){tx8G5f*-mYm&#%Y3e$hC zmpk_ycIi@6)Vg)6vy2@2gy6`-IN1Q<*EdfQHk#zQFLV8xjKGId)~BUPjgHJrB$*?w zH}Eoc&r&W>3Cob@5Id8K+e+q%XnB%sbI$NIflWxZgvykf_?2v$?==y`~G z6k-j!zVA<{B)j!yRc^Q1uoCv`M8WDyrX8M(0S;9&b1_(9>M3o7tJiWd2NCLXElKKz zJOnOR_i0(7HfTv!@8n^Y!&B5(P_;MDYE|Q3KpO(o11}&xP;Jr@r1rmH{dAIFeOv&xYdE_V9GGk}O_rfP<*FucwoV>*YG^#B$Pr)UrdI0sB5dJn`QdjQ<>Gx}hg>iJ@(pUji`EITmxsoOUSA2x zH|l&F(^juoyJltTb-&ASW908*fP#RSe}k0oqLn| zvo0@b(0a4ezMIuO2pYFf2g!;IMN=I`jvuWy zy@VpikG>Wk9F%lDe)BDAKjOVM-!dc~&%97+`W#PPRX~K(ooZBp)peXpy^($7VrmV?$=Gu;BybK+do?|ML zC+hka-0yUUF?90{+fhH3prfDXbvjdQQtFyVgPwRK<(bq?Dc8zooRmG}ad=>onp$X` z@W_El*V-IB^r^SVSBKBaT$h}bk+Nb{%8IA&S^mTmN!Q9{JRL>okZC;PtM+ffm>)6n zv)&naDmvQQc!&C=&^pfEc*l@>hb-^aQ*`+KxwiQXSk%tHkit}9d5dyGpM}Z+wK@=e3WsWfvw7amwpL)cmd1+aFwqYOlo)@w?fmE?gfX?*H%I z#&GG@kR^RCRK2$q!>?bKUn>tw+Obskg{g~MvHSO-jo0F_lpVWlZ@8LXWWC*MFWPu5 z9!t{kpc;?1g{!Us>&;%qM@N^j8XZOKFp{|cXuZwL_~=N2#pftx^GsceaojOJGD%qI z^12_3tnZF=3Z7B-CuJSs0+;^YZtF}nHs5A_rOZ0TDPX0VS_U5;pq6S0R4h!M{S8RCdi)IpMyPFXAVZRRU(0fJQOB)Nlix&KvU>bY)EJbaw!LYct`@(Er`ORp zji=XlZz6S|x_u8)2dT&R7D2MrEU7j<~3notP|Q}ZkFKn+lvv;?ZR zAS$a8iBDBpebC~cbvT~QZ$a>Ee#^-E;#+7(n0il3xVrcjMlnfEecO6Jn!4s~>)p!l zZIp2EZEFNtd+}{d%-*-r%HX}$aHr)f)tbF1B}Kiq7a3NlvwMxcjjKW_5$e$@R1~US zs4^P&CoSRXY?U!4W8Q%zsRy+zSI=u%q5kv^k|e9M@92YVin{3!T34$3{(#_Mwf+y* z&z)w>P!I0I={O{)Zp%Ka(=exyV72X!)?d)=Z3i%$Ek#yK-SGp~(O6J8K)+}G!pV-U z;@Aq#@G8qpv;O}Fd+p}1d9HgLrZcu$SU6%F`8WRW`LVgK=VvkXqk_ z6aNhLCoRG1yC$?GL{0brDMQsGTEf(eTEf+PS|Zd%h^qep)lB;Bw4Nb zSl{hZ)P6%(s*4|6e}(>r{tXhSp4WnlnU)#qhGWJc&({*7wrL4fpFmXcF|=}Qt2G3b z&TmCHDs4rcB=xzLr!RmP}A?iadq3VV&9oIw8$pRfj^(u*gMDqKx&heW8Q z?S_YXRm*bqIYjMhN8<6HBXP2t|G9OhzWZ%4bfx<6b0jGI90{ynAVHwI=L=*EQk%5Q zQ15<$o&>8Ow1lY8lL!n|>$QZb{U?piUepqyrgvZjlGFw*%hmf@R;b}$LQv_K7~bV@ z;)bqNpL~fC2~bY|fCQ@0e;A!zqh*GAOG~i&N=t|ua|#lw=4-*m(SpscB|`n6B}q;1 zge+GpwX9IDX-QU}cVc)~q^KLd(u#KgUm-X^J+B253Q;*M;dvGBsP1;07I18FoUk)g#8vBUo*B41NOW*8T)iCj zOy^YkRqLHz=dMSGh2l`-h+c;K!`qM_pI+q-7 zf`=Tj&f&I!($>4&iocD(mug0kqog5s!zC(n&^pm`iN}zVhV<&Vsu@JDjt`ASvmM9N zT-7sZz11^!%#hq@rlVH@%IjzAot^==T#F71!vWZFOgpcVen#EruSW+554j&KQDr~l z1h-`DwcNoWLtct4_C&af8fUxJ%lIhc5HjSXzXZ3TyH(R+>n&c!M@JGI_8mPi;bL^R za^Hp|#z#jI9F`puKYF}QGJccGSXDLKX7Ms?N4g>1DKOG)-{f+OI{u5*)zh#Y>2SDq zbo;96`vu*;s*^jS@lbaxq@$(&w%fdpdJTyk^283Gpc^wgd&txpL5_m3dK?8ED6O>J z=5$~}>3rK5vv+By?G8`A9C8rZsl3d%h3p&}jrHVc@hES#)NH%mbCmax>_d+1 zht)2#ZKCJlq0v|+jscve+EKdqG@l{4hpduvBmBv=DtD*L1hvi8Hr%P)N4;;hjd3zf zRF6B^CVQGDUe6keHQ*>YL+x@xw=#xCWBwh{2UUlT);}ZW=ym9jxu2#yhuLoR)ITzI zEgJLg7{8q=b{J-2=g{aO)9pGL+0>}bnC|jnHdjx>mT3qbGTqs#X&444TPJr!51H=S zY7n(}&co#2L{ChDKwK9W&#t(wuD*oxG>03C@`10yoE*-tmZ%8zz*%5tSdAcC_{LttjzF@J6)6t8k4#|yKb~I(4Ds(|V=iyR&t!~V+ zBf3#F>*&Uz(L?-DfHDt9bO7$Tj@)5GHv1kGIUIAbXJ|Ag+EKXvS+~2@f~_v2Rq=3} z#nZ55u){Fpjvii6H7LgOf==#;9x~%gR1c!ZEtx(fddQ4B-=%IJfo-6FTJBnQ%(SEQ z43#(njm#JtjhS}5hFXRG+^yo`ZFhPa9~}+AY&-gqt2#$u6mrp~YZYL&9dBdiC{I`0 z3@`n2Zr7smgmP3c32nJsP5Yh8#8-Ts*vrQx{f=SCtAFZ#wu_Bbpo zr0)5VwpWKc1&7s*bGQ9&1dbW|$J$=PSs~QZcG`l&%@|*saj)^U>2u`3Gl+!fxM zYP-)Vbfx-62M4IBciQxUYx$jMc#zt5r%fMqKGqVfhEGHLL)6S^NExa&K~%&v6ntcw zO&{BToMyXQ)$4%S{s=&S{gH6FdRNN|^@EmV6*?XD;<~WjP@K7@qwE0njg~+)`7V^v zGaY5DzRMPfs$WBZK4sm7&fr=W04r2I9)P04)T;ruFqII1#HRvKVT8IV5aCJc5iQHr z%UV{bPqiegn}Tei`o{2JkPUCwSE}cO@NYH))P602>Z>4hJ4lV00l}LPEy3zVEg|at z8R#~?$_CCPWMFD8WdAi;)&wjDj&uE7Suan1^KbatKBiH-^s*U8%-}A~rxR z*Al4S3AH_p8h;E${WH|mFr%9*!;Few3$xv2$9{5r#W~)LZ;egUS7fYRf9+hyFk`WX ztia}SEb!w-+J);$S5VQ%KGsE_t8I47W}6+Gi9X(b$ZRo#Qg+QL4IwfPSVU74bm$Jzq%VWoN{ z77+pJlUQTrjhv67g4E3USW|BEv8J-;+a@`M&!~H2zU>|-r;w1kvkPpSoSZ^~>Xt6F zeLYN7EwSDB_JYT3PENrAb&n+29v$Ws9HHJ>Vr-nxm!NFicN0-)u)0S}h+3m1RK2Dp zOns7wB;jiKQdkixbSYYqq}DIBEq4kDQ=c!jy$*B36Sim3_KQzo^{3PYEweqRzogoq zWc$V`G@$O)<+dNp>PiuYt~}W`-s&_1SB`b4AKOU_t}y9FYwkeKZ|lBArTfh_<3`uY<18m_nhGjs3U5Sg1q>mHG(qf=kc3z&sM@L64vJbz?WNVmR>WSr7S+D3(rPVLq}5ineto~s zIdf<3_5OeV^Z889cb@G$XFqf9oC%M~76myZ8(!e&scdv4JR5$WjgE{Bv#=ZpMe$A) z;dws?viLEQ?&|aJb6_==hvtHaJz_+>TrSFXey&~^SZkhX^}p6k!K# z9C(BHwsEk49kg*s6px3Y<5AOiJZwK6LU=qJkJ@TC9u|*|hs7BFfavvkSRSHSo}7n5 z#XdtGlp3LI@?f%I;e$N=xQb@BYZ6KY#rk}*eo28FXQzm~|AB~qHU&28b zUIy_g6k#7AALB=TWItc8rPd$9ol`-M;>{?E<{1>l;8#B3#^)4a+?+-#4GNn~)6*4O z12nx2(~+wv{xwC>y!4xhVtD&Ek$!zXj-pt;;Z0a-z(0QzCK__b3=kXf7>XM60W(01 z8khh)%l}7j_Nf_8X3n|9&o3lit z3!RO-fjoIOLWd(hBD;)F;~2*w{kH5`8UZ?go7GN`12$iyezqXe4;AV9F}UNAYc| zL{eX`f~^={`W<*zpSOMoJZz`DgN}gK`wn>6VJ2c64_!?O@b(l9bqma#SFlPb(|c?12*U`zHpr$ z>pIM6{G|{NE(z?r*e9HKIjooEkJssqT={GUo^&bDkroW+EIjYCO435|dObdD1bZUb zcU`1LrDb_|f%x6W0dT0zcYPcvebUx?%Xz)AcFaAz5rSVlvX0+<>32 z@QoYv=C185h0;d2hnQgA1qg&6(L;E^Mm@&$2@A){mcqlKQlPD2p%NdzQE%#clXW1w z2)l6+Ji7Iu$VerAccb3MwTrFrBQ}ZvPbri{V@g7lRp0mY#;!dq$`HuYq=hpikhMt< z<;UJbVSdQ6jKcJTIwf(#6sW!l0*hE3Lm<`=I64l62@9QE@3Ey0N*p=!k;+fTOI|2{ zvuDftz3@&oz0&3ZFeCRO1;A zeBa3KU?+tF9V#R1i*n(6)DAtICvDLix)!nu?q+6}0!QPED)B{I^!Bc;Y!PW7+=5jy zJd8^1$rc#?fCU&uehV)s5O0fFCnL7%QLc$>Fi{b%;t~Q>D7&{pc{j78p;5SFD6cS; zGd|XRdF(bl(zS%uz&;HHI$%c@TA+b1-;ECN_BM2Y(`+&xc`4A53G%eWCD|-0@xMu6 z8oOb*@DG>-SFD>L`j`;#pqlS+XsK8t7M9)~v0??o+ zY=H-){HzlyZuU+ziz2B3+CyB#OGSeeng4AkI?Vx=M-~w#gGu}lGM;)uFUR}u(p$Ms zv44za(*+ew0=+xKxEMb!?LxN3i&`ZMw{QsoYBmt4#$Wva4Q~>A54A%f2Qj6#1>*-? zXv7bGpx1NFXOjgNbi`z!1X2Khoa=2i)nLsqSm9{YV724dcI$OrJJ?mjx$by9g-p*j z8$je943DeKF7+NpEE4EKeQxR=G|TBM)fmN|8SQ-$_0?N@^wzG;;yfdz{iKT2yVn7k z5<^AuhiH}`vu9vXSRF0}o|!4{B7x5sJz!Gkj*D^?MJWplz8~pHu32Wb7a0QUjN!_~ zCz8NHmS>b39rP8MGX^{tfAA49Hy7sXZ#%R<5M##Sa$~{_DS?>Qa>UAdzH+m+W8zzB$W)9K08oQ3N6JSuFbHOBV zgPNVlAq0H*S0C#QTr1gA!^ty7``Kc&pAa7Z30m(vY_idMV~t#_ATy$QuOope>>i%@ zDGY8dbCF6D6dG8_@{gOy<{?%sWj0&tMQKe(2g_A3L6C>GSh`dSRt@~pWZ5XB+Dapgj8H4u%%8uueU?5 z&g1r@E4{&n85J5}^wT_YRE)qM?Z-efnYExwLP#|nWpH%)0W{X*Y$^sX3IXBLyDg%h z9>6eI$ev--i9#NBkH|uA;)yQ$KL=2iC;rb2zMHZp1ezYi%y@=fHU`qC@Q^%zMuY5% zgRnk^O@+4<_QEvrX49l2l!Fez`f}0yNT7s~t#v;m`IJLwWhYq)!*ChH@NTNRy@z1< zU3LSzR}=;hm2Tgl)`^M_;ZdJrPRS9cqDg?38~@iy7scY?tGzPQmK_NyVvK3(Z1J6eFAfy)AWha6QA-m&>%dXHh3gR8;WlIB>lRJNXh}U?oW0jo=&~BdBH`?NPb$J-|D*`+jbqdYDbS0Ql<+e#mLJoTU0c{0A|RYMcwMNPyBxz3 z;KngMCOFp=*kTBTbeha79oM_L-Vz^5Al;?LAP``#G1nf)P&UWxI`I&qbOIj2_><$9 z8@I78MjN7U5D>374Mdot+Pg-vsfNS!`ZMuTsicmc(EA3j6Y~j3W@hvDkK^@D>b+cZ zS%@*_bT_J@H#Hon)#j&9Voo|{>bhH29u;ELNxi0T3`=Yo8`~-|I+izIr&n=JV7-kI z?v7CzQ^^M`Z_1XT*I_%RW#IMcu`DVvF{V}h*jWDdcD-7KEk*@)F&ua@=_-CekwL7f zgCngMuUSIFmi6m5j7?%(S+7?MTP6kw68;7kWxFlhqk9TMy@7{%WPGzhufLu&JUeSt z+JwYWY1!F>Sfd#HAl5QEk<~pASxgovOfE_2Jj*q{#U(>^tN7lqa%5R(|XJNvFTGmFJstH zSyf{Km(Eh#I%)K2m9(i)c52gA=Rrk>GeaIdiI?WTfv7P=HvmLviGQeN7l3paK1 zf|)T938sU+h4pff#;2UoT>&fL6_#}(s4P8)hn&%?R|yY{#juT^-3+?n9q!0@GVyrA zXL_(LDk_U7oY6zosD*qFVukVDi1690I}oZZ^=Xvy$Z^MXe;0Vd03Pm|;Kq17cuBC` z=v*(J&BF+umRvmSEK>ZLzxtV8uDQahmu0NY|1-s;;iJLpWAZ%9@xiH6;KlIhg}y<2 z(HY&&&wQpkgFHnTE01xlDvvm;mknqRXcdeN^Wa&%dL=ts0lJlqa4%QC;1%I%-#{l8 z^p*^LOF#xH)OO%m)MeQTLb0HI;)bo?^C2ON7 z;G$RCY}^A~!{k|YMS3Z{aJG>bS1w7uL`7Zf&Dd*ZZoJ%%D%Y2>k;0cMb~XbytIYg) zI~~?foZypAx5SNm{(#fbhK?xVH1K{fQ}cE@sXuM`%Ybrqs|mfn;3Y^;hG)EkoARch zr^|!VJ^^pI5X3A}X@EFsCPb;6`MS$`C_0JTG&xfD^_OIBT-F-~c^Zvjw^A`S3!`X{ zzu_j*eG`%9zENR5>xv$V@qI2Ib44#_3lBUgfDeYqff!?WAj$_VqbY7&ZWp`arl#SK zaMAB`Y!Fck#o#$|5DpNUrRC{UTGqR0YgJ4|?@{;|@k9!I=I43agWg-boU|IahZoeaKg&`1Nqr3a_JCmt`prU!H1YkGj{V7$ULy*eJ6 zl)pT+OeN8NOMq9-v`9_mnjV_(a2tlq^>#J9^piYzgS*!QZ-%Kak2lgS<^Ln_l8l1D zL$qmBVLiJ4`5XhQspp-Oq4vKSJ1w$;z7qKlW2jsad|`ygUe~K*G1KY=O$dC-b&Q^Q z*Y#S?2d4}vB)&J5@4l{=4|H_Er!U=83RXFce*krPKFdurahQi&r2`Cqh!)jHhAgfc$7@~*sYcFJ&PuDsAV*z z=TR?3XU;j~wRV+VWawY}-3m)OLEm-M5T-l%YvZ*WofDgSsW4)=J3$<4Bbdpb)0 zKvV{WrDcSIXVtxTV~g<8^KNU6!OOQ4J?nn#;O1V6J%?Kfb{W;vD?!hOI6A$*m)>9x zy%Fg--g;EpGXDy?&m=F!EQ}8_C@ec=v6rH!GnwHlz4W~6ez%uiw{**9QhK4#Gs+)* z)PtEj`l6R&u1Ec5j<^OM7TO~CvyL8mnK{K?dMwdOaA?Xik)T^IO;#_ZudwJS{|L`I z%PXyf|*!^$e>^#%kt9e;?WIrvu1henT?zNRdAXy_^zzxL@OoHlTe-+|uS?*}@KLXU_obO&W{#=I zh77NaulOD_d1F0FEj{B7ctvJ{!#zgQ^g)|yDCSm4zCRo4F#&Z<-{-;fXP$j~Z1y?u z44Wvml%AF|!!yr&^AarH(6kHSg_@40cx0kSe)e53-H*}!EW?ADlUo`e<8`lN{k?XF zaym8uZ^$X!bCG-X(+WOuiqUg4dKir|g5Nl#zS z#oQhWn{Q^qvkKG4x_T<&Jpy9CToo;QDm6Wr-c^wSMfa05CCGPtPs_E0cY0Y}Fo1av zu^)kVprrI9fEhz9ZfS%aoo1Cv02U%rig<%_-vQ6vumkXU0gIQBz8btM#=EXRvg>`~w~hqEbeU zRLsZWKnxR>Om5b6@Z8JoKsLyuEe^}v2A+HT3S`+Hqkc@(F)yCyjF2$)Yw+BiG_aS~ zbdlIZ8-?;UJP2eSgBzT02%dWZ9mu@Lw(j87GW9ZZ_|ZG4;hf>SL9cAkOQTs@naj!k z9K0_~UU-ZrZ_{Y>7o$+2=QRYSWGU>DCZ$WW^bVF@N{`y(6c*v;<+Jn*i`gxw!z6`1 zq9_6sJ$ij+P62rC^B~3VNyVHh_26^gxS3v=$sT@V4rUtDsP`%O-W4FA{eSM(2Wg&e^r~67&zI28@9L@NS`{I{@ z)AzA^$=Fw5(~C+J+?#NONww>{3LD3#J(0|2U<+jsf8&83 z+Kf%#pfHTwBDmMJbVKGAgXbP-UgmuYUNkR$fL}2fd&GZvpqE1@7`+iIXFg*ijJS=}0%2!wVkjq1ZivR0%`%U4ypMq&e8fz?B5w!L9~~+rvv9^y|R& z4I?GDD-0!xf_JdR!1WAV1iZ>H-j4@95#HY4;Wk*A{Rv#E6g4z!yNxil0Ck_`L`mR2 zyleB4vT+RDZzAh=$PkgViR|Qp7e&COaQL|-#z=LwI z(5*P{nZkM*L$Z6n+nt;5dBU%-``dGctriv>Z~u*Tic@-9*;mCLweYqJpdw*c3nl|r zl+;WM&bQ!JzzR~}B;Y6sqf4nQK*9vTKnarp2g)4n#k-8yQlw&KNES;@6^lE__v51>{zf$2c`ai!V5r$gf?*; zkf=&^-tiB3*#;E+iuW9KpAMMz3SamS2JiLYDev=7N#v(Qm2DRyT0xS^s`DbUTG&=) z<@g>bYM0xoY>5;Y)ShI8fU~p8`U~4epM({qBi}p&K);<-nnmU0udyctlH7_86<9sI~?U#uv!_VFjQ2KM_ zZ!q4LQIUwW-zHJpBEI$%&?wYSd<;ajoGB`%9l_iLh||0zcguuId48MZ?&ed;iTWBb zO~p4(h1^ZRVSJC`EUUEUUH^gHq8TcS6-?x>h$z=U!E{9KJ&_dUEjLB00QiNp^%yWt z%GKb}FQ8d-rixKlq?tI&ton_B%cWc#Ur%!9XRGXhG%|CJir=e*Zz}=IO1a%U@IR3I z0hG#;sm*oQm{uCFu9R!er;%JLC`OqS02*bt81ROa8^Mc7?#z6ZeI_W5f(0sD3ZdA-Pg3-MvYx3AjSa6#<@>aBl0?ZT2N;4jzK(6Tq z>VKlsUEHj)exg3Lnp@o^u3$ofoKlJJB=I^sMCzz>HF=k8j|;h?LZFaWr08cJhscq- zTV(|{-b{76lwv*xBrP59zLnt-sQEf zhGw>iceO$03?Ge1%Q~RqCu3qbCIAL#e4!1=&B1wJ;m@}ubovNY@NEcHd(gYcDVW`pduhYWOw%F@7bLp=-`1Gq)+p@h_s&}f<~)B zI_NlFsNw4Yal~O7F}s3tR8X|Q6Dr;nAg0y?u#A-J#EVI8Dk#yCvWM4nfYR?Ib$wxL z15YE$SD^Sv$}PTD$)?ZSV^D9I-4+?&IL?Vs{fDdf^u;z4WSI-hT%?FPC$`gFx z{6QR+h5YYdsO$%x;IHC^6CbBtyKzm$+)RR6@O8J2R^NhM0ez%EZ$V8c0i)x1LFjE;*)J9|TAJ2@G2jQ>hy%j|qW38%~9cT;7WBCr#z&54 zRW?F!wPwH2KuUtzF2FhhDqr&=k}C$Kl4J%vqEv-kBw#}+H<(A4g52Anbe7DUfF&io z3)n=$h{xy`5`G9cSVGqmH^c%U&=1}}6p=QdSjBQvB$fjhEa4nL)UhAR{e3=-#P9Pp zh_pZcp~gxK?N7iKJWz)W)^8+pi|aaiW;w;iKF4bzerOdx+iWaC%KO=EXv8G1#cDPT zVFK=Q*f7`#c-6f(l+E-XoUc-;56#|JJOyN2fH zkLEW6PrT#s!fF^EF}YCu7FXc8^2A=G*FsL<~qO;68hqB3)VX% zw}yAcTUgqApcryL0Jf8Ib?VxfzsxVbpaD7MBL5bVLy5AnpKQV#?QVS=^#B-iXt6e& zn~~(`MpSGfjn;g4X{1rNG3CCfG*W$=uLnh`!#^cPL^HB58VpBsz)~vDD2?vXo(Bd& zXc(`HNGqRYW6k*bAPDsV#EH{RK@e)gr-7^bx8ZApoS{lC-%rA~+t{#T3@n4B?($-? zQkUyx;JAMm8(XIE!%)@U>q^NAp<_G^T(r(NC_2JdQuHgoLeWzh{lS01o%W)S4e!Pk z!?ISduMKNGf=WD32nKV6Nzujw){t`V0%q|wq~f1q!vK3F7%DCJ1yZ>U%2Gkma{Jp@ zFUdU5BV1s90g9hweh1iD!pH$OJn{=8(|G~OEqI;klPHexR5+#ZN5RNo-8384GeU3( zSIQzUlXyjnF7h};+TFo6mdFdr!kb!r3^5A%0%G(YMotk!dk8pE%Jky5N#+iJK{89R zTOG^Cgh1vD-~|DdWxQ($WOnk=h_qc}Z8$tEWS#?t3FrvPwy|L<4-0{dQ*&)t@sWh% zAmAqszP7xxtbMW#i}0@H;8+D7T@D7%@s5bJc2iJ&f}!0694}#yeCq8at~~-YsPu|y zs-&I-+#%tZY1F@O|AUua1Ijt=ju|s;td_$6L(c4)Mcqf(`2cXFfR51FHrB%?B{JvP zST#vr3OLtL3|l~LQz)jG(6I_|o?R$9sx3zL4e7)sHau+$>2ZLiq`hf?zm?#fLXrK| zRJ1~13t)kSacgY!+)TM#42TCJK*tKeQ_`?H;9WkTf-_XheHYzOup`z3VznwlBah7` z8kA~mu(4Ls;Ap^#63zvzz+X_kZr);Jk7Y8;w%S;-;s4!jHY_@YBfGcTu+$KaTm`IP zNIcnLW5=Y#hdXVUfrRiuz%VKN6<~={vP^I9b61(#dp{2gLk7AXpo)kHL;ku0_KD}a z!cadu|FE%^d`u;*`yT(n7m{Slzp3RDNxKGELBe9dsS=L)$A(p`LINcnc1$!vwiY0k zb7ZNRgJ)E7hN|6Vtc?IGPO>%{r2Urk1qZ(gY3(nNY6z)_2p>DEC`*{d8!<&x#Ld8y zV%iWuyqrdkJOPxcYjzy9SS6`z0kPf-hfkYJ^26asrO4OLE=z7fDLb}eg!)lHKMBtR z?vOCg&yFu63xVr^4JGu`?I=k>)dBM)d<)Ppwihr+Qcqj5c?fU;8Nk1HqqaX zP9dm20xpy=8;4*F*#baaQr7||NcbI~QSL0z&MrynB|xlckzMU_Y13}gAUo?Q1!e;V z%ko%LM%0n^Q5n z790SGf+6Y-3qA)N#G`9a5_Rn?L_jsSE|07MXJ>&lkO$TT_dZ~tgwFwM3#e9$o%g*-M`IK51*1qhAm*u5oW{MqKZo=fn6yB^hOdcL!#}G>- z?RyJ4UbnNKc|vVai&LrN3xUpQRQm!>0er#>>Odf4upQe=g4#UY^zSraoTRcLc0Aq- zfzyD038)?&$`{sw1Kmg1u}3JlrvQ6NSaGDCy&)Y~HOh{MF_F}Iyf7Ug1@-`bDFtR{ z+41N>&Z@`8@Qk`J`eP1tUtu&o*N)#51S~a<#z=zdvT^(-2_Bka#{-JshUZfg6M4>< zYG?0Csy@w*XImj~0q{2ok4~q-gQ$*cfD3WB14XS4n#~VK!s^7?}2me$nHDm#Q6orgsfP`Ib zkhJY4SNjlfsHB!#NaZO6-T;h}a3>&^vZQtZuryDIfzk5|`Ne1$t-6RtA0lZ@07E29 zHlaFV5pNa)!90*=@GH>}{HK7r&mPhVT1TT10CsBHm#BRKmG{%~~A*rqV zz>cjD!F~Z)-X_>u$VYZ;`w>}d0*G0IU@_q95_Z{Z!Vds3O_RVYAJfPs;5b0T!V16< zlB#|}z6LgeY}rCnAP&$F*l1Bt0$$?l8#+VmIAUkm`UFslD&ai30an;8_q!?Tj{V%( z2$?#6K+MVHQMrS5JiqLTgAsv*Z<7EqHxPe2;5G?+95Ug*7To%&9oxS`)^=Ddv`8)9 zg1Hvl1(+;l*%3-ts6|_Fpaqv$@C0BRDO>8O36lZwFKj8bPXMvPBls9FQo@Qw)FcHp z4iFOp6>FDcVh$$R(H5L*!S^kA05>=01ax*GX$?RMimPr_~kw` z`2~P4WG)w;6AK8W;Mf6}kt91qXaGMPk9HFqpwS>34+k;;v9={R4)CIYYEmGNd=-LQ z%V^BTZ$HEK-;;Q3|Lq9Yut*cqM=ba`V7#Pae83Vx2*d#zvK;_1;vx~Xn~OV}q37m+ zRIKuw@z6*wr?I!B(gQ$03I70$l(1^3hGn_1+87YSH2K>N&`9=ez!`$-2r93!P`fl- zw~|I9GNs$H5+BeU3zjq)Yg54*$kUp`&i8;{Nq8`v(j=;SKb&8Lg7$f3vLOWT0^-+z z7SJhEMZ-^21l77#c(WE%s1~WCLF#Ujw9$Z}Qg;?0wq>B}*aY|ywk}(s6na;qoJAzS zdNyDm0UhT7oeFQ30Ew@wYZ!TjgyR(r3ugiA0tO4Hw!}|t32>z&NIEYdQ++KsR0tAP zoooos0tpKQ5?ly~Cy$nZp91a_P#sZ&XS9UHZ8bD39|ZRRppS$_7Cd9YOMnxlK)ae6 z4QOO^qy-lMHkQ z%>t|<;Wohi5)O*i*kTEP2XskTDn`QuEz~Lk21*zSSV6+}fLIo^f>T{%_@h>EY6eIS zLDJ@$T&+Opkf65Hf}dINM+++T$-a=SXu&uO_ORd>3ofwWRtuiA;B5=Ouwc1ZGqna5 z>}tW$7Mx?jO%^P&;I|h1%YwlT%p{@#@!|=ULu-pV(1hxg2E17tXL-9x(LS-@=O$Di z;T!BE*U&Uw-GVJms1CrtM`-IMx7=iEA6oDtAeM;j;n+jKdIGBD@mcxysMN$p8rEWh z+Yhivax35~X~a!xtg&5!#CNxL+7-i2K%5va$z&D4@lt;k;8p=0c;AruVv*Y(k5L_) zYOJQj+PHWP{pNNr{PGmfogI+E1VIVxfOa;?AWgPNQw&nRMVe-iri0|eNl}{vh;gqw zW*dvRNf3qM1M&P(UzC(daa;#<*m-0J^q_BAXn4jFhJFOZoJ}_Wv8Y-CQEzvFc_2fy znji|%c#GP~qNV^k$(GPM%Eutn{7MI`j-p%AfGkwo0~!gY0pbZ0X)C*>Tp=hWq}&le zVXUln0T4fH^@H6+vjhSGL!@X;K*MAUz|OpwT(Cr!1D245Wf3<4R+0K=Eb1k|SNN5V zUivQtQFvc9$#kGLAjY0#h+4!RfOzDk;>@{`VI3KA_>N zUn|prAV9qJLsl(fV?h)S^t7n`E$SqTI^CkKv#9R_8i}2?s8=l6$AT)#$Rd_$ZTeLn z(8yVwMQs5XFH2^!MST;{NNlr3-3e$|IA>8mx2R7n>YpZ64Q|74c0r?WqtWkPR0k~q zjYiZ3u(71h2E;&5jRZ)xH-+juC&(&j}Wt6*rb0~y)+))M{M5-t0hnS2411~15lkajjtuayCz9{1UOj=j+ibgEDco$SCgSam zR7}RV-lDc7>_2*ouS$b`Z6=jzaT-#u42ZD`P^~$WKO*jJlce1PY$gS(&mzIJfk++5 zUlQX5Q5Z@DbP1}X4`8y!odc2j_WAViMiPCF0J={BnJ3STLa(wwWA1}`_*#J(s6x7d z7i3Ug<_!VwA71oA3CbtYflKie^tGo}$7Y%kg@<;kH zb|eCaUU4-1J6sf|<9+*|a8djxj^^~imjJG#3Vy^-b`;;l!MP+Om z{{&tMu87j2n65*h(djMsl@6K>*Inqft-@HZF#NA*TonHVhePphaUIzEFdodoWf(h# zs~&Pe*9UkZd=H8i|5%09L=}7q;WuzqgR$n|4M250hTLP`e~7bosjeu%8YpR8ONt)$ ztkB{%1CFo!heT4kK263f1ec}=;9F*ojsQ9|2K#` zbfvS<;aRUJXa(Ev}R%0eCNR${7dfa>zhO00UJ%<0pnM=GnHrUbe60&TK-?)W=4mhVMJnDe6gsTRM9*S%jJidc?DM~WQpYJ;8 zjC7@w>nkdp^EMmx~6D=Ft{4@f0#UICy9V z75-*y-FkdV1h#V=eB2>tL!~O;dB{1^**%Mi4;%K5Qy6}BpLs8g2Ylmu2fbkS0gnulTweFnHHs) z=2}>pOIcZIX<1p16`HM&n)X#!oN#`J22F*V7sKhw&yT{RD=(!7ve<^@xEb}O@%ddwXWe8jkM!-a|EDOaZJtlAam zGNVi1@83`1Ie2CHEoF~9*yZJrfybMT_~@_Q@xke?u=htczjgX|Cv(gCzw-N&EvJR= z%-*bah2@xG)`4fw?>#ap`O;IPp6qw7*L6`m7M2rMCtz~@Ev-lGzSLp+gQex^JM92< z2rz6&>)(4#%4oA_J>`;A)?$;kLw0*1Q6Q_HxS$E{*$>^Dn)^`Pjn3bGsK-JegWjeqw20GYaay zT@!PH!%{MD9RI_7D(z&8=L^c#m)cq9l%CBg3JbgM_}iDqr*AIobo|RvU3-^)VJA1d zSIs()*V!ADUGx10@fmBME~{&2Z%IyASnoyS4t@OLgbSaayMO%`xo5rQwiZR}=URU< zZQ$SSm#>IB)oI|~f7>Cpaza->8d!06wedy!kAL!N#Hg-uwqi$4ov{2r@^fQ%zq;=G zZ#v~xR0NK&6-RQ+nnAhNgdw~^+p+I$E7$$+vbLAzUEl3Gel1K_Tn!B@zs5hc zJM3((3UCJ)Mm0V2uh8AQBhKZifTg$}E?@9>=whWqZiGfZ9{58$J@iIs{oVOL40Q$7 zr#_`34Ie-B?}4hLuJJ?Y^v6ri#|KIMDL^s$@lVgUOc=w_Sma-(VVp+3LV8<CWMnDYkC5+>DY&O1-*a3Dr#(LNLQ2edl9+%@L?$6pwPzrcwfZx( zcCVQn&O&A*MaWJ}b|H6hd^ZxviM2+SA@|^(gIwhJH>8H!FdE=aLpo`yMZ@5T$MNSA z@wncZrD~UlnXZ4S$9@fTxqBJL|NA*}a+H!gAPR+jWmB-(zT*|fUw!k{Neh&J>%@!`!b92;I*PX!$ zzm%uQDF1*ZI9wjy~C2wR1JNy8S&JcAGloI(q2zqvhvsQ+rgccE%;w3n(M&ATZ;9i{>tMj44uAT7Y)Gg zhYyna=nZnTZS$4~%a0CFt!OYqR}WHWRc86OgH%Tq!nJkZsNpiC8_^>cg+%FYLsY}W zOd|x3o-V^}8gAoPj&l&Np)wNm#-)_^x*@7WRjWn}d5Z(|jb>)cYTj@^>w=*w#T|%d z_F}zssA^ZKcuy2TDDGRVe;umoS@#h%G2V*N&F@f6t5x)ubbr?4?ocT@|4!vHPc7EV z?@(El5u8Bdu1*BsEY?luTUCmVccKVEF>Hxm>#ukLMYS3zMlT7_&Hf7RP#IU`FoJ}l znYl!F8s?YFd7`L^V$Kr%WwBM2{qIB(hGO{=9Xedq3tzq@z%IMGMp8I6*?3834_Arm zrByRc{_6#{LvQr@ov{7Rc>UA}vC|pK_RJok8ip@<$QxNKkr5Y>9dcK%t&)N#c@|% z)IkK!TddbV;fmE|BUKlZ%k@%;6}x(r3Jc=OaB9jJsdrAdYU}h-YO7og(d#Q>@Qq_I zS6^<3K~lcjU{d(D!RdS&+vp|wV!rBXQoOcj^A}z2kVLyWWsx$4JF)=v@+IZZ6sX?H zJn?Y(#nGyc(yk&E@22~4zgR=37O9+=|5+a;>o3-D>BOC`7`>rL&Yw)W|@yqQ5@qQPZgU%@(L1Ec4rl^5_TE(cT77;b zhHFR!omx859mz-LAZw5v$Z_OHB#^6}gybOkNC~nI*@GNKF6r#q>gknMl1^H$Tvn?H zQ{VV1XoN0VucFle{nUEZ3>;gp`b)-=o>u8@Vul z4XOuTpKnl20S;Yblen=m#Yhmq4r2)%B7Buf`OrJgR$%Uk`tN^&Oz z819ZMb?Wo<0v%Vn^z^6IPrCW2pkVK1YvitrLHCt<+NR2unV`3AqEaWK$X%(gH#1u~ zZ8<@QZ$?2z+z+kP?Kk^{xK|X(C|0c0&umup8m(CA?e6LrR`?#Swu`HI3$^KO$6uN< zPNPuI98V#ZO`>1=HbUA|g3f$_zN8+J{g(`P7^&J;roT}%DQJeRa_Ogwt9P!{gl{1O z_0c@MO1Iyl+BsK5PTzM$>JxcKopDd~I9;|yg<0K+ebj&G6pwGA&^gtMThw^2nA~&{QbGysd>$a*^*2CoRuR$tC zpWmu-I}YN)%s`ePWyn6{IPxQ6FxW;T&5;}=ACWp2; zdlauW)ffF0O?IL90mZ?lddM!ns8)&MM-=Uw>HWJXE%@~=RmbYu%oz#8cB>XnjjPbT zcB_=mKVd$+nNv`C1$WIJ=Pjr_8rM;z9tGmlOF?8K^QCap;cC*TA`D71tjXLFH^kB76kI^UXze1X0ntO}EH{h1)htS59s;c2}I$=|ZBh-%L5TS_UCkgzm6IcdVsoteJ zxm?Ae?dZiFAi+PXNq6T?nl{BSBtWnopww%*tz0FBUw5LD^OydC4DY2bUMg2%;SDpq z`4n9ZpYAqQp-1fHv@ghMx6q6Bs?_kT7FCuQ8jtBW_Da9=s)`7zM`*ez{4VcRJ)G%L zh3@z&aWFG>f73#be^oWD_l*;WZ|3m0sw$4cabqVH7<$@ks*XO2ab+y(HDdXNSkhbS z#;=i+^p-d0WTh^6O-045^oz__wvwrpy7V>Gt1`MXL>F?2=oUHA=o70$YU`BORd}q= zODbo5ieoAw7oe=A?)$pRt#;P#Un}&+*U8dl;yBV$zyCUO0~oqb)d~ODiPLw2t90vq z%yqo|a)q9^k8r;dF0++{OVvmBsTR&G*4Mmc7MqV0+dYRen(52makZMip>oZanv~Cf zLxn1n&SLp~HQ%If2tAt0NB4347a?GTP}AW0)w-IHYC-(I)JUd69SWbnOt6r>y4X>)%v=nkH3a z?c2o0%qbPQF26U{S#=oqeCx$mvB+>OLQ+lRFV=CJ0)I>KurrMad*|aB1@g_;HKc*U+g-!JPqMXyjTbJTLRPjwuQ7%`I5PFd$ zq#crrj72=i8e|7@1UVhDGkdLCeOx6~+eBtA)d|qk7gvweS;tj~WxJkM8G7z<^^UI? zhn`Ro)iz@r9Cgz&ZIj-1f`WMgP4_7M*@?hgD*rn!4x~w%q%n*)QUd08l zZpS1ezFJ&>%-iPa{_)kKwC5z_6d{M1%#KbfvEC`i`#9E{KUYI_(x)m=2cA+PHKvcA zZ1?bTV)JzNrwj@6^a!Ajpw=ayst7#72L?y!9h{Mw8LgY1QjPVGIBK2n%PmdGn5Xne z4_$5iXDXt`_?W6w3Dz@Dsl)(j0`qjiXDX%EN$zDtZJ|3Y`s3U^|j9_ zkNMscO5zN|*EmC6-Di}{ic{=!%-5?Z;FHplDWFIByu&A#;Xi7%-PIbT)|YMb=DFEQSM@ws^YJjUVY9Ag>=|UzHuiCS59uT`1}$=-2!ef1{|j8%6Jg0Nrm! z0PXKI1&Pa$sf(|fEYOFx1}CZo`phaTE^{;0d0Zad765+Kp#7;8U}4- zi6imU(L1HOhkZpy_?hD;Cn6VVfi9fFB);!gDmJ`Ul4FmK#V5L*j|6n1?BDo`6WBvO zJ0$7vzoHIxa4aQ<63arVLy2mk-H3r*Wfn@6iPUSqR-xg!P5{ZMjQUu9qHZN>^$k(K zOwK6qu7!T+Z-*B!E=#7QJwO3a#C-hy2CKUuN zC+MF^dI$;=Ha?>g^e++BeVy|r{i#^(#VRyeU$5Y#LRsJWid_R zt%bpXH|6}87{8A3Ps#fCvnsX5Pkwm{)h8xcaXRD!D^M-geTX1tvGSXt70j{wA1U6& zdfvB`&Em?fAD78j-F((e)U}C{ENEq9nFDl zUAL9$9Y~$wQbs7>a5M=tN#3*8Xwf%9vzessLzZ-H}!jF zT)9!@^S_sQS!{Iq@*mVi(=3iFpZ~MkqO67SESIha$LQ|oRlG$H;&si%WztcsJ+Ee& z^Z}t4R2!=%jnuZyzkrsuJpTf7%iam)Z(dLzsvvKhP*j`nRj%54>o4kX&_TP-DkDUn zI7V)kT_Pa$dCMi$S1RS7msH~*Z?#iKoOf~E<+5rO5f8Es*@GNK&LKukW_U;|Bo`Tr%th8AdytdJc_bvvXlB%BIPHQAMdlzY zkR8YoC?mB?1) zFmjqxyPKWz5FK(&MYtu2hDAE{8hcd@ivsj7X9KtB7rqVbP~QA+wOV<1tRnU4>)8Gq z+m=Q8_v@7--Osx94T|DCiY`TZbD8ch zJI`ghpfx?^x|zX&`Wn|quTy52j{bwAy&R!`Pnjv;f@0d^?HT>cTXwD}m`EHDBzG8H7wkJjj|_rP*~?yUhA( zuWsNn8-hMAa|(FXWsabrN4>#DLVAE1txoG60T`Utg#qTcC~w{dTU8y7>@n}vKLwcG zuxa8pb?6QfIF9^?xN7grZmL!Xnn~5Zqi|!msxr@acFB9;M}F+FVSWbM!$p@)3-glT2&>NgVk(Z7-ROs=8YJ$I5da!h9gDDGSYoTt&S&Mmu?Vm zCYr9d^!gODsm@PvN9$$r<`5~Q309=O8c!jm>F@-zk9Z}R3E|s_+xHnxQFRqY4ZES9nXZcTv3h1R@OM44kHnapVy0VL z-Z6FY1I)`-q_9-jqMu4JA0$inMz^q?+$1)qbx;q$N$+zR``8paUaGS%!8 z^ox_@M)rUdemgqG7=v4jo_KhN-j+%OkJcwr&A0}GnLAO*9NH0$hqBK&0XBdWb;pKg!=RClb%vd6%oxL1BoR-+iW{0nA*7s)Y5IwV zW?WF_+upcu^=@4sZ)gU_+>1#nCilapa2|KPd%}m=F`?)3=YA=W|9;OoZsSzVfD)((n#$D8a3Zzpvy%?wQ5jtN)9*a4;G?}8M( z@v>n&G8`V(Kc!J%MY={KGp^AQCd87-qgb_u$6yVvWDR3-W#LJK-lF?AqCp=i-`L2! z-oK4;pC4uZ&u{{}xw-o|j=ZtaF6Zs6ehF5m8h{q)Sw3 zcF)x<%p^Cr-rRGW>(mxzU2AT0`;2^@aMz$V0hZn8+IJmJx8P(R#Qd@5{&$Z`bVf_^ zx(LN<|4^(F#bOj^|DpIp6iZOl%h2^&nZEnbC3;*d6c3^3pP`qxqLBM%xb&?*2H)z; zV@kAYjm1(d$}@E1)_y??Me#6-pELAof5jJ~ScW2@g*MxmzNJ=)?$rjxBPcqw&|kOl zi|S=jEJrczAByC*C>}-eXbWAponMGYM6m+JuPyY_cBb#1cZvQ@6s0KYvFqp`qM#j$ z$51qDd2@*OMDaL^td{!Mc1&5aTKejYcMaZEU(Ph6R9D^6i{$oZW@YiL$|N+mvfN8s z>iwC7Ui$wLI>tNvOI7eyE@^gB9XiCg`&f^0F#Qs%h12cLR@Q4?SBCE1fvL*b=H7c` zUG$k6%!NE1%;rJ$GQ57xyo-^e9n3J33;J~jYG}EmYw6YHXPIF^Ki}-P3_p{LwLXh^ z5!dE@7&NVgH_l|;e@}2s?XGsuTAy4#>L|u|Bh2bZV6H;njs&LA?}I_j>_SjR4X@2X zY=XSSs*JwgwZ{35W~(4?VO9ENbuzmY52d+GMM{u0$PVN%avHgW1V%F#L$Z)T$W&wr zvH>}WoISxDWivfze>ZBguJA=jtMB9}7Uh|dkjLh>P3K33NVHKStuvp;Kg z)n-hr?igxDOEx`3AektCpz1{MB7&KY#U7kF_~e&VS%laY&xM+|>PvmhK%Ldw3`|-l zzI;}BVgFC03S~a%4XBeh^MKd%95Wz6?lw%sTugmxDIf_Gr%Q9pj#8hG=a><(xl*I} z+~bA)KZ#gBd{AG{F;f#Z5KS~TqW{oI>3@mpniJI%eo-Y8RgXpbrCvlOyB$Xm(f3$X zby38;Dp$>WldH{Ax%v3#svc2&y-1Jj%@&V=z6cTh*Z+G|1Boh6ChdIk?f>3?DMU4R zu@1h?tedcvXyUOE{ouv_Yp#fD@KqX$4b9b(=bA z%oMvu4~BV`?qj+_#l%C5F8YA!%k-Uj zW~@Hg-{b)#vDfeMDcEc((R2 z2gS;EfP5O;1A_NBm9r~)M920u2T5;fSIRw(ou8S}5WDru_4>Z{0=3ydGcvY5b8Gob z@xuO}hS}50b)9}@7hmTacaZtBeAqsy{4~NY_)$x5f4F*NLK+dtgj)>ow7V!NN*XYa z1+j%57eH5GB(Mn+XW!yUsOoDIWbNLCS$uVJ+uAR%B$c2u^31rpCoz!)KptN2Iwn%~ za()R)f8EbrM|87)!y zMgfT_kC?c^M(xL{GAUhWf}Tfk`#hFl5{Fl|pNaIH3HIF!yJK5DfPSqD(|-BL^3wNd z%+(p?gwtW{;aT7QH=m z5k?jo62@mI{&Vp=j10zqlV46H+PeDk0CQlhOs?d^%DwV4jE#`cm3rhrvkSShYopA! z(oeU0GEZr2;1E%fq=4H3Jnu12rpDtE%!Rr<15l zhnR_xVp4|5y?AA7uSu-FJd_)>r-qne{Y8HYy)3~0aP(5kWpqyTtHKkDMpsrk2@^uG zG{)vD9@mshFJYw8Q7qkvJAXiMV?BS3<@OGm@q^63{w~>$;8WMHsx+arBcJd_Ve~1O zG;K(WQMuC#q^8(aC5L2=v)dqHe0GwQ^d3q2tJ@j)ll*d7l##(BTHf3z>FlX0&VH~* zGM1z>hMI{99wHn|gxPqtbP|>babi+9l*JO36S&>Co*O2%`5MgmGw$&-mrfwb?gVU; zqv$1y#I;qWAuTwms(sZPU^KQ<8D19!A8E$EPg9Da6AjOo1jp$oC@wGRa zgxAwA-(hxE$@;fDs1(UM;Z9CI+3)0MPb{!+hf3Kb>ppjy*_AVklTMniu{6b>a=Z+W$!3;Cz~qwV7*mn_-O4r-ZZtp00N!? z5S*|ftstPSZ52M;_Rknj*A$V+)R_2QAil?)_aPc zRd0M}rUY{XVmP~5{voE0n`VcQ+MJ?mjIcvA0vY~Rcg^xn!$XqTt*ggsjmkFfNvExl zo(w&l&^jwJ(F%`Frq9P{KSoRajHFLUkvsj7djAO1eN#51>ywPjP?Dm*8ev8y?b0 z2;!JXvQq6*^q~SXN*^CdPn4q7dx22_wQcXqBdPK!I%w2C3VZ7GF?OS-KPGU;QB*en zGMhc7z&<6q0@Q_sCX$E#MC^L`{($X5Xt?XIk4A#}> zxqIxJZm231slLt`Z>&0% zG_Og4ooB9t)TyyVwFBEl*goWED;+GAVYC^Qxd)T2n7oYFbw86^#6(q1H6|6ZbmJq} zJzaFVV6>goJTIOA3H|{l%qo~60pv0@w*#CQZQf!x&GV!uXV~r8s_G_@r^v*DvKeD$ zC2e-Pj8^#jKJ4A4s>CezI&WK?_fevCr_>hpLe*9z7M-e?j^oV+%;otLD9G| z6UVU{;UkltCB&RdI0@sklhc)y8hB4Pf2G^SW-%RWTtJ}hP3Ib=!y;UPI(niRqL+*} zLlO=WQ3Mh3{DQH@Nl?y4^3p)>98WE1ppT8G_70+6okp_JWIyLEA4yUMjs{vypp}S8 z7?DX?EOJa_m~`1D;ZIso$&z_VGY2yY(MWl|s+I)UW;_|w(L5WW!v>iV{nMp3@^N4v zvjOcM=L9nb+hvnmFnZinQA+eBM12*JFg`mO-bJ6Pn>-fK!`=%b`qYBVi(m%pj2$DDx(ps)|FdWkY>t5*Ka9bTdAo zqzU(=uljh$_vy9%TAzq}l61>8;XaJs1}tr=4cc!~-N(Y4#LE#*s9+Ngt(; z4h|0Fp6$Fs+C`dv!V8&2sJeQ=EUxtFLNfx*%krqL9;quz`>fmgLHRo751Gl}we zy4}tsCKrY9B<=4f$4p|9Ye`~jt*C?@#A0Bw0F(dvnMegs)7jJQ?2njE#W;s$8vXTT zYH9tgRcVIWmekVP0c>XwXeWUZvY3ZnLi*u#tDkk4ZDQBeWvI_1QdjTvGm&l+M${6;_dY$PA>Erd3fp8jCUS+tcKA~FcH`WGW`n{uS&50%joyxl zl&N&%jbviMqwKTHrsj|^yOWM>o{56b0Iq@W)1DK4aEER>n_l!dab0WY)j#OO=NqgV z+l^6sX48u{me!~@*oRuJxX*X$ruUdV^@dQMWV}U}c5@{HHWnE7 zN4XpO_S0g^oV4ourIkfm8+PgScbo07TRq#1%iHxEm<=V5+}{nI&SVC+O0mH52rh5f%1DOT*(AKt?T z^bBHdg^lPdc2`wiF>Ip4=a^BgoA{Of=z_b(ib{%U4?&v~bR6y<{esFxC8&I*Cn?TK zm6?aVfqmM^iu9?zPiM07%pU#z9J706Q4W&MiI1~ZwvW4D_u?Mi>0WbWT=!14mk}tv zuJg%8|K1);KfPWhCk!QmFpR_iPeTe@N=(>PpD19TsHxpBn%_qoX{t9q8JL~ny`3uQ z$evzPXOm#Flh!@HgdlGeaGy9}*#VvWvSuycbIA6nAGwKLpOjJqgZ(cfn$~ z04{*5-~;eQSc1xPh=T|5_#7^RKf@*PclZ!Axqi!FAbbSYfGc1!d<>?+m2ePT1!qGI z?}Jak7vXxi7d{OS!RO#n_&izje9pmUJkG)w;03r1{s+n#{|2|?{;$JOx&U#@my|_c z2kyk(5blC~;2t;-?uFc3HC}^r;p^~axDUPo4@l8`$iYE)0Um^;!V$$J9xI4n*a2PE9l!K`pdmbb zO=WnhQEhp2)l&zuhhjhK6a*XLX7}HIL?{IIz+D3lhM{mAtOcjQ2uQDPU)<@i4sMU* zU*d2njKQCpX2d~iRMq(lb5gz#uhG+PX5f+g}dr#p+saH5#-WPa;f(sgUW2 zN4glPOT8eYi)Sjl1(w2e_>7}}2{zM>7H~s+haRzjy8tcGhTz)@#>3XI1*Bbia$s9H z61IagVJ4(q8twJY1!lu)GIVlZ-2Sq2aVK1qA!;ozwV;L-Fj&4W5e8gCe$6Ig(JPAwTH}Em|1AH9*0wuvK zkhAx=>2NfRf@>hRgN-L3w~CClkc}7Ho+Y5M4tFoO9^MI`R*VJXIM{%P^l%&DT~HFZ z4?c^VC$Nm?;8T!d_H2fm;C3i>d*Bw_@4>C`B-{p1!i^1 z_zCO_Pr^Ilr*J&{49<9u{E^%Ut^pRhNIb zZ>@Ak8krntIx+X=`$=Y06aR!ILq4@+#+RYCPLLekGScjvS(TYc2BS!$m80%e8N{2( zDm$;chkh~AOiUBA@yG~1sI0=CnzJ-zhMHr z08`*E@D_L(c7=2m_K@%gyc73dP)4Y0a3%a3)-W3Iuxkc#3lgt~Ei@Yhc^?B&#y$4i zDaI(%n=TLd*y#p9Nw*r5bc3LzTOCTebWL`;HQ^xKEHCX5vNpUMcLc0Tx2c`(4N2Gg z%!o3c&>Ld{Y8OXiC+8ar<$M!hUC7+c9+9O6O1deyeFH^P+^M+b+A+8Dbb*awPuLU= zgw3IpM+-O(wt|wcHgGX)57+QKlhMJ{Z$4nA@zle=A0T_)=TIt(r88!dy=*Ai>jtG* zdO#_bTcKpH7nEYT4ax}J2THN@gOYrID9I0iRmI}H9FLZeuJ@r8W#rp4fnh_ilXQnd zN%u}D=?;gI?no%<=0h3FN5hVAEbI%%!%=VotV*wueHm_f&`dU8Uab2*XvP*#!5|#N zLKp*QKpB{4!Dg@sc82%BTjBk10F>(@CpZtc%#g%=JM`cl4Hv>mums8sX%V~!E`jsm zQuruO9vI6wSc}JU_##|k>OUVeTX8*_Ei#jfz0bs`%13ENU^0t96FGjJ81KvPqFNb&woxK|R8eYP`0!CUqLjc=AiKrbshg&8W z-$R*9{0tv~=V3X#2)~8I;rTaYqT;y^rnvkbO|Qj6Qemtht>2|K~xU>C?r#15AVyWwuAjOw;WBRslWde+0{0Biknp0QnS z#T56(!Z)ZTVes^F@A75}vB^hzvIzX;(-&K5y#1i8PWnUHupJER!y!;QddYQjI25<6 z5X9XQ4#O>HE$%Lm+IG7q+wtfI^D&UFPz>_mXx#lBw~P?ua7!_XJ|9lNUEsLKz)83# z!^xI@WtlnJ41QF{K0@(N$6vbMyP)(ccf(U@_of z+%?z|^t6WTta;kQmtj{(gZJDC_d>=S<25)3?uU#Y#zFWXJOrPDZ^9QLiwh53r*Rm{ zD=^=NUoiq2A8_ysJO%^kHKd5D!4tS?$Tnjg|9JQe{tX>>YxpVdwhjk4{)6D>y2hjC zUqRky)|A}QaHIApAG));xb-`~z zwTpkmKyL1whba;eN)5UMWt_SUWt{pClsOBFC3_C{8=QmtclZ$eFI)}jC_S6tA8-%+ z6TS`qf*-?c@LTvdyu?!3xXyu8p&L-f8NL7^+X?Yom*P_f)KwL2#60D2mb3X3?q$+mOp;K$6=pxm3yyE^9G z9P{puc@LK!kGaXSbju$z>lH`iA4+s=S=!&-qx-k#MDb9jEIfhlNrH(`u1hkM=|BpU z9;5+m1*MkAl<^kaogvTbd1N}lb4s3RkVgq*N@8%|ebE*u_B7aHgWYG(F+94Uke11! z)ZPTmg+nQhesC1bgVK-&Kw0V!f~+Zx+u>n&2b58nT{_RVa1^XgH7gM`U;<_^PX^;t(F%wDynGN^DB6u9$0~z3qdm-bJ!Q$9+3zRcrlrZMu zW|Xkqj1Fw!(j&lykp9?s07`pU1g95sz&D{h_rOvp?#JL__&9tNu7-3YhK4V~C*ddX zDR>4laN2v98(<^GG|32;!PtbG+G0EpDMj1AKYRiAK=>kT!r2-xaUjF81mtXt9k}mz z+{LgVZZc`?F8^XB&$tD7pZHVkvn5}l1%8LRI#=#{D1*??ur6d^wg;16Tt>+qxPQYv zO8iNt0R9*EXvo0rnFarZ{zEAP_=CIfw*uHbhU^lQd<%nd{|rOmW%>4KC~A#4mA zLm4d71N0)z_uIy=we$zaR7`O{6w(z*K4R>9s`j?3agw#V_qjY}Kck0<@f>mlfBCc} zoD`shs{u1{OPdrXIIIV=aZAEoVMo{<7Qo(+L9y7ljRRQ+^a(H?SOxpzehLnRWpFT* z#&1>OOrZ@UwI2HBDJoP{Ic1vm=+1;;^|N>6|>a1v|)*>88MrvVX@;wx<`0 zX^>4pgZ&uK1ULgug)^Z{sb|6EkZ?P)daT8DlT+X06qgVU>WQL zpNBo*CO91Onkvt1$V;g_Oj-=y3*}+xH@3oeA#V$^Z&>g;AkTNWdDD-Fp~%=7z;Y^5 z8Yv!h-UctG@zCiSyobiq6PCka@Krb(z6R;?3|`sdp=&et!3FRQD2@F9q(?Fi!e`-| za4Tf1%=0pQC%|}UbO6%<++2U-lYn9(;(#qQ&;9T-SOQN$4Znn(wY(73vjs}ga~1}7 zH#{V2R6rs(&cF}hS@Nq9M2#q_IJQq zxaFPW5l~(a9toE?`bVnK{$ucvSChuVXJH)N1Gy38c^f9cA7EX0117=1K$b(WHcWx_ zVFP#zOof?{8%Un6@D?~6ro-{D37icnWsfItETcRJi}7dyOJPg692cT*_s0$|IR3xF&hGNMPnqjYbL_Kv|I=n{MmG%Wa|yabS-A9o zHH=AY#WbzFeIm0!?-PrPH&k8@Fl*Q1^4pWb-f#u#+uXY82D6UE3Cd&_u;+{=fav!uNyACFm73C(nvf> zZ~^QGX)K;0@BuguE^-?SAAyp=N8wWZxu0PygEEB^|0m$1xSv$<%z!x9iU+OD^Oj>E z-Tz9r?(~eg)*Sb|{_+{KUOjfpAC%Hxj~$?dtKQUb9($fHtotk_`V4w0(Pv>Cd>*Di zTCb-a+ze&1`U30?x5B}YR_z%NcS4!G?uN_ZURVlWgX8%*<;;JF@8SO2adUgrIEK3&{0Pc;cmf`PpFnOS7$@PspoC`=+xQH( zobcz6T~pitR(KkBZ<7Y`6$hj6I0MJSZ{cM49h?ilhcfB?5z3_Z7d@%W+!Vy)gmz8s zVb6$K{>N>U#FEWFuu6h|!4~ju*a_Z%-JwxUYJE+vM+-gbIWs0`gcA?no}$?`cA*c) zEC6!34LU{a^Re$**;-rCwcq!G-v1oeFBmDdA_Jw&c9}a-BOTe&V?+)A! zWp{w##q%WO;b{*$yYixI&lZ_bjpjgZe2#;!L0(GlVFOft6T?#h`5g?;Pp}aF3a3Gt z5XqTUV_q@?cPJFM>=qQ^?gja|3lCcq@-}S`I}65r@OyYaya2_%m^HUC4-b~u#(Wsz z@+#`U2XM1!HA*0hOoM^YUhOP}9dR#%-QjY0D|{TXwlvm4)|SSTkTs&Q9?G8gMtC=T z7Ro&6IR;eEBOGkP;~BUGZh>3jLHH6p0(Zcpa2GrU8F1~r$yeZiaPNh_JxG=^#(vzf z@E}Zphal5Y<4w2<%9+c2>FsJ07|k7zweTGbn8g|I!gt{j_yK$$egZ#$-@w=4&+tQd z8GZzr(-_C$btsjOsfV2qGX>*RdFBh|0e%H!yZ&5Oih)@Qk1eglz!VWMQ&VwmXc1z?;Wxx^lddTF=^StBU?&#lvsrY~BxQ{z-8F$j~ z{}*fwe}GKtJXh#N?1*Im5)T*sMmh|E;*Nxpa5`*)TLvUaAlvcp4>JPw+HK~vAn&u2 z%6Lz2d|TDNvo&T?McP2A0&Sse2Q!JZH{04nS&(*un_*`tSD*`g3rezYLnfOZIWKV^ zf!zc3eBLc>ZP>+Q?g3^@;~WfRsoV?Jg}rU}EtGU?u1b{sW)WHXAKs;}zeIr#KrbWD zASfgK?NIh4hQeX+PBJ*JlrxjPh&h3J*LL$xlLs(EcaYKh(YuLgE)0b8U@#Q>5I7&V zG&+>_#B%|Z#v^ujIxK__;C>L6z}1jhxn1X%z@fRU z&+z!c0qq!m>o7a5DpMYbY`kqYE05}(KrjSNL*Aj^<45fc9WTv_X*?}BI&LJUO`ua!?l8?+mRv>$jqsTd=@>7}{w|b}wDG%9a4&V)q z<-E=+&XmV*H|#ef%2ymPCo6sfMu)wLE9{VY-BRD`ns1x4?I&;FHY4xrdiscYKROVpo4;p{_Z@HbJ5GDw_J8z!bGQACAxU)T z2j+*iL$Z~1)U2n(m4A$zbR>ApyvK`3J@rF#G{+x(Sd~uxN51&#=&wF9$NAD6dffIu zaNN#WvlHG7dQtOZ+g1Fr--!o);&-ld{T-KZP?Y^nnhj0zRX*o4^Y_AQ;=aI06#DnA_W04YM9kLHO ziCjTK(x@^>cVtEy6@Cc^dyu2ZRV1ttQ%GbGBHxu;hsc-1P9ay25XS8;$WTPa@HNO` zM81X=$O)05%C~p z$Ua2AOLZOz(;GYUYg%EZ>!@03)i=|+*bjEEDzTzf&s9%Z&G>)Jnkm(wi?Y(qKf38@ z%Bm||uB@wE*2r)J)OWaUk^#taRFAid7-Cn8ek1EulLl80<7E^?@ukT@y>>0)lY(@ zb+L5KXH>6%5R2J(d8XT{ZAs4h23bp0+ww1hEK8B(SHaf96656R)}p3qO(}I`C^8pW ziO84W4k8uERV2C@Jq9wonfLb&SBF|j0W1&Pb9IAItEHM-en+S^Q#r41e4Z@%a&?X} zn5)m!wEpWZB7$|zc4pU8(h=y8T9jzAZcxigw32`34VPin6LiSmXlB&1?xY;;cf?hQ zRhs?-tC%z%Es!#m=lf+i%|qzKjX^r2wk2q7X|$DMF1sKmz+8#*){3V%o&KctQ7#wdAWE-W;rpC1{9#IhM?Y=rgfa6p1IqbAEKe zcH+b1u;{Aqit|O@L>20<;;e=-g*?LHEB7lwwBcZC14a3uL~y^_r=N)Tg^AQZ#uLrk zS|wNw&9^V=uM_xvvhE31Qz;8Ooh1oYw0YyAekQ@H7kk4mYI(8JHDoeTqbFppeCKFK zG9}ZcF0roAcht4yM{w?~Ydxx7&_Ri0-)Av3k!Y{{q8BAvb=4Iyc|fNnSs|*1E=cyX zTa!dgL-o!iVj8MXBoR}wzePH4Df=oJ<@@^YWa}Zxww;4@^{i+s>$0g2v~c+@$m$g0 z8lYoRtW4*1irguytol+!$v^99X}nFRB*luS8gERoo(=NWOvNu+*+0~lU*FoGPM50& z){BZ7wJnv-VV7>w(0ZLK^b-hLW>*|#q`IzgOQa-mJR>F5lsvzG$@^-~S>88=&uC^1wF_fZ0WZNg*UU$DhFZgHKif)wZuWlL_{`ZS0Y=HgUBgFzK`f)Wf0%0H2dP}7Iv@m z(N{tIGExicLt0Yjme!%rRv6?U`N*7B(*OOcR=2T|+%s%3oTnsgH?*&3O0y?ey>dip+LaO10W37Pbq}2R?Q2Ghgkj zFmqu${b2_yr<(UWMK$#on1!&3?_TfAYxtWXkvbvMs%@_ShwXw)Y}x2{zvgEfrQgkD zgnI2CwvF0jTL;_E{A?ri)b>_{`Pn~gPhhLNWLd7jUvDyw=z#IB|1iF{11HQq7I$c- zex`%f*n~HoQ9>35F&H$?)IGDfI`Afg!t=c4{%DpJ;%3Le-7`~voyAwd;7wM8I}!~y zE!?9s_56;c1H~ZFDLHoOkMX;rVV#JFdm8TfnYvyl;(<5C^F$}&Nx)!jrhc=NRnLSs z8MN+<0e3;%uVm_xorwY7WbmmNBx3M!roP^p7~o9?GrM4rgu%s3y|xQ6z?%%hvoT1< zAh^A5pN#>$$zUf2I;@-JGE>{@FU11hWYNDXQKS$>*Y^6pu4DqSHjny{^*@ z19+3cL)|cFfWdw3^)4}hHyJeOjzKC0tJ~|o-N^&I$>412c2Ha7hqwySy(Su<=O?x6Sg;&kCnk+trPL30c?b>KyO7{HqhJ{5xu4BqOXulFW9 z@Fs(qw^1>U=Tb4g>7du%MilTSi||}5X7s`0uMWC>E^)w{EVg0cZbc$dS^BeFqJTFU z^yz~^YYbXu>AU+71H8%LCo$lDox5L_uGNF>n=ih=VoTj}n7vswl%qXWI_^fX>K>dCX>&93eA z`aG+zN$-3y&uVPl@6)#GkCr}n{}6`Osp6nhwH;;Rpx3k=r^P|HXgeYX;Go;H9l7G5 zi?bai;-EXT9mj|BTcZaDFz=!3vVE?Inr_N=qz}YFXJk9Zii3{FcB~Tzos8``DGoXm z+YvGd2c3uQXg)XCrE>-mKfQ(RGgs7f47OvBIOqgy$9Zwk;B80!!8mB#wqv+BXvnr> zr8sD`w&SQcXrQ*kH3SEZ(RO5sgEnV7io`)X;|IHVE#VM`FxnKFHqvx#i?G|Vplvk0 z9ZzWrQq~^vq`I#cPinR8c}YB}z@bC&q?+2E`9txfO3oKgYM$+RTs)~|7sZphWP5hG z15fJB$UE?)df1*j?y%B|S1>y$L-rvRh`c@^qBWyCl7r+UbCH$EUgS6;U+oWR!~6)z zL8c-lNExyZIf9$5a;|d2M+-|CmbU}t9MaVK_GjdQT z-)Yq@ZkNfr37LwNARCaq$Vucp64IV1knYHEWDc?dkuQ25L{1@>kgyI+v5@Y_aAXd$ z0@;ilL{1}DkdQ3mL%Jiwvy2p@h=XOwX5=7p3b}*?cH|_Hb{$KzKW2d#p^tP64XO4k zt!^_vFmm(nSr2Ds!)-wK*?(%@7R?njH~y(7R zJF0TH;73$Oq4*QU#JPIWDEhUDbIV^E#i}LIJIVMNm9Nv8L#IPguoP2#Vbl9#D*4vf zAPT|u^ZpLFKK`i7rDqga&4VZdThZ3}(T@Tv*OIeOyti76UNf3sgKah1$}#704x_E5 z)@P_5{hOC^*B@hr1$oa%@huhmcNz1>uo@%x>&Gx=lG*piSgU*HalOVObCDIuW@I07 z68RC4S1U#!=|~r3C^7?Cf|McqkW-y@X5Xn+k7q*7LqG25RJ~k&oGE)eTNly%7!NPR z@1fU?xAN2yoo&A|af0RIxW)vlKhte~TBDKs4Fa~c1GWioo9ew1b)E0j|Bq0-X>p>J z>Rg(Ay5mHyzfKPNO^{Pl%NR?F4r=^THYXoUo= z@Y(9*$^5|0)TgX0*2H}#5igG|x%WEpmQJ#wYV7sPU9dhgm33xytqM8eOOtqq!&3dm zL{{cYb@*f(jV4=(x_hA&&wGWqTr&!-Ks|Rd|4tS1%RDP4TlE7jd2>`~Md@pkfZe``;H3~#>@;GgSk1yGIwo}}C)V_s$eWm)<;Fh!)D#*8Pg}W5 z8}h@N>#8T~AE#I$mbhv@RsEjI;=5}qr+Emw|HIe00QOY>|NnD7=X1_BhAoqgjk(`1 zlY}O7A7(a2bIaUf8HTBm%jTBLFk&ytWqeg5G=&dEO;IYnye;p4TkyHcH8TRU$GnYL0cJxfd@ z?dxonnKAbD{#Q5yF2&<6di4NRk4Sd3vq>B@t!+pOi9gp?T#D`Mb5lsdm1?iL8d7zt zUNyMHzwJES*gYd%AFEkO*7XzEWz+R! z=NnDj{buN^ox1YEI%w)VfqgLJSS>;Wa941~nM2gx8EEQ?v&ZC~Ew zjKndIZWgnBPe48C{W$O9yoEll*9a)CVXvDwW;Yi3kL&4XK8mMNyvCtEjKO8^09$OBwY6FStGC z=uJE}d|NIx5729#>|4btgq!E+;bwR@8Uze=*Yf7-k$$X@Fn?e9w`O@vvc_8+oa#BU zBH8Ekrg!I3l%;nm<@D!?+udY_ez99S+YK|h?Z8vqMRH1#QRH1#QRH1#QRH1#QRG~UksI<)QcSRak!Boj*Fw7IIo*p~iHk=Qm@*_yji1 zw8Uu`9eA-&@1tFlT?>g0%T&zG>!kA|T1U^hbG~IE7J2g8_lXs~NN?{Xm#x!$a~9FT ztCi#4x=81sIdTiv=1wx_i^ckUCwXB>Wh_Ce&MNsSg+5{a66zgEZgDOv4$1t;7&t*o z;q+VO?z~k0Rtwn72iWT28Dg#fk?3W5`=QB{#5AxNYz7CwX>b{^4#*J-+JiVS31orI z-~c!cE`vKDqz9D~^aLY&Scg$rvt29n_tbf0>I5kF^_9#I_%$PWG~HqC&;qCKYJE&6 z<|eEUmKbWcCV;F_e-i%va%8nWTI(!fYxEWiXhX78 zlNST62_;z8hqVOBn*Z(zrOWB)4ebLZE36MZ`$7kE-yf<5Uk5;!K;xlHp$X6f&_U3H zP?`j5+IcASC+;7H{;ZZt4C5k5WBwXi6FM4NADRMH3zEh{)%^W<=r_;_&@$*ms9Hds z3Zu3g9 z?PRVw;ThXsRUBAb`mAG)fJS&7jj+wpIC4lG3f)bGAc!=};(vXp3IV-y$3iIiV1f5w87G7J+ml-`>;LwLH{F%Ht?9# zhDkskBg9Y0usnSXq3QYp-z*j9F=G9Oe4nQ`fK(9%i;Lws(eHC!>LXu>-p=`bAE~-g z-^xJo-i^fKqPzX+ zEPocw%I^Ko>JMt1W%c7`g!V{1HF-8t61V6JoIehfkGIg>{c)iC-&^!r8a8TdgFQle zZDag-EI10Or(X(v1XMRZ@6WB=0IIA0&U;X^%LjpwKA)I$PDEUPg{vq!*lcj|kzH{4yGBjnmi z_k`#5%1)v%y+E(&RH0n4Tkoe4pif`a|J3yS!S+f6iQGr4`ntQ(KK)m{OAeWm4-SK~ z;5zW{<#0rTXpjWb!7^|d6oackRmg_2eXTxve?lCSj*;%j1G?!{C1@*o7JW!p)7#G; z(q}T+Tg|Nxa5aubB?+W~Tu=axg0tW@2%>(s@3Xes{Jf)jWYvC@(AQ7eCDaium+G;{ zWUr%oD^K%0+-K4vjo{d#8i$doV?mo8rs&;^^ATuW=xb0l0HP`jqwNF33udiy{EHIE*d+*QE(Pq2dZ%j z1s!8mBr=%U2t2`e>m$)V)rsyRIHEs*$+@9pw@AKG)hv_6fZ~ z@N+)SNV18}k0+R4q&%=(ig(uIwg*a!#=vGb32xzWRy}6ja&B}|pB&hOAocLDRvio-V0()V0q8+4mz<#^3zGZ)`Hhu_KG1zLvUAVSp)hy_dE<7Z$N2m97Ry|Ab1l> zE9iI&Iv08Z`ZV+uG#~mdbT{-psA{5>Jva0t?oU9^KtF?i4E=_+WsXm|P;Ivo{5SLq z+4Q#luuep*?|Ze2Qso`JcGUz@GZW;3LbBq$yi>F{Q>4);y@5XE2(z~DY4^LcPU*YV zQ_gB)V&0?9Wy`SltU1A_-(!~bh#Y^92Iq)ec~4)ZYGB6udP{ALY=2+BAGOclN9Hjx zP9yV}yV+@7Q>z)I<%dkK&v`?>+FZH5%>7UgR5w+(RL=AqF4^6u*s5On6bbuC?}68& zKGG)!964goSQS|9u9SYH&&9`4#WX9Axi=K+FF3V1(&ZCkC1pi_o`b54Q0{;4Y(rI(c3$j@D3>ge@6`3pS1TOc#O;2qZrP%BQ8pZ*1}y=7nM&Ano6zeKFTE~#^|BHWvC z)B4H5FKJ-=$%QYixA!*Z@$r(3I&V!}Tk$JAkKE7lu8&jr1$nc2d4Vptj8RaXPJ>!sUvOQ^$)qHJ8MTmLiGSN^2*_E?UX)r@D)i zR;6BE4aq7+e5`CLwFIp2mMN$C5^$-)>yejm+AXter)uAjYp0aci*o6b-it)CoT9(R z>17%6b%j%*aw<|%A@bAtz)CXW8&b=XZ>7B>UB0nIEpIn|Lz?`1x4irfPf_R>-{=LZ z(iDDyE(?`7^7Jx`0v5^s%a~Xs=Pujp3{tL8^In!!S8#n<4qnlZE3M3L^_F_v9?cqN z^9Hc&TSD`N%=?Zph^F7^jd36N9Z7OkIknNQy7zv^AO&Z8oxDn=8Y*|M>I0p(_e%Wt zdOK~FWPeYu;*WiD=zD#rYEG^pR6}|x@{Y{A#xtAa)D?MBt|+oi!hV2UkO7KtIMxsP zV4nP+{$S}~mD!L^q@vxksXYW|2ggjQUw0L5=0Eww(Q0 z57Hl^s$XoThvk*&G1SyN4sI`X@U+F&~v?xt{XURRgRqLaYGNM z`VF{28+B6F-axJtxov!_DVLSpZ?;^}FN`r$$6EhFg$j~Zzo47(3nOw3cBz*ajm@9c z=L?em3vc@UAxgVzY^x3Wz?^v)-83%8{e-OHRQN*sv?Ouaf-RAyCn1`139&K zli6(Kpqzr__OA>vrEx`FK)$wYys3u=v}5-y^{Ce-Z01EyntZ-*_8)dAIDl&4_&2Z=^txRQVl=caYeYfJD;oy!=ss zSNu-*a*^Elojxn8XKv{$se2#X(l1g3_ueK7SKU``>$L+8nXUtx{;S*LL9w4JNM-WZ zey&&P2XFCr^;mF|hB~kxeJT(Ql0XK?0eip+a30(QLA*6I1wFw?Fc+)`2f%4?9k}AK z1)@O`NCS((W^fo3gX_S>i&NwPUNSmzkqpv74%i8bKnb`B0(rA)3Sz)WkO6W*0XPLp zf!a$s6m$d$APp=A1)vC=2RA_wZ)Z(G92gIlB_#8>;^G8257fA2C}?S;e)~``mXQt?If*SFXju zuIEj4ks0cG-RT?>Bnj0yIyA1fOReg9p|-1;)>h8ccCm)ZT{+zKo37SW{Hbe>Ly@lY zm4dJ07aJKkLP0c0k{bc8>fJAMc?UG)?K2vT1Q}p6H~@;lRp1&zG(ZeU2ALoi6bxD0 z?e)C2u1J&7KXc;-Y24OTN8h-CgDBP0JF~5;pKAEt@T(yuZCxSvH%Dss26aRvzcl-_ z8P&Zk=5{>2!ekg;zUmPwv8hro%2iXFDxIQSO@d23+TL#DRGA*-stuRXMyhX=%ilRw zlm8B84M9LueWn~Coh`GABxcuMyN>r`&{*dL;03pMbjINX=;n>PM#rN4Bdx(E9Bc^ zNXfVT|I0_UN4_=ku_D9UyS#&4&14gd``f@6>M`I*ojP;Ej0|f*U%rdZzd?~BBwoIE z{43oa|4O&F-7lD2IZ&eScLizbGT?raAl+lmo6zZU?0!bJHX{;TnGJnZ+!RlB+AUtU zu=}iGK~)lb$8}X{c&QbQdD{-Irq10P+`~Iiz;&m%#9HWd=K)vK06VobN2uKl$8{)q=R-b>UJtogYSY!_a;9~cslJ^3aLfUyOzAFP_%b58!ia}4t-JK@>SJrUVhn_l z-d$eyW&EZX2{2}KmpU;%8e?K$B*K{4T~_!qK2VH7Fy?fZ-+dXKy15$E7z|@gcYBP| zF>yl1=-%wg`$)e&KBkr{#v?FV^^uo-88;MTG>i^?q*knt#;{lzDKG}~ z@g4Z@E5{XM42%(dpJT{BrY|oXePv!>1jiy+J64{@$=}`x zyRRwpLtXdg^>YPQ9S665tfxfH4*Aw1Rji)`TcxK?{USL0AoJQ^l7~5lIXn!A#O)#oXgi%o8*CYLX{4(OuxhKiaEeXqwfG1e2#58`^pT)h-y3g+VNA5tz{I@vp|gt<6fRz9sKN- zMSZ1pq7P#_3^N0b@A}F!zKjcsF$=~|eZ?H)TUK757jQ3U)VTr!ABSC|pPiV}?MK4D za*$8>j|?J{`F`CD_sBSA%A7$y!EH8}M94&-tJlbWWn}VTA0wNPsX7~(-W5iM5B4z< zkc5#r2#og{srQr0h9n;&vyrL#Br=mLjC4-&G4j1KG8cj6UL$LjkrqRIj0_usk$K4E zRv4)@#K*|H2n5bYV4v5B_A^E*5A`w9X(&ecG~YZ}VdUSwMs^_(n1#S6UL(_gW;k#1 z!#+mpJxtzYBlAT+c_^95!|Ov`t;@^YCb)qM;okLHxbbsfq+B24YFsW;BbldN+hG(4 zSAS(9uAH+LPT*p+>-YC$Y<3yirO7_pRfggJ5@ecL%C#h6n5$j6h2?Mqm%{DiwGe!R z81x_R69a8H7M?;T-eckPFrOIAh8wsHZkpG^T4mwE5k3}fC=1Jxnb}|dJCZawI^4%X z>If{XfV54Q;Sw_DN@O;AEbJNKV`11xEU*WH`I^_l+F$;jik~7QWur*N zH!TwtshBtl?bT?PdbR8Qigx}epH%z+8FLLX-+BBGdc-Fc`#yq&T)0M@Cm;6zN(?HG z_KCr9WX!e51jgBEkn@O73_6X*!aBIky%wTw^4ZMi2|gAMB4a*{OjMkFHQJ{bM5Um- z9>x?OeR_Pd@=x#yA6lAt~%>0EL zHWmvT;U4{qg$ut02Fl1`K54oEL30y=Z^g;$V}0TiJPr%bz_|1m3sZh4J|o8Y#Ai8z z=CcT1^#tU9MYQpVY(~T!AkD}7G^SG&V+)Kb10>IvaSle{Rv7mU@V1t>Xc=lx@bS3s z1X_k|$aM3_&{|fS;M2SuK_D<6f!SUo`<0RZ_!?>UC`Ps;lT~5lny-;f2$(w%ST;c3 zeAFlG#zYwZg0XFYw4Uh0m<}UwCybxG-mblkw>^ex6_2?~O8Gftej6Z_Ciy((5+|Yj zJdC?uW$h2vLsU-niTFum%omWU94|jja`h~4NIInwnF1JtMqnX~Dg!-b zBk?~ZQMD;PNz`QuGW(GU@ye|FADR8gm@gv}K2W}x;^T9psW4uF(R`r9PxWDJf)RKC z##pb_Zg=qc;#41>t4u@YATp_5nR)*slZ}jd2$|^vS>xm5!EcJ;hLJf?>ZJQHQq#%V z!!YtZR>|3_(|vOG0s`g{1h!b3H6>!Yt5tcyNSscfUWHra4b=X-fuRyO!zYJMB4fUW z%sT_+r|CX^cbb9nQ5e^}%2EHNX1jInu+%7XxB*a%GXBZy*z%pp?Vp=b5hi$^+jl0}DlPW4sm;|D<96A;Txtw`J~zs#dr%wT7vBJW!zAV6EKz}NUg_xG)6rR<0Ooy6J)6` z<6Xsg8^#+6^2_5s1-#P}1pgfvZ+n8j;Zha)I8XS5eitI*GYFK7B#{zF-QA4auAZ?-7Q z?`Qf1D|I%(I*m-tL|Hf6NBJC#zz<+F@+wC;QGRi@k8u6@7=dSCJmFOi)={4Pq>pmIT$DdX=G8=LH`hmb zHjKbeU>x@nCGMXE;8n4$moOQ z7hmO0^HKgBMx{ZX)E?tPx$=A;a@{LkvR#!C=$p-G!*)rv$?|MhA6~7`WV;&p zUBKVNgIT}0pmNvp+S+X)A^Hl=k-_rVLWT*C47L+ZjgExl^A2lt#E4Lr>Vzw!j^&uG z21eAh`wn}IB+}xmv!Lr)j+Yd_zIAC0l{By})p6*Cny%TQR=L$S8d;atkV#|fk|C4Y zMic9jVUyZMQ?IKvbP~w45farUVX>?HI^E|w*XO#>=epSEy3FS~Xo+PfVhL%sL%P^x zluhQ@WQ$FX+2n#v?%E_`sjX*|Q8t-plPxwm^Nq$qd`n&a*gv8o;FfA$yla#1pTh9SBs=4jCL`Tw)>~$2 zLhh9j%Uof>$A;JEMDqzE9A?U6V}dSDy-gPagQ%&kbQ?-u*n~g2;U?b zJ7d;N^*yKx`Ms7x)Cx;szzWOi6#H(uO`fwIPp)tcrtpWYWGwO`Mf|0iwy%zXQwL3$ znL1~}U&kV|kuyt?dv~VnUg=Y7zlR~EIWAX~Vy}gnjAlykL%vV_9JIeiyM$qc9G{2S zF~#@>#>JWPtuLe5Dk|k=7~jpLQXbHIc-G*0pEAD?PgPeYc2{d~o9n6FS!=5%|8A~g z_KXo?Yh`ZaYFCh+=4Hik=VT=Kk<}>NzaH{60A=_7|vb@IC-pQb>B@mg5z{`IXh|5Lbo$l_1xvs~Y zPDV9?CTTHRu7|-mq@^-f zaTt4q6YpfG@vHS1XGF2m2G>_k1`e%Yx$+2>Jx-`O!t4?Mwt0;BGc@?semu@Vz{zmn zhtG49pXZ8mG6eWjo~yZ5AY)!&t!;a8g{yV91ze{I!i?w57uTashVPUYc^mP;9;vhD z6t0jmEjMC^VK~c&^$0kl`r1Ae!I8`tUE$Jn6B8g$Nw*iVo3sf()`+%;>m1yjjF)ZQ z#B|#c+b!f7+!ztt_Y8rIdBzo^eP=T^D+U8!ForWZzx^c)H+t4p%^BWL8DPNUS%kYv zy?t2T^DM%>`^oFiB0S!9YrmNyz+jU#FD@yYkzQ_dj>2)~_LC1cBfZad>$wGK283+s z^esq#VslQzaWcyD)fS}h+HOf(k#_a>NM~(z#W?Htx3lFuEGL69KW%jlclNOyYs-Xf zu4;O`S3Y+e@@XFV>)Vi511Q^&U+Zzq$j6Z}5i6qk`G~*f;oMOihB~TlN4(VIxOh9k z`Oa&;a65rFB=HpzCU6Jh3{BM8LEu?TqTJTw77%5wlpmw%bnJ^sRB82p9hg>7zEMDdY+sZUPc=`7ZI#ma=GR(eR$ zizI8FhZVjDQ@p6P-b1k{@;L5Pj=XzWrKorh;@3Q!mV4pwUiHvk#B1=TqI^DpqaL0> z;2QGjXz5<$V?3S+5bQ0b2W+KdaaGxti!plnu4;r2R{% z@mfVuB`ObwJ9#azlL<$iR{>k0Xg?`Pr=Mce-1$VJRC*av`tg=%*2{>}ceh3N zyo~L4y|ypIbAE2wX0`q+1cpAirIq#yoJxaa{woCjoqE_Xc(BYrM9_{5cJDsqT3y-s(oE_6Cha~CXv?>q zZ(^5cvK_|aH;E2U-=E$jRW5p6+rQ-s58w&Qe6r?fXK#d&_Lgh>fOt29Yg5m}IxeENp5Caecl0hcO1%==gxC+!K2$7&8NCxR(BPawVpbSKg zgAXQwEKmqef!iQxJUoy9GC?j_aF{>E;5G=FfB;AUnIIPwffC^VD8@kom;^S0LQn$A zK;zD3zFlWRL|mf+A1?Zi2waNJ0<; zQa~oy2ns0lWs07ak_+yN($o*-2~ zEJy)tK|0Z~k&DBi7?c73Od1f-6HEeXx66ER7?glA;6Iz#fsP;nOakiLqK%*soCcSH zV-A4_(R2298>Ah2k7;-B;**Z2UF*31^8>b)DLw5{3;eC?*biKToNPSR_FI;H6@K7~ zw;2q{m5chD|RUji=9(!v90U5*DLwwow1A#JX2wz z_>3j;(pjuUe@r)t<;m)Lk9} zTVArME6RtzsVE%o$jh#(PBw09^R0{TLS)-j z*S+pt-@1nA-2C}{MYQH#vts(uHOtAi`9np}5C2dR+@{ydgXrFP-Swu4DN7;!*NQ-# z|5e#@x4G%M&tGkTR(O_@nt7)}^XeU!scG%qKi_pdsJ>Lm`w)ScKdn%xXt)dhq-%g_ ztBhTB8oSHQ6zJBC(r{0589^GW3uhaKTJ89XVchMoAc@+P4wiwP;3y~oWgzfLT365! zB!Edked)Im6oS*>GEk?ghk~{s7NmeoupaCIr$8yV148B@2V%jbc|0!EroQ>$FenCB zf%-%)6to9%U=mP!&*p=}pahhGKwA5TAO<9ZOppr-!6|SRII?J3Ku0hVWPpvJ5S-3J z;4&BL%ePR_9>jr3APZ~;2S72n3e=Zzp`a~@1t}mC5r5z)cXi1Q`$mMuH5G3ktvqa30(QflEmZ5Dk(*8pr}0 zK_NH=E`vKD2K^z#rg0DOmbFmp52F0KZ_^%|-Ku3@S(!es14~jquxDA4G zNEr|Vl5^H}Tag!IG}P{wMlnWR{r*&42L8L!ti1k4P+omAP+Imk0^OHmjHc9~RH@qC zXy?3@D&4yqKWVKbs)sRH`IBV znt?ag0^eo*VJFG<{zhHM@&3jwEy;Z(&PdhRbhbgf(Ta^Y6XOl_sfKXppI+kmx^qgc zDs^RAJfZ6()dwQ?gmfEd^yO|PcmDIeayM#KsqK~16OdaXQ3;0HuVRt9%aQ#FmezmN z-P6)6(Yl+N$lWut-M;%l-EEh!K^AY^Anpoe?I7bp$OnUrn$EXMq|(DiV+kB=G$-5- z3`SyzOc-o5(1y5|4>lg=dqugFWIVu5mSIC6-6U~{aUVPNEm3zTgh5=j%jJzB*nCb} z4YedE3^ktAuU&9Ti{reY-Wh5HIviNO7g=-OXtsD$ul#JNk}$Aoi#4X)~#B7$w@W>wHoeC$;Nce^TAfO&j(vcl;I9+Nn?y4>E{h6u+G#H zd#}W@5k@#md#j8z9&kS4aZ4GA+kBa)+?IIU*#0P-r2J92J?(Le8HL+3GHMiV+dXcD z%8fJ|WvnD&hCO0T)B}j1L%qfsQtwm0>T-UJabEwKc<}BRCP9_`T~adE2(_Z7c9b^8 z`*XmJyW2Qpf&YTD6t%0sv5FQ4v;|2Z4QvF3pahhG(ADrk3djWc;4ml!w?X6@svH;( z=7K%o1UL_Ff{V`4Eqb+IBPd|$;~v@>m_)iGDOm68!qSXGu)5QHonlbMI10{!>%g^+#tg)OR^B`%tafQ&{}Zmof2k27>B#|s(sZd& zO}c8%Dr{H*BUasxR<~KUjv(e3osVONq3vN2%)=`+A_+5W75O*y*I3c`(rMx+44v$yMg!-!|CMK!8MUN%8D)q z@3W>T{k%rPWNWh1l)z<1d#$&0TV^!yizV*uoGzKX%xD$Bg&iunw45o&1Iy@Qx0930 z*u2QzGpn}*EJumsRm_tp-M8H6@0q0TElU)qADl~YURrK63*f>scduMpX;e2dqM{u2 zMa#i*;0mL2l*c3*YPm)`&vK2DU_#4psY-p%uRk(l_`Gglx=|w{sj9=V6CovlqveB| zzzjsVy`5X7lbkNCy)_YzFs^pqZB_ziP!Em!2qjp4lt>TlS$5Y48m@uwlubK8TCda57 zRun`hl+547Hw)gPW>_XSDYmbLG2_%1JoY?rdpUy#wQi$*2DQq5p1gvs3SE0mo_VHn zEs0!ZxWd|!KGSg=Td6`wrDuETvI;NKV5`%NW>l^SK_!blYn9O;EFbp0+#U(E*(wB; zEjIgD^=PhYmCCX1o*YZK2OhtAHnIM4nvnTjpwwAy#CEWk<#@Hc%W{f5S}I+=zc?)W zb4;#E6^W|Hl8%>F8%_RZptr}{Xq7qqR7kzQad;cv~tN(W=8=D}^_SJJwJ-e~s$|f|~6OYODGxu514>sCzsHd{aA~pt4WN z{Iy2UasPK7jr62#Q`>jzF9*z;pL@J@%t{|WCS$^YG3g1@W~OGOPMfNNs0SC~TT^tE zo>#WMoLOhEiPk!!<;1^6vV$i%18dse`1;0Sz-D+=yF^s@HhkK&DYj23_)_BW$t%~` zlf)0ml*xPm{L4C{ZO6a*=q*AgJU;T0R{nd8WbNtoFEx|vAWKddU1)*C%NOVhjs$Xf^6huPjfQ|`NU?6LWERhhru zsM91m6b3Si|FtJfDt$9?zXR6W?$V-@xhnYY#yiTG4TNGap_p4u=4>$PM0CWKs}^sh zRIs_#D(b#^0(BIcJ+^M%z|*6ne7eD?8VZj zV&^DAN&rXuQA6s4;&vFkXS>TwJ1WnX^I|mbU~l;CO(<`6jSshdXk!!W?@&CNc8{ke zn$oaJs3dJP8vjFnm&n?Ur1Zn+Y`sTzZ~Vvn-Wg$gvB$@!WVCkQBXu^BKj#UFI^#z1 zcYA#IegN0WezaL1z;%)_mDuNycmVnxDa{uf3>_hxG~c9#M7W#H;<>b-NMsw`%T9%47-NLG_)8;IW$0e8>MZI$pu> zCbr#=e9TWm>#LfwbqAGWWMh&EC_ZiB zN6WX+Jcic3F!}g@wY;I;*;;y4`ufY9!)H^wC;U=Q$(JGsxyGFJ7Z3B>OqC zUKjz5Dc7(;M&?A4}+W2y{&yJpvm9z*Q?W1#ypSlY3O`hTjo4( z)M?zYIU`pfix_fO~=1M;WG6Fqo?)QC|B}^OPvO#eyUU8{Y^({dANN2g6CONuH^N}+IS0TU!P{6 z^hUT0D)=X#8n&|Sd&-Y>GZUrX!{zM)qfWKOghU-ZrTD*x^Uhh!-phfzjMo2CKP9t;r?9utL__=g(Mv9%o}dYt9IS=ehEAys$(V+~M8J*nRo zn^=DzN2_;)%-?O)sTvJ`4^VvEcs#}ZgZ~Mh=c4c9@d+$_!ydCQ8Zi_9`i${5OFi4# z9v|`XKNGEc>eyw`F@DCh^l7s)M%xQ+ty++T7eVML9j}}k-%uu^<%1WE+V@9m6|cIF zPMa}h5-e35b5IRLRTaJI9xqh4QS~yTC1Q`!qr5ND&(rlEDbx3mHM0rS`*mc+9;0=H zI@LxUG_w-5_dQnBQ$W3lc2Rv*Mnv{7VAaJMCJfrEF4g!~wPhI-T;eP*Ulm@s~H&uO#9rcLOPmO5^-mHR1p zqYnR3dPD26K+c%-x0l*@Po{H%r}cB&#QOUrKJ4`PAi=GwG?CGZO(UWqfjJG7sF$r$ zL+Si)$M|p00B<3)HfTk`)9NW*$6WjyQQy-fk7`w=flS-~KQGbVrZ3;q=6O=aGB6JV zOY6(q`{}+fCPM0<0mWbHF{(nT3jRZ)z08>ALsHKss;q<+p)d&r)ugWSD5!#<$(REa zgk>)q?aP}|Zy?xk!TPmU-679!K7n|(zI^*KflwzLobBjvDE_NHfl&2^)yA(7h_2Gj zCSz=3mGG`wMQ!$$aF?Y+30FF2DCm&vr;J*S$zQv!m*QI_z76I6mQM^+;JQky1N1hP zNHHR_NrtfvD$1T|iC8;`tAiCzg9Jq8ctljf`B@?r`>S`ABL}RoV7R7~9q>sW?~`V( zCwU%3)%#mO@?32s@dy90j}+V4mQC^Z>hP3Bt3hLV^Po|`aTZoXkWu^wjqNz7mZJ#w zAl&C04#$0srP3iIsqJ6;mfpf1?FrEJ3J)CF_^_z8tUhG43yZ^wKQfBHsI~2bRdyu% zFdMiBzE6KX#_G>Q#%yH_wW-@^KJFi0V4`hbJP%OoW+9$UYhxRBbRUv5dgizpsp%P` z?V4-nW()y13zVK$)*if-Q*K@&{B!t|^AxivKf8@Ke|tuGpEe`A*q*;-6YK9HJm1_# z;tw0OBGj=JO_5Rj&7J_Mn5x3oO?B_kl%Atvv^L|j{M_SkO>-Q@lwMwh6+=1Obt2%aab5mqSeKOA&!j&AF+=GHtP zd#H&k?`B2~d93w3?*8eB(Y&FP$%R^98IL+I-gPhhitWxlBj}prX`WEzQTW$JoUTU7 zCx30+?->u*99cH=D9iwR1Y2_~mEdoT?-s10xvzu7CTLw~KC}V!1hf(KJ!li?XV4Z< zCpCucpR?4XOYJw>1lpGSrk?xe(01I%LK#@j8t9>_rgh+6?dZ&ou34$jPMTvuRt6Uj z;*bS>2&x{x%J3>^4EL)&_qovS+~+}iLSKRQh8~CZfu4Z&g}wuggI5|jagtb1r-^Pml&0_Bq>$5!YV z=yvF2D4%a-Er2R}*(M8^3UFXk4af6P_HJ;z2z>^+7g`8?1}I4M^J` zj96!O6`Avc5$|Nw{=FYCXpgOHj;6L}Dc6}HY46uj7eHl%iYRvk&F+AWyYam%| z)gQG}tDg6x5$^oDs=LmQ24@1yt>$k1lhICdGG06OXXBc4Td+I6%y4P}_F$;ShRtiQ z)3Bx8Fk+kxcJ8}DFzlg9&9O%`f4}N^zZmHOL#wM+SaUog^)8VNIlma=0}goHSev5U z0)I8e>({E&(B3e^Bq0iPHaVE;rcu8}1CDzSD?gLG zA#L?@As*d3H_>I7t?F+C#vT^a9P1_cGqbuot*HoRZX|^50!Fz zL*4iM+o+{E8P;h1ALG%0Fl%H%a}2N(tnfcZOn^PwpuW<(6u>@(fp?6n&L?Ycm`@yo z?qY3iZE1binD69;f8SjrFJMr(or(|GDVFkI!oA$%=1Ij;<@Uzk`X%1XSNpY_1RZ#^cn+ zF2z}z+1`0i9XX_#*PQRyaqn=NpE;fM{O1_v@Bq8Bt~uN?y)rQ_Gt6Y2{If<52_ zI1kEz|I>8EK~InlmVp9L1WG^|2whLwfCMlJtOt8Q2`B?08?XVAKpMye1>h7Y1$Q>k z$cE(cFa^nAE?5r^fYabQaEZea2|9u#kOtO+J)js|1%Vss^MIaUBv=eKgQMUqxC25q z@x~33Kqklq2R6~jp622v2z&-lKmy1Fx!^D;2Dd@bv&07U1mnS6kPi-n^WY{3*^CT` z1LMImkPnJL3Ahb{wvcKd7ED^epDeHw90jG|HVEHJ9|a_VG>{7lz$s7)9NS2K5Dk(* z2FL+N!C7z{1mzQ0FcRc|o!|sG5AJ}F?G8utX#OODxnMmw4K4%M4gvu>f&?&W$J%a> z=e2XPD{F}PJc~-KB_roUOttF1MGaG}t6o#XR7>e^*>@xEH9um_b&HzjE0BvdO|{H@ zV5s?t_O-h~n0dw7I}5w(!5&ZqO2BpC`WIOaI)Vf+3CsoS!5(k|Tn2YQ$WCh)%Q|L5 zz2m)3`SU`+C|O*`3}vI}Ep^N`+EDigbP8a#Mp_xVu1~)QWX&WWGk$IoC z(S5KH3vD?1;dovntilGGOVeo z&Jw@a%B&$rn-bv9<EQ z`I7$tq0EgkL;e3V$g==8xP29l`;9`Zll&Zo9e;^vhyVWWZtXCky(Po$BdT`>%ewnW z;)ms3Zuv}EYi};lzLf0t1msKE+aB5PC-fxwZUH6+U z!iEm9Jy-9tYBIcOC?(H92U>o-pIm)Ux^%EL+fF9Sws*kxIXTh+pU%mZ4%j{?VGoeQ z7o_h4<|2y72kLI4+N$o4VuuG57KA z=8Ky1);O8klVbasZ0U&?7vzJU=2O~e8PdxtA`}?TFX)9{njG(iUYdO0%bcf*h*fCk z_J-w@4ZY2}kb}L6QB!Hv#~jSb>e+n=iA#?3A z4U1yUU@ciT#L{dnmOo+%%ra@#7m_2x`Vyvx7orJ{;Q?lK;oYun+9TJx_mH@ zg5OI9Bv2fC$?ODktx7g4Ad!ivWlN_-vxT0WNtJKT)Ie6E*`d7domLVb%9TVS^I^HN zRV|MWf>lXA9b~rAE6x6!a`IrarGFx0S*mEtrH)JpzA)Gfb|%i2ISFR2m2q>)(=kbA zP5)J1xq6+b+md7k>p1;2Gy*i%?Ls^K}L-rnJ37q5mqaCQ90(xnUQRh-Do5c&XX>RJTGCR%n?#J z(u`#7JnS|QZ4{hKit{8V)od7L-WL|QprVK#?n*wy&|*O{<!t=7yU&dA1oJ`2mI>x`4Dc9g#n~fW9<^E=E6%x(A{QpR9yPlmpq%n1 z;!;b(CXx!Zq}N1JyR#fugf)Yc%pr*VIfOVDOhRtG9G_&xtXe9jn@g8e^TDv@%PMkZ zQhz$BAdOtdI_?VF!w{7g5{0@HS$a!<%s0F0SHx=jYFZQZ_+M=j1uB050DE^M}wo}0DT=1S*{ZIZX#?5AyFjW+T6O2SqUhZ-_u z1$DKJoLNC;wvj(pz~c>lC1kavt~6KDk@;;U!ENcjKgWDazBWmlU)zgpzGUjPh{3G^w5_x)GJCO}(x}HK5A@{F0 zU(zPYmGxxFtvzz@2D6(}DHC}a$ zL#CfjZK`sFSGa}lOGnHnoYaP4N6mlnsJnZVFebV89y1@%1OALxQPCX3t#ORJMu(!%?@Po6X%bkcX%PMJTbcZpMY zcFukLU3x{d8)5IGlq#3rH-B)__xZta)m54yJ6J?|oUONZ-NsX2njUf3o2C?Bf3+H&9$13Gk>tc2)e5BUUr zZ6>SU(d(s*axMNE0lQbE4%@MYK})|j+Xo!*C^eV;ja=2;ZNH%qP`0~VCf(viyMpn8 z%Vsj29Ij_l&n>6iE7-ow8QV9o?fTXXqNSe?y%Q-EGaXb4NsX6$RR1Ff}!cJR> zxJB#|t*4&GS1DGSq~9WT3+31?;>`kjr`*yVKC(_DV-X?C`|{3ep)0fyfK zn&9OI>Vw_&Ouzmbw^RK5Ryv1ok*R)uwIsyfFI|6dt8+se#%J^W{pwq>t{62=BG&O+ z?Iik-JuX}3?-xUJ5fy-Ow|jqpA2p(lBvvLkE!|q6-$b3GD^siaP16X;xgfuRw0O;e z2||$jc(8Jfa7R`5qp|2A--i&D1v09J-?RlScQOtIMuIG`5gY)g!A%hO9534-1|)-Y zkOOvtqu?yK3LMWn9Fd?SNCIgf7ZiXK;5@huf?iqBrNgxa4gTtT%lmY+U1Pa7}WRMP)fdWtjN_HNP&(Z0c3() za9{y{PJ=Sw{}QnVv0xI&0{P%DC;??4v=AAP1k%7pPzXvu8Hn7ECty673-*8$pcLE& z;V+YFAPJ;_1^N6r46XvlD;Ni{AO&QCji3+|gR8)G03#q4q<~D23l4zO;5u*}WW*Ol zgYjT4$OnhPd2ka19im(vBL8E#NCAt%W^fdo1-C(vo4fSQa~;!0O!F?5b`Qn4dTG~SCjCVi_PFDI19>v|7(OEB!L{T6PyP(LEuqh z2a-WL$Onf(F}MmG$JTcHHm{anq&b44h2GgLjcfVU(cjt3qCL*#&8zJfq&v4TH51On zLd)8I-RW6PtL@j!9EtR*EwZ(?U;W@!ThwfZy?V<9onbFGn89*`y3(?aUr63;M%{|D zSVbLI$B$1(!~KFKOGR|M0< z-b{PZbIN+trOmXKM&!?AX~azHvo<5ZlGv`ca;>B;`KYa??2Pmak&-%oK}daH$FFt- zQ{2IDt>3h?@#)iMRxDzhDfR05)s>uj#4E0@U+6tMpR0(Ffyzux9(uzWE%P_(Ceb=l zmjI6@z^}bvt<{sDNWZ|~*O>73CT>-fI7CQ=shYY}fi{9HM{ToS+fYHtP+#KJl$^Py zzm_3;BmEi#Puo@DuQHV(mz4ATy|!~LPx@v^je34ff=BJQo$KSQThasS`Lzk|bf7|7 zWpakBs)vy{A7>S(3^}fx+04uewX&_!Izw*M_p50g8k8Y?li4KrV;>3satTSP@8=@i zh|~=`je9h#>IW-~sl4zQt886bl9A+AJ8sAONCtW(Yuol}N_tU%OPU_m+LPF$8j#p2 zB=-D6va|t(nBCUO(^-|aS+e#XPBT&|FpFn06U(KUn!ll<&PkCfiGv#Y1qHA0sHup; zf)~}0_&@D&R%KTu`7GH!g-_H+$X>YS82tV6kbKtAuXU|2%O&;To5U`LXuXC?t;15M zk>5~MW;H@(EGoYrk*$sV+Bu=Gw(yHBFX{CfBQOqu&{vf}9hubFFT}~s{KkIw2KRi` zj+hFH3gP4OTw`iiKaX=APY55EPjL==T&pP1<0nkCKE73H@VHcILf2q~3~PdCRsw3najKB#nTEAv{C{yC9aIi)PKkwltBVG^Q22j*odb&zA1w(7Ae^25y)BH8`5&Qpic>2FB4VriYPX`W^oF+)l!(mZC za_e+5Z+{aCd(qocxtS-mIHoa8;hh0*<9GbAn4@?zn!?-oo%?y;h1We3-izDh_fak)J`O{`FJVy zUP)+jyEhZa6B0coWwQ~!u*cwQ>*tewy(z!@cp_U8{NwQCz9+3(1_l3wa#(=FmiJ^& zOR@=iUp6JQg5e1muDvG%TEPIlkKqywVNb%)@VLKFw)7$R_=h}^&W6YD=Uw~|ybIxd zCct~CPk8M8eV>*D&mwqE1$e6V4UdvL8$wHZh>7rc7Q^%R@eny%%~?qfBn5S!-{I_D zf^)eOQmVD5M#XZxrmj9Oswb!(kCF_^VRoOiRknwVo6VNi_}nfS7Jn#*l{j2` zpSKk~fp^*l%7}J2tis{n4`g{ePv9-cfpT6sJdK0nl>FTe4G&s5*^^sbAD>Nz;Tafa zpOVALFhK8P=-(cO)iB&SC6Bca68$a?a-;+G(s5dT4t7cCfR_Ti=%-~shafK-m4o0A zaa!IBb}%}6;-l8!5PiD1CN~|L*0sCjj&lc|{o(@-o8)#P$hgz8sbi4jE4aAXfatDu zTFg#C4r!fmSdT-a(=sjC;dSM(0f)rX@=YgCjmSiQ&;bQxhOA0)wl3~k26y(9FHNl| z{@aM(nWyE+&OzmHx-${H)x{H{Z}dwOZ2&WeRl0a;20qbgT?lwHp39z*X8k}(E*aXV*ecWznqn^ zT}$kbD*J8Nk2)tex_a7&jygwX%b}hqI%n@NdwI1dqlXFIJmI3J^A%a4e$`UHUQ)kO z)UUJZ*J#_diaT5urK6JT5A(HoT*)GDRPHG{Q?yj{RHXpUl=O!^6`7aFdDx>SWS9BK zZl7gl8i8JZ7!B}dkO)segz|^?^7b&o7U3I4*kUS%D%EwSAga8qOhw_HDFJzU%#o0?mqaZ*Ah&#|8Uy%b7o^!fi5?fr_dE|&5AR?JuG#PS5udL`?Kivc+ zx^uY2M~!EQ0$1WBNBfitm2H7(?z=c1-{Acw-Q(1p%Qkwy??pGHhN5O)&mQM%h2A&% zdR_~0zWIW8(g4p`-N``Xt6`o3=a;W}rw#Ws*0eum{&arvP4@EFgNno?M8mW*+*lt1ia*)|RqR8L&mJD)r3os{jVp(!oVX5F6yE1DtF zwkn0sw%jlt%eW&x|Ch((f5{Q=*a@C5G-H>oXQ{oJ=ZCw>NXA4@uHn-Ns!`8(P&8%7_t2WqYfvTjN9aRPcBkj}gx-RV zhTeuwfc^?y09Ct}pM?H_d7+;&^=I2Nb?5jK`*4mxMLMF1S_OG?vZtlt)8>lf^fx>z zPXC3fINgP+IB_+S9Vf0Ivg70o@x{pvRdMn_Rh)FFijx5ijuW@d*l|)cI8JPtzAsKI zrVyu#@2Eyy9H$6)RGcEADo)&vV8@9)#de&^LRCIRLsdSp`_+yUn^o;NRfeiKRe=V_ zsVZibPl^V|sT$_sd?HTGB=D4ZG>0ZaTS)pePeo_UyFRvu{A@{nw$^^O zHa<4AU0YgvKU)VsTSq@zC%LVpq5GDa?x|37I&)PfIT5=3)ywVO&IEhcUpS@80*2|cgo{BDXd1?ERD<*-dJt{Vnw@?)w6-*WA zF3fSzB4}N|eSPR2IX}}=(?HL+nYqlz9RI1w4UXO zH+<^9<|r>!e>cj^OT^4ph#ej&|fd&U{{iGb>xD#`iNTA2sGf;$!|UqizksSd+oI)25h+D5ngS-vfy8=Y6aT?q~hU&-$~?`fxF8J)*qD&)S8}Y9VFj{SHel;`Jv~ z^;Vol${!2817+35@fUOj^uN&c(7RC8Fa8641$qzq7F6ZnQK&Q2k$)cQf?k1!K>vh> zLRF4>prxTYv@&lyI1GN&!NP<#hblpd&~VHx{j{UszB9Cxq|Nn=GOkh9D$C2u7N=Qe zUKHFa8ReiV8RelW8PQOcj2Ng&2C9*rj992jh6-&bG!8SX7LKaWlhA6=ub}ZzYKWr- z^lxZQXmG`-gPDp^+M#{~*NnQ7InVQ`>)#JhReAm?rjcUw*MmF+IZpZFKU=OWaFuD< z9B0+~T0m8!PlWb^wuDZDs(31I4`H6+H_w75Ny~gsU1RqB(%QqNq;-HQX&s?TS|@0* zv@V!~rKQO0NORpe6=L7cYNX=s!C#sr&-avZIZpfS)BX0neD-?4{t>_Zqq0x&M+EE# z`t1k#>=|_Wee4nLwceaAFUt`d4Ns@>QRv zO12Y}*@XO2e)AY8Qvh}iR&=W0emeA7`S@|Vc?Pqk79f5t&Z?VdEN+Wulx&M@(+Ph2iO?5h#sb7MB(`J!B5X>05md$gC8&!1K4@_4U&S08`vaI& z`%^SH_ODB&ClJrb+7^EZXC?kHREa+dRpQ@)28%zAIavJrn3Z@%gT;R!N0oR6=(hN? zI4kkzpi2BlP$m9jXt4OtF$askh*^nOG+6v4pLoXkw)iVJEAihzmH6+VO8gJdVDUd< z4i^72W+h(HVDY~w@lED6We{&q70|u?LyxEa)R$MC;Z=XX;Vl~aCsciA?m$&-{0mwO z`ZrW*ApeCngWiL-gEA>)E1*uODtZ@mHdNKX`Or|zPoTg!Jp5RSg${iNYCzXPP3RVA z7<3Ob9Qr2o0q6y21oS7U68H<01E=}FL8G9m^DGP1NKiSb`l^wjFaOvO#Yd%M49o31YnU8^Vu7-cj_t<;?m}<}UVhcRu!^_sn9?q=xgN4L8*Bjk!Bub<)H{NFkP8-p{ooXE z9HnTYkKzahfkmJYoCDWD)Z2IleLyx?33h-B;3kNA2X~MPvOpeK3HF0i;1}g7r?;wJKdMz-lBmV}0Jg^e%1t-8Y;5dzj2U5Unuo@fz zpMj7w)C-UbvcPIk1g?U+AnGhd1A3lal{~ZHAe$P>u~qTwr=-R~Po2oG`DSPYpjMV3 zj+Z3!pr>VwZ)WEPZ&3zjc9L*}S>`R_%<8Fwo~G{62wjBGzYF?kVQp2TQ-2kG#QuMp znV|;td;vH{@j_BW3HCkw{sQS+8nl$lu7ELGLZiMBVKAz= z1}|w^s@)91S%uP490Ld+IX&7N&8vhxV^3Q>;?t4e5Hl*0J?Lry9f&y* zO5xf8O@_9{oDXda4X4^fIy#b$M9>Kg0(C$yIGC*=eE}s&jfQ+#t~vZgA>)2?g+JH< zK^`1C+5+nrd&s~p%q}CfSJWPMrof{7c7v9IJ`5#4?YOB*-UGABoOHSLj;CU)-}$N7 z-KsqJs|5;aAqT)Ya24DI(dTH&pby9fE6=S;enY)>;SGC_Rd%(NXp>gfJNvk2rlz(! z?>)`#ny`~Nv3>gk4=yJ?~@4@q)(zd*FA9`we>eBA(4oS=O8Kk>`1xV~M|f>3LMExLG*{D5cC1rU=b(;$G}D4_y``52zr8SumJ1; zN5E&`7Kpmw@Hp!6@$YzHRdSoxE_>bx|RmtT{XP!DJuuAdxivl*Sk^jyU_Rh-y5FE>SRa$_vGQCAMK2{ z{oVP|=6&D~WMtp;3`6eOo1TU|eB}N2XV14z^>olJ<>}6Cwy3o9_W0G)!c{D3!ylff zRcSQ()1w|R@x|oNlF;k@r{s5`@Atp|VUs7Nev<$f-C++{6WMsjqh28T^p2;t@tRwI zI#P@GK2u(wugx1oMoj@r!Cr6zTm^SQ#K)8x=m-XZ*KWAmkI;Gw29LgM6?J z90Zra9T58|O&Ih8xnK?03r>9Mc+_#3A9q32XB0n30i!`aC<4d8Rd5%?eNOR%L0}44 z1NMRo;3kOrg2;f5U#v&)K#7Ox{=NsYKeN3yD=?n z#B7-x8rqaNHEgMm21)7Va0*-ncR|!eQVTkQ(I6je0|&una0f(RB3D5lkPQ}G zT9sV6ptD}xHR`ti-IfKN^=M9uZtP6-j!R@0y^40+o6tqyty1uHie6v4AmLqA9!Zz3 zm_C-NUE%pyp6#mt82#j%Z|8e+UCy<0}_By=So#OhBLk@S>$8!w2eh(y0lifX#I9D$9(7Uj@_FzxF zt+rD}^wiY>?^k+~l#_C$rylP*>Ei8_30926rR$AV+1SC1PS>NIH(c^qx?V@oJ?VOP z=WUnVgGs9)3BB|t&R;`hWG_8cHQ`1N6SWh)$jj1lr5DL9Ek$85usioZRhqsnesXvT`lCH=b z@`NHzdA+|roTD_A22eZ>=|3RI_rU@9t|uQ4z;`{-2EzZ0G*e`^jDa|Rvt-jieVEou zv_bkq&f8(qW{@vOGP0=ETL$Un^-AIX!n&P<8uRHOJ(A-y*9YnAdE()T!T!)x{#_eP zXd^`%LY|D2+Czv|jw~BOXj|pz5WCHI{##1g3?&<(_II5ZrS0n=DXQ)HIR z&(MFME{(}V&S6=VsZUhJ8Zu0;$FbmqVenLu5ySK`%J!VH-7WtN(>tkNH)1I9=r^2r z9FU2_gX~TzyLaTf;S|O@QZ`HPs(h2kdK?;FmZhtssvl+Pwb_g0a9@e^y?o=pIdxOe z+eat}j!}{}f|7c|yK#g*RHxbflcRT_oh6San?LsEjMryre9f;<(1$v;!``lw^nW?0 z?eKP+qW|oq+P0jo_n=OCmrU1R)3nmwOf?KD>(=j2Pj zFJIA0-b#<_93B`chZg8>l6l^lPw1P}Jqa-jiA@z5vygVPTdFS7D@w>BJ(euscMI1$ zkuLkZ!jwgNwK6r)*~%AdK#fSvCq5s?@ZnMke=8bY|L!6^Y2F69oc-VwxCQjD=rlo7 zkP5Ou9#{#Az%g(QIKHN{2Z^937!4MILU0gV0KbE<%XDub1!RK-U|9zTKDHKr2|P$9aBcsI+`qsD0ss ze?!g+dD^p;o#mu(sU8-2nYls@L28ew6S`gIx3#KpJSDPONEIm>;tG?y z)jVOLif6lAnQpfB?_0Scga6XvJ=2K&-aH0k95k!q+t?XAPFsmLB0>^Ce&1ZC z&vss(CS#ZDHw?VmZdL5{1j${Y*D9AtT2et4mIp~z86fZKzU1** zL4h6@_78c}g*|pEt#WjtDv1I;GBRKl*uL|EWESWZxe#HFkF52P+bx}CnEO`~i>C|p z@-Z(2jqNhAR%1S;lD{DT6zFW7_Xnh`UAA?m=w+mx=n;`G2Dzz`5Fv`*+VhA#G`u0( zg@U|CWLwXbGosgsY(2N65Mg)lq#GNfC2ox#!kN8^9YU%=>ann zZu#=s8YFbfFOi@kxlL;Cx^B%3Y0!b_Q=Ly&)sk z5nl%-J9oY;U#ADQaNdy9%0a{7rTOybI=x!tOMXErk}6ww`A!h1ceUj12Hlhj%|gn_ z(hYheI~}UZ@3Oa#6j$r(>k;WhSoHWXuTdL9XIRUi)D@3sKwi5W)lI2 zz`TBewBJNp*84rFw5Uug3OWr@WH(T)NS19N*Nf!*CY$^OaTalC;d!gFqC=jys^MB` zqu!}FQfoI8PAK8TKPhi-*6W1FKUq@v4lX31%eEg|*zK!2yJZzMND2pOv7sSEW4D}F z=F5Y)vf}qmT3|Es4f(E6kC*%zW{B&dg}xra--`wJ2pwr%UFLWPY|+_D(|WG=`K|h6 zPG`4#Z=LP>lbSKtEdg&b?rDxiGI4^Zj5l?c`X;)&lRd5%?en+1HQb88T2W!9qa1Q(q!oFud5hQ^@UboiN4Ak z_mbWK?bq95ul|>_>^2wxLCO0WYQ1Q)>XAnY0$29iJq$O9X| zesJpAzT^U};61&%^QVDQ<2}8y>!*P(nXs8FnPy*b)sw;^GgMA5VMwv}J(PPs9>+;= zWl1}ZZdX~R9@pPw%U{9?l*7I#r)_+vlNqr>+N_I>UhlV^+{&gDXSL&^Ps zQ6o3#d_WMKZ2drAtb#~6MG1$=)Khv*XV?%q{DIDPv2>|*TCeBI7~+zOjg1(|Jx!n) zGUqgUJZC`8P)FuS>ofY}+Bi9S26^M;yEFPS<NHQVwE#$^pB%iYIaNkf}=LffmM$(4GWZ*}L;Youl7xd9@2l zhWWTq<B6p5HtcQKPr9VwXgI|A>_EX@Ed)u8u3=S>KmUQyQ=@GO5)&m`uECx+xHCB zl|{%keJp$vu92vg^6fRMPD>enos4cNKU}vxdzaqOPt+cgK`41(CD;#6fy>|yh`Pz( z9i)H^kPp^?1K=FE1@xcb0Uf~=$*HRy3lu_OiXAQ4?~yqVXu?!B}G+n*H`zEDy-(SYriuqYbWPG;#j5S)Q(B zaNb`|Rx%#fvLvmtQ3aAy8IM`=Ze_!(y(e?3;J=gnQ^kmfRE;xwbD7T6IAb%nHI=PO zB%YD3RgHP>W>l&^TWtleuCGq5)Jp2q-VpY%tX1l!<`@%71> z{(^a&-<$)zg?S3}bIGh}bZ{NmtVxe2oH6tM#NLhlU(lM+|3Yg)??D?v$(H;U5GA*z z-<%9}VxIzKP0-#wsN8$`%>$uq1+n8{LZ@T4pfmjLk3kjx)Al{oIIQ|HPH`^hiB+yMF|RQabU?3N?gZ@)?F>zas$d?0reMy8c7yJMra^y)D!#w{ zR4r90esZ?7eg89AYg?#pxDR6{8c82nTgMpKAnIpQ0#ZO0m<`r|z2F464DNy`YD>Le zRwdsksAp7n?b)hH&G+<5_K*MH7qGrjU;A3p>eB$fmWlO^9$e#cw7&6-Yshn&oPA$c zmkF(C0MiIL)PNQ|LM}Bhx-hhOu%Yn`J?`rb@oCAWhQ~NXih-ST(>;LE$ z)=KRJV}kRqZL%)G=*d^&#{{G$NK9iKd2h6_@e+6T-EM3&JO3eLp++=~)`n=uyjxn61%w;f)(|JbY|=w2$g#FYt-c*8ntmV`ECPk# z05}J(g1aD!#$6AjfDAAjtOk3*32+(Q0b#dk5Fp9BFN(ri)ibxCz3~NwWG_J6YHz4P zaoY}tx~3Dt&66Dr^@{TY9SwDXCxn^&j>a1*XCgY1ul+jNUTlYh{8n1akyInf8`l{J z^|{LJVvM(cTuw1s+25^p9dK{d4Z*r^nRb^$?#J(3)r#@;l4Kbo=j`cuCY2D74UNFdr3vEl)*vIv3)X9C4HpnRNIz8Gc zJ>Ep|F;m=))CHQQEd5Bpp1h}GLh!N*L#yaVt+EQbPQQ38< zcBs-luS=t$hDp{xG}Nf=eiw!twPoy3BXHd6nCu&B#Jk_a!Bt1T7-|Fty2qG^G~&y$ zImm6Y|BjAx9ZfJG2(XF1yECaYA^=As#{Jjkj+-5#D-Z zjFEwgBs<0$QK4y6nw4^NtWmS#O7;(`5>ku*pE(iFJVaT{x63d}coU^&{5+$S3>s&| zX>l@V9Nk--Y#E2T(@FjqXQ)+#4%u{zpUT8+s^F)xHrv@?8^|Fh9i{3Nql$!0LEEe+ zWv9TEC|#$}^KO=tQ^=gn-k+uzT)W#&{+eo}IlqmPp5w@fLDPucA(=W2mP6jP(~O5* z&fC@H`x!=K6wR2KH2Y)n`Ao#6N%$-xJCF_8Mi1v-wPg7$qYVdLPR}yhlA!R}#zL1~ zm#oXz+LHE9XA}EI5<16FH`&@b(QghV+?NbWkco2)H6#CZJ{fdsjuEZ5t?Ms`D^Jow z{+(k)azA9`T%)(MTU}W`-$+%fLUR#0SFX%8YR1g<^Q+o%ryLcuyzg??xl(nWG0S2pL}*q$f9T5=a<`&4pB%R% zr!L3~pKsK4JywtL)oD)~nK9oeLuoFXPae|W+m-3oeDd(97?0U$>hTz{G-b|XeCJHr z`IxbuEBrb=P7W5xjK?XE82RgQ++yUx1;z*3BXWCz@vJHjTh@jr$c!T1-ceOw_AR1P ze)I&HQ6%3zfuy>;42~pfg(9ov`jf^y=hqEo>_QUzbwlsEg~p#6H!iMPjPp5pcQIwt zS3;NYS$$WQEitCMzHP!#Zj)A3YCUCy*`~9bv>r+)SoD-p%kwC?@jwgTSkpfd{aVmi zlUW=G?U>kUj&(9|In#BqOO12dO7BlgjR!QE;6KYyBR-Yg%Z#Lk+s(tPq_{1l^tX) z-*ncwO-4KFR^(=~F+o~yHd;8_)|JCsjB2uGGaAucxxU#rZcym9uV?I&QgW)$IN+kB zWkM|{w>xbiT<)FPLOhR3!d8gs-M$qqk&^l6IpaTuuM{*#6Ul5IQpOvx-N@Ed9?yN= zc;D%ImwZ%xshb<<9N#wauG?w6?BrBnT9NVayeV{pi$Ebb0zLz`01Kmz>L3YZfIP4o z6oJpcEf9N$Su)TMCYMnHmw)a>> zyouAf4~%b+@z&?`3MWn(Y9Md_PB~rj`^0JEd-hDcbjJ9Px~=%g=lDB#*7#l-Y#|5E zp(pu0HahQfD0~C1dLJ6g?SPe+b07Ldene0`KSCSB$498VHYqFpE(EN~%0>Tg6|0Po zjj@5`$>opveEB^L`o!4f|Lu+a6zxRC=iG5ZO8SiILVE4Q$9`^XRcxOdZ$dV|VU+c* z{KDwPYM?KrcP`q|8h*(bN9LZrWPI(k{a&VNHlS(d91iU7@s_z_^e(5>^^W?FQHCu( z-dX<|zl3Tvz2id7?H%T=rl59!Bj75y3!?r(NdqY$11ta=zzJ{}sL^dSNCJJpY_J*} z0iOZKzqo@$&=cf>MW6^A12=&>q)^Mjp4@i)$O5y$4sZng4!D+&2ZJ=;>S6E()_@b> zGKgUKTnqFAxnKj>53Yi{pgNmBl0Y_C0Cs>Q;CB$lkh>k|2bPAg*>@X1J_ENvbr#-| zKsHza_JR}OE{I}Go&qw!0A5ozv`>6Qz2(84+G{h%a^as-PtI zHo0wRD)*ao>}{5|64>SFTTe|BEyJvc)T0wkR*2F~U4^hPvO~R{ki=Jq$s4`Q8j-L1 zJ*gzp%R9Qul@odusny2}Q@5~0N51K2P|;Ln)LpiuIV(y=Z?hhoK$i7J-s{Lq8!oT) zHmilF4fjPt$#Y3UUlQ9$c$Y0i($(*XTOsZ$zJlwam8_3VnmXQI^;7}$kmNpQmB@6z zAeBfJu^uw9kJ*7BU+qJXZxCeBaQUi_StGnCC`d!D^fN2UxiTR-`+Runk}IP7nj!q= zmCK5f%Wr2-O$Ou|6=bE);n}{NcE8%sL_5iGhQYaI3=z#uFqE&`eUX;fUuDKvmo9OS zm?5%A8Ba|N4U?otOuZ7*(RM{7j*j8uhGr_NGE0?OPsx15jE{`ZDk&LMe5{{U)?fOq zRbHtA>nRf_6WrBD%!tyxMwEC_RgXw_@28iO*hlSr@A{}2U-L~eVS}H~@#v&6fi22C zEk-V&I{t8%6$9OYwZoU?IzHVTE_5FmA*K77)tpe?@2wy``Iium zuE?wYZ~{#sU9B*dx8K~0Ne{|_Nh2oOsaGYL?z<;Um0r59a;Hn=NHRB@9E?0V(w9P& zSE?4LOL``^vK1<~&Kz1*5>(+cZHn8W{$~060-8L<=d3a=U4H6scA;)G8$h%C83=>zWIljxq%&iPFA|>k5+v|1=+nO+>(X^&B)05oRj`8#KsNOF!g9 z8JRtZX5L$#@bPSi#Pt4u)9`pwpsBLfzHsfob8&eW)# zb2BH|#iOcJZy7w84ySh@^N!-#eUv1nj*}aM&A?ql38fBP`D8|eT z+}~C5a%4${lE*1!RTwIzO5UTYu9THCS*DvuJ}!+g%R}t$^HE>E#$}SPk4o)KyUWPQ zMBaPI+caJZGR-=Xn>g*PKcrG zs&nU)qi)OS=erW4pX^hYW*o?(Yq&VfY*3svk;4g^bHVP$6Q$K~GjJ=;%Q8nfoWNn* zM0tKVc>ujHQ!8b`z`<1aehPv}6%d`<@L6vDizA=2;(ZYi!m%1kKEz!9VH!ck853foJK$Q7JK50ssnc^~N8 z!g6^O-TXjxiDJQM^(*L|<2av1@jJ)uf*AUZrZEmwUxzZ1=liV^=JnEtoz8Vzt zKzVmGAK5kj&{djMEV!Cd^;%QLnGq5;gA8gk#tez!fL8H0VY0tRRDIk)NgG3x8z^HS zm4dl)MogYOCd*gDRiovCH6N$_VDiOS20oQJTa8Q7G++8v3=Er-_hI8B`}nN`{SQ|N z>|y-hW~^B%GAGCj-vxvZ9*dX7LDpfm^{TPvqZHG1T-_Y^bdQ`arN^1oLPt&~Ox_MK zAC;Bk%rIxsbQzLk)~K|!3Nx`_CcbOrmBdS>b&y;cXFiOy`q@Z3gS5gtc_bUPs?g7= zqN;kf!7@KLvZ}AbOR!MFKH+f>EzB2in`1YobHzSNdwhvaV-FLOmVBa^TXAa+u zyE97Spgy#N?HXArwJO;M)Bxb*J2#z;AN7qFlCrD;2h2qHSyUa&f-jcB5$L``u|GU$jga z;UnDoQ(iVqM4?TbLj5n^1DL54*^2OGj(4$70|tKo-oK6(&>mO)@LS zEUn>i#9{n8$XV5rOr_42uhg+RqcvFOW7RpoM1oScYzgs^+a4>)1offIlYKl&s zoJj%g@O;S68mJ1xq~#R$Lw*~j%7ngu3dME-k@udE=ck}N+zSd^C1kj*g|jAxuFaTV zjTZV%BXg@yH6vn%2i1>&x}_@na9^8HSvlO-Ci17!CPEgLWRl9q;j(e6{Z+g&l~{aC zEK(PWIgMDP264jZ$dcq~d|9)k|1>i`bdz$GIn()CteM6aXUB9RbYPms`_<6*{NUQ2?VN2M@4f)@D|dS z<-t5;e~RoE7fJU#vq9vGi%LpUMRugRDvf=DdDOF!s_e?k5#R5VdGxg-gEB3P!+c}L zPqBkixy63(8B~OkQfWqzk}`M(A&zH4V$))Ias~t2O^bsEwl`;(>g0qykjA=Z zd_!KfKP~+|W}}zRGN+Zj|E&Tgr%?Gh$IZ@-W}C52#U~mmu1sPV znysSl54I1%qB)OUXbx}=8tr{=q4~ViiS{^t2?3!b{=CHe%85>R<|%U|I-a-rQj;60 zw&!?b9x6(yoo0LID~r9ocAC|+c}JKhxd3hg2UlW5 zgLSa(4^Y8ub^|%U> zR>qaUWbXre@e?ks_nKE9|-ibU?SO%LzG)K_NgGvgr}_nB#GuJh(T z2Jv$w=4FyIXMjsRcIJEV$G^dV`_YQKh$%#9qj$^8CR^9eNu~W}UDt<1=cQ$8FKTP2 zTgL7;P1gmi>^c9H`^{LAvwOce$_O9eTO0_ND?@3(jb24{uOP{<6d7Rp8*_nrP4nq<}0i8>|LJ z;8UY6B!L)n*b5OqCWP98M9tPssVM49tM-XXIE3nD)qG9M4?K=1m^ zE50LPvZauvE;(#QI=^{Eer{;LP4(ZyW_|sU{eF%sg{(exdCOFbVH4gW8e?VSTc%pr z`~j0|+)@pB<%g{wTMPnhhaU-zMIa@#?qD zTA>|@jm9=sGq4f1RZz)hP_uSO_&eq(?V@+;J0@?cq{>Z`)*e>GoHNtQHz}iZpsqpra24}+>=ZSB zgf-{9`P2h<2`aiQl?tSm)x4TBuA_B0e#rbt}==s^#cbRoI`Hk!;H8|B3kn^Q+09nk}4vB+ATB&AAlp zU!M}+9BRjCaNko#R7{LT4nP+~jMWU71TUnHuUedz7pDpGa zvpdJ7{`toIKx>#qHspboU_Uqot^r3mdRovFq=GE4s2sEMhF0*s85i1$V;gTt)ean= zNc`RmbG?;hUsn*AnQw12=SKVxr(cP=_`MnBc?d6;U{mkE`uA_Nl7t`7gpzOxYb^tQ zFq;-TJgXd92`R5w)+u_ixjnue~LJ7ThgGx90Ix7cV+xYgkltW`A zGq}ZV*>!5idf9#*UAw7W&sxd#>t?(s85!TU36+6m-6hFNyMgrfxUdXA?M6_ruPTQQ zI7GFTuWq2uMYSyniGUm%B>YG8%eb3nv?Tp#*6>eOw30DDn(@s#;`1rL4@a*F_SF$; zfRKw?OD;NgA|c?e;;tlal%qeIRYEr_Z*ue}gx~#{6JQ2lKHQM zmX8T`p5b>^BaKb+4^h0&`H?)IZ>73#lKMaYuQM|QO1PTZ*d&Ah*LiwlpR=0J*d)vT zFXtJJZQp8Kwn+~CuXCP1Y&9FSNq+jjoc+F;ImNlsFaHy@8Kg`_O_jqYNy9ljINdX) z>Q82U|HUGzMFn(srTnTE^>uAJ<8!~5?F<@@t;sj^E#cR@WwvwDWX9h@yH+jamRUzt z{u{T?_ET+h$XvnO&1LHWKcez*srrSF_0ZEp6dfvyMw^8!A=qnK8nbJw){1 z%xJ?`9W}>vpPHQX8*1`XZDr4I$fXL5{T+3@O|tjB-^~izsKRn|8sHST4DNui^5~f$ z5%dJ3K|WXm_JUL3D!2n8*mzqDv;+M>E?5K#!9j2V+=`~td0i{GW5%(4qv{=V4jnL; zGwk+ooWoH)hL6T>-%jzr&0lf)_ivN6Um5pbn|$gc9q#fWY$-3=#9QVcGfiulg!g_R z7c2$az!C5n_#K2*Ks-nSeJa@Nk*lpZw?;7)Hhs2+Rl^DCZmmYH+K&G09V^PsRZs3+ zO{KJECHea+HgP9VRdb0e&SpV85K#FVMIs%p9- zBWQFHj8s_zb_Cp2AgW6c-!V*xi#17+Ef5(UYDGz09e0>43bn%IrptEC579hUMacc(4D*lx zi*UYgAxk{LiGCj!4|jOE@3sh)x}LBmCHc`n$BApb+@%sjW!4s}MTt{^aw>&W6`a&3 z(|?Lh)xSVDQJrWOHsyw8RPXAB72(>|G*n)?L!Z&puwtFmxABHm$Mtr=HsUmEr3VZv z+VE8;%`sVS*Q8gtX;_8M4$Wk_X>Bz++d0o&kuq^1b1`X_)z(RQEw`)zPD; z(W0$4owrBH;b`)iXJGTAR2z)3qMgl0%bpWNx@U|PrZtzrF_wKQEV_bKE3`i&g!iRW z1={ZWGNOW&?$;UJ%q9h@kh=V?zxQ+nix)79yhbJKQzx;#QpFM;#+(snRdH$0de_EV z?CWaoy&Vg%yBZrPSkOcaG?8+2HjQ?a$Eh}2> z+OI`6?eM16vJAC(qpiA8BfB)=`WEin=4m8?3sKzbQw=RiHaldR0dmkzmC;ljxG0TNPwm zf)yJ%r@4=(oa$q3p3IG|E^2#iV=F#v13?}3b4cWFo*)_2*a|#BLUiD9Z-nP^b9uS3 z71%w#M*hMfauW`Y7C!NgF)1VR1Fy}Wdr13*md#Tl&&#Nc#{+#TjUhXO{ zgK%@!N|e_gvTDdmW$2kGHJCGk^QtUrEXiB?#6 zw;;DL6$@T{z&>=cvX`o@tgi zKS*)5q|~-hYR!{mc}uH7c=M!^l$f%rHR0}^&&TITdzL#p+nZyF>K$B4jIb#QPzwq6_F8lOL4}V zs{gz{E~+J{7J)DF0nW(gaK@q8N5lCRE-9@`a#FP!BKi;+JSNCmX$A=Rm_R>!$cl(u z?sro~rkYS^*^N|*NTPW~weg8l%}cGkbe7ghh%542tN5tG?<^CQ_1Pe6Rrvl;4kQuE z9lx6jMU7+pq1;Nc+L8MSt;zkZ zx7u2D{3FjbQnekDwj=44_R_6gP{*@MIXsWU`|ah8U>CQSZobY)Rg`Y_9R=9jR+nFN6T34~Mcz#kI#^vwtMCIK;tZ_$pe*TNjWmwip9IYj zDYtLAs7xK{T=-m6?r4p4x|(^P>}VZ!IuAFOJt_2x8C}o`=!5rkvF17*Eu=vTlx`Kr zkWykiMvm`|<(>BG#@23ftG5;6EZ4#NXK!oM1M_05Fuw*;Ko*z{ zR)QVi1h@=B;?Uqg66gbR!6L91oB+1~ms&XLfsP;x%m%AL5jX}eg1aE98k!(T1=-cK z2*(0`YykVgXVvUUzDwF_E2{Lv<2tk6R!uOSR(mn^J4!V3iHT2X(7Jc`RXI#1=Cny>pD}GK?yKAhMdpSXZ zT93z}4-WO$OM`zAkUyRVhoOx-tb!D&tx0Ojri^xng~`%?gGBzLeD=lX==JjRzd<5L zOu*q093EdU%O`LP3Uto|)JWg%z(mn$bck~6I6&CfXJ*3QpXckQrkA-z~gGP8{Yj5x@<|+?BI@!dW~d_*8=S2 z-Heuch%}mPr8ud+GbdXkU8=U)D-CxiTM^EBYo*i_Qc5jsHO1=g9JbcGWQtWmGaj?+ z1)YHJQJ^DJt$t4GLWOD8B)hbySzBE-$iSBtFy>92jwniP$aK2U(RL=NN8q>cbc$S_ zZZ&m14(9_~S(s{+XEim*csq`9zBuOR(T$STXY%Ma$;#$4tUsNkzrjpvkMrdX^3_bM z{k-b&bXcGd7!C5l8n73f1J^)EbvicC2&90~ARnv-Mc^2?2!01)4>AD;+JSx`7c2l9 zz+P|yTm$N)d2|grwnqHu2nK;EHRxH=xsIy3_N_cP8|D7nBQkz7H{XTKu^KslJ0i{J zSbwv4l`z+8p}izy6uB&0=2{~H1FhJ3RdV!9+F-_fs}A0t!os!hZ5EiA z%fS50e5BYqRDe3cfuFM;^Cg3HZ|ER$W3|wE(@b`U0z#=nJe^8LfV$s$WIw z*Gl#47QbwoPN@>*W}tQwCb^AGiM=V)_&eq3#~(H zILn32^|ci;XR$ThdFNC4W-$s|OPMERVd4_R&vATR%>-8r{{C%+KpBc zsaK`zN-Me8t`IxtuiwZUE1AeqXOmXI7_kaQU23mVlN{dkRn}xpOY*+^w3;aBD3w+- zpK$w{3|MWo(vHZptC=_GC!x<3ae%zA!1(26zZGn}e4hG)Z zMHsPSMTNGaxA{n#iKP}!$+-I3RoN}%*;TnD)@ijIYRCM@8X}Z0pRb|j%UCi zXzMI4B9!!X)cjOgtVlaKs>o{jYaP)zEA`hi6*EG{tcNpMURS14^2d7IE=cVS%=Y|Y z$dC=zTso0U8wj?Hgm1KFs9-O@NE|n8B-mtmb)%I={9K!eUwcW|WKRVBvWsF~vk8U{ zvTu`}fUjS~Dq=HM8B%+*?Z>uSij_Xc^sgLiZ-iH|-&91T?W`B#W1Unjw0%q{B$U@= zW1*!EfzEphk#`hBHHq9}sa*)RRmK*q8rxRIrFKHuF~P9Ks_E)rIi+rN$ipfrc9CXp zwW3|y!&rHKTOIJ*O1;`HySG|f{CQkY%a%FM**(Hr&k=(u^3!ucRj1uHWY3ZQ+iVWI zitklcPs+({Rzv5L;nLsFObthb=ZRhiSC)~SkJ5^G-+U0-o zc`{|}1AztigDkjL`NTe3+V%y)A1664P$1)E;|o-;1PR|ky{7KuQ*9)72SM+Y#XAUk zXM}8e!5Spxc3P#K10to=4!ZgPduRdLFco8B3O)R&_iVAy(TKz*H&@G42 z%bqK;Y8IE%SY_>Qi;rGcIk$(|@h80>@3CCvXpEm9vz{_me4@V6+)*QupSa6-^WU`= zXvUpSeU?+10`xEfJZ|N(jJ)c&wZcg+RP}u|Rd~od_>{%Q$r@$Qo_2nZF(8^--siy4um6boWpyn%57%?5;QYitI=^XM zHQ4y$xq;&~yZa_C#X^YbL*_tLt>yN^j^E%`(ysEb*S8bL**UK@^kC!eLIvzY^^5wg zmz>0YM1@=h!J`W8LTK-w_;)=kR}4&i#m@fWtJyTq@6ohB9S-;&kACf{57%GN&qNUk zf0+0&X2!@5DCQ$A`0bz{QB0@G_z|vdx*E0XYt;ppj4PgTt4J@rjqZPO;wFq|%|&#i zyDA)-xGHak5AJKgQjiI@fxX}eI0?=H2VZPAz#_05WP)vAFE|2DgMMJ1i>n@33|4|o zU>7(Dj)M!p=_YKoz+#Yk6F%d$2`~17Bj7wR&BMM1ECCz94sZmV0$0FPKQsg^2b;hy zZ~!!ev*03_JRf@=uo$can?Wf!1Wtl};BYhY+?k$OJ{83N(YW0DtM&SUsGMPJioZm{P8>Pr7OY40AjNzUDbGH`o%a8^1?y3< zm$BC#LY~*2QIB69y@lve^+>q!5)wX?gRQ^8h&_$IIcmfclQ`_zAA*f^^=;Jnd(?O9 z9LKArzx|$KkJ|b(3Li!pp+)M|pC<-7hZf0}UnP&=hV9DFh%+mT)%FqGUmPuT43uBy z>rv@faO7ni`D*dld$u0ciG+}!k#M4zMUA~@>&E@sK|BU~9?i0)>t|N_`A)ii$MQz! zZ{;vI{E1GqV8h77sm?!+`eJ`U?5-TaMHsy|f+k!+O=&yTgkNxhfd0Sl?|M}EFUUWF z{IBdBdw;dAu3eRX+mOztuF zd_8zm6U}o#xnDdx_MQ)a$_NQpt;3bYXBY4J{d#b$&dPGcQ9t$$mf-`R`@R+yY>N|;dHgZFfVoP->JK9^d|AFVGbU56~@halQ?gZIoKJaXw5O5H;J1j znU~sQtni`Z>FS&|FbaWJn}4#`y*AmrVw~!14DJK5}$w+!KB4cH8Jfdil!oCR0F z)F8xDumr3G8^B(01e^gEfI~0>JO~C$K`Ph;O2I*J9CU+=z#M|!1mR$Lh}|?(CSGg< zd%+=a5}XS`ysN;s-r%#ZQ_NEx@4?tUtGuU}Bjx?Uv462*0Y>&&l{>|J&sA4&?2J&n zpXO(`d#c$fuP6b3>;R8Pn{GFukMPGCw@`ClrCRU?p!SF0{aUSwU(r7@AlgceT}^et zC(U)fo^PqqMbyD-sV(nQhgVrO&*b7wNBmRN&V!1m0{HK z+o;aChHJlv3{CGJ= zi2AMeAg(~#-|!YSdKNVb6IuKH@R!Z3>G;bWTDvfTwHACtb=^lDoWhEtXVbRe<4QVT zM=5QW>(Kw&Q6gg+&_laVQ9baUl1_I$P3<{Lt((e%T4atC;4@A-U+z?<``$_&I!vvu zqPAKm9eSjLc1PY!9@tt!$MF5s;wP!~OQ{=Wl4c#HZG=)oWR-OOop!(}YMl$qt=>vI z?QLr9W~#3=ATPI_j;vp)3ICzCETeA3GZbqNNsrXZ*d-<~y=<7;dXCzGNu~3*+VQx= zPTKW&8%F!<%BYclv}&Fy$BT|$X;};&x9f~q*c@sdurR%P9PJiY+G*IH=ybnEYUN65 zy!5223`LJS{W+pTU(${qugk;uri^EB;<3MlF~^(E8M_9`_NZ)WNP>Yb^P$fRw{M5>)cILF1b zo3=>09G@X^Az4DU_g74Bk&vD4PrC#?VqO2vtLdowmYP!}2V6^aK2EJ=%rX;|9x#1JZC|9f6ztC=xm|ZV1JNixfMakJtSx7B7rFCG>Ol$B4N_jO)sOLSmG#{!v)k?$9+)fs06gN?lhSWF{Y^hnT~A29 zb<{$ce63H?Zkb7ql=QT#SWfRG`tx;tdi~e@N{5GZv0bbjD51Aq(cUVdw>&}eU!uC$ zvtX}I@xM*o_(y82C$&ZDX~#Xjb(LY?U|s+95=e$*T^GuvtazRW_P#^yTq(MXn)5$u z7Vg7!ff;h#R%>X*A9Xm!^!f*=hHOakf2KVYAnV^wS`@H}33YNtSr5|gxsDnkAvak< zZp4f9557zFO`;Yo68}M}*L$KV)Z&xW$_MlKB1bgiDcW5%)MQz1)%LXO{HcC2mRlwC z4!%l%p@iHD^oH({jS_Op<+x;-yt%DRAIOs~>XFHm^DPtVil}ARQe)ny=A=>so~91T z^}VK+cEJv6WiYi^wrKT7Y3Ix28<8H*E0HmDkpsPQn9*wvHA-f6vRrf;is=ssr8Wgo zvphKm`lM?&-Y)sRqvH2btv%A?Mzv!E%`?@mp`%t}vxkJxv^x6BWb7-)(>B7X^{-KT z|4S{F$mw#0cGP{;2q|aCm-g1})M4w;V%#kf0W&O2z#kg0wzNr>--wKTaXr(UuBWz0 z1yQ%sj((ErzJ%I~NucLIlMF$Qq<8qykKgF#`j7Y*9X(#u>IKyHd#N=qQxor|CS1b? zw%tIxOm?-gGB+B+=y${eL*0O(&uMR!%d)#f+Fk?uADzKP4vcDK##T9lV)1)i&4Q{w zW_tQrs!KF=P(o_S1=~N`M62e_0;1@r`AE~+4vg}|FpwHx_nS}vu$q7SRtAw zTc*#(d*Xtgz-H)m^krR#o-a^t*^!zLa(E{23Fr%4ACXl=jGJYV|2< z`-fEb25LtowdN&izG#hE>v%W+G?g6PSl>Os101sd8UnyboAL%5eBS15&J83=o#v;w75++o5K&$AJsvP zkvZa8LOWS5*Ae(F5Z$vex6z*uL))&l{eRYf=*X4Z>U!I({vG`#^QZw;)Z`j!)B);% zM9OwqEm=}wzEoHz6`@lc@!_Q=_*~>s}R=A#9NSNvA*ke(uzUR%+R5YNwQwgCVe9 zA~Iyz7rf657Mbj|owUYurS{OieZl+d?-$epyv<$_dOiuS%%-1PHkQXsX zhp)8I{Uh4NcZ*;4BgSmnB^RkRA4on~mXWd_Y51Ie_anUotkmLVN27wd)?LyIcy2K4= zg8@0yWSM;Vxh%-?s}%eRwc579QM7#}LOZXZz4bCR0cGpCh%nDWG}TsLT#Hw)E3!dhFs6|CU;r? ziCgJNe~nsTJJVj;(Q>A)vfPHJ(LZvWYDuG3d`>N2N^M<3t?#E=UZQrqNA1i@;fn!p zs#grv<8^9;JVHi$tdq$-mYVfFHMfsiZ=p6Uq`IV2+Zw6f6WFu0axE#8Nu1Z=!3?ey z)U7vC^S4pk-=Idzs^|%(?IG$YAvoux948eI%W6rK*`6E7^t9>JvJ+O#Gr2!RN0TqL zOG2>Ub+p?esTsJTK_{5%hiF&)o!awHs>?s9#Wzu#B)#~s*fXeQS5YIwwPK0+N$8EA zz=RQbK2hmM+x0DKk6ezE@1q?p%dyLmcE&-fyZAE-X-CRr^_Au7^)mfkI#8j0Q=}Ii zIk!?1WY+gQNxSe)YR1RZR#|4Q^6)GD2Koo_`4HVhF0yRZ=hwd2$?P@7E9_3>G z)Q$#U9*|D*QGYVdHS-B3zRZlET}&{a!_j+SRnwf|+hk=iSBB1WzyLozuF_AtG` zx;ilakJj>EG1CBh)g910K>tG4Imv z{U8+eo1$gRx?~wf?PZ4K7Ha23YK1e^;}Er0*7M*l+Cy@08t@wJ1i6S6PG^tB^wJ*{ zKy8{P>p!BEj{JVA<4aVR_o-zm)Xo{yHfccbQ?z?zHAKt3U5l6aWye##h4$cI<@md( z#XrdUPmrrqj;w~Vxy*nsu&~bBV(}+SLB67nOPQ}mhNR&}+EH@xDtm)=fy^b>5ZcN1 z)Ls|4{?|#QYL#VGE6XQZB3<7&9*`xg!Fhmo;WgBnKx)8rYU>GV=W1$GH`QZ1wL+F_ zdfs((IEPUq;zVWnRmfGZU`X=G>WC7xd`^GIP1J(FQzH*kM`Xy7ucEy%T>Q6D^PC;{ zA|Zy_RZlIvp6YiWHR=|s_iSpr%z8%`+O9LHY3s2vg~%H(QSC(E=`E>;#<4Oudm>Z^I2H?DFz@>%2r>tCncdqpeO z-^SB)L`G92~gtwOdpbZIxfLR z{U#4-DZVzw+R_S%`Mxrnho!=3S=ZIbrO#;OKg{nam+b)wWGxcPTbDCES>{sh%{;Ct zi+kNO$pJDnbyI1Nlv4fVT2Q%yw)1-GRvEe)MY~;AOM+}Z zy&ZA>`b!iZOOxhW;TKdFa$sWN+ z#AKEm60@TZ@qnHpYIF!S@?q+rgz91$nxS<1N4}%>NGKk0ryU}pxZ)w&5x&%c0NKM&RG ze@H^4pC1$2$5HJh^yb_`JN_eTR04HtD78aYL-ZNi)lyNER1_f_7gsrMP$Fi?e`NhP zoZ^8^60;MIO2MAgE{WMuvi`TqO{v|-OmCA=T_%yPM?$kj9)`C_!@MUmfB9N!RD)dq zD`ihtE?qY)V>tX3Gser9cSY0Ak&BS8tm87dHZ(0@diC8@KUtOoGD#zT5&tLDf@SD` zOk`8>{nWlMsKZ{=CJ7*Ya^{0F6j=+I9wkFoFBJ?){vK(-h!gYWKSr(CNFDf<+M0(k z&Fdz%I4H1h<2+xHC;k(;zN?pms(#yb$OFI zJYClR#xOeUZleywQ-^ej#2J=Ik7P+mj+R(oB5@){La~>G;;zFyZmYx-yQ^q-hEx6i zN%fe4{?`>$$ZSrR^;|ZN{+PF@H8ZKzvi`kguK3C13pmJh*Xfd9dcy8=+Cz2JhG6RO zDQZdHOMFonLp6?4oxQ}Ch_+QCphZG%nS|VEc{JlEV{FK#wOBs2(<}RmP6@e{a^?wN zu>3sluld5=R>3{AE261&5^579)Y>)B-!7}5UFJ%OXx1gB=l((+=%5<1=c|5}cFX-% z%`>%~rz7e*YJN4fav{}OhGb(L?XBI^2;0Nz@seMbr!NLn4{6zd=y$w^n!B5tE)mu* zLE9Mrwna?Hk%qX+k)zo*rs|tHcW#ngVH{_d86_kcM{Y zWsCYvxiZTOCDba z<8@j8u0>23evw+6O!bJTmPrKz@+MQk1o}HSQsZU$wY*Hb;v?#?gxvf!vkiS5kkFd5oOaU&YOKV8ice|R%Mkg>)wAI;{pGU$hcD7@eUw_f zgqr6pAu~Y&MxD&wblc~MK4iuw>FOwHNP#q@;Rw^~CQ*$_YNf1}PKlK6x6vPi?$$kC zu)?Z&ruOY}fMo2Aqz%)Wv4I&)iGj2OWNe!xVzx`fte3fwcnkAIeL^jMm)aq#Doc*5 z_SZv#@z1!I8EQVGw#enwRnFYo7CPm?3aO~NoB7k_%q@@5j{P^aq=H%_5i{c++Ldw{ z@6|nm`c3ZkOlXsqy8NDYeJ(X(DYZ_zuupo%RU%sXjZC-8r*^(VE%=5yBHM6RiKu;2 zZU)M=uKxk4z`2G8q{)uQLt=b{>=7%bG2Q(MYOI`*MIvOBtdeBe1NtswK8q~7>U!ES za{R#GWc^o{Fd1GPdTsN)y3b7XFmUrpO9 z)2ex($aZRC9JNIvYmP+L5~;8L zL!|5VA0o@FDS!ub%GEB)hjy1to{iQP<1?qX(%)7_HDp84BpZ^gk@RD=SsUcFf*L)Y zS|+P20>@d`|DYULCkJ9GSPzVs0}G@fL$(MgA-A`R`PyVMdP$&3lt~#ck*-a4LdEiQ ztypg5(yqw*_a07H`D-m7#%4Wk9?WCZXHQi?(B( zRk8oyM@JK;oE;|KfG6#c0;-*8*Ie4UGK*d1=F~&FG_i^4X<~QDs;GRNetc1Zwfx-q zRA=jC#P|Qa0lkF0UyY8evT|#lWgyLE! z`n&Y;di{4vfJl=H-K8LlOs*WMz*WY&RwivlH47S+RgyJ!|rM>$BuBoXcMNjk~FXh1BRaYUS^# z372I3mq@Iy&SHY!BI=OL*1m1D3!x|FJXv|gh#0*Q>o<=!(*<{Zj;y@yOFjrkLruAw8K!wK0+;il{%P7t&>mZ4=2VcH)sz?HjSDtlRN7b ztDR@^`i2P&5mXn+XpsQYDuJW+9Mk)zP`zZf`~8jf5SphOSR<>%Zx8(?zeu{AK${G0 zr*)2CDJ9A*ulSxBYx<}e(j)P*-V@kjQ|I+e$Dd)dRv0f8bV{HpaAbPqd}@ST_3~wC zIv=CI{%I)cH`(o{qg^Ipi3A+uPWmIH0iD@m%bQb)G6Y=%^d|;TTjhjCWC*?F_>DI+ zy)TJcjcWt%{{!i;dxDyK7qvwimL-uZS|(M5oN0Rj^OcL%NgSz_3i74FeK<=!G-Wb$ z!y9PFPsjP|gyOAqxZg+Z45AM9Q_JOs!b>(3F|yr`mZ7R!%Y2D47Xsu=y>N!Qd_UQY z7W7ED63C3n(z1$mOb95X8r@>cI?rvU-5~)cS2nAizoUOJi<&R9K1Ukl=R<#;1h5<# z+OGHMH}aDB!aI?=Q7*U1vuKw+MRmQM8f{NalV#WWAngc=biFc(2PD$94>R3jaI*T! z94mg5{=C7Je9<6hSR*a0dx!pZiGZ$hk#avpe}VLj@dNGFlhmkr)ZxEV8)O-e$ce;C zLk3q^)ALLT;mjC$gjyg6IL6SlXN#-pPvOpT%)z0+Tm#H}yseb-E;}O}MM&3)m zhxA;AH4KS3Zg5k4Pl7 z%%R4;fi0wVijA^~pVd?6$8)=v4Q>!H~4a#chlSo>3HPbC}T#Lk$ zEa~Ca1G4^mrR5g6F-Skd13l!7Yvhq>&Hw1{nojkT%c|uY+8vjviMLW~ucPLRcI~Ad zB>`)|_Wobti;^H?S1X~nKmtvatly2BnXgzH93uM$<1h5LNKY2X{eF&w-WW5}U1W>b z>m#B2arD0q5Ed!8Rc3!-CH>Ah)Jj>7#a>d-&(zv+)C75S>o=7JR}|CV>O>8Z$QmV) zbyy;6M4p6JcV}h{xQ3ecB{hEvwZuiVmFgu84ymTyH-Q=>$9b)$Jt(_mjI8xUH%dHk zk;nOY!>LRNd7av}TWnb-!)~-4KcOZ|NZmM(XFB*3{dO|h24o`>6H9-(G{jDJKKT-u z1}0n6@%i5@W=xRf5+m!~(n5b_D78G2I_OW0Os5vFr`r92nk$piRn~u{3{{)Vm4rpi zH()&u z)PiTBsNWPNlgLrVCP(br6U^u$_aGH zHKRDMj2XO-Qk~@%s^e?g!$s75nG5dn9`3O8i1&>git_EuSACTPAWz!$a=Fct9*vgc zHzqPY50`Ok4|pY02VbLRyhBY8zePf9-9Gv&WR^S1R;>6G{ppWU^Cz((BUi)@qQ;B* zQu9nB5^^`*$qdE&sp;9&k?*O_-%tx>mbc0zERzPcCo$bodZI$+M()-0cge%4TKSNQ z#aa)>HT?-@7?9ZPUPZe^y2?vpcv}wr<;SV7og zQ8O@Et?S?8zf6dcbzUboiD_~fEtacVygaw_l`*wQ!-~J<@fk8{JHDdb)PAo=0F`@ zL#+wK`P*R#@?}zNyoL#b5(Mq$5^9HJ z2<>F~CQ5lj($kS!W&OKKC@tH}f?E2h=`za;!)S+WrL%RM=f2AzP z)(N!J|3K}Lz*Tm$%%z{{&$CG6%2`iGu@qb<73IX!?<`~LA(6~ZuJ4I*4e;<}!F@6` zE;59EMLa%aCbdJ#OJkhC{lCm^UkMcXpD<&A6j&l%Jh+yA;|6M!=&)Q|nr6|TE}?wT zHt8X%hKLK46CShp9u-r43S03|nk6=JHJ4dzjC0617~Go1Z)> z@q3p3iXp1ItOoacXnX5&P`}CWp(8*dSAzNYAD1C09l7JEUNlv>RWfUD-^H#E9x; z>>>@wdX)aoCnVoLr~wkFN=C2$PE1Ib7#=GXSfqds2_#*E%-6P=+F4C4k=Y(0%dX&8 z`rBnS3`xcH5;wdhKyA&Ff(^L}7RuNR$PGjCAr=(z6m>A08g)Ch)r}f0lPkxbw%tW) zfb0WuWzN`1Xb+J)?f7o9@rxlw|q%EZ6-CRf!ZOHGC?jzes9t5a+o?Kt0O`J z(2(SFm$^{U#C%y2fcidzjrvU`5`bbP06G7O8Eb;5)e=wwcF~TK0My$}yUn1wNCeG! zgLZrwwN@f!*0Z#0WcKUt7q(vi2X10Q@{`m;2|x`JfSM-Cfiku|vek+XrN2eicZkfP z&V}?_WDX?v(~c^o_Sv4GR>}G=+0BH6d#Q$ONCxGxnw<=ZmxH9wrDk1E?X*R}D6y?$ zi#MzGNWMmD{bSTYS+)TWq5pNj=o^*<$bF4KUUUx&7HL4 zC1CYQgZ#4TZ<5&WB|YesCu804A~U2(B&%IbJNG;4px8rFfFTX{Udr??2{3jtwk>kG zj+MYxCV_41$IPD~_0G+gWfU(3IlsaTX%f+#C(t&gsO^uKe`gn`PCSC|L~>9U9x%+qE?PT2LuOApW4wq|ntWFLopUYpgrb>{2wO)Jl=GsoembL-4E%!_UO zLs6!Wr_bIS?sRj{ALsN&>A0R)$E3irqA9(ur|rf+{12b-FU~o5?;AHIP6cI}L-7SU z4`-Th(ZBI(LL4w%0oZDpJi$t^25i8esW;!8XC8-di3CYtEyxB%pb8uUjlc=>XDaXn zE5RDD0c-|40KOB;gfBoe^#lB&b<n#4_JRZ86u1cD#$zHUjYq}c5NHG^ z!5MH4%tLq%2g|@pumhBWec&KC3LG$0lR+?81eSwTkO?+{W^fTKaWe|-~zY;re1>z z!91`T90kY0Y0wS&!6mS0DozM&1G~Tha0Hy1it#^-7w3V=6=w*NK-Dyy4LAqF-ElTx z8Q1_y!BNl+`hgFwjKN?VI1l`3#z~&&7)h0|wzdUii;O;eZsGdK&*gV{Ht4v+-)fRi`oVWjcm0=NR4d~il!1K0-+f}`L#I1Rc%KM3~4 zS%F<(FE|Cxf_XQgcfew>46FqEz(H^nILyO312cdR2+qTQOTluG3O0dlU>Dd6&V!4< z-w!9FI0%k{;R>p8%z#CMIaa~0=vLoZ~&YI7lD5$P7W*q zaUcn-1&yH?|C4xe1~_5&=Ly2WVz3OX1V=$XxC9)+Q6X3gHi2DWFE|VE6&|M9z#l9C zOF$e*0&Bq`a0X1h1?7WfU}YZuTLU(L&EPob2L0d?2)-4SflXi=H~=mJ(*jfg;y@Bu z3$no$Pz26^bKnYaia=#xC0GMCfE}O|yg90xNNqkNDFHi2!6^Kf=}aUNU* zrYOu#FbyPuwICZ5fjyuK90HBtB=Ecg6@qZE8SDW2z)^4fB2vmVX;0(9`t^m(yj49Xw_JMBD4=w?RJ26?o4B!Jc zfo)(HI0epvyz}_)A~4;Bvjz*m5)cQnK@r#k8o^0$0bBu2OEHVVGO!u!0Ht6bI0{aK ze&7&;1^^!r3^Ktsa0E2RVEj+v#YJGc8(j~k0e`RnECFjlHrN98fGThZG=h`B=^pd~ zmmPI1Rc%Kez-OmZ4{WkN$1qRJ_Opo4^5Z1T=%Q;5@hp7Q~_vU<=p- zs=y&|5}X0&zy)vxOuZKq5NrlV!D-M9`oSgO@CWn=SPGWs;lEUn3HE{m;0QPc&VrTk zC=46~-Jl=LxDPD{!C(xbKnASdH@Xqo?spb2aCZnun!yrM?pWh1RNejW55jH0~Ud$ zU^z$yncx&S3(kX!z?_7h$-{sCUl$Od~r6*vSgfGfZ$6_tY> zpcL!_2f=Z08gzqx;FE@)0I6UT*ah~21E3k4O2hb{#fyu;v>FWo{$K%E0+PU5kPRBa zNpJ?715OX2N5EpR608BIK{uGZ215ZBfu&$M$ON0fE^ro{2h-B?P+>YM1aTk9$eH<6K1bP zBft_62a-TG*aE7+A;R?UC^!yIgKp3dE&+!}&?{gD@BzVK zImk=Jf0m1I0}w~)1VtTY`~d-8Ndgmf^A?IH~>z8 zv*02yZ^Re_f3N^70db%RRDnYqG5(EsaT1&Z7r+(Z^ccQ0&77L*aNCSBRC1pfOFsi2+u(e zfgPX}>;nhEQE(jegG*rP<7fcb1@?j?pc$M6=fOo_{tJ2rC5;A&dmLjH{;9bztUn+Zhtce*(IwxwWO#gw5(FE zYe_x))!)qX?A1Mw;{Aushi7az58L4zo!xfexYg>89p?G=0siVSZHB0apEfVF4-Gr~ z%G2f-$JwQ-J9nalH1)(z^G(Y6S@T47Xs3C$eW1VkbSI7r3{VrE#c_e^mS@djc0p>r zwu045&*G~D)BM#3P_=xQ*{mFP;kjj?n!5|>LHOQlYqssXPdHZ4R|x?XNEHHs5W(IzZj2 z%=e(i=M?e=s}B^43sIM~gsM5EaE7TBr8tMM5VgJ3TIHLi)&_hN9PnswvOmfHZa6bFfyc$DTuJDgJ8zbLK$%lmPXqb_c3S&m&WiTKGJU z3|5apl=~iZ9&m&iun!X3g;p$#37~wtUTT$tIdytl*F7GkltO}koU#-H+ z%`@~l-dB#QaE?zw)#8K3WYt`5_QDZgm7}s0<@N#^y-MBo0<2WE{sptL3pxDhi{`uR z&S2g--fy00w@md^ny*vGE6oNf|D+PR($s|gkkxA8esiEYvmX;; z(|)s$y(K{H*9n2@Q-~^f8T~TtA7)=P;I@C5KYG~BmEh9~T z#jEcazkjH|zkhH*s`fK~>Hi}?{gNN$%#!>UC#soM=2_GAgV=C9Vz8EnjmaEI-)mMY zs?2ky?=}CH9_asD`Z7a3r_+}iW6}eDE8jFpeTwouOq0f>2mY3RK>O9?yYMZae%0oQ z)2+6&BQWT5EBo1LaxZCgE|zn#ybDQe0q<~ezbri`g4?6-Q3Sp6}{>5tqO_~0Gu)@R(lcHN_C zsiWhnLe`qQInk60%GCkNA{(3Iag(R8f}{U~ET7o7+~GZEP@CZF4bcrdoXfb4@=qmN^g>f}(75;LJ?5|A2Ys^fSMu2M1y<+vb4J zjq0-l=D_JbH;x`39E7=S>(T=^s<}1h>C+F4O~+iemA}D9Jy3%$_Jz)T)$C?J%~$P) zJ$;(*XnA2FXs@ljZNBOQly~>G-_nDFFsE(lTW-?F#b>4_Z%A93oRWrJ@o0B3jolSA zW}f@cQ=zY-PXBqMbp{7vp4--c_k8sT+BUs={+M*k@43?52X9s{ylS31{ou`G(lNhn zZSujT3vKrBLBH76SrF#2EnPpH3|C$y#p=>{Fx zTgVAUUfV2DjcLZT>Ga6SVm{hVX3;I`?bmQJi*6ZH(wO;Hb&LA$H4IqQ*mO(?+l0xy zRn0nRp5u{u>zL!m1V8<}Fw!cqf4`2M3dDsEhh3^{8 zx9DBS+$LN*0|L|oP1dWzPAx&|y(aUmD(4t34(4O#09=+99>eu9R6VW*8=+&?Yv*^z z^kwp0ryVi^0ciNez<}|}vt?p|^eb~)xw`zcTyV+Xr z4>~nS&1!)Jt9v1;uLT9~XhFfD>dhA9!lhD6xSIJMO0=l^v?Qyi--9zn9eWRlu2Mf} zNmaAnw^q91eWa~cPrr{!gZ$O8_i+^u3Q#|2cc7Yc+*;{<$B{Q!J*_S5jgBJ?dn0XO zZ`2CGE&-z4_ZetVD=zzi>eW_UpM%t=T7uR16Xu)Dn4wc-w(n9dC(PHVWhZb!4pk2z z6-8}7VJ+&d6DZ%JzSEMdX8ju-x=KCpZ}aVF^-J1HQ=e&TwVHJjL$u0YJ#Z4=A-yU< zy>t=<1gnouA~jICwV~C4>h3lilA^Y^p^k9%W*f3t)K^-PmD>lXBSqb*WtDnDOR9QZ zOPc!X17umP+&)B)U^wouYJhs|L%2iL{twNc*auqF6Q{5_4Gus2_9?UdIQ!sab?jsF zuc-CdX;dC``0{D<%n9~EVTY%GZvKzGoxghh3pB%`KGTw{CVUA=QK4U2>wj2Fs(Rr| z)R3k=(6UH~;M@743L*X*mx^{YjAg(DyC#h8Zp zs~4;qpg!uw5rJy_S130~g=z^_tG~jAHAL;#f}P)2*i+|xjWT9@jnZoLt7UkF7C-(q zj>fJRqN2~k->?1H_@0L!8(%Hhlxtb7UO$gc3-woDKvi}h_Et0ckULP_(TDUP^|+Q` z^(sU~f1?Z2$)U>a8~DT2om#@x6Iv|lbuHLOLR7)G$UOU7Y*SaMd%r~&r>gB*($q06 ztJURianfP_YJNXpv*A!l6FLY z2gf<>u&62D!BMXrao@p_qMpPao(>X;Ubvi|{+tZvhSdVfGc2|uEs z(?6gf?DT&`32ADDmeuN|A5pIbJ#N(iHS3~v4XoA@q+Yp*GJ@4N5LG{<8#9D5Le=^q z92}B~=CfPj}e=P{M});p|cG|IDFk$tCpj zx&PsgE;&F=xukpS60*cyLY5%)BpmvTwLg6r{wtRdF+!Riq$A?lSYIHOSYjg~MqcLdIGwOWfsy)UHf%u!rNKcC1pf?BQtDj#PU%($r4vu#AJ_w7oIUKGk2@k26A5 z)i}ef7LP-gK(&4xvbZ}S%OULuR$pjGfp*MxfFo4h>tKZ8^tWrlT+?DvmmLg!cNgji zNm1(^;asI&(UPjZa5Qv0nlc`Ob02Ta*Z0xut%{gC-q7d%iIyNW;VKjmeE5#5jO(V@ z1sqOsH-2%n4@p)j*TWy8Ubr4*gsKm&H*~zetexR1)YG^fO?ccBwV@Y0jhoHbYS^|4 zXVrkGaihEb)W)s6!iR<8HpRB5iBo=F#`V+n2RS4;I2aod+pem4ih9M%nCXp;)aVYb z`M11bq1g4=@-9-u%I%MHd&9+R>AA8q-Vecf^GSCe-+UaK;1Fr3`2w(OQd#%!Y(sNx&Yhy~L|iwO=H z)79asRVV9@t&BEe%%*vPvYTyO=dob=m}GRH?G(DTUp17NubpmvX{#T7WE<*>*QtkR z8*@A^;%;TM2JBUBeYj?ZF5+OR(apUytvB{WIwzIf!y}EafG0XkJ*z_^m;&*cF$6G-)PKn z@18ZLC`=GrdYme}5hojW!zQkDjG94Jk=m7a`(i&rfoz+$J|5} zDPLbb;A4}=tTmHL_C?_)pD{;cKG@FUpeo1F_6L2`{JF-pszVpG9Cx9kHDUB^d5*RjozFM0cw#JspN2wKegiszfpF zCv|pP@|YoApt_JeeF5%>N0Y}4>ACsJZ60R-xv}XOM_cJ}Ds~<{6op%!MsBg92Mo+T7WXFburW{^>v+>+``=HdrlR}MWufi?QOA*H3 zuosxS(D-~Jb_x^j#Kj-?Ja=Nluu46w1@}C68v42UXLlNUe>LYW>@jfraNk|VE%u=S zYUf?pAz+Vj7cvDYx24DwtRB#UI~OgX>N_oADm2EpT{+*4-OiR6!-8GK+cCyn*i}rp z8~#r1Uw$|ItJKcBkv~;^3P0+dc@Iintsb}s_2K5>xqFP;?85@oXWAX8W-i0dBuL%2 z3=I!fPcE}=W!}~jsxB`>`@_`ySmX>>k3f{~y{P6$EdESLvidI8xK&kaNASHyi0ad? zHsBSie&t>qlBT}VvRcjk1FFV-!)mCS7KaVpfj<}lsQj}(pq?N#Jq{AA?$Z*Yc51;s zDh{m=Q&Zw$;q8fdlw?s)$6NPN?`bPVjlU1FO5LF)RXwF8O}(dOwHklF5vuPQ7T#|J z>gV3;@5k;eP`#ujNPToaHjX*V(cr1ev2nzM_vI)UPdFgTJpuls%MD)@qhDRXD^xu_ z0iBVo?$&}kmIUNqrQXtl+oS|^c$&Ip1;%5wdTIrFIN4vFuxfys^hcxys{6DAsTcle z+=G+-?vH3lh?=?5da^54TC3l=(zrPsOUU*l0UuX4Ej7(wwPD@*(H$Or)(cq3Dy%2l zoNiRZD{+Zwv>qbKSWmV{;G_H!5ea4?p&Vao;$Vx(V;!oXs~pP{!qaYZ-x0qQp>@q9si2gec#? zV(3pki9fz-Q9nG1T*+$gUy+=mR{RyMSfzIV)kv`qPF0uxYP^V(eQt~KXS8j~R?OPq z!}o19{-WRO`RFO*8~c#Z!*Bo1_{q*bB<%2;1;$*neP9~iTEl|FyH&d(LFyJQcwn*H zxJy4tvIXEhDr>hf6H9f1vpToiaMf#ax3!IP6?!aOJ)p&+b}DNFPbidWz&d>NJ`o+{l|hD^A#(h{UzDns62^@+AZ)cEI6YN%TH z9Gqcly%yZcYO&zWHdK|Y#y<}$Mctxhm3l-Ao?|_aG(6*Z9*1Kg?m>;Xn_IZYn6J+4 z!Q#)}g9U}9xCiNYh_(j@1*=Kr5UfKjq3W@6^l_MayS1>;?NyP(4# z?ZrAnFVB3*_|Q%VqL;1bJ$)Yp;Xn)Ch1-XdNK-FqS*VT{O4@ zRf?7%wG*Oz_v;a_MB75tPnFhY%-xTp0#gn@u-{0t8yAY1_})Lz=s@+07CdLFg5Vas z3N?n{Eh$K-danv)hN+*bP(-+zTMZ|kR%%IBPgcX3qTbZjD)mJ*a^hjfD_AGKO;|xo zUNKf;npo8Se;Nv9EIfdG;p*W7ILe}4&{ncKaR8O3DEk`gG+bB%D^)#KgDh$4l^SdC z`=$nK0TF2Ks~BZGwpjftG6mupy!C89(1OQA+8LrkUxVN+M=fD$|7%DKSD(Cw!tsFU zAkIHDRo!vW>V51W8i2wYBAb)F85L``Z**(eNc*l!=SO09oK-?8IP{T<{FR3E%!t>>3_P*$)CZA5i=kG&CT;c9my zRsd#hBhr%9lqNV+)WRklfSIcWSL!BfFMg!0)yn>u;X5t_acDkY1gI6qaBQI3dCXeN zv12F#k^GpRq^s4;cX8^$tKSHi@PXa#X2U$a#bnz4o@w1<@0$>lu_15VgO6U|UcLK9 zJPtP&xc$vE&jBWW;>Pj!j@EqI>Y*mThufN`n~h+%dXpy-^v?p6fPeUG%G(}l*%#Pd zf8T6`x&6ho1$UnMM}K@DvDn{@N4Ek*zT|)MMk>Tt&h$_cgjBvMd z(;~cws(&uwy;xmB=?yI5KG!3r1J)FLqynlB_VHY($rq8^3p}HkF!nGCm1{8wFiM_-GHUIF9BYF!@V{Y)6(*r88u<8q?LWJvG z8HZb|xOj2~Gt6m4h8?DPk|9_!oLY3kTEg9KFPe6Zx7KdTzKRDQ|Iv2vcde+t$TV#- zGc@8IW!=7{NE~b(!Fx|2!?UJFY(e!;KeoZT`cuC{hP@|@g>Gw2MN_RwrpXgKaqYpVr^c z(rM@9;4`{l>%ot78WU9T2gZEYXG}hLN}_)bxk~k3%hj(RV_rS;0jB*i(YvQt zv*|}gvNoyFPe6F#CB2O5Lv_aXYX z%v6*EFMh(GkPO#jf};;txV>s>w5FhFsIFp-o>+TN8IQOfGC4Riu^Xxjo~-8-dSHfH z)NTa2J#Ctd38jCk&;osMksjG??U)uvc?5j@K&S0R+V0a>^FOv@(bSo;Wo$MfQKx6? zRhM+$a94>R8BuOcrYkaSmSKQ(hQ_4(T^Kb!{0OJD!8)q&o4SF{utX-Fw~F`}6YtNa zeHb166Asn2`JnsIgfR85kByt%wwX3rQ-3@6OJz;EiI2Jc-LzSfwm@~+M}9b|lcH6} zX~WO;AEwjNxVQ-{dK+WPwQ7C`0#?cBirVMG^hUj4Hg{lFK4D6NPybx9O?N#U-5tgq zZWX4*c#fohF5DpHmNv=6y7v>z%7dm$NYFp}iITMk7wg5OgYB!x;M#23U`@tig6ft} zPO%27Yt@AR7>iy1I(pJYlJ3u7cCC6G>27bDvZd3ON~aZ##)5DDgHzjN>XuVCBdX{Y zT>33opFyxFFs+qnQiYhTGgRpnx%Z55o7)?vQVB)+S2T6&OvxBjOsQ+t)twmBDwC%y zOZ}UXIzy74bGDTg?)ooNGZOTV{uM}_q14v%Sb0~e&Q2r5ZI|^oJawkyGIyrw^@*4? zO)dBoGk3RXlg!*;ISD5{`>a!Yug>te^;cbV2}h%N5@+;T>JoPU7wIqkpKkWo?X=dA z^k0l*q3N9U^h~BjQ2p}KXcLgZQFZ>;u(&BxGj7uLkNyVTI$k>bzR`s! zlWkgLok!?uX=$lmCZA!dzHQo!$fbWKd$M_@I!Gpch8Xy|=@K6L=$~vn-O(j%)ym=viPp`H(7NF`d4Ii)1AC92&JE+^hd0}->cIOp=h0U zMxVF!;A^^3da+4QKmDVBL0D%9*MVzgH)dI*$q92q|4fyFJ#}0<)Qy6lGo8WnDgCqb zAvU{Pr(xu$DgPc^P_j&G<(xNRnOa*lI=^@J;8MHAl*s}{HzRB0a_^>o=rNYKJ!zUI zanpn*>Jpad3~2j(Zm*dRp}G3!5N4+CwPmC0_oFYcdiIzmBSHVzuJlQ|eb|lM>6U5g zmyue6Qgy-Sb*F6p67y}H$&62L>7OMMRkrE0v--HVOeSfNz7p%>E@j)UbqH5ZYQ?$# zudnj}kD_Sf`0U>8C6rq@LfWN}1f+x(AkqmWAWd2T=`Bcr0HKT2gwQ)ubU+kAg%1%6 zSOQ23Dqy47D@8#N1c{9<-~XMN+s&OO`#hKZ-P@+m&hG7QP_Ef*fLeu3g*91?wC0|@ z=iRNs^4Shw7*(#<#n`-na;;`Brc>gWW7P^_2=#`U7m&5b*hs0erliJHqtHe0>lcu} zNsLAzZOc@-`jA1lpWWTVUSP*4E7(3(y2hBKNf*bz{u!&YiI%}OWw2>TZ(ix5yGLjq zJEkgot(pc-`sTWg7crI1x5iF$#HVDEh9c9~FXF(sg>_SXXp@>}F46eK@u_3jC^lQ= zcem<$$EdCkU2^ve-5?I6lwaTc+X`vc{l(ooYypcGJ zU~f!mCjH{B(XT#hotB*ZQ0schtoGhIg&M;pLu|ey7#d4_r#~7V?I5|TH&8DUi%ny3 zcySW$GFBZ47g70lSKN3`!-Fcq0!~?_DxxT3SY_x!iqSRn^LwO--$d5l&o7(tk-xgr zg4pcYkXPi|HFs!kb{%S)_fne)d(4`VOKJ2QyY7p)d#heh!>s@z; z#n$gmEG#Ht-{OlBE~Ss>6Rx`Hp9Ar;SKVGmqGu032gr4uhf__ic$vFOiSoug&`mQn>)HC4&0E~ z+4nE@XMQ^WqM2A#%R-=jJ8;i+cVsMcO@`F2;Bhp9#HO*!M|k<`ZZF2(hh)Rgq2J-l zU-%+3gvJbsF1}6q?Cb6*opt4Th{E%)yUXc#$HlSh?zGAoQ~D>1XH!K|P9&vLMZ3N^ zVbL~K(?8F2meASOs5F=86h*efh_hc+2ArYpX5Q8nOXUv{vgF!pRC#%d^m zli`O1wQ0=7PZYXqwk_Jdoz8Dz@tI}*<`CN)@7ZsPf1PXT?3SdId8^-%MUB;M1{;yD z;a_&3oBt9lhc>=gC|wh_8aj*?u{l|yTGP@nU~DUNz9E94ZFL!qWlnw%x|6CmIWc_r z_rGI^mC~O~q4r4q1GN?Rhr2Ca9pu|E6HGDF7^|yBZBRfxw?Hp`lNbE$4s*E*!4bSL ztyBmcgpf_U^RSAPwMv>`& zvEzO4EUu;VkIK*fiB?MV(8H5Yiz27EV*A^pE-+Rabn1-aUpdTx?k7=IB8P1T;-@1K zGQrgkoT^F_#Kugv3wHU)2I!(hm6UrMm}QxvJO1U4!re%2li&QyZHD+yjkO0ewoq1O z(%p^6pw$|U9ZP;=x~)STmLi;`|11#`~~Rn zZX&S-^hf^N4R_6ePS|v~cywEt`*)Z5(8W^Cg$5^jUci?Rd-DS~aIQG>rrTSAxuzbF z*Ye0Ym}O1m+itq6R&hFm58C6m6lO9J9DgWRRiW!zk6*imFu}LnUc6K+1Xc3A%5f?2 z9G`U1FuZ^JU0y*U35DX_ZlROhxaD^9skcz~(vtqtyS`#?*vF*6NSV-$Qs#k~Isx4i z{OT=?(@VG9c;geldCOfDS^MrL4NbX~W)r6=L{d)YkA6C2tz(StdY)xHaT+gw$L$UAZ>t-(aUqDO-p0Wx(KF%> zV@K&rn8#J;u6Q(7xR+)bllkmB?y42C#y)h9egcZ^vY3N;^}7h+bnbU*Y?qR|sd0wfbw^>4&4e27c)ah%g2__*PBba(o6M3<)_kTm*6;j=+W}p1 zO>qo5oO6pUuz;UKha&iID#ent->w9xg_A9=d}6N)Yy2s$+em{Bi?xy1R%nQ1=mZD(1gR z_;Cq3dQCjep2ZdrGnZY2(sz~|pkx(lXx4f)Q1>8o3;#PP+XtQK+0Y02HN$&PM_PV9 zD+s7$FZd~ymC}`|sj;2KRO!B2_G%_D!Sm4hPDuiFopZ6KQI{$ImD7#T<*Vg-pyMOy z#WzJS=zN!u0{!MeSG3lw@>9XeboUL5e^*-!blDDBBY{DeJfg8>sJFEn`xZLiNc8kp3Db@eG{$JGo{|Ly zZ3vxjl^m$+30-0lKVG)9SrtdD*C9{fd9|E$F@mvA@%1zN>y~VEeXb31grt&oz<7+vt<3E1)f%fUb9e!GMiXK_ z#BDYVYQz3mt8zqVc=vr@!eU)zp0tmiAvnX6^-Eph@{w?U%56sRVAC{lVisBR7q;9@BF@sz-ef4Y=I30lG$(t_cq*XI2Yxv2P&G;;H4#@Fr=`X>5wJ z2xFO(6e2s>Y&Uc}ES>)u>@dEnoEeFWvJdfB%9&A3dOmNT>-mNjxgxKwNznPma5&5C zX{W*1T&|TjqvBtMiEj`@1YBJ^16?kUFK<#+4tfF0GWrsh;>rYXRly?Im<&5^HY@X@ z##UH5|Gck(z3(z9(1^jAhrlGb|q7L?E9a_ zQsq}n5mj)FS8k-c2VJO0uTq?+!Zv$d8OfYJI}t9D7kE&qah^sz9Z<=|Qef?y03rkG zWq`0oolJ+3$tQTsuw2(7u`%L( z6Il<%us+03RW$Ki)=>x>SPq%E>?t?;E$cRPi!GghJIs9u{h5z=$^K8 z{_W6dhdpjl2I^0Jl9IlK)NWN~9SSv8CFv4$Wy;8KzN>Wf4OjixANfU#8&|}SvD^9l zc&O<$dhAhsH7wUN66_mpUY1lO*NiQI?o(CuUZkrEfOH(5K404NtT$j}t%NR1RgSO4 zW&W7w=2sefOa=0?PW~Cp#vNgyYGva^wb=<`mGZ5|nyH%eA_GNr`%j|~Iv*5fhQ)k$ zR%6|*1pMu4b1fWG?^{1=tc7Lb@_W_+gVauYK)P6m}+` zfJnw?w>9Pw*2a0@GlZeJUv`*%2WvUid|v!q;@jw#rI6CPwWRh2{IZk^ov&A+=B%t~ zY+^>5pU(d%*&4bSm57%Qj4;b-LwI_G8TH7lq8ckU^_8r#PebP$S>Ax-=-beZ@kI>y z*(iY*Aarj1GP>0-y=+`JyO0h~Yv_hrUBFi)ad2c?aPP-aD|FFr73Ue_)~yM|8*r?c z44qn#(?r4_4l~PCPD+~PFD}wCsw6FdZlY+EmQHq)zF2wk?_HzH6|H#xUNaiH6h4r; z#7pIMHn^A&!QA6Dy-htIRnV;o$1C0qDa%T3pZe)07nxh)Jm2snjY3>qBa}$v2_H^N5tC@gX{U$*N8NQbqDY3YpB^QKq+_r+Y=*NuYA?Yj^U5$nyrq zT{9IXnoSz1Q1qB<(D}MzG#fj@*2Q`Lgsw98M4916c$m)OB{l}e@>9`fxYmoGioy~8 z(X4!aH3~y!T}z#{0hO9L$`zS9G2i2ny$0;R>rI< z6ZLtgyUyIguAe8kht58;?1mPpKgPc6sk0eYS`)`96!qTg5uMGobeWIaI`kIk4)Ve% zED_^8>w4?#6eUJqvij(3t^AV7?%_+W_|iM$(V2a9cF~Ggv`3AZ_Gmv;h#Fm}kRrV; zWAy$(){I25V@B#YKN3y8lfM*;me#X$+#rA~hHHKJIY_h=eh)j> zTjO;0jfYX2}~3L zjMLL~{Kh1*(1q8FLxQvAZkN~@=VxG$OZ^4Dne;9Be(a3Q9G%sZil?|I9*R?9XOzv= z*~c=SuYq%AI{ou>{ErWj&Iz6ebE6UNIO-_v@_@+_-vWB1-4R|$cIRx#?^5EPkG>&o z&hm@|*hDVy<PG@N{*}FhFYZ%`3I!;(b zF?R6@WH;?;oqa3qdThXCA>&QM!*J)MT|a(~?3!)#Re;e2ct^T)cur?yd3rT7f~QwC zqx8C)`EiVOqt^3OiDEW7xK(HUc|jbytCttR$e8|;&YqI~<+oFHky4M@!4JflUad8+ zR}DtFuj;IZG};DC<^|Poj{iOIF^!L{W`=3$d@~HSANhW=?}b}FD+(iH6i^eWjpm-} zP<{dle$l1~SAbzo5y8;*;9x8bvw0p2wLJbT+3$g38{b?VZI-bYM@NC$C_F$8<@AGC zXh_L6JTnf-Zb)kL+BHzb3wTT%an|!$wEKy#C;gbiIQsHJ(xZQq;xV3@i1YJbYnXks zAgS5Sr$J&TPV0k>l+5b=F8a<^zMI;{jk_d?Iaug_ ze8K;zg%051_sF5{my{iHz;jaRwGpW&&!$}#FQDCcxqDpha^!Bl+%1#4HFAerUdUmy z*csctrg}U_aUa3E5s>iZANYYf=(N9`re-3IaRV4DjY7GnF1+J;ZS0Kdmub$dR~I(p zfY}1I?|B|6r{GRo49Fxi!U-BB&7!Z;>`5NlGG0h#yCDge$`im!60ZSqvmn`( zLuITHd?(q==bvC_9KB29QcFfLKL=_8wJ&&leb|KZ7T6gF?(679srAw9H<*Kcs`G30 z(Ci=ZRiwS_aG)QP)~H}O*mQ}@TnsT&3fDQNrD(RWJ4)!z8YlKp~&odgK|Nqp0 z=QKiflxsvaM7eTR0bXR>Y>Z-*;iq7wW%H}FE6qzaMrrQ1aNzt_8pQBah%iqLq+MG+ z4LjpjYX?^M8I6%lBfgU)543f#V?ttF1rC?kqn!hD@XjW%JILdkAi(>)1?|f4zSz00 zc6G2PH9n{bax#anBF!fL3TY1XaIiB@p>aLi2j$avN>f;!jHu}~6{GX<%o!9{mwwY_q5a=Lqtw5~@ zPj7}m+XqrALb(%&ci@uUeqdK=SC$vR4rh-)kooAr)H1^6AE29`gE>lEuQ`-$GDJru zNnf5tk{v@G3|I7;L-Ib~42c%Z_haXJas={(>od*GFjvEo$dqJ^bWaOdJ;-a*?lA9w zoiP!=4JGsaEf8fZ&m+Yo{w(d5@;#(qHqpU4N&VNn5EA|GiQG&<(FZ-|z`e8NX{-nC z=UN(q;3m}+cx!wXcE;3p{pU#fot+9SduoGkCv1c$AP%4PsR@| zaIp0fPXm?ok%bN{%Y?yOz#Rhhj75A%;WcSk$#H;9XjqUcF5LABDZ~>^%oor3FyA&H#Hj`PkNGn4`Y#$S$J8*}@ULj7L4xDNWJ*c4+UIt=iOQu(VQzbrH zkwOXSYG8=OEkI?v6^P|8-1PS<@|1QcOP??&#)|NH7q~)VdbrQf7zf14T$BZvDsewh zRsU(=2`POgf|3#?d^OUF8|ii8gi}Nq4h)qBGoq-e3LiqbKq~B~K-t(v_h=^;q{3@4 zP!;^3E&Urx|=Y4{>A zUt<3RCsth|0}Fu30$qE7bsVw}UV6ZZ>5wd3m2q)pNU#*ot>a|BO2=_^oj4&7F`faw zD{*j=6Jt|kVJ04|e;8R<4N-Mo?_o6PUK@V|wvy6>dQ<{okPaL!F(24K;$<6S>Qn0p z+h#yzFcugur7MAtO8gy|Br%}@wX|@nYh!aD&h{y1ODxpC#+v{;Bj3%Eow#A%-5J^* zzzPEOOuU$cv_~QG@C?#^4Xi2A@t~8v!*_Op^gu%=PMC$kSzw$**2uy*pfu3a@G6Kd znDiSqcd}m`Jf|}z{YtHzIIs%;vA|RjRevp&zY0s^jWj3L*FyWDjpuB<35*p6uCUfl zb}dpybq=I~xT-5MSRNQGP>&eMS9C?xO%Rom+LtVh-39dBjhsqzhuUZgxi^siL!NI9 zb>gI3#O?g36PI=fT|0o+HU4T>l;@dDCr!XTFen5GgY&>E%HYHZnhivV+9Rn)2#W#0 z>$(ilX|xm9sz|KIjFCCsGKS_q;dB~!RN|IwC%Yy6H;#3(waUN#1Sc-(3gZ`ny`{w+ z;4GO3*VIW)7No3mA9J$u(qtv@D`hhLaVKl4c+*rT9s!e?dv^wnZxOupOefna@fY9{ z8D!Ed4C-KM{PcV$&SA*d^$)O%s)9}no$NX3cm;S!;>(Nh+l<7Gi)oS(es2I*7&2Vy zO3@p7ni1Mceys=EV>KiiFYJMKUIUDl_!*7MV3 z*d8LU5V?i|<21gaH|lrJ(>NSUr&oauB%T94B(drSD!fRbHn5q*k-#X4bAdQ*ryOhs z#z`yyHj#K6h!ZL@81@WJZ~}J$apFVLqrfBF(+{~_{w&|v7r7n0iG~A-TyF!7Aby}P zR*3KX4->m7SkHNzoBc3HefKu9;t(?9?>#hyk(&{*myRw1PXGr?tn-eA%Yk@hB-tAK zXlfJK6R09g0gjT=v%pZEJ{Y!t?Y9iV4_F3yK+K)}F`0l)NUwL6 zM8yn}6er_vFQ6m1$jc32J&Dy1Ti6#^S4tNFw@a-5u7%&*xZph}>n9D)0&(SF01|tj zNTkr+#-+gSQu+f>rE4Csu%(UTZQKlOC*3aDSobLPev!l)pi1pyU>zyF4U873haKZx z2BXPqe?UiS;nUH^5jM`VaWk-;s4xA}htmE2N7UtoJNwwlW=foC<4qub*P`}jpI8`d zV|g1R1d2AYh1G3LvavBRO@^HgtjsqLK^22k-wHiWbG%4)Ay7&0+xYkiOZuCQBThQm zJ=r6MeM$q2BDm%N$F`Au{d$-|lUW8vP3drcEdy2921Ua)Pl$|8z~cg4-Ux$bI=DI1 z4AXO?_@JS%oD*$e%_=OPv~e2{*V4%UJg}z3axs=|0uYle3}R~li6(AV!;DR7*8r+)WCG_2ss2kmj~#}fj;aPt z%w!k=ti)Fh12(cy?^TtrAj91deIvE2s!@_;=sF1e1&6m`nEbZYpishpKd?5Rkcry7 zT!W9zq=XWwutHQiQHmr8m?rTUaDv1p$p#Ll!eA4yG*2Cc(Y zketdwa~)QqlMqefByzQW&|nUY=VT%EwhaxsN)NFy6p!#69DXC;W?u(a6(dkhpmKXxPmVN`Z5Pi@=RG?zQnt8-KUa zY(gmsw?qr|woQ1Qv1XLhk{CHQK5e1?HeTN5Z+Fd78l{{1LhDtVa&sKwSrTKAjnggE zpK8i;{OyigO5?JPu4cZ_MgkDG%~5SMvZXz29B1QF8~l*V(Wpjn~86#xpkGL6@Htf<6z8Ok7`GRg{B$0w(vldV9WA?PU}c$nOG}E&^Qk$AH_VodmXgJ` zQDz$fP z>0#UUtS!ALq#9K#-WR2^P!=dNrYCmdrzfG(AZaeMnr+)n2C9U(kj7J=1F2H&vrXT% zrRQwvC0pw1Y$fjo;&(6Vl?{NZgQNl*lQhCZ$%6r_l{ob|>PPej94ybIyfhz6;KovLLw(Vov z4gsoGe;n9a=3%dGTVUIM090|m0;;%0F`YVP_<7V+jg+9-I;4f7@&0g z=!U6R-`ztT0rWjR_}Dxg30|8-i%jaD`UjJE>}-rANK_hM167ARV@odr>+@B!&4`%E z$b(v;`|c*Cue4IHHko&sg9IAD#?8~`U;wlNjuhzH2K*U!e#}9ZR!rdsV5y&-!oMYt z*Qe6jyMR1S09*3TbCEl98m}`KR*R?ej@TR9rqhCVGgQWpz!-u0{poxoX&cTka2hAH zvw(diehI7~@e*)|#P%}{Tw4&fBY{5DAs1!5VBNUjyY*0{H0K90wy zmQr6537lEVKU{zW{)Q-q$1gq|+hjRv_LTidhyf2!Z_<;dt$Z7tcOk z!L5G{5U3rTcU8ujDsB^`&lNcLME2?5*)+sMp!E44?j<+yh9Kw&wmVGk?ZP^DRgI$~9((O8l!`W);T>{ATjcF7x>6(oXNH z57WD%a@iwm^J~7ie15C9%Jw)}ci@RTd#dNhzG=QwJ$fjV+wnmG*wtxIpLsO4AZW~t zNo)IWyT6p5{J|WS-~6ISMUd$-UScxl+Ta- z(ag~*oJZNKLpTy?pT~Y}8NT-?vrdIhI@$pBw+}^hqG7+EkADhh_TvN2n-O8lIFx9R z=sS3a>}I@Z1bLN=grY(8{E~}3Nex!;>iKV6EB+G&3S*PJ@_PJXLP=00uBvQOvb&%SIv5n75~rPlzT`fuF2I8Nuo ap4FaN)$Qh*Cw`6Q!!DTB->80VpZ0&|ea7Gb diff --git a/Tools/ArdupilotMegaPlanner/srtm.cs b/Tools/ArdupilotMegaPlanner/srtm.cs index 08e5bca0ef..7583ab71c3 100644 --- a/Tools/ArdupilotMegaPlanner/srtm.cs +++ b/Tools/ArdupilotMegaPlanner/srtm.cs @@ -190,6 +190,7 @@ namespace ArdupilotMega requestThread = new Thread(requestRunner); requestThread.IsBackground = true; + requestThread.Name = "SRTM request runner"; requestThread.Start(); } else diff --git a/Tools/ArdupilotMegaPlanner/temp.cs b/Tools/ArdupilotMegaPlanner/temp.cs index 8994baf70e..94b8f99faa 100644 --- a/Tools/ArdupilotMegaPlanner/temp.cs +++ b/Tools/ArdupilotMegaPlanner/temp.cs @@ -878,7 +878,7 @@ namespace ArdupilotMega private void BUT_follow_me_Click(object sender, EventArgs e) { SerialInput si = new SerialInput(); - MainV2.fixtheme((Form)si); + ThemeManager.ApplyThemeTo((Form)si); si.Show(); } From 444f29410b6faa5d517361ace2e6ee2191503e24 Mon Sep 17 00:00:00 2001 From: Michael Oborne Date: Sun, 4 Mar 2012 08:49:45 +0800 Subject: [PATCH 004/178] planner cleanup --- .../Controls/ProgressReporter.cs | 64 --------- .../Controls/ProgressReporter.designer.cs | 94 ------------- .../Controls/ProgressReporter.resx | 120 ---------------- .../ArdupilotMegaPlanner/CustomMessageBox.cs | 132 ------------------ Tools/ArdupilotMegaPlanner/Utility.cs | 64 --------- 5 files changed, 474 deletions(-) delete mode 100644 Tools/ArdupilotMegaPlanner/Controls/ProgressReporter.cs delete mode 100644 Tools/ArdupilotMegaPlanner/Controls/ProgressReporter.designer.cs delete mode 100644 Tools/ArdupilotMegaPlanner/Controls/ProgressReporter.resx delete mode 100644 Tools/ArdupilotMegaPlanner/CustomMessageBox.cs delete mode 100644 Tools/ArdupilotMegaPlanner/Utility.cs diff --git a/Tools/ArdupilotMegaPlanner/Controls/ProgressReporter.cs b/Tools/ArdupilotMegaPlanner/Controls/ProgressReporter.cs deleted file mode 100644 index 33389e8c03..0000000000 --- a/Tools/ArdupilotMegaPlanner/Controls/ProgressReporter.cs +++ /dev/null @@ -1,64 +0,0 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel; -using System.Data; -using System.Drawing; -using System.Linq; -using System.Text; -using System.Windows.Forms; - -namespace ArdupilotMega -{ - public partial class ProgressReporter : Form - { - bool cancel = false; - - public ProgressReporter() - { - InitializeComponent(); - cancel = false; - } - - private void btnCancel_Click(object sender, EventArgs e) - { - cancel = true; - this.Close(); - } - - public void updateProgressAndStatus(int progress, string status) - { - //Console.WriteLine(progress + " " + status); - - if (cancel) - { - throw new Exception("User Canceled"); - } - - if (this.IsDisposed) - { - return; - } - - try - { - this.Invoke((MethodInvoker)delegate - { - - lblProgressMessage.Text = status; - if (progress == -1) - { - this.progressBar1.Style = ProgressBarStyle.Marquee; - } - else - { - this.progressBar1.Style = ProgressBarStyle.Continuous; - this.progressBar1.Value = progress; - } - }); - } - catch { } - - System.Windows.Forms.Application.DoEvents(); - } - } -} diff --git a/Tools/ArdupilotMegaPlanner/Controls/ProgressReporter.designer.cs b/Tools/ArdupilotMegaPlanner/Controls/ProgressReporter.designer.cs deleted file mode 100644 index d24768765e..0000000000 --- a/Tools/ArdupilotMegaPlanner/Controls/ProgressReporter.designer.cs +++ /dev/null @@ -1,94 +0,0 @@ -using System.Windows.Forms; - -namespace ArdupilotMega -{ - partial class ProgressReporter - { - /// - /// Required designer variable. - /// - private System.ComponentModel.IContainer components = null; - - /// - /// Clean up any resources being used. - /// - /// true if managed resources should be disposed; otherwise, false. - protected override void Dispose(bool disposing) - { - if (disposing && (components != null)) - { - components.Dispose(); - } - base.Dispose(disposing); - } - - #region Windows Form Designer generated code - - /// - /// Required method for Designer support - do not modify - /// the contents of this method with the code editor. - /// - private void InitializeComponent() - { - this.progressBar1 = new System.Windows.Forms.ProgressBar(); - this.lblProgressMessage = new System.Windows.Forms.Label(); - this.btnCancel = new System.Windows.Forms.Button(); - this.SuspendLayout(); - // - // progressBar1 - // - this.progressBar1.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left) - | System.Windows.Forms.AnchorStyles.Right))); - this.progressBar1.Location = new System.Drawing.Point(12, 82); - this.progressBar1.Name = "progressBar1"; - this.progressBar1.Size = new System.Drawing.Size(277, 13); - this.progressBar1.TabIndex = 0; - // - // lblProgressMessage - // - this.lblProgressMessage.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) - | System.Windows.Forms.AnchorStyles.Left) - | System.Windows.Forms.AnchorStyles.Right))); - this.lblProgressMessage.Location = new System.Drawing.Point(13, 13); - this.lblProgressMessage.Name = "lblProgressMessage"; - this.lblProgressMessage.Size = new System.Drawing.Size(276, 66); - this.lblProgressMessage.TabIndex = 1; - this.lblProgressMessage.Text = "label1"; - // - // btnCancel - // - this.btnCancel.Location = new System.Drawing.Point(213, 109); - this.btnCancel.Name = "btnCancel"; - this.btnCancel.Size = new System.Drawing.Size(75, 23); - this.btnCancel.TabIndex = 2; - this.btnCancel.Text = "Cancel"; - this.btnCancel.UseVisualStyleBackColor = true; - this.btnCancel.Click += new System.EventHandler(this.btnCancel_Click); - // - // ProgressReporter - // - this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); - this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; - this.ClientSize = new System.Drawing.Size(306, 144); - this.ControlBox = false; - this.Controls.Add(this.btnCancel); - this.Controls.Add(this.lblProgressMessage); - this.Controls.Add(this.progressBar1); - this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedToolWindow; - this.MaximizeBox = false; - this.MinimizeBox = false; - this.Name = "ProgressReporter"; - this.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Hide; - this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; - this.Text = "Progress"; - this.ResumeLayout(false); - - } - - #endregion - - private ProgressBar progressBar1; - private System.Windows.Forms.Label lblProgressMessage; - private Button btnCancel; - } -} \ No newline at end of file diff --git a/Tools/ArdupilotMegaPlanner/Controls/ProgressReporter.resx b/Tools/ArdupilotMegaPlanner/Controls/ProgressReporter.resx deleted file mode 100644 index 7080a7d118..0000000000 --- a/Tools/ArdupilotMegaPlanner/Controls/ProgressReporter.resx +++ /dev/null @@ -1,120 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - \ No newline at end of file diff --git a/Tools/ArdupilotMegaPlanner/CustomMessageBox.cs b/Tools/ArdupilotMegaPlanner/CustomMessageBox.cs deleted file mode 100644 index 592263567f..0000000000 --- a/Tools/ArdupilotMegaPlanner/CustomMessageBox.cs +++ /dev/null @@ -1,132 +0,0 @@ -using System; -using System.Drawing; -using System.Windows.Forms; -using ArdupilotMega.Controls; - -namespace ArdupilotMega -{ - public static class CustomMessageBox - { - const int FORM_Y_MARGIN = 10; - const int FORM_X_MARGIN = 16; - - public static DialogResult Show(string text) - { - return Show(text, string.Empty, MessageBoxButtons.OK, MessageBoxIcon.None); - } - - public static DialogResult Show(string text, string caption) - { - return Show(text, caption, MessageBoxButtons.OK, MessageBoxIcon.None); - } - - public static DialogResult Show(string text, string caption, MessageBoxButtons buttons) - { - return Show(text, caption, buttons, MessageBoxIcon.None); - } - - public static DialogResult Show(string text, string caption, MessageBoxButtons buttons, MessageBoxIcon icon) - { - var msgBoxFrm = new Form - { - FormBorderStyle = FormBorderStyle.FixedDialog, - ShowInTaskbar = false, - StartPosition = FormStartPosition.CenterScreen, - Text = caption, - MaximizeBox = false, - MinimizeBox = false, - Width = 400, - Height = 170 - }; - - Rectangle screenRectangle = msgBoxFrm.RectangleToScreen(msgBoxFrm.ClientRectangle); - int titleHeight = screenRectangle.Top - msgBoxFrm.Top; - - var lblMessage = new Label - { - Left = 58, - Top = 15, - Width = 300, - Text = text, - AutoSize = true, - }; - - - - msgBoxFrm.Controls.Add(lblMessage); - - var actualIcon = getMessageBoxIcon(icon); - - if (actualIcon == null) - { - lblMessage.Location = new Point(FORM_X_MARGIN, FORM_Y_MARGIN); - } - else - { - var iconPbox = new PictureBox - { - Image = actualIcon.ToBitmap(), - Location = new Point(FORM_X_MARGIN, FORM_Y_MARGIN) - }; - msgBoxFrm.Controls.Add(iconPbox); - } - - - AddButtonsToForm(msgBoxFrm, buttons); - - ThemeManager.ApplyThemeTo(msgBoxFrm); - - msgBoxFrm.ShowDialog(); - - return DialogResult.OK; - } - - private static void AddButtonsToForm(Form msgBoxFrm, MessageBoxButtons buttons) - { - Rectangle screenRectangle = msgBoxFrm.RectangleToScreen(msgBoxFrm.ClientRectangle); - int titleHeight = screenRectangle.Top - msgBoxFrm.Top; - - switch (buttons) - { - case MessageBoxButtons.OK: - var but = new CustomButton - { - Size = new Size(75, 23), - Text = "OK", - Left = msgBoxFrm.Width - 75 - FORM_X_MARGIN, - Top = msgBoxFrm.Height - 23 - FORM_Y_MARGIN - titleHeight - }; - - but.Click += delegate { msgBoxFrm.Close(); }; - msgBoxFrm.Controls.Add(but); - break; - - default: - throw new NotImplementedException("Only MessageBoxButtons.OK supported at this time"); - } - } - - /// - /// Get system icon for MessageBoxIcon. - /// - /// The MessageBoxIcon value. - /// SystemIcon type Icon. - private static Icon getMessageBoxIcon(MessageBoxIcon icon) - { - switch (icon) - { - case MessageBoxIcon.Asterisk: - return SystemIcons.Asterisk; - case MessageBoxIcon.Error: - return SystemIcons.Error; - case MessageBoxIcon.Exclamation: - return SystemIcons.Exclamation; - case MessageBoxIcon.Question: - return SystemIcons.Question; - default: - return null; - } - } - - } -} \ No newline at end of file diff --git a/Tools/ArdupilotMegaPlanner/Utility.cs b/Tools/ArdupilotMegaPlanner/Utility.cs deleted file mode 100644 index 4c807daf90..0000000000 --- a/Tools/ArdupilotMegaPlanner/Utility.cs +++ /dev/null @@ -1,64 +0,0 @@ -//this file contains some simple extension methods - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Globalization; -using System.ComponentModel; -using System.Windows.Forms; - -namespace ArdupilotMega -{ - static class CultureInfoEx - { - public static CultureInfo GetCultureInfo(string name) - { - try { return new CultureInfo(name); } - catch (Exception) { return null; } - } - - public static bool IsChildOf(this CultureInfo cX, CultureInfo cY) - { - - if (cX == null || cY == null) - return false; - - CultureInfo c = cX; - while (!c.Equals(CultureInfo.InvariantCulture)) - { - if (c.Equals(cY)) - return true; - c = c.Parent; - } - return false; - } - } - - static class ComponentResourceManagerEx - { - public static void ApplyResource(this ComponentResourceManager rm, Control ctrl) - { - rm.ApplyResources(ctrl, ctrl.Name); - foreach (Control subctrl in ctrl.Controls) - ApplyResource(rm, subctrl); - - if (ctrl.ContextMenu != null) - ApplyResource(rm, ctrl.ContextMenu); - - - if (ctrl is DataGridView) - { - foreach (DataGridViewColumn col in (ctrl as DataGridView).Columns) - rm.ApplyResources(col, col.Name); - } - } - - public static void ApplyResource(this ComponentResourceManager rm, Menu menu) - { - rm.ApplyResources(menu, menu.Name); - foreach (MenuItem submenu in menu.MenuItems) - ApplyResource(rm, submenu); - } - } -} From 6c3cf9ad5bf6a31a110afd3b2763510fee357246 Mon Sep 17 00:00:00 2001 From: rmackay9 Date: Sun, 4 Mar 2012 18:21:52 +0900 Subject: [PATCH 005/178] AP_RC - removed unused library --- libraries/AP_RC/AP_RC.cpp | 247 ----------------------- libraries/AP_RC/AP_RC.h | 16 -- libraries/AP_RC/examples/AP_RC/AP_RC.pde | 46 ----- libraries/AP_RC/examples/AP_RC/Makefile | 2 - 4 files changed, 311 deletions(-) delete mode 100644 libraries/AP_RC/AP_RC.cpp delete mode 100644 libraries/AP_RC/AP_RC.h delete mode 100644 libraries/AP_RC/examples/AP_RC/AP_RC.pde delete mode 100644 libraries/AP_RC/examples/AP_RC/Makefile diff --git a/libraries/AP_RC/AP_RC.cpp b/libraries/AP_RC/AP_RC.cpp deleted file mode 100644 index ee20c5f1e0..0000000000 --- a/libraries/AP_RC/AP_RC.cpp +++ /dev/null @@ -1,247 +0,0 @@ -/* - AP_RC.cpp - Radio library for Arduino - Code by Jason Short. DIYDrones.com - - This library is free software; you can redistribute it and / or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - -*/ - -#include "AP_RC.h" -#include -#if defined(ARDUINO) && ARDUINO >= 100 - #include "Arduino.h" -#else - #include "WProgram.h" -#endif - -// Variable definition for interrupt -volatile uint16_t timer1count = 0; -volatile uint16_t timer2count = 0; -volatile uint16_t timer3count = 0; -volatile uint16_t timer4count = 0; - -volatile int16_t timer1diff = 1500 * 2; -volatile int16_t timer2diff = 1500 * 2; -volatile int16_t timer3diff = 1100 * 2; -volatile int16_t timer4diff = 1500 * 2; - -//volatile uint16_t raw[8]; -#define CH1_READ 1 -#define CH2_READ 2 -#define CH3_READ 4 -#define CH4_READ 8 - -#define CH_1 0 -#define CH_2 1 -#define CH_3 2 -#define CH_4 3 - -volatile int8_t _rc_ch_read; -volatile uint16_t _timer_out; -volatile uint16_t _timer_ovf_a; -volatile uint16_t _timer_ovf_b; -volatile uint16_t _timer_ovf; - - -AP_RC::AP_RC() -{ - pinMode(2,INPUT); // PD2 - INT0 - CH 1 in - pinMode(3,INPUT); // PD3 - INT1 - CH 2 in - pinMode(11,INPUT); // PB3 - MOSI/OC2 - CH 3 in - pinMode(13,INPUT); // PB5 - SCK - CH 4 in - - pinMode(10,OUTPUT); // PB2 - OC1B - CH 1 out - pinMode(8, OUTPUT); // PB0 - AIN1 - CH 3 out - pinMode(9, OUTPUT); // PB1 - OC1A - CH 2 out - DDRC |= B00010000; // PC4 - - CH 4 out -} - -void -AP_RC::init() -{ - // enable pin change interrupt 2 - PCINT23..16 - PCICR = _BV(PCIE2); - // enable pin change interrupt 0 - PCINT7..0 - PCICR |= _BV(PCIE0); - // enable in change interrupt on PB5 (digital pin 13) - PCMSK0 = _BV(PCINT3) | _BV(PCINT5); - // enable pin change interrupt on PD2,PD3 (digital pin 2,3) - PCMSK2 = _BV(PCINT18) | _BV(PCINT19); - - // Timer 1 - TCCR1A = ((1 << WGM11) | (1 << COM1B1) | (1 << COM1A1)); - TCCR1B = (1 << WGM13) | (1 << WGM12) | (1 << CS11); - // Loop value - ICR1 = 40000; - - // Throttle; - // Setting up the Timer 2 - 8 bit timer - TCCR2A = 0x0; // Normal Mode - TCCR2B = _BV(CS21) |_BV(CS20); //prescaler 32, at 16mhz (32/16) = 2, the counter will increment 1 every 2us - - // enable throttle and Ch4 output - TIMSK1 |= _BV(ICIE1); // Timer / Counter1, Input Capture Interrupt Enable // PB0 - output throttle - TIMSK2 = _BV(TOIE1) | _BV(OCIE2A) | _BV(OCIE2B); // Timer / Counter2 Compare Match A - - /* - set_ch_pwm(0, 1500); - set_ch_pwm(1, 1500); - set_ch_pwm(2, 1500); - set_ch_pwm(3, 1500); - */ -} - -uint16_t -AP_RC::input_ch(uint8_t ch) -{ - switch(ch){ - case CH_1: - return timer1diff; - break; - - case CH_2: - return timer2diff; - break; - - case CH_3: - return timer3diff; - break; - - case CH_4: - return timer4diff; - break; - } -} - -void -AP_RC::output_ch_pwm(uint8_t ch, uint16_t pwm) -{ - switch(ch){ - case CH_1: - pwm <<= 1; // multiplies by 2 - OCR1A = pwm; - break; - - case CH_2: - pwm <<= 1; - OCR1B = pwm; // multiplies by 2 - break; - - case CH_3: - _timer_out = pwm % 512; - _timer_ovf_a = pwm / 512; - _timer_out >>= 1; // divides by 2 - //OCR2A = _timer_out; - if(OCR2A != _timer_out) - OCR2A = _timer_out; - - break; - - case CH_4: - _timer_out = pwm % 512; - _timer_ovf_b = pwm / 512; - _timer_out >>= 1; // divides by 2 - //OCR2B = _timer_out; - if(OCR2B != _timer_out) - OCR2B = _timer_out; - - break; - } -} - - - -// radio PWM input timers -ISR(PCINT2_vect) { - int cnt = TCNT1; - if(PIND & B00000100){ // ch 1 (pin 2) is high - if ((_rc_ch_read & CH1_READ) != CH1_READ){ - _rc_ch_read |= CH1_READ; - timer1count = cnt; - } - }else if ((_rc_ch_read & CH1_READ) == CH1_READ){ // ch 1 (pin 2) is Low, and we were reading - _rc_ch_read &= B11111110; - if (cnt < timer1count) // Timer1 reset during the read of this pulse - timer1diff = (cnt + 40000 - timer1count) >> 1; // Timer1 TOP = 40000 - else - timer1diff = (cnt - timer1count) >> 1; - } - - if(PIND & B00001000){ // ch 2 (pin 3) is high - if ((_rc_ch_read & CH2_READ) != CH2_READ){ - _rc_ch_read |= CH2_READ; - timer2count = cnt; - } - }else if ((_rc_ch_read & CH2_READ) == CH2_READ){ // ch 1 (pin 2) is Low - _rc_ch_read &= B11111101; - if (cnt < timer2count) // Timer1 reset during the read of this pulse - timer2diff = (cnt + 40000 - timer2count) >> 1; // Timer1 TOP = 40000 - else - timer2diff = (cnt - timer2count) >> 1; - } -} - -ISR(PCINT0_vect) -{ - int cnt = TCNT1; - if(PINB & 8){ // pin 11 - if ((_rc_ch_read & CH3_READ) != CH3_READ){ - _rc_ch_read |= CH3_READ; - timer3count = cnt; - } - }else if ((_rc_ch_read & CH3_READ) == CH3_READ){ // ch 1 (pin 2) is Low - _rc_ch_read &= B11111011; - if (cnt < timer3count) // Timer1 reset during the read of this pulse - timer3diff = (cnt + 40000 - timer3count) >> 1; // Timer1 TOP = 40000 - else - timer3diff = (cnt - timer3count) >> 1; - } - - if(PINB & 32){ // pin 13 - if ((_rc_ch_read & CH4_READ) != CH4_READ){ - _rc_ch_read |= CH4_READ; - timer4count = cnt; - } - }else if ((_rc_ch_read & CH4_READ) == CH4_READ){ // ch 1 (pin 2) is Low - _rc_ch_read &= B11110111; - if (cnt < timer4count) // Timer1 reset during the read of this pulse - timer4diff = (cnt + 40000 - timer4count) >> 1; // Timer1 TOP = 40000 - else - timer4diff = (cnt - timer4count) >> 1; - } -} - - - -// Throttle Timer Interrupt -// ------------------------ -ISR(TIMER1_CAPT_vect) // Timer/Counter1 Capture Event -{ - //This is a timer 1 interrupts, executed every 20us - PORTB |= B00000001; //Putting the pin high! - PORTC |= B00010000; //Putting the pin high! - TCNT2 = 0; //restarting the counter of timer 2 - _timer_ovf = 0; -} - -ISR(TIMER2_OVF_vect) -{ - _timer_ovf++; -} - -ISR(TIMER2_COMPA_vect) // Timer/Counter2 Compare Match A -{ - if(_timer_ovf == _timer_ovf_a){ - PORTB &= B11111110; //Putting the pin low - } -} - -ISR(TIMER2_COMPB_vect) // Timer/Counter2 Compare Match B Rudder Servo -{ - if(_timer_ovf == _timer_ovf_b){ - PORTC &= B11101111; //Putting the pin low! - } -} \ No newline at end of file diff --git a/libraries/AP_RC/AP_RC.h b/libraries/AP_RC/AP_RC.h deleted file mode 100644 index 1bef703a1a..0000000000 --- a/libraries/AP_RC/AP_RC.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef AP_RC_h -#define AP_RC_h - -#include - -class AP_RC -{ - private: - public: - AP_RC(); - void init(); - void output_ch_pwm(uint8_t ch, uint16_t pwm); - uint16_t input_ch(uint8_t ch); -}; - -#endif diff --git a/libraries/AP_RC/examples/AP_RC/AP_RC.pde b/libraries/AP_RC/examples/AP_RC/AP_RC.pde deleted file mode 100644 index 9ddf4a4a9f..0000000000 --- a/libraries/AP_RC/examples/AP_RC/AP_RC.pde +++ /dev/null @@ -1,46 +0,0 @@ -/* - Example of AP_RC library. - Code by Jason Short. DIYDrones.com -*/ - -#include // ArduPilot RC Library -AP_RC rc; - -#define CH_ROLL 0 -#define CH_PITCH 1 -#define CH_THROTTLE 2 -#define CH_RUDDER 3 - -int radio_in[4]; - -void setup() -{ - Serial.begin(38400); - Serial.println("ArduPilot RC library test"); - rc.init(); - delay(1000); -} - -void loop() -{ - delay(20); - for(int y = 0; y < 4; y++) { - radio_in[y] = rc.input_ch(y); - } - for(int y = 0; y < 4; y++) { - rc.output_ch_pwm(y, radio_in[y]); // send to Servos - } - print_pwm(); -} - -void print_pwm() -{ - Serial.print("ch1 "); - Serial.print(radio_in[CH_ROLL], DEC); - Serial.print("\tch2: "); - Serial.print(radio_in[CH_PITCH], DEC); - Serial.print("\tch3 :"); - Serial.print(radio_in[CH_THROTTLE], DEC); - Serial.print("\tch4 :"); - Serial.println(radio_in[CH_RUDDER], DEC); -} \ No newline at end of file diff --git a/libraries/AP_RC/examples/AP_RC/Makefile b/libraries/AP_RC/examples/AP_RC/Makefile deleted file mode 100644 index 85b4d8856b..0000000000 --- a/libraries/AP_RC/examples/AP_RC/Makefile +++ /dev/null @@ -1,2 +0,0 @@ -BOARD = mega -include ../../../AP_Common/Arduino.mk From 46d7da4d14aaf6113924ffb3f8a922a22b0b133f Mon Sep 17 00:00:00 2001 From: Jason Short Date: Mon, 5 Mar 2012 22:12:53 -0800 Subject: [PATCH 006/178] Added define for throttle range for altitude changes, updated it to 250 --- ArduCopter/ArduCopter.pde | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/ArduCopter/ArduCopter.pde b/ArduCopter/ArduCopter.pde index d7b95c700e..f59fe98a26 100644 --- a/ArduCopter/ArduCopter.pde +++ b/ArduCopter/ArduCopter.pde @@ -1949,20 +1949,20 @@ static void update_altitude() next_WP.alt = get_new_altitude(); } +#define THROTTLE_ADJUST 250 static void adjust_altitude() { - if(g.rc_3.control_in <= (MINIMUM_THROTTLE + 100)){ + if(g.rc_3.control_in <= (MINIMUM_THROTTLE + THROTTLE_ADJUST)){ // we remove 0 to 100 PWM from hover - manual_boost = (g.rc_3.control_in - MINIMUM_THROTTLE) -100; - manual_boost = max(-100, manual_boost); - update_throttle_cruise(); + manual_boost = (g.rc_3.control_in - MINIMUM_THROTTLE) - THROTTLE_ADJUST; + manual_boost = max(-THROTTLE_ADJUST, manual_boost); - }else if (g.rc_3.control_in >= (MAXIMUM_THROTTLE - 100)){ + }else if (g.rc_3.control_in >= (MAXIMUM_THROTTLE - THROTTLE_ADJUST)){ // we add 0 to 100 PWM to hover - manual_boost = g.rc_3.control_in - (MAXIMUM_THROTTLE - 100); - manual_boost = min(100, manual_boost); - update_throttle_cruise(); + manual_boost = g.rc_3.control_in - (MAXIMUM_THROTTLE - THROTTLE_ADJUST); + manual_boost = min(THROTTLE_ADJUST, manual_boost); + }else { manual_boost = 0; } From 7f47640b9233d77a3a3abea2475b2be6df9d67c1 Mon Sep 17 00:00:00 2001 From: Michael Oborne Date: Tue, 6 Mar 2012 18:27:43 +0800 Subject: [PATCH 007/178] APM Planner 1.1.49 mode TUNE_ param scale add mavlink tlog graphing mod tracker options --- .../Antenna/Tracker.Designer.cs | 39 +- Tools/ArdupilotMegaPlanner/Antenna/Tracker.cs | 20 + .../ArdupilotMegaPlanner/ArdupilotMega.csproj | 25 +- .../ArdupilotMega.csproj.user | 2 +- Tools/ArdupilotMegaPlanner/Capture.cs | 2 +- Tools/ArdupilotMegaPlanner/CodeGen.cs | 339 +++ .../Controls/MessageBox.cs | 8 +- .../ArdupilotMegaPlanner/Controls/MyButton.cs | 14 +- .../GCSViews/FlightPlanner.cs | 6 + .../GCSViews/Simulation.cs | 3 - Tools/ArdupilotMegaPlanner/MAVLink.cs | 78 +- Tools/ArdupilotMegaPlanner/MAVLinkTypes0.9.cs | 49 +- Tools/ArdupilotMegaPlanner/MainV2.cs | 35 +- .../MavlinkLog.Designer.cs | 15 + Tools/ArdupilotMegaPlanner/MavlinkLog.cs | 366 ++- Tools/ArdupilotMegaPlanner/MavlinkLog.resx | 51 +- Tools/ArdupilotMegaPlanner/Program.cs | 1 + .../Properties/AssemblyInfo.cs | 2 +- .../Properties/Resources.Designer.cs | 2 +- .../Setup/Setup.Designer.cs | 2 +- Tools/ArdupilotMegaPlanner/Setup/Setup.resx | 2623 ++++------------- Tools/ArdupilotMegaPlanner/ThemeManager.cs | 94 +- .../bin/Release/.gitignore | 3 +- .../bin/Release/ArdupilotMegaPlanner.pdb | Bin 984576 -> 1000960 bytes Tools/ArdupilotMegaPlanner/mavlinklist.pl | 2 +- 25 files changed, 1483 insertions(+), 2298 deletions(-) create mode 100644 Tools/ArdupilotMegaPlanner/CodeGen.cs diff --git a/Tools/ArdupilotMegaPlanner/Antenna/Tracker.Designer.cs b/Tools/ArdupilotMegaPlanner/Antenna/Tracker.Designer.cs index 361db2dea5..fd998debfe 100644 --- a/Tools/ArdupilotMegaPlanner/Antenna/Tracker.Designer.cs +++ b/Tools/ArdupilotMegaPlanner/Antenna/Tracker.Designer.cs @@ -84,7 +84,7 @@ this.CMB_baudrate.Location = new System.Drawing.Point(337, 9); this.CMB_baudrate.Name = "CMB_baudrate"; this.CMB_baudrate.Size = new System.Drawing.Size(121, 21); - this.CMB_baudrate.TabIndex = 5; + this.CMB_baudrate.TabIndex = 2; // // CMB_serialport // @@ -93,14 +93,14 @@ this.CMB_serialport.Location = new System.Drawing.Point(210, 10); this.CMB_serialport.Name = "CMB_serialport"; this.CMB_serialport.Size = new System.Drawing.Size(121, 21); - this.CMB_serialport.TabIndex = 3; + this.CMB_serialport.TabIndex = 1; // // BUT_connect // this.BUT_connect.Location = new System.Drawing.Point(476, 9); this.BUT_connect.Name = "BUT_connect"; this.BUT_connect.Size = new System.Drawing.Size(75, 23); - this.BUT_connect.TabIndex = 4; + this.BUT_connect.TabIndex = 3; this.BUT_connect.Text = "Connect"; this.BUT_connect.UseVisualStyleBackColor = true; this.BUT_connect.Click += new System.EventHandler(this.BUT_connect_Click); @@ -108,11 +108,12 @@ // TRK_pantrim // this.TRK_pantrim.Location = new System.Drawing.Point(153, 65); - this.TRK_pantrim.Maximum = 180; - this.TRK_pantrim.Minimum = -180; + this.TRK_pantrim.Maximum = 90; + this.TRK_pantrim.Minimum = -90; this.TRK_pantrim.Name = "TRK_pantrim"; this.TRK_pantrim.Size = new System.Drawing.Size(375, 45); - this.TRK_pantrim.TabIndex = 6; + this.TRK_pantrim.TabIndex = 5; + this.TRK_pantrim.TickFrequency = 5; this.TRK_pantrim.Scroll += new System.EventHandler(this.TRK_pantrim_Scroll); // // TXT_panrange @@ -120,17 +121,18 @@ this.TXT_panrange.Location = new System.Drawing.Point(83, 65); this.TXT_panrange.Name = "TXT_panrange"; this.TXT_panrange.Size = new System.Drawing.Size(64, 20); - this.TXT_panrange.TabIndex = 7; + this.TXT_panrange.TabIndex = 4; this.TXT_panrange.Text = "180"; + this.TXT_panrange.TextChanged += new System.EventHandler(this.TXT_panrange_TextChanged); // // label3 // this.label3.AutoSize = true; - this.label3.Location = new System.Drawing.Point(331, 49); + this.label3.Location = new System.Drawing.Point(326, 49); this.label3.Name = "label3"; - this.label3.Size = new System.Drawing.Size(38, 13); + this.label3.Size = new System.Drawing.Size(27, 13); this.label3.TabIndex = 10; - this.label3.Text = "Center"; + this.label3.Text = "Trim"; // // label4 // @@ -153,29 +155,30 @@ // label6 // this.label6.AutoSize = true; - this.label6.Location = new System.Drawing.Point(331, 125); + this.label6.Location = new System.Drawing.Point(326, 125); this.label6.Name = "label6"; - this.label6.Size = new System.Drawing.Size(38, 13); + this.label6.Size = new System.Drawing.Size(27, 13); this.label6.TabIndex = 16; - this.label6.Text = "Center"; + this.label6.Text = "Trim"; // // TXT_tiltrange // this.TXT_tiltrange.Location = new System.Drawing.Point(83, 141); this.TXT_tiltrange.Name = "TXT_tiltrange"; this.TXT_tiltrange.Size = new System.Drawing.Size(64, 20); - this.TXT_tiltrange.TabIndex = 13; + this.TXT_tiltrange.TabIndex = 6; this.TXT_tiltrange.Text = "90"; + this.TXT_tiltrange.TextChanged += new System.EventHandler(this.TXT_tiltrange_TextChanged); // // TRK_tilttrim // this.TRK_tilttrim.Location = new System.Drawing.Point(153, 141); - this.TRK_tilttrim.Maximum = 90; - this.TRK_tilttrim.Minimum = -90; + this.TRK_tilttrim.Maximum = 45; + this.TRK_tilttrim.Minimum = -45; this.TRK_tilttrim.Name = "TRK_tilttrim"; this.TRK_tilttrim.Size = new System.Drawing.Size(375, 45); - this.TRK_tilttrim.TabIndex = 12; - this.TRK_tilttrim.Value = 45; + this.TRK_tilttrim.TabIndex = 7; + this.TRK_tilttrim.TickFrequency = 5; this.TRK_tilttrim.Scroll += new System.EventHandler(this.TRK_tilttrim_Scroll); // // label2 diff --git a/Tools/ArdupilotMegaPlanner/Antenna/Tracker.cs b/Tools/ArdupilotMegaPlanner/Antenna/Tracker.cs index 80114f674e..65f2f8c242 100644 --- a/Tools/ArdupilotMegaPlanner/Antenna/Tracker.cs +++ b/Tools/ArdupilotMegaPlanner/Antenna/Tracker.cs @@ -111,5 +111,25 @@ namespace ArdupilotMega.Antenna if (tracker != null) tracker.TrimTilt = TRK_tilttrim.Value; } + + private void TXT_panrange_TextChanged(object sender, EventArgs e) + { + int range; + + int.TryParse(TXT_panrange.Text, out range); + + TRK_pantrim.Minimum = range / 2 * -1; + TRK_pantrim.Maximum = range / 2; + } + + private void TXT_tiltrange_TextChanged(object sender, EventArgs e) + { + int range; + + int.TryParse(TXT_tiltrange.Text, out range); + + TRK_tilttrim.Minimum = range / 2 * -1; + TRK_tilttrim.Maximum = range / 2; + } } } diff --git a/Tools/ArdupilotMegaPlanner/ArdupilotMega.csproj b/Tools/ArdupilotMegaPlanner/ArdupilotMega.csproj index d059812cba..2846b45652 100644 --- a/Tools/ArdupilotMegaPlanner/ArdupilotMega.csproj +++ b/Tools/ArdupilotMegaPlanner/ArdupilotMega.csproj @@ -120,82 +120,60 @@ False - Lib\alglibnet2.dll - ..\..\..\..\..\Desktop\DIYDrones\myquad\greatmaps_e1bb830a18a3\Demo.WindowsForms\bin\Debug\BSE.Windows.Forms.dll - ..\..\..\..\..\Desktop\DIYDrones\kml-library\KmlTestbed\bin\Release\Core.dll - ..\..\..\..\..\Desktop\DIYDrones\myquad\DirectShowLib-2005.dll - ..\..\..\..\..\Desktop\DIYDrones\myquad\greatmaps_e1bb830a18a3\GMap.NET.WindowsForms\bin\Debug\GMap.NET.Core.dll - ..\..\..\..\..\Desktop\DIYDrones\myquad\greatmaps_e1bb830a18a3\GMap.NET.WindowsForms\bin\Debug\GMap.NET.WindowsForms.dll - ..\..\..\..\..\Desktop\DIYDrones\SrcSamples\bin\ICSharpCode.SharpZipLib.dll False - ..\..\..\..\..\..\..\Program Files (x86)\IronPython 2.7.1\IronPython-2.6.1\IronPython.dll False - ..\..\..\..\..\..\..\Program Files (x86)\IronPython 2.7.1\IronPython-2.6.1\IronPython.Modules.dll - ..\..\..\..\..\Desktop\DIYDrones\kml-library\KmlTestbed\bin\Release\KMLib.dll False - Lib\log4net.dll - ..\..\..\..\..\Desktop\DIYDrones\myquad\MetaDataExtractorCSharp240d\bin\Release\MetaDataExtractor.dll False - ..\..\..\..\..\..\..\Windows\Microsoft.NET\DirectX for Managed Code\1.0.2902.0\Microsoft.DirectX.dll False False - ..\..\..\..\..\..\..\Windows\Microsoft.NET\DirectX for Managed Code\1.0.2902.0\Microsoft.DirectX.DirectInput.dll False - ..\..\..\..\..\..\..\Program Files (x86)\IronPython 2.7.1\IronPython-2.6.1\Microsoft.Dynamic.dll False - ..\..\..\..\..\..\..\Program Files (x86)\IronPython 2.7.1\IronPython-2.6.1\Microsoft.Scripting.dll - ..\..\..\..\..\..\..\Program Files (x86)\IronPython 2.7.1\IronPython-2.6.1\Microsoft.Scripting.Core.dll - ..\..\..\..\..\..\..\Program Files (x86)\IronPython 2.7.1\IronPython-2.6.1\Microsoft.Scripting.Debugging.dll False - ..\..\..\..\..\..\..\Program Files (x86)\IronPython 2.7.1\IronPython-2.6.1\Microsoft.Scripting.ExtensionAttribute.dll False - ..\..\..\..\..\Desktop\DIYDrones\virtualglobebook-OpenGlobe-ddf1d7e\ThirdParty\OpenTKGL4\Binaries\OpenTK\Release\OpenTK.dll False - ..\..\..\..\..\Desktop\DIYDrones\opentk\trunk\Binaries\OpenTK\Release\OpenTK.GLControl.dll False - ..\..\..\..\..\Desktop\DIYDrones\myquad\sharpkml\SharpKml\bin\Release\SharpKml.dll False @@ -207,7 +185,6 @@ False - ..\..\..\..\..\Desktop\DIYDrones\myquad\greatmaps_e1bb830a18a3\Demo.WindowsForms\bin\Debug\x86\System.Data.SQLite.DLL False @@ -229,7 +206,6 @@ False - ..\..\ArdupilotSim\ArdupilotSim\bin\Release\ZedGraph.dll @@ -241,6 +217,7 @@ Tracker.cs + Form diff --git a/Tools/ArdupilotMegaPlanner/ArdupilotMega.csproj.user b/Tools/ArdupilotMegaPlanner/ArdupilotMega.csproj.user index 496c214467..730cb9c526 100644 --- a/Tools/ArdupilotMegaPlanner/ArdupilotMega.csproj.user +++ b/Tools/ArdupilotMegaPlanner/ArdupilotMega.csproj.user @@ -11,6 +11,6 @@ - C:\Users\hog\Desktop\DIYDrones\myquad\greatmaps_e1bb830a18a3\Demo.WindowsForms\bin\Debug\;C:\Users\hog\Desktop\DIYDrones\myquad\sharpkml\SharpKml\bin\Release\;C:\Users\hog\Desktop\DIYDrones\myquad\MetaDataExtractorCSharp240d\bin\Release\;C:\Users\hog\Documents\Visual Studio 2010\Projects\ArdupilotMega\ArdupilotMega\Lib\ + C:\Users\hog\Documents\Visual Studio 2010\Projects\ArdupilotMega\ArdupilotMega\Lib\;C:\Users\hog\Desktop\DIYDrones\myquad\greatmaps_e1bb830a18a3\Demo.WindowsForms\bin\Debug\;C:\Users\hog\Desktop\DIYDrones\myquad\sharpkml\SharpKml\bin\Release\;C:\Users\hog\Desktop\DIYDrones\myquad\MetaDataExtractorCSharp240d\bin\Release\ \ No newline at end of file diff --git a/Tools/ArdupilotMegaPlanner/Capture.cs b/Tools/ArdupilotMegaPlanner/Capture.cs index 87596b04ba..bb1c5b0863 100644 --- a/Tools/ArdupilotMegaPlanner/Capture.cs +++ b/Tools/ArdupilotMegaPlanner/Capture.cs @@ -157,7 +157,7 @@ namespace WebCamService Start(); // Start waiting - if ( ! m_PictureReady.WaitOne(5000, false) ) + if ( ! m_PictureReady.WaitOne(2000, false) ) { throw new Exception("Timeout waiting to get picture"); } diff --git a/Tools/ArdupilotMegaPlanner/CodeGen.cs b/Tools/ArdupilotMegaPlanner/CodeGen.cs new file mode 100644 index 0000000000..f3faeaca2a --- /dev/null +++ b/Tools/ArdupilotMegaPlanner/CodeGen.cs @@ -0,0 +1,339 @@ +using System; +using System.Text; +using System.Drawing; +using System.Collections; +using System.ComponentModel; +using System.Windows.Forms; +using System.Data; +using System.CodeDom; +using Microsoft.CSharp; +using System.CodeDom.Compiler; +using System.Reflection; +using System.IO; +using System.Text.RegularExpressions; + +namespace ArdupilotMega +{ + static class CodeGen + { + public static string runCode(string code) + { + string answer = ""; + + GetMathMemberNames(); + + // change evaluation string to pick up Math class members + string expression = RefineEvaluationString(code); + + // build the class using codedom + BuildClass(expression); + + // compile the class into an in-memory assembly. + // if it doesn't compile, show errors in the window + CompilerResults results = CompileAssembly(); + + Console.WriteLine("...........................\r\n"); + Console.WriteLine(_source.ToString()); + + // if the code compiled okay, + // run the code using the new assembly (which is inside the results) + if (results != null && results.CompiledAssembly != null) + { + // run the evaluation function + answer = RunCode(results); + } + else + { + } + + return answer; + } + + static ICodeCompiler CreateCompiler() + { + //Create an instance of the C# compiler + CodeDomProvider codeProvider = null; + codeProvider = new CSharpCodeProvider(); + ICodeCompiler compiler = codeProvider.CreateCompiler(); + return compiler; + } + + /// + /// Creawte parameters for compiling + /// + /// + static CompilerParameters CreateCompilerParameters() + { + //add compiler parameters and assembly references + CompilerParameters compilerParams = new CompilerParameters(); + compilerParams.CompilerOptions = "/target:library /optimize"; + compilerParams.GenerateExecutable = false; + compilerParams.GenerateInMemory = true; + compilerParams.IncludeDebugInformation = false; + compilerParams.ReferencedAssemblies.Add("mscorlib.dll"); + compilerParams.ReferencedAssemblies.Add("System.dll"); + compilerParams.ReferencedAssemblies.Add("System.Windows.Forms.dll"); + + //add any aditional references needed + // foreach (string refAssembly in code.References) + // compilerParams.ReferencedAssemblies.Add(refAssembly); + + return compilerParams; + } + + /// + /// Compiles the code from the code string + /// + /// + /// + /// + /// + static private CompilerResults CompileCode(ICodeCompiler compiler, CompilerParameters parms, string source) + { + //actually compile the code + CompilerResults results = compiler.CompileAssemblyFromSource( + parms, source); + + //Do we have any compiler errors? + if (results.Errors.Count > 0) + { + foreach (CompilerError error in results.Errors) + Console.WriteLine("Compile Error:" + error.ErrorText); + return null; + } + + return results; + } + + /// + /// Need to change eval string to use .NET Math library + /// + /// evaluation expression + /// + static string RefineEvaluationString(string eval) + { + // look for regular expressions with only letters + Regex regularExpression = new Regex("[a-zA-Z_]+"); + + // track all functions and constants in the evaluation expression we already replaced + ArrayList replacelist = new ArrayList(); + + // find all alpha words inside the evaluation function that are possible functions + MatchCollection matches = regularExpression.Matches(eval); + foreach (Match m in matches) + { + // if the word is found in the math member map, add a Math prefix to it + bool isContainedInMathLibrary = _mathMembersMap[m.Value.ToUpper()] != null; + if (replacelist.Contains(m.Value) == false && isContainedInMathLibrary) + { + eval = eval.Replace(m.Value, "Math." + _mathMembersMap[m.Value.ToUpper()]); + } + + // we matched it already, so don't allow us to replace it again + replacelist.Add(m.Value); + } + + // return the modified evaluation string + return eval; + } + + /// + /// Compiles the c# into an assembly if there are no syntax errors + /// + /// + static private CompilerResults CompileAssembly() + { + // create a compiler + ICodeCompiler compiler = CreateCompiler(); + // get all the compiler parameters + CompilerParameters parms = CreateCompilerParameters(); + // compile the code into an assembly + CompilerResults results = CompileCode(compiler, parms, _source.ToString()); + return results; + + } + + static ArrayList _mathMembers = new ArrayList(); + static Hashtable _mathMembersMap = new Hashtable(); + + static void GetMathMemberNames() + { + // get a reflected assembly of the System assembly + Assembly systemAssembly = Assembly.GetAssembly(typeof(System.Math)); + try + { + //cant call the entry method if the assembly is null + if (systemAssembly != null) + { + //Use reflection to get a reference to the Math class + + Module[] modules = systemAssembly.GetModules(false); + Type[] types = modules[0].GetTypes(); + + //loop through each class that was defined and look for the first occurrance of the Math class + foreach (Type type in types) + { + if (type.Name == "Math") + { + // get all of the members of the math class and map them to the same member + // name in uppercase + MemberInfo[] mis = type.GetMembers(); + foreach (MemberInfo mi in mis) + { + _mathMembers.Add(mi.Name); + _mathMembersMap[mi.Name.ToUpper()] = mi.Name; + } + } + //if the entry point method does return in Int32, then capture it and return it + } + + + //if it got here, then there was no entry point method defined. Tell user about it + } + } + catch (Exception ex) + { + Console.WriteLine("Error: An exception occurred while executing the script", ex); + } + } + + /// + /// Runs the Calculate method in our on-the-fly assembly + /// + /// + static private string RunCode(CompilerResults results) + { + Assembly executingAssembly = results.CompiledAssembly; + try + { + //cant call the entry method if the assembly is null + if (executingAssembly != null) + { + object assemblyInstance = executingAssembly.CreateInstance("ExpressionEvaluator.Calculator"); + //Use reflection to call the static Main function + + Module[] modules = executingAssembly.GetModules(false); + Type[] types = modules[0].GetTypes(); + + //loop through each class that was defined and look for the first occurrance of the entry point method + foreach (Type type in types) + { + MethodInfo[] mis = type.GetMethods(); + foreach (MethodInfo mi in mis) + { + if (mi.Name == "Calculate") + { + object result = mi.Invoke(assemblyInstance, null); + return result.ToString(); + } + } + } + + } + } + catch (Exception ex) + { + Console.WriteLine("Error: An exception occurred while executing the script", ex); + } + return ""; + } + + + static CodeMemberField FieldVariable(string fieldName, string typeName, MemberAttributes accessLevel) + { + CodeMemberField field = new CodeMemberField(typeName, fieldName); + field.Attributes = accessLevel; + return field; + } + static CodeMemberField FieldVariable(string fieldName, Type type, MemberAttributes accessLevel) + { + CodeMemberField field = new CodeMemberField(type, fieldName); + field.Attributes = accessLevel; + return field; + } + + /// + /// Very simplistic getter/setter properties + /// + /// + /// + /// + /// + static CodeMemberProperty MakeProperty(string propertyName, string internalName, Type type) + { + CodeMemberProperty myProperty = new CodeMemberProperty(); + myProperty.Name = propertyName; + myProperty.Comments.Add(new CodeCommentStatement(String.Format("The {0} property is the returned result", propertyName))); + myProperty.Attributes = MemberAttributes.Public; + myProperty.Type = new CodeTypeReference(type); + myProperty.HasGet = true; + myProperty.GetStatements.Add( + new CodeMethodReturnStatement( + new CodeFieldReferenceExpression(new CodeThisReferenceExpression(), internalName))); + + myProperty.HasSet = true; + myProperty.SetStatements.Add( + new CodeAssignStatement( + new CodeFieldReferenceExpression(new CodeThisReferenceExpression(), internalName), + new CodePropertySetValueReferenceExpression())); + + return myProperty; + } + + + static StringBuilder _source = new StringBuilder(); + + /// + /// Main driving routine for building a class + /// + static void BuildClass(string expression) + { + // need a string to put the code into + _source = new StringBuilder(); + StringWriter sw = new StringWriter(_source); + + //Declare your provider and generator + CSharpCodeProvider codeProvider = new CSharpCodeProvider(); + ICodeGenerator generator = codeProvider.CreateGenerator(sw); + CodeGeneratorOptions codeOpts = new CodeGeneratorOptions(); + + CodeNamespace myNamespace = new CodeNamespace("ExpressionEvaluator"); + myNamespace.Imports.Add(new CodeNamespaceImport("System")); + myNamespace.Imports.Add(new CodeNamespaceImport("System.Windows.Forms")); + + //Build the class declaration and member variables + CodeTypeDeclaration classDeclaration = new CodeTypeDeclaration(); + classDeclaration.IsClass = true; + classDeclaration.Name = "Calculator"; + classDeclaration.Attributes = MemberAttributes.Public; + classDeclaration.Members.Add(FieldVariable("answer", typeof(string), MemberAttributes.Private)); + + //default constructor + CodeConstructor defaultConstructor = new CodeConstructor(); + defaultConstructor.Attributes = MemberAttributes.Public; + defaultConstructor.Comments.Add(new CodeCommentStatement("Default Constructor for class", true)); + defaultConstructor.Statements.Add(new CodeSnippetStatement("//TODO: implement default constructor")); + classDeclaration.Members.Add(defaultConstructor); + + //property + classDeclaration.Members.Add(MakeProperty("Answer", "answer", typeof(string))); + + //Our Calculate Method + CodeMemberMethod myMethod = new CodeMemberMethod(); + myMethod.Name = "Calculate"; + myMethod.ReturnType = new CodeTypeReference(typeof(string)); + myMethod.Comments.Add(new CodeCommentStatement("Calculate an expression", true)); + myMethod.Attributes = MemberAttributes.Public; + myMethod.Statements.Add(new CodeAssignStatement(new CodeSnippetExpression("Object obj"), new CodeSnippetExpression(expression))); + myMethod.Statements.Add(new CodeAssignStatement(new CodeSnippetExpression("Answer"), new CodeSnippetExpression("obj.ToString()"))); + myMethod.Statements.Add( + new CodeMethodReturnStatement(new CodeFieldReferenceExpression(new CodeThisReferenceExpression(), "Answer"))); + classDeclaration.Members.Add(myMethod); + //write code + myNamespace.Types.Add(classDeclaration); + generator.GenerateCodeFromNamespace(myNamespace, sw, codeOpts); + sw.Flush(); + sw.Close(); + } + } +} diff --git a/Tools/ArdupilotMegaPlanner/Controls/MessageBox.cs b/Tools/ArdupilotMegaPlanner/Controls/MessageBox.cs index 53cd628146..8d08925fe1 100644 --- a/Tools/ArdupilotMegaPlanner/Controls/MessageBox.cs +++ b/Tools/ArdupilotMegaPlanner/Controls/MessageBox.cs @@ -7,6 +7,7 @@ using ArdupilotMega; namespace System.Windows.Forms { +#pragma warning disable 414, 3021 public static class MessageBox { const int FORM_Y_MARGIN = 10; @@ -94,7 +95,12 @@ namespace System.Windows.Forms AddButtonsToForm(msgBoxFrm, buttons); - ThemeManager.ApplyThemeTo(msgBoxFrm); + // display even if theme fails + try + { + ThemeManager.ApplyThemeTo(msgBoxFrm); + } + catch { } if (System.Windows.Forms.Application.OpenForms.Count > 0) { diff --git a/Tools/ArdupilotMegaPlanner/Controls/MyButton.cs b/Tools/ArdupilotMegaPlanner/Controls/MyButton.cs index d95acf2373..8eb9d97e84 100644 --- a/Tools/ArdupilotMegaPlanner/Controls/MyButton.cs +++ b/Tools/ArdupilotMegaPlanner/Controls/MyButton.cs @@ -19,6 +19,14 @@ namespace ArdupilotMega bool inOnPaint = false; + public Color BGGradTop = Color.FromArgb(0x94, 0xc1, 0x1f); + + public Color BGGradBot = Color.FromArgb(0xcd, 0xe2, 0x96); + + public new Color ForeColor = Color.FromArgb(0x40, 0x57, 0x04); + + public Color Outline = Color.FromArgb(0x79, 0x94, 0x29); + protected override void OnPaint(PaintEventArgs pevent) { //base.OnPaint(pevent); @@ -36,9 +44,9 @@ namespace ArdupilotMega Rectangle outside = new Rectangle(0, 0, this.Width, this.Height); - LinearGradientBrush linear = new LinearGradientBrush(outside, Color.FromArgb(0x94, 0xc1, 0x1f), Color.FromArgb(0xcd, 0xe2, 0x96), LinearGradientMode.Vertical); + LinearGradientBrush linear = new LinearGradientBrush(outside, BGGradTop, BGGradBot, LinearGradientMode.Vertical); - Pen mypen = new Pen(Color.FromArgb(0x79, 0x94, 0x29), 2); + Pen mypen = new Pen(Outline, 2); /* gr.FillRectangle(new SolidBrush(Color.FromArgb(0x26, 0x27, 0x28)), outside); @@ -71,7 +79,7 @@ namespace ArdupilotMega gr.DrawRectangle(mypen, outside); - SolidBrush mybrush = new SolidBrush(Color.FromArgb(0x40, 0x57, 0x04)); + SolidBrush mybrush = new SolidBrush(ForeColor); if (mouseover) { diff --git a/Tools/ArdupilotMegaPlanner/GCSViews/FlightPlanner.cs b/Tools/ArdupilotMegaPlanner/GCSViews/FlightPlanner.cs index d615283bad..5aac614ce6 100644 --- a/Tools/ArdupilotMegaPlanner/GCSViews/FlightPlanner.cs +++ b/Tools/ArdupilotMegaPlanner/GCSViews/FlightPlanner.cs @@ -1427,6 +1427,12 @@ namespace ArdupilotMega.GCSViews quickadd = true; Commands.Rows.Clear(); + if (cmds.Count == 0) + { + quickadd = false; + return; + } + int i = -1; foreach (Locationwp temp in cmds) { diff --git a/Tools/ArdupilotMegaPlanner/GCSViews/Simulation.cs b/Tools/ArdupilotMegaPlanner/GCSViews/Simulation.cs index 988580f1b9..6a313ca07d 100644 --- a/Tools/ArdupilotMegaPlanner/GCSViews/Simulation.cs +++ b/Tools/ArdupilotMegaPlanner/GCSViews/Simulation.cs @@ -439,9 +439,6 @@ namespace ArdupilotMega.GCSViews } } } - - - } FGNetFDM lastfdmdata = new FGNetFDM(); diff --git a/Tools/ArdupilotMegaPlanner/MAVLink.cs b/Tools/ArdupilotMegaPlanner/MAVLink.cs index 0f66e80614..576cdead7f 100644 --- a/Tools/ArdupilotMegaPlanner/MAVLink.cs +++ b/Tools/ArdupilotMegaPlanner/MAVLink.cs @@ -734,6 +734,17 @@ namespace ArdupilotMega value *= 100.0f; } } + else if (paramname.ToUpper().StartsWith("TUNE_")) + { + if (fromapm) + { + value /= 1000.0f; + } + else + { + value *= 1000.0f; + } + } } /// @@ -1440,7 +1451,18 @@ namespace ArdupilotMega public object DebugPacket(byte[] datin) { string text = ""; - return DebugPacket(datin, ref text); + return DebugPacket(datin, ref text,true); + } + + public object DebugPacket(byte[] datin, bool PrintToConsole) + { + string text = ""; + return DebugPacket(datin, ref text, PrintToConsole); + } + + public object DebugPacket(byte[] datin, ref string text) + { + return DebugPacket(datin, ref text, true); } /// @@ -1448,7 +1470,7 @@ namespace ArdupilotMega /// /// packet byte array /// struct of data - public object DebugPacket(byte[] datin, ref string text) + public object DebugPacket(byte[] datin, ref string text, bool PrintToConsole) { string textoutput; try @@ -1470,34 +1492,46 @@ namespace ArdupilotMega Type test = data.GetType(); - textoutput = textoutput + test.Name + " "; - - foreach (var field in test.GetFields()) + if (PrintToConsole) { - // field.Name has the field's name. - object fieldValue = field.GetValue(data); // Get value + textoutput = textoutput + test.Name + " "; - if (field.FieldType.IsArray) + foreach (var field in test.GetFields()) { - textoutput = textoutput + field.Name + "="; - byte[] crap = (byte[])fieldValue; - foreach (byte fiel in crap) + // field.Name has the field's name. + + object fieldValue = field.GetValue(data); // Get value + + if (field.FieldType.IsArray) { - textoutput = textoutput + fiel + ","; + textoutput = textoutput + field.Name + "="; + byte[] crap = (byte[])fieldValue; + foreach (byte fiel in crap) + { + if (fiel == 0) + { + break; + } + else + { + textoutput = textoutput + (char)fiel; + } + } + textoutput = textoutput + " "; + } + else + { + textoutput = textoutput + field.Name + "=" + fieldValue.ToString() + " "; } - textoutput = textoutput + " "; } - else - { - textoutput = textoutput + field.Name + "=" + fieldValue.ToString() + " "; - } - } - textoutput = textoutput + " Len:" + datin.Length + "\r\n"; - Console.Write(textoutput); + textoutput = textoutput + " Len:" + datin.Length + "\r\n"; + if (PrintToConsole) + Console.Write(textoutput); - if (text != null) - text = textoutput; + if (text != null) + text = textoutput; + } return data; } diff --git a/Tools/ArdupilotMegaPlanner/MAVLinkTypes0.9.cs b/Tools/ArdupilotMegaPlanner/MAVLinkTypes0.9.cs index be128df151..73d32cf4b8 100644 --- a/Tools/ArdupilotMegaPlanner/MAVLinkTypes0.9.cs +++ b/Tools/ArdupilotMegaPlanner/MAVLinkTypes0.9.cs @@ -5,11 +5,11 @@ using System.Runtime.InteropServices; namespace ArdupilotMega { -#if !MAVLINK10 + #if !MAVLINK10 partial class MAVLink { - public byte[] MAVLINK_MESSAGE_LENGTHS = new byte[] {3, 4, 8, 14, 8, 28, 3, 32, 0, 2, 3, 2, 2, 0, 0, 0, 0, 0, 0, 0, 19, 2, 23, 21, 0, 37, 26, 101, 26, 16, 32, 32, 37, 32, 11, 17, 17, 16, 18, 36, 4, 4, 2, 2, 4, 2, 2, 3, 14, 12, 18, 16, 8, 27, 25, 18, 18, 24, 24, 0, 0, 0, 26, 16, 36, 5, 6, 56, 26, 21, 18, 0, 0, 18, 20, 20, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 36, 0, 0, 0, 0, 0, 0, 0, 0, 0, 42, 8, 4, 12, 15, 13, 6, 15, 14, 0, 12, 3, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30, 14, 14, 51, 5}; - public byte[] MAVLINK_MESSAGE_CRCS = new byte[] {72, 39, 190, 92, 191, 217, 104, 119, 0, 219, 60, 186, 10, 0, 0, 0, 0, 0, 0, 0, 89, 159, 162, 121, 0, 149, 222, 110, 179, 136, 66, 126, 185, 147, 112, 252, 162, 215, 229, 128, 9, 106, 101, 213, 4, 229, 21, 214, 215, 14, 206, 50, 157, 126, 108, 213, 95, 5, 127, 0, 0, 0, 57, 126, 130, 119, 193, 191, 236, 158, 143, 0, 0, 104, 123, 131, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 174, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 155, 0, 0, 0, 0, 0, 0, 0, 0, 0, 143, 29, 208, 188, 118, 242, 19, 97, 233, 0, 18, 68, 136, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 178, 224, 60, 106, 7}; + public byte[] MAVLINK_MESSAGE_LENGTHS = new byte[] {3, 4, 8, 14, 8, 28, 3, 32, 0, 2, 3, 2, 2, 0, 0, 0, 0, 0, 0, 0, 19, 2, 23, 21, 0, 37, 26, 101, 26, 16, 32, 32, 37, 32, 11, 17, 17, 16, 18, 36, 4, 4, 2, 2, 4, 2, 2, 3, 14, 12, 18, 16, 8, 27, 25, 18, 18, 24, 24, 0, 0, 0, 26, 16, 36, 5, 6, 56, 26, 21, 18, 0, 0, 18, 20, 20, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 36, 0, 0, 0, 0, 0, 0, 0, 0, 0, 42, 8, 4, 12, 15, 13, 6, 15, 14, 0, 12, 3, 8, 28, 36, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30, 14, 14, 51, 5}; + public byte[] MAVLINK_MESSAGE_CRCS = new byte[] {72, 39, 190, 92, 191, 217, 104, 119, 0, 219, 60, 186, 10, 0, 0, 0, 0, 0, 0, 0, 89, 159, 162, 121, 0, 149, 222, 110, 179, 136, 66, 126, 185, 147, 112, 252, 162, 215, 229, 128, 9, 106, 101, 213, 4, 229, 21, 214, 215, 14, 206, 50, 157, 126, 108, 213, 95, 5, 127, 0, 0, 0, 57, 126, 130, 119, 193, 191, 236, 158, 143, 0, 0, 104, 123, 131, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 174, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 155, 0, 0, 0, 0, 0, 0, 0, 0, 0, 143, 29, 208, 188, 118, 242, 19, 97, 233, 0, 18, 68, 136, 205, 42, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 178, 224, 60, 106, 7}; public enum MAV_MOUNT_MODE { MAV_MOUNT_MODE_RETRACT=0, /* Load and keep safe position (Roll,Pitch,Yaw) from EEPROM and stop stabilization | */ @@ -78,6 +78,20 @@ namespace ArdupilotMega }; public const byte MAVLINK_MSG_ID_AP_ADC_LEN = 12; + public const byte MAVLINK_MSG_ID_DCM = 163; + [StructLayout(LayoutKind.Sequential,Pack=1)] + public struct __mavlink_dcm_t + { + public float omegaIx; /// X gyro drift estimate rad/s + public float omegaIy; /// Y gyro drift estimate rad/s + public float omegaIz; /// Z gyro drift estimate rad/s + public float accel_weight; /// average accel_weight + public float renorm_val; /// average renormalisation value + public float error_rp; /// average error_roll_pitch value + public float error_yaw; /// average error_yaw value + }; + + public const byte MAVLINK_MSG_ID_DCM_LEN = 28; public const byte MAVLINK_MSG_ID_DIGICAM_CONFIGURE = 154; [StructLayout(LayoutKind.Sequential,Pack=1)] public struct __mavlink_digicam_configure_t @@ -166,6 +180,15 @@ namespace ArdupilotMega }; public const byte MAVLINK_MSG_ID_FENCE_STATUS_LEN = 8; + public const byte MAVLINK_MSG_ID_HWSTATUS = 165; + [StructLayout(LayoutKind.Sequential,Pack=1)] + public struct __mavlink_hwstatus_t + { + public ushort Vcc; /// board voltage (mV) + public byte I2Cerr; /// I2C error count + }; + + public const byte MAVLINK_MSG_ID_HWSTATUS_LEN = 3; public const byte MAVLINK_MSG_ID_MEMINFO = 152; [StructLayout(LayoutKind.Sequential,Pack=1)] public struct __mavlink_meminfo_t @@ -244,6 +267,22 @@ namespace ArdupilotMega }; public const byte MAVLINK_MSG_ID_SET_MAG_OFFSETS_LEN = 8; + public const byte MAVLINK_MSG_ID_SIMSTATE = 164; + [StructLayout(LayoutKind.Sequential,Pack=1)] + public struct __mavlink_simstate_t + { + public float roll; /// Roll angle (rad) + public float pitch; /// Pitch angle (rad) + public float yaw; /// Yaw angle (rad) + public float xacc; /// X acceleration m/s/s + public float yacc; /// Y acceleration m/s/s + public float zacc; /// Z acceleration m/s/s + public float xgyro; /// Angular speed around X axis rad/s + public float ygyro; /// Angular speed around Y axis rad/s + public float zgyro; /// Angular speed around Z axis rad/s + }; + + public const byte MAVLINK_MSG_ID_SIMSTATE_LEN = 36; public enum MAV_DATA_STREAM { MAV_DATA_STREAM_ALL=0, /* Enable all data streams | */ @@ -1305,9 +1344,9 @@ namespace ArdupilotMega MAV_FRAME_LOCAL_ENU = 4 }; -Type[] mavstructs = new Type[] {typeof( __mavlink_heartbeat_t) ,typeof( __mavlink_boot_t) ,null ,typeof( __mavlink_ping_t) ,null ,typeof( __mavlink_change_operator_control_t) ,typeof( __mavlink_change_operator_control_ack_t) ,typeof( __mavlink_auth_key_t) ,null ,typeof( __mavlink_action_ack_t) ,typeof( __mavlink_action_t) ,typeof( __mavlink_set_mode_t) ,typeof( __mavlink_set_nav_mode_t) ,null ,null ,null ,null ,null ,null ,null ,typeof( __mavlink_param_request_read_t) ,typeof( __mavlink_param_request_list_t) ,typeof( __mavlink_param_value_t) ,typeof( __mavlink_param_set_t) ,null ,typeof( __mavlink_gps_raw_int_t) ,typeof( __mavlink_scaled_imu_t) ,typeof( __mavlink_gps_status_t) ,typeof( __mavlink_raw_imu_t) ,typeof( __mavlink_raw_pressure_t) ,typeof( __mavlink_attitude_t) ,typeof( __mavlink_local_position_t) ,typeof( __mavlink_gps_raw_t) ,typeof( __mavlink_global_position_t) ,typeof( __mavlink_sys_status_t) ,typeof( __mavlink_rc_channels_raw_t) ,typeof( __mavlink_rc_channels_scaled_t) ,typeof( __mavlink_servo_output_raw_t) ,typeof( __mavlink_scaled_pressure_t) ,typeof( __mavlink_waypoint_t) ,typeof( __mavlink_waypoint_request_t) ,typeof( __mavlink_waypoint_set_current_t) ,typeof( __mavlink_waypoint_current_t) ,typeof( __mavlink_waypoint_request_list_t) ,typeof( __mavlink_waypoint_count_t) ,typeof( __mavlink_waypoint_clear_all_t) ,typeof( __mavlink_waypoint_reached_t) ,typeof( __mavlink_waypoint_ack_t) ,typeof( __mavlink_gps_set_global_origin_t) ,typeof( __mavlink_gps_local_origin_set_t) ,typeof( __mavlink_local_position_setpoint_set_t) ,typeof( __mavlink_local_position_setpoint_t) ,typeof( __mavlink_control_status_t) ,typeof( __mavlink_safety_set_allowed_area_t) ,typeof( __mavlink_safety_allowed_area_t) ,typeof( __mavlink_set_roll_pitch_yaw_thrust_t) ,typeof( __mavlink_set_roll_pitch_yaw_speed_thrust_t) ,typeof( __mavlink_roll_pitch_yaw_thrust_setpoint_t) ,typeof( __mavlink_roll_pitch_yaw_speed_thrust_setpoint_t) ,null ,null ,null ,typeof( __mavlink_nav_controller_output_t) ,typeof( __mavlink_position_target_t) ,typeof( __mavlink_state_correction_t) ,typeof( __mavlink_set_altitude_t) ,typeof( __mavlink_request_data_stream_t) ,typeof( __mavlink_hil_state_t) ,typeof( __mavlink_hil_controls_t) ,typeof( __mavlink_manual_control_t) ,typeof( __mavlink_rc_channels_override_t) ,null ,null ,typeof( __mavlink_global_position_int_t) ,typeof( __mavlink_vfr_hud_t) ,typeof( __mavlink_command_t) ,typeof( __mavlink_command_ack_t) ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,typeof( __mavlink_optical_flow_t) ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,typeof( __mavlink_object_detection_event_t) ,null ,null ,null ,null ,null ,null ,null ,null ,null ,typeof( __mavlink_sensor_offsets_t) ,typeof( __mavlink_set_mag_offsets_t) ,typeof( __mavlink_meminfo_t) ,typeof( __mavlink_ap_adc_t) ,typeof( __mavlink_digicam_configure_t) ,typeof( __mavlink_digicam_control_t) ,typeof( __mavlink_mount_configure_t) ,typeof( __mavlink_mount_control_t) ,typeof( __mavlink_mount_status_t) ,null ,typeof( __mavlink_fence_point_t) ,typeof( __mavlink_fence_fetch_point_t) ,typeof( __mavlink_fence_status_t) ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,typeof( __mavlink_debug_vect_t) ,typeof( __mavlink_named_value_float_t) ,typeof( __mavlink_named_value_int_t) ,typeof( __mavlink_statustext_t) ,typeof( __mavlink_debug_t) ,null ,}; +Type[] mavstructs = new Type[] {typeof( __mavlink_heartbeat_t) ,typeof( __mavlink_boot_t) ,null ,typeof( __mavlink_ping_t) ,null ,typeof( __mavlink_change_operator_control_t) ,typeof( __mavlink_change_operator_control_ack_t) ,typeof( __mavlink_auth_key_t) ,null ,typeof( __mavlink_action_ack_t) ,typeof( __mavlink_action_t) ,typeof( __mavlink_set_mode_t) ,typeof( __mavlink_set_nav_mode_t) ,null ,null ,null ,null ,null ,null ,null ,typeof( __mavlink_param_request_read_t) ,typeof( __mavlink_param_request_list_t) ,typeof( __mavlink_param_value_t) ,typeof( __mavlink_param_set_t) ,null ,typeof( __mavlink_gps_raw_int_t) ,typeof( __mavlink_scaled_imu_t) ,typeof( __mavlink_gps_status_t) ,typeof( __mavlink_raw_imu_t) ,typeof( __mavlink_raw_pressure_t) ,typeof( __mavlink_attitude_t) ,typeof( __mavlink_local_position_t) ,typeof( __mavlink_gps_raw_t) ,typeof( __mavlink_global_position_t) ,typeof( __mavlink_sys_status_t) ,typeof( __mavlink_rc_channels_raw_t) ,typeof( __mavlink_rc_channels_scaled_t) ,typeof( __mavlink_servo_output_raw_t) ,typeof( __mavlink_scaled_pressure_t) ,typeof( __mavlink_waypoint_t) ,typeof( __mavlink_waypoint_request_t) ,typeof( __mavlink_waypoint_set_current_t) ,typeof( __mavlink_waypoint_current_t) ,typeof( __mavlink_waypoint_request_list_t) ,typeof( __mavlink_waypoint_count_t) ,typeof( __mavlink_waypoint_clear_all_t) ,typeof( __mavlink_waypoint_reached_t) ,typeof( __mavlink_waypoint_ack_t) ,typeof( __mavlink_gps_set_global_origin_t) ,typeof( __mavlink_gps_local_origin_set_t) ,typeof( __mavlink_local_position_setpoint_set_t) ,typeof( __mavlink_local_position_setpoint_t) ,typeof( __mavlink_control_status_t) ,typeof( __mavlink_safety_set_allowed_area_t) ,typeof( __mavlink_safety_allowed_area_t) ,typeof( __mavlink_set_roll_pitch_yaw_thrust_t) ,typeof( __mavlink_set_roll_pitch_yaw_speed_thrust_t) ,typeof( __mavlink_roll_pitch_yaw_thrust_setpoint_t) ,typeof( __mavlink_roll_pitch_yaw_speed_thrust_setpoint_t) ,null ,null ,null ,typeof( __mavlink_nav_controller_output_t) ,typeof( __mavlink_position_target_t) ,typeof( __mavlink_state_correction_t) ,typeof( __mavlink_set_altitude_t) ,typeof( __mavlink_request_data_stream_t) ,typeof( __mavlink_hil_state_t) ,typeof( __mavlink_hil_controls_t) ,typeof( __mavlink_manual_control_t) ,typeof( __mavlink_rc_channels_override_t) ,null ,null ,typeof( __mavlink_global_position_int_t) ,typeof( __mavlink_vfr_hud_t) ,typeof( __mavlink_command_t) ,typeof( __mavlink_command_ack_t) ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,typeof( __mavlink_optical_flow_t) ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,typeof( __mavlink_object_detection_event_t) ,null ,null ,null ,null ,null ,null ,null ,null ,null ,typeof( __mavlink_sensor_offsets_t) ,typeof( __mavlink_set_mag_offsets_t) ,typeof( __mavlink_meminfo_t) ,typeof( __mavlink_ap_adc_t) ,typeof( __mavlink_digicam_configure_t) ,typeof( __mavlink_digicam_control_t) ,typeof( __mavlink_mount_configure_t) ,typeof( __mavlink_mount_control_t) ,typeof( __mavlink_mount_status_t) ,null ,typeof( __mavlink_fence_point_t) ,typeof( __mavlink_fence_fetch_point_t) ,typeof( __mavlink_fence_status_t) ,typeof( __mavlink_dcm_t) ,typeof( __mavlink_simstate_t) ,typeof( __mavlink_hwstatus_t) ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,null ,typeof( __mavlink_debug_vect_t) ,typeof( __mavlink_named_value_float_t) ,typeof( __mavlink_named_value_int_t) ,typeof( __mavlink_statustext_t) ,typeof( __mavlink_debug_t) ,null ,}; } - #endif +#endif } diff --git a/Tools/ArdupilotMegaPlanner/MainV2.cs b/Tools/ArdupilotMegaPlanner/MainV2.cs index 0a1d312b20..63bf33780c 100644 --- a/Tools/ArdupilotMegaPlanner/MainV2.cs +++ b/Tools/ArdupilotMegaPlanner/MainV2.cs @@ -205,8 +205,15 @@ namespace ArdupilotMega if (config["speechenable"] != null) MainV2.speechenable = bool.Parse(config["speechenable"].ToString()); - - + + //int fixme; + /* + MainV2.cs.rateattitude = 50; + MainV2.cs.rateposition = 50; + MainV2.cs.ratestatus = 50; + MainV2.cs.raterc = 50; + MainV2.cs.ratesensors = 50; + */ try { if (config["TXT_homelat"] != null) @@ -329,10 +336,6 @@ namespace ArdupilotMega temp.Dock = DockStyle.Fill; - //temp.ForeColor = Color.White; - - //temp.BackColor = Color.FromArgb(0x26, 0x27, 0x28); - MyView.Controls.Add(temp); if (MainV2.config["FlightSplitter"] != null) @@ -355,10 +358,6 @@ namespace ArdupilotMega temp.Dock = DockStyle.Fill; - temp.ForeColor = Color.White; - - temp.BackColor = Color.FromArgb(0x26, 0x27, 0x28); - MyView.Controls.Add(temp); } @@ -390,10 +389,6 @@ namespace ArdupilotMega temp.Dock = DockStyle.Fill; - temp.ForeColor = Color.White; - - temp.BackColor = Color.FromArgb(0x26, 0x27, 0x28); - temp.Size = MyView.Size; //temp.Parent = MyView; @@ -417,10 +412,6 @@ namespace ArdupilotMega temp.Dock = DockStyle.Fill; - temp.ForeColor = Color.White; - - temp.BackColor = Color.FromArgb(0x26, 0x27, 0x28); - MyView.Controls.Add(temp); } @@ -438,10 +429,6 @@ namespace ArdupilotMega temp.Dock = DockStyle.Fill; - temp.ForeColor = Color.White; - - temp.BackColor = Color.FromArgb(0x26, 0x27, 0x28); - MyView.Controls.Add(temp); } @@ -480,10 +467,6 @@ namespace ArdupilotMega MyView.Controls.Add(temp); - temp.ForeColor = Color.White; - - temp.BackColor = Color.FromArgb(0x26, 0x27, 0x28); - } private void MenuConnect_Click(object sender, EventArgs e) diff --git a/Tools/ArdupilotMegaPlanner/MavlinkLog.Designer.cs b/Tools/ArdupilotMegaPlanner/MavlinkLog.Designer.cs index 38356beb49..cd4e7d8217 100644 --- a/Tools/ArdupilotMegaPlanner/MavlinkLog.Designer.cs +++ b/Tools/ArdupilotMegaPlanner/MavlinkLog.Designer.cs @@ -33,6 +33,7 @@ this.progressBar1 = new System.Windows.Forms.ProgressBar(); this.BUT_humanreadable = new ArdupilotMega.MyButton(); this.BUT_graphmavlog = new ArdupilotMega.MyButton(); + this.zg1 = new ZedGraph.ZedGraphControl(); this.SuspendLayout(); // // BUT_redokml @@ -61,10 +62,23 @@ this.BUT_graphmavlog.UseVisualStyleBackColor = true; this.BUT_graphmavlog.Click += new System.EventHandler(this.BUT_graphmavlog_Click); // + // zg1 + // + resources.ApplyResources(this.zg1, "zg1"); + this.zg1.Name = "zg1"; + this.zg1.ScrollGrace = 0D; + this.zg1.ScrollMaxX = 0D; + this.zg1.ScrollMaxY = 0D; + this.zg1.ScrollMaxY2 = 0D; + this.zg1.ScrollMinX = 0D; + this.zg1.ScrollMinY = 0D; + this.zg1.ScrollMinY2 = 0D; + // // MavlinkLog // resources.ApplyResources(this, "$this"); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.Controls.Add(this.zg1); this.Controls.Add(this.BUT_graphmavlog); this.Controls.Add(this.BUT_humanreadable); this.Controls.Add(this.progressBar1); @@ -81,5 +95,6 @@ private System.Windows.Forms.ProgressBar progressBar1; private MyButton BUT_humanreadable; private MyButton BUT_graphmavlog; + private ZedGraph.ZedGraphControl zg1; } } \ No newline at end of file diff --git a/Tools/ArdupilotMegaPlanner/MavlinkLog.cs b/Tools/ArdupilotMegaPlanner/MavlinkLog.cs index 381a0a0463..4b01b971ff 100644 --- a/Tools/ArdupilotMegaPlanner/MavlinkLog.cs +++ b/Tools/ArdupilotMegaPlanner/MavlinkLog.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Collections; using System.ComponentModel; using System.Data; using System.Drawing; @@ -22,14 +23,19 @@ using SharpKml.Dom.GX; using System.Reflection; using System.Xml; - +using log4net; +using ZedGraph; // Graphs namespace ArdupilotMega { public partial class MavlinkLog : Form { + private static readonly ILog log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + List flightdata = new List(); + List selection = new List(); + public MavlinkLog() { InitializeComponent(); @@ -232,7 +238,7 @@ namespace ArdupilotMega } catch { } - Link link = new Link(); + SharpKml.Dom.Link link = new SharpKml.Dom.Link(); link.Href = new Uri("block_plane_0.dae", UriKind.Relative); model.Link = link; @@ -369,7 +375,7 @@ namespace ArdupilotMega float oldlatlngalt = 0; - DateTime appui = DateTime.Now; + int appui = 0; while (mine.logplaybackfile.BaseStream.Position < mine.logplaybackfile.BaseStream.Length) { @@ -384,11 +390,11 @@ namespace ArdupilotMega cs.UpdateCurrentSettings(null, true, mine); - if (appui != DateTime.Now) + if (appui != DateTime.Now.Second) { // cant do entire app as mixes with flightdata timer this.Refresh(); - appui = DateTime.Now; + appui = DateTime.Now.Second; } try @@ -514,11 +520,19 @@ namespace ArdupilotMega private void BUT_graphmavlog_Click(object sender, EventArgs e) { + + //http://devreminder.wordpress.com/net/net-framework-fundamentals/c-dynamic-math-expression-evaluation/ + //http://www.c-sharpcorner.com/UploadFile/mgold/CodeDomCalculator08082005003253AM/CodeDomCalculator.aspx + +//string mathExpression = "(1+1)*3"; + //Console.WriteLine(String.Format("{0}={1}",mathExpression, Evaluate(mathExpression))); + + OpenFileDialog openFileDialog1 = new OpenFileDialog(); openFileDialog1.Filter = "*.tlog|*.tlog"; openFileDialog1.FilterIndex = 2; openFileDialog1.RestoreDirectory = true; - openFileDialog1.Multiselect = true; + openFileDialog1.Multiselect = false; try { openFileDialog1.InitialDirectory = Path.GetDirectoryName(Application.ExecutablePath) + Path.DirectorySeparatorChar + @"logs" + Path.DirectorySeparatorChar; @@ -527,73 +541,289 @@ namespace ArdupilotMega if (openFileDialog1.ShowDialog() == DialogResult.OK) { - foreach (string logfile in openFileDialog1.FileNames) + List fields = GetLogFileValidFields(openFileDialog1.FileName); + + zg1.GraphPane.CurveList.Clear(); + + GetLogFileData(zg1, openFileDialog1.FileName, fields); + + try { + // fix new line types + ThemeManager.ApplyThemeTo(this); - MAVLink mine = new MAVLink(); - mine.logplaybackfile = new BinaryReader(File.Open(logfile, FileMode.Open, FileAccess.Read, FileShare.Read)); - mine.logreadmode = true; - - mine.packets.Initialize(); // clear - - CurrentState cs = new CurrentState(); - - float oldlatlngalt = 0; - - DateTime appui = DateTime.Now; - - while (mine.logplaybackfile.BaseStream.Position < mine.logplaybackfile.BaseStream.Length) - { - // bar moves to 50 % in this step - progressBar1.Value = (int)((float)mine.logplaybackfile.BaseStream.Position / (float)mine.logplaybackfile.BaseStream.Length * 100.0f / 2.0f); - progressBar1.Invalidate(); - progressBar1.Refresh(); - - byte[] packet = mine.readPacket(); - - cs.datetime = mine.lastlogread; - - cs.UpdateCurrentSettings(null, true, mine); - - if (appui != DateTime.Now) - { - // cant do entire app as mixes with flightdata timer - this.Refresh(); - appui = DateTime.Now; - } - - try - { - if (MainV2.talk != null) - MainV2.talk.SpeakAsyncCancelAll(); - } - catch { } // ignore because of this Exception System.PlatformNotSupportedException: No voice installed on the system or none available with the current security setting. - - if ((float)(cs.lat + cs.lng) != oldlatlngalt - && cs.lat != 0 && cs.lng != 0) - { - Console.WriteLine(cs.lat + " " + cs.lng + " " + cs.alt + " lah " + (float)(cs.lat + cs.lng) + "!=" + oldlatlngalt); - CurrentState cs2 = (CurrentState)cs.Clone(); - - flightdata.Add(cs2); - - oldlatlngalt = (cs.lat + cs.lng); - } - } - - mine.logreadmode = false; - mine.logplaybackfile.Close(); - mine.logplaybackfile = null; - - Application.DoEvents(); - - //writeKML(logfile + ".kml"); - - progressBar1.Value = 100; - + zg1.Invalidate(); + zg1.AxisChange(); } + catch { } } } + static int[] ColourValues = new int[] { + 0xFF0000,0x00FF00,0x0000FF,0xFFFF00,0xFF00FF,0x00FFFF,0x000000, + 0x800000,0x008000,0x000080,0x808000,0x800080,0x008080,0x808080, + 0xC00000,0x00C000,0x0000C0,0xC0C000,0xC000C0,0x00C0C0,0xC0C0C0, + 0x400000,0x004000,0x000040,0x404000,0x400040,0x004040,0x404040, + 0x200000,0x002000,0x000020,0x202000,0x200020,0x002020,0x202020, + 0x600000,0x006000,0x000060,0x606000,0x600060,0x006060,0x606060, + 0xA00000,0x00A000,0x0000A0,0xA0A000,0xA000A0,0x00A0A0,0xA0A0A0, + 0xE00000,0x00E000,0x0000E0,0xE0E000,0xE000E0,0x00E0E0,0xE0E0E0, + }; + + + private void GetLogFileData(ZedGraphControl zg1, string logfile, List lookforfields) + { + if (zg1 == null) + return; + + if (lookforfields != null && lookforfields.Count == 0) + return; + + PointPairList[] lists = new PointPairList[lookforfields.Count]; + + Random rand = new Random(); + + int step = 0; + + // setup display and arrays + for (int a = 0; a < lookforfields.Count; a++) + { + lists[a] = new PointPairList(); + + LineItem myCurve; + + int colorvalue = ColourValues[step % ColourValues.Length]; + step++; + + myCurve = zg1.GraphPane.AddCurve(lookforfields[a].Replace("__mavlink_", ""), lists[a], Color.FromArgb(unchecked( colorvalue + (int)0xff000000)), SymbolType.None); + } + + { + + MAVLink MavlinkInterface = new MAVLink(); + MavlinkInterface.logplaybackfile = new BinaryReader(File.Open(logfile, FileMode.Open, FileAccess.Read, FileShare.Read)); + MavlinkInterface.logreadmode = true; + + MavlinkInterface.packets.Initialize(); // clear + + int appui = 0; + + // to get first packet time + MavlinkInterface.readPacket(); + + DateTime startlogtime = MavlinkInterface.lastlogread; + + while (MavlinkInterface.logplaybackfile.BaseStream.Position < MavlinkInterface.logplaybackfile.BaseStream.Length) + { + progressBar1.Value = (int)((float)MavlinkInterface.logplaybackfile.BaseStream.Position / (float)MavlinkInterface.logplaybackfile.BaseStream.Length * 100.0f); + progressBar1.Refresh(); + + byte[] packet = MavlinkInterface.readPacket(); + + object data = MavlinkInterface.DebugPacket(packet, false); + + Type test = data.GetType(); + + foreach (var field in test.GetFields()) + { + // field.Name has the field's name. + + object fieldValue = field.GetValue(data); // Get value + + if (field.FieldType.IsArray) + { + + } + else + { + string currentitem = field.Name + " " + field.DeclaringType.Name; + int a = 0; + foreach (var lookforfield in lookforfields) + { + + if (currentitem == lookforfield) + { + object value = field.GetValue(data); + // seconds scale + double time = (MavlinkInterface.lastlogread - startlogtime).TotalMilliseconds / 1000.0; + + if (value.GetType() == typeof(Single)) + { + lists[a].Add(time, (Single)field.GetValue(data)); + } + else if (value.GetType() == typeof(short)) + { + lists[a].Add(time, (short)field.GetValue(data)); + } + else if (value.GetType() == typeof(ushort)) + { + lists[a].Add(time, (ushort)field.GetValue(data)); + } + else if (value.GetType() == typeof(byte)) + { + lists[a].Add(time, (byte)field.GetValue(data)); + } + else if (value.GetType() == typeof(Int32)) + { + lists[a].Add(time, (Int32)field.GetValue(data)); + } + } + a++; + } + } + } + + if (appui != DateTime.Now.Second) + { + // cant do entire app as mixes with flightdata timer + this.Refresh(); + appui = DateTime.Now.Second; + } + } + + MavlinkInterface.logreadmode = false; + MavlinkInterface.logplaybackfile.Close(); + MavlinkInterface.logplaybackfile = null; + + + //writeKML(logfile + ".kml"); + + progressBar1.Value = 100; + } + } + + private List GetLogFileValidFields(string logfile) + { + Form selectform = SelectDataToGraphForm(); + + Hashtable seenIt = new Hashtable(); + + { + + MAVLink mine = new MAVLink(); + mine.logplaybackfile = new BinaryReader(File.Open(logfile, FileMode.Open, FileAccess.Read, FileShare.Read)); + mine.logreadmode = true; + + mine.packets.Initialize(); // clear + + while (mine.logplaybackfile.BaseStream.Position < mine.logplaybackfile.BaseStream.Length) + { + progressBar1.Value = (int)((float)mine.logplaybackfile.BaseStream.Position / (float)mine.logplaybackfile.BaseStream.Length * 100.0f); + this.Refresh(); + + byte[] packet = mine.readPacket(); + + object data = mine.DebugPacket(packet, false); + + Type test = data.GetType(); + + foreach (var field in test.GetFields()) + { + // field.Name has the field's name. + + object fieldValue = field.GetValue(data); // Get value + + if (field.FieldType.IsArray) + { + + } + else + { + if (!seenIt.ContainsKey(field.DeclaringType.Name + "." + field.Name)) + { + AddDataOption(selectform, field.Name + " " + field.DeclaringType.Name); + seenIt[field.DeclaringType.Name + "." + field.Name] = 1; + } + } + } + } + + mine.logreadmode = false; + mine.logplaybackfile.Close(); + mine.logplaybackfile = null; + + selectform.ShowDialog(); + + progressBar1.Value = 100; + + } + + return selection; + } + + private void AddDataOption(Form selectform, string Name) + { + + CheckBox chk_box = new CheckBox(); + + log.Info("Add Option " + Name); + + chk_box.Text = Name; + chk_box.Name = Name; + chk_box.Location = new System.Drawing.Point(x, y); + chk_box.Size = new System.Drawing.Size(100, 20); + chk_box.CheckedChanged += new EventHandler(chk_box_CheckedChanged); + + selectform.Controls.Add(chk_box); + + Application.DoEvents(); + + x += 0; + y += 20; + + if (y > selectform.Height - 50) + { + x += 100; + y = 10; + + selectform.Width = x + 100; + } + } + + void chk_box_CheckedChanged(object sender, EventArgs e) + { + if (((CheckBox)sender).Checked) + { + selection.Add(((CheckBox)sender).Name); + } + else + { + selection.Remove(((CheckBox)sender).Name); + } + } + + int x = 10; + int y = 10; + + private Form SelectDataToGraphForm() + { + Form selectform = new Form() + { + Name = "select", + Width = 50, + Height = 500, + Text = "Graph This" + }; + + x = 10; + y = 10; + + { + CheckBox chk_box = new CheckBox(); + chk_box.Text = "Logarithmic"; + chk_box.Name = "Logarithmic"; + chk_box.Location = new System.Drawing.Point(x, y); + chk_box.Size = new System.Drawing.Size(100, 20); + //chk_box.CheckedChanged += new EventHandler(chk_log_CheckedChanged); + + selectform.Controls.Add(chk_box); + } + + y += 20; + + ThemeManager.ApplyThemeTo(selectform); + + return selectform; + } } } \ No newline at end of file diff --git a/Tools/ArdupilotMegaPlanner/MavlinkLog.resx b/Tools/ArdupilotMegaPlanner/MavlinkLog.resx index 7aadc69694..58503a2863 100644 --- a/Tools/ArdupilotMegaPlanner/MavlinkLog.resx +++ b/Tools/ArdupilotMegaPlanner/MavlinkLog.resx @@ -117,6 +117,10 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Top + 45, 12 @@ -141,7 +145,10 @@ $this - 3 + 4 + + + Top, Left, Right 10, 42 @@ -162,9 +169,11 @@ $this - 2 + 3 + + + Top - NoControl @@ -190,13 +199,16 @@ $this - 1 + 2 + + + Top NoControl - 289, 13 + 289, 12 116, 23 @@ -217,6 +229,30 @@ $this + 1 + + + Top, Bottom, Left, Right + + + 10, 74 + + + 434, 293 + + + 12 + + + zg1 + + + ZedGraph.ZedGraphControl, ZedGraph, Version=5.1.2.878, Culture=neutral, PublicKeyToken=02a83cbd123fcd60 + + + $this + + 0 @@ -226,7 +262,7 @@ 6, 13 - 456, 82 + 456, 379 @@ -304,6 +340,9 @@ AAf4AAAP/AAAH/4AAD//gAD//+AD//////8= + + 472, 417 + Log diff --git a/Tools/ArdupilotMegaPlanner/Program.cs b/Tools/ArdupilotMegaPlanner/Program.cs index e1f808f6c2..d80b848cdf 100644 --- a/Tools/ArdupilotMegaPlanner/Program.cs +++ b/Tools/ArdupilotMegaPlanner/Program.cs @@ -31,6 +31,7 @@ namespace ArdupilotMega Application.Idle += Application_Idle; + CodeGen.runCode("Sin(0.55)"); //MagCalib.doWork(); diff --git a/Tools/ArdupilotMegaPlanner/Properties/AssemblyInfo.cs b/Tools/ArdupilotMegaPlanner/Properties/AssemblyInfo.cs index 951e78d73e..14484783e3 100644 --- a/Tools/ArdupilotMegaPlanner/Properties/AssemblyInfo.cs +++ b/Tools/ArdupilotMegaPlanner/Properties/AssemblyInfo.cs @@ -34,5 +34,5 @@ using System.Resources; // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.1.48")] +[assembly: AssemblyFileVersion("1.1.49")] [assembly: NeutralResourcesLanguageAttribute("")] diff --git a/Tools/ArdupilotMegaPlanner/Properties/Resources.Designer.cs b/Tools/ArdupilotMegaPlanner/Properties/Resources.Designer.cs index 3b135b9e1e..df3eb279ae 100644 --- a/Tools/ArdupilotMegaPlanner/Properties/Resources.Designer.cs +++ b/Tools/ArdupilotMegaPlanner/Properties/Resources.Designer.cs @@ -1,7 +1,7 @@ //------------------------------------------------------------------------------ // // This code was generated by a tool. -// Runtime Version:4.0.30319.239 +// Runtime Version:4.0.30319.261 // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. diff --git a/Tools/ArdupilotMegaPlanner/Setup/Setup.Designer.cs b/Tools/ArdupilotMegaPlanner/Setup/Setup.Designer.cs index 8312591884..968142c6c3 100644 --- a/Tools/ArdupilotMegaPlanner/Setup/Setup.Designer.cs +++ b/Tools/ArdupilotMegaPlanner/Setup/Setup.Designer.cs @@ -405,7 +405,7 @@ this.BARthrottle.minline = 0; this.BARthrottle.Name = "BARthrottle"; this.BARthrottle.Value = 1000; - this.BARthrottle.ValueColor = System.Drawing.Color.FromArgb(((int)(((byte)(148)))), ((int)(((byte)(193)))), ((int)(((byte)(31))))); + this.BARthrottle.ValueColor = System.Drawing.Color.Magenta; // // BARyaw // diff --git a/Tools/ArdupilotMegaPlanner/Setup/Setup.resx b/Tools/ArdupilotMegaPlanner/Setup/Setup.resx index 4743bd1a83..63fda6166a 100644 --- a/Tools/ArdupilotMegaPlanner/Setup/Setup.resx +++ b/Tools/ArdupilotMegaPlanner/Setup/Setup.resx @@ -117,1815 +117,15 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - groupBoxElevons - - - System.Windows.Forms.GroupBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - tabRadioIn - - - 0 - - - CHK_revch3 - - - System.Windows.Forms.CheckBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - tabRadioIn - - - 1 - - - CHK_revch4 - - - System.Windows.Forms.CheckBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - tabRadioIn - - - 2 - - - CHK_revch2 - - - System.Windows.Forms.CheckBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - tabRadioIn - - - 3 - - - CHK_revch1 - - - System.Windows.Forms.CheckBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - tabRadioIn - - - 4 - - - BUT_Calibrateradio - - - ArdupilotMega.MyButton, ArdupilotMegaPlanner, Version=1.0.0.0, Culture=neutral, PublicKeyToken=38326cb7e06851fc - - - tabRadioIn - - - 5 - - - BAR8 - - - ArdupilotMega.HorizontalProgressBar2, ArdupilotMegaPlanner, Version=1.0.0.0, Culture=neutral, PublicKeyToken=38326cb7e06851fc - - - tabRadioIn - - - 6 - - - BAR7 - - - ArdupilotMega.HorizontalProgressBar2, ArdupilotMegaPlanner, Version=1.0.0.0, Culture=neutral, PublicKeyToken=38326cb7e06851fc - - - tabRadioIn - - - 7 - - - BAR6 - - - ArdupilotMega.HorizontalProgressBar2, ArdupilotMegaPlanner, Version=1.0.0.0, Culture=neutral, PublicKeyToken=38326cb7e06851fc - - - tabRadioIn - - - 8 - - - BAR5 - - - ArdupilotMega.HorizontalProgressBar2, ArdupilotMegaPlanner, Version=1.0.0.0, Culture=neutral, PublicKeyToken=38326cb7e06851fc - - - tabRadioIn - - - 9 - - - BARpitch - - - ArdupilotMega.VerticalProgressBar2, ArdupilotMegaPlanner, Version=1.0.0.0, Culture=neutral, PublicKeyToken=38326cb7e06851fc - - - tabRadioIn - - - 10 - - - BARthrottle - - - ArdupilotMega.VerticalProgressBar2, ArdupilotMegaPlanner, Version=1.0.0.0, Culture=neutral, PublicKeyToken=38326cb7e06851fc - - - tabRadioIn - - - 11 - - - BARyaw - - - ArdupilotMega.HorizontalProgressBar2, ArdupilotMegaPlanner, Version=1.0.0.0, Culture=neutral, PublicKeyToken=38326cb7e06851fc - - - tabRadioIn - - - 12 - - - BARroll - - - ArdupilotMega.HorizontalProgressBar2, ArdupilotMegaPlanner, Version=1.0.0.0, Culture=neutral, PublicKeyToken=38326cb7e06851fc - - - tabRadioIn - - - 13 - - - - 4, 22 - - - - 3, 3, 3, 3 - - - 666, 393 - - - 0 - - - Radio Input - - - tabRadioIn - - - System.Windows.Forms.TabPage, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - tabControl1 - - - 0 - - - CB_simple6 - - - System.Windows.Forms.CheckBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - tabModes - - - 0 - - - CB_simple5 - - - System.Windows.Forms.CheckBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - tabModes - - - 1 - - - CB_simple4 - - - System.Windows.Forms.CheckBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - tabModes - - - 2 - - - CB_simple3 - - - System.Windows.Forms.CheckBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - tabModes - - - 3 - - - CB_simple2 - - - System.Windows.Forms.CheckBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - tabModes - - - 4 - - - CB_simple1 - - - System.Windows.Forms.CheckBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - tabModes - - - 5 - - - label14 - - - System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - tabModes - - - 6 - - - LBL_flightmodepwm - - - System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - tabModes - - - 7 - - - label13 - - - System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - tabModes - - - 8 - - - lbl_currentmode - - - System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - tabModes - - - 9 - - - label12 - - - System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - tabModes - - - 10 - - - label11 - - - System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - tabModes - - - 11 - - - label10 - - - System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - tabModes - - - 12 - - - label9 - - - System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - tabModes - - - 13 - - - label8 - - - System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - tabModes - - - 14 - - - label7 - - - System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - tabModes - - - 15 - - - label6 - - - System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - tabModes - - - 16 - - - CMB_fmode6 - - - System.Windows.Forms.ComboBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - tabModes - - - 17 - - - label5 - - - System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - tabModes - - - 18 - - - CMB_fmode5 - - - System.Windows.Forms.ComboBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - tabModes - - - 19 - - - label4 - - - System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - tabModes - - - 20 - - - CMB_fmode4 - - - System.Windows.Forms.ComboBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - tabModes - - - 21 - - - label3 - - - System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - tabModes - - - 22 - - - CMB_fmode3 - - - System.Windows.Forms.ComboBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - tabModes - - - 23 - - - label2 - - - System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - tabModes - - - 24 - - - CMB_fmode2 - - - System.Windows.Forms.ComboBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - tabModes - - - 25 - - - label1 - - - System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - tabModes - - - 26 - - - CMB_fmode1 - - - System.Windows.Forms.ComboBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - tabModes - - - 27 - - - BUT_SaveModes - - - ArdupilotMega.MyButton, ArdupilotMegaPlanner, Version=1.0.0.0, Culture=neutral, PublicKeyToken=38326cb7e06851fc - - - tabModes - - - 28 - - - 4, 22 - - - 666, 393 - - - 3 - - - Modes - - - tabModes - - - System.Windows.Forms.TabPage, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - tabControl1 - - - 1 - - - label27 - - - System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - tabHardware - - - 0 - - - CMB_sonartype - - - System.Windows.Forms.ComboBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - tabHardware - - - 1 - - - CHK_enableoptflow - - - System.Windows.Forms.CheckBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - tabHardware - - - 2 - - - pictureBox2 - - - System.Windows.Forms.PictureBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - tabHardware - - - 3 - - - linkLabelmagdec - - - System.Windows.Forms.LinkLabel, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - tabHardware - - - 4 - - - label100 - - - System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - tabHardware - - - 5 - - - TXT_declination - - - System.Windows.Forms.TextBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - tabHardware - - - 6 - - - CHK_enableairspeed - - - System.Windows.Forms.CheckBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - tabHardware - - - 7 - - - CHK_enablesonar - - - System.Windows.Forms.CheckBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - tabHardware - - - 8 - - - CHK_enablecompass - - - System.Windows.Forms.CheckBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - tabHardware - - - 9 - - - pictureBox4 - - - System.Windows.Forms.PictureBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - tabHardware - - - 10 - - - pictureBox3 - - - System.Windows.Forms.PictureBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - tabHardware - - - 11 - - - pictureBox1 - - - System.Windows.Forms.PictureBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - tabHardware - - - 12 - - - 4, 22 - - - 3, 3, 3, 3 - - - 666, 393 - - - 1 - - - Hardware - - - tabHardware - - - System.Windows.Forms.TabPage, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - tabControl1 - - - 2 - - - label31 - - - System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - groupBox4 - - - 0 - - - label32 - - - System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - groupBox4 - - - 1 - - - label33 - - - System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - groupBox4 - - - 2 - - - TXT_ampspervolt - - - System.Windows.Forms.TextBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - groupBox4 - - - 3 - - - label34 - - - System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - groupBox4 - - - 4 - - - TXT_divider - - - System.Windows.Forms.TextBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - groupBox4 - - - 5 - - - label35 - - - System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - groupBox4 - - - 6 - - - TXT_voltage - - - System.Windows.Forms.TextBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - groupBox4 - - - 7 - - - TXT_inputvoltage - - - System.Windows.Forms.TextBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - groupBox4 - - - 8 - - - TXT_measuredvoltage - - - System.Windows.Forms.TextBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - groupBox4 - - - 9 - - - 31, 177 - - - 238, 131 - - - 41 - - - Calibration - - - groupBox4 - - - System.Windows.Forms.GroupBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - tabBattery - - - 0 - - - NoControl - - - 123, 76 - - - 42, 13 - - - 40 - - - Sensor - - - label47 - - - System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - tabBattery - - - 1 - - - 0: Other - - - 1: AttoPilot 45A - - - 2: AttoPilot 90A - - - 3: AttoPilot 180A - - - 177, 73 - - - 121, 21 - - - 39 - - - CMB_batmonsensortype - - - System.Windows.Forms.ComboBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - tabBattery - - - 2 - - - Microsoft Sans Serif, 8.25pt - - - 299, 177 - - - 2, 2, 2, 2 - - - True - - - 219, 131 - - - 28 - - - Voltage sensor calibration: -To calibrate your sensor, use a multimeter to measure the voltage coming out of your ESC's battery-elimination circuit (these are black and red wires in the three-wire cable that is powering your APM board). -Then subtract 0.3v from that value and enter it in field #1 at left. - - - - textBox3 - - - System.Windows.Forms.TextBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - tabBattery - - - 3 - - - True - - - NoControl - - - 305, 50 - - - 48, 13 - - - 23 - - - Capacity - - - label29 - - - System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - tabBattery - - - 4 - - - NoControl - - - 123, 50 - - - 42, 13 - - - 24 - - - Monitor - - - label30 - - - System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - tabBattery - - - 5 - - - 366, 47 - - - 83, 20 - - - 25 - - - TXT_battcapacity - - - System.Windows.Forms.TextBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - tabBattery - - - 6 - - - 0: Disabled - - - 3: Battery Volts - - - 4: Volts & Current - - - 177, 46 - - - 121, 21 - - - 26 - - - CMB_batmontype - - - System.Windows.Forms.ComboBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - tabBattery - - - 7 - - - Zoom - - - NoControl - - - 31, 21 - - - 75, 75 - - - 2 - - - pictureBox5 - - - System.Windows.Forms.PictureBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - tabBattery - - - 8 - - - 4, 22 - - - 2, 2, 2, 2 - - - 666, 393 - - - 6 - - - Battery - - - tabBattery - - - System.Windows.Forms.TabPage, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - tabControl1 - - - 3 - - - label28 - - - System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - tabArducopter - - - 0 - - - label16 - - - System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - tabArducopter - - - 1 - - - label15 - - - System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - tabArducopter - - - 2 - - - pictureBoxQuadX - - - System.Windows.Forms.PictureBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - tabArducopter - - - 3 - - - pictureBoxQuad - - - System.Windows.Forms.PictureBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - tabArducopter - - - 4 - - - BUT_levelac2 - - - ArdupilotMega.MyButton, ArdupilotMegaPlanner, Version=1.0.0.0, Culture=neutral, PublicKeyToken=38326cb7e06851fc - - - tabArducopter - - - 5 - - - 4, 22 - - - 666, 393 - - - 2 - - - ArduCopter2 - - - tabArducopter - - - System.Windows.Forms.TabPage, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - tabControl1 - - - 4 - - - BUT_HS4save - - - ArdupilotMega.MyButton, ArdupilotMegaPlanner, Version=1.0.0.0, Culture=neutral, PublicKeyToken=38326cb7e06851fc - - - tabHeli - - - 0 - - - BUT_swash_manual - - - ArdupilotMega.MyButton, ArdupilotMegaPlanner, Version=1.0.0.0, Culture=neutral, PublicKeyToken=38326cb7e06851fc - - - tabHeli - - - 1 - - - groupBox3 - - - System.Windows.Forms.GroupBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - tabHeli - - - 2 - - - label44 - - - System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - tabHeli - - - 3 - - - label43 - - - System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - tabHeli - - - 4 - - - label42 - - - System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - tabHeli - - - 5 - - - groupBox2 - - - System.Windows.Forms.GroupBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - tabHeli - - - 6 - - - groupBox1 - - - System.Windows.Forms.GroupBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - tabHeli - - - 7 - - - HS4_TRIM - - - System.Windows.Forms.NumericUpDown, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - tabHeli - - - 8 - - - HS3_TRIM - - - System.Windows.Forms.NumericUpDown, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - tabHeli - - - 9 - - - HS2_TRIM - - - System.Windows.Forms.NumericUpDown, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - tabHeli - - - 10 - - - HS1_TRIM - - - System.Windows.Forms.NumericUpDown, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - tabHeli - - - 11 - - - label39 - - - System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - tabHeli - - - 12 - - - label38 - - - System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - tabHeli - - - 13 - - - label37 - - - System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - tabHeli - - - 14 - - - label36 - - - System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - tabHeli - - - 15 - - - label26 - - - System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - tabHeli - - - 16 - - - PIT_MAX_ - - - System.Windows.Forms.TextBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - tabHeli - - - 17 - - - label25 - - - System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - tabHeli - - - 18 - - - ROL_MAX_ - - - System.Windows.Forms.TextBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - tabHeli - - - 19 - - - label23 - - - System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - tabHeli - - - 20 - - - label22 - - - System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - tabHeli - - - 21 - - - HS4_REV - - - System.Windows.Forms.CheckBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - tabHeli - - - 22 - - - label20 - - - System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - tabHeli - - - 23 - - - label19 - - - System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - tabHeli - - - 24 - - - label18 - - - System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - tabHeli - - - 25 - - - SV3_POS_ - - - System.Windows.Forms.TextBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - tabHeli - - - 26 - - - SV2_POS_ - - - System.Windows.Forms.TextBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - tabHeli - - - 27 - - - SV1_POS_ - - - System.Windows.Forms.TextBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - tabHeli - - - 28 - - - HS3_REV - - - System.Windows.Forms.CheckBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - tabHeli - - - 29 - - - HS2_REV - - - System.Windows.Forms.CheckBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - tabHeli - - - 30 - - - HS1_REV - - - System.Windows.Forms.CheckBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - tabHeli - - - 31 - - - label17 - - - System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - tabHeli - - - 32 - - - HS4 - - - ArdupilotMega.HorizontalProgressBar2, ArdupilotMegaPlanner, Version=1.0.0.0, Culture=neutral, PublicKeyToken=38326cb7e06851fc - - - tabHeli - - - 33 - - - HS3 - - - ArdupilotMega.VerticalProgressBar2, ArdupilotMegaPlanner, Version=1.0.0.0, Culture=neutral, PublicKeyToken=38326cb7e06851fc - - - tabHeli - - - 34 - - - Gservoloc - - - AGaugeApp.AGauge, ArdupilotMegaPlanner, Version=1.0.0.0, Culture=neutral, PublicKeyToken=38326cb7e06851fc - - - tabHeli - - - 35 - - - 4, 22 - - - 666, 393 - - - 5 - - - AC2 Heli - - - tabHeli - - - System.Windows.Forms.TabPage, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - tabControl1 - - - 5 - - - Fill - - - 0, 0 - - - 674, 419 - - - 93 - - - tabControl1 - - - System.Windows.Forms.TabControl, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - $this - - - 0 - - - CHK_mixmode - - - System.Windows.Forms.CheckBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - groupBoxElevons - - - 0 - - - CHK_elevonch2rev - - - System.Windows.Forms.CheckBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - groupBoxElevons - - - 1 - - - CHK_elevonrev - - - System.Windows.Forms.CheckBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - groupBoxElevons - - - 2 - - - CHK_elevonch1rev - - - System.Windows.Forms.CheckBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - groupBoxElevons - - - 3 - - - 21, 349 - - - 409, 42 - - - 111 - - - Elevon Config - - - groupBoxElevons - - - System.Windows.Forms.GroupBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - tabRadioIn - - - 0 - True + NoControl + 13, 19 @@ -2055,6 +255,30 @@ Then subtract 0.3v from that value and enter it in field #1 at left. 3 + + 21, 349 + + + 409, 42 + + + 111 + + + Elevon Config + + + groupBoxElevons + + + System.Windows.Forms.GroupBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tabRadioIn + + + 0 + True @@ -2194,7 +418,7 @@ Then subtract 0.3v from that value and enter it in field #1 at left. BUT_Calibrateradio - ArdupilotMega.MyButton, ArdupilotMegaPlanner, Version=1.0.0.0, Culture=neutral, PublicKeyToken=38326cb7e06851fc + ArdupilotMega.MyButton, ArdupilotMegaPlanner, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null tabRadioIn @@ -2218,7 +442,7 @@ Then subtract 0.3v from that value and enter it in field #1 at left. BAR8 - ArdupilotMega.HorizontalProgressBar2, ArdupilotMegaPlanner, Version=1.0.0.0, Culture=neutral, PublicKeyToken=38326cb7e06851fc + ArdupilotMega.HorizontalProgressBar2, ArdupilotMegaPlanner, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null tabRadioIn @@ -2226,9 +450,6 @@ Then subtract 0.3v from that value and enter it in field #1 at left. 6 - - 17, 17 - 446, 185 @@ -2242,7 +463,7 @@ Then subtract 0.3v from that value and enter it in field #1 at left. BAR7 - ArdupilotMega.HorizontalProgressBar2, ArdupilotMegaPlanner, Version=1.0.0.0, Culture=neutral, PublicKeyToken=38326cb7e06851fc + ArdupilotMega.HorizontalProgressBar2, ArdupilotMegaPlanner, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null tabRadioIn @@ -2263,7 +484,7 @@ Then subtract 0.3v from that value and enter it in field #1 at left. BAR6 - ArdupilotMega.HorizontalProgressBar2, ArdupilotMegaPlanner, Version=1.0.0.0, Culture=neutral, PublicKeyToken=38326cb7e06851fc + ArdupilotMega.HorizontalProgressBar2, ArdupilotMegaPlanner, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null tabRadioIn @@ -2284,7 +505,7 @@ Then subtract 0.3v from that value and enter it in field #1 at left. BAR5 - ArdupilotMega.HorizontalProgressBar2, ArdupilotMegaPlanner, Version=1.0.0.0, Culture=neutral, PublicKeyToken=38326cb7e06851fc + ArdupilotMega.HorizontalProgressBar2, ArdupilotMegaPlanner, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null tabRadioIn @@ -2305,7 +526,7 @@ Then subtract 0.3v from that value and enter it in field #1 at left. BARpitch - ArdupilotMega.VerticalProgressBar2, ArdupilotMegaPlanner, Version=1.0.0.0, Culture=neutral, PublicKeyToken=38326cb7e06851fc + ArdupilotMega.VerticalProgressBar2, ArdupilotMegaPlanner, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null tabRadioIn @@ -2326,7 +547,7 @@ Then subtract 0.3v from that value and enter it in field #1 at left. BARthrottle - ArdupilotMega.VerticalProgressBar2, ArdupilotMegaPlanner, Version=1.0.0.0, Culture=neutral, PublicKeyToken=38326cb7e06851fc + ArdupilotMega.VerticalProgressBar2, ArdupilotMegaPlanner, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null tabRadioIn @@ -2347,7 +568,7 @@ Then subtract 0.3v from that value and enter it in field #1 at left. BARyaw - ArdupilotMega.HorizontalProgressBar2, ArdupilotMegaPlanner, Version=1.0.0.0, Culture=neutral, PublicKeyToken=38326cb7e06851fc + ArdupilotMega.HorizontalProgressBar2, ArdupilotMegaPlanner, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null tabRadioIn @@ -2368,7 +589,7 @@ Then subtract 0.3v from that value and enter it in field #1 at left. BARroll - ArdupilotMega.HorizontalProgressBar2, ArdupilotMegaPlanner, Version=1.0.0.0, Culture=neutral, PublicKeyToken=38326cb7e06851fc + ArdupilotMega.HorizontalProgressBar2, ArdupilotMegaPlanner, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null tabRadioIn @@ -2376,6 +597,33 @@ Then subtract 0.3v from that value and enter it in field #1 at left. 13 + + 4, 22 + + + 3, 3, 3, 3 + + + 666, 393 + + + 0 + + + Radio Input + + + tabRadioIn + + + System.Windows.Forms.TabPage, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tabControl1 + + + 0 + True @@ -3199,7 +1447,7 @@ Then subtract 0.3v from that value and enter it in field #1 at left. BUT_SaveModes - ArdupilotMega.MyButton, ArdupilotMegaPlanner, Version=1.0.0.0, Culture=neutral, PublicKeyToken=38326cb7e06851fc + ArdupilotMega.MyButton, ArdupilotMegaPlanner, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null tabModes @@ -3207,6 +1455,30 @@ Then subtract 0.3v from that value and enter it in field #1 at left. 28 + + 4, 22 + + + 666, 393 + + + 3 + + + Modes + + + tabModes + + + System.Windows.Forms.TabPage, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tabControl1 + + + 1 + NoControl @@ -3567,6 +1839,33 @@ Then subtract 0.3v from that value and enter it in field #1 at left. 12 + + 4, 22 + + + 3, 3, 3, 3 + + + 666, 393 + + + 1 + + + Hardware + + + tabHardware + + + System.Windows.Forms.TabPage, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tabControl1 + + + 2 + True @@ -3852,6 +2151,288 @@ Then subtract 0.3v from that value and enter it in field #1 at left. 9 + + 31, 177 + + + 238, 131 + + + 41 + + + Calibration + + + groupBox4 + + + System.Windows.Forms.GroupBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tabBattery + + + 0 + + + NoControl + + + 123, 76 + + + 42, 13 + + + 40 + + + Sensor + + + label47 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tabBattery + + + 1 + + + 0: Other + + + 1: AttoPilot 45A + + + 2: AttoPilot 90A + + + 3: AttoPilot 180A + + + 177, 73 + + + 121, 21 + + + 39 + + + CMB_batmonsensortype + + + System.Windows.Forms.ComboBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tabBattery + + + 2 + + + Microsoft Sans Serif, 8.25pt + + + 299, 177 + + + 2, 2, 2, 2 + + + True + + + 219, 131 + + + 28 + + + Voltage sensor calibration: +To calibrate your sensor, use a multimeter to measure the voltage coming out of your ESC's battery-elimination circuit (these are black and red wires in the three-wire cable that is powering your APM board). +Then subtract 0.3v from that value and enter it in field #1 at left. + + + + textBox3 + + + System.Windows.Forms.TextBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tabBattery + + + 3 + + + True + + + NoControl + + + 305, 50 + + + 48, 13 + + + 23 + + + Capacity + + + label29 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tabBattery + + + 4 + + + NoControl + + + 123, 50 + + + 42, 13 + + + 24 + + + Monitor + + + label30 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tabBattery + + + 5 + + + 366, 47 + + + 83, 20 + + + 25 + + + TXT_battcapacity + + + System.Windows.Forms.TextBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tabBattery + + + 6 + + + 0: Disabled + + + 3: Battery Volts + + + 4: Volts & Current + + + 177, 46 + + + 121, 21 + + + 26 + + + CMB_batmontype + + + System.Windows.Forms.ComboBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tabBattery + + + 7 + + + Zoom + + + NoControl + + + 31, 21 + + + 75, 75 + + + 2 + + + pictureBox5 + + + System.Windows.Forms.PictureBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tabBattery + + + 8 + + + 4, 22 + + + 2, 2, 2, 2 + + + 666, 393 + + + 6 + + + Battery + + + tabBattery + + + System.Windows.Forms.TabPage, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tabControl1 + + + 3 + True @@ -4016,7 +2597,7 @@ will work with hexa's etc BUT_levelac2 - ArdupilotMega.MyButton, ArdupilotMegaPlanner, Version=1.0.0.0, Culture=neutral, PublicKeyToken=38326cb7e06851fc + ArdupilotMega.MyButton, ArdupilotMegaPlanner, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null tabArducopter @@ -4024,6 +2605,30 @@ will work with hexa's etc 5 + + 4, 22 + + + 666, 393 + + + 2 + + + ArduCopter2 + + + tabArducopter + + + System.Windows.Forms.TabPage, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tabControl1 + + + 4 + NoControl @@ -4043,7 +2648,7 @@ will work with hexa's etc BUT_HS4save - ArdupilotMega.MyButton, ArdupilotMegaPlanner, Version=1.0.0.0, Culture=neutral, PublicKeyToken=38326cb7e06851fc + ArdupilotMega.MyButton, ArdupilotMegaPlanner, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null tabHeli @@ -4070,7 +2675,7 @@ will work with hexa's etc BUT_swash_manual - ArdupilotMega.MyButton, ArdupilotMegaPlanner, Version=1.0.0.0, Culture=neutral, PublicKeyToken=38326cb7e06851fc + ArdupilotMega.MyButton, ArdupilotMegaPlanner, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null tabHeli @@ -4078,78 +2683,6 @@ will work with hexa's etc 1 - - label46 - - - System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - groupBox3 - - - 0 - - - label45 - - - System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - groupBox3 - - - 1 - - - GYR_ENABLE_ - - - System.Windows.Forms.CheckBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - groupBox3 - - - 2 - - - GYR_GAIN_ - - - System.Windows.Forms.TextBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - groupBox3 - - - 3 - - - 433, 271 - - - 101, 63 - - - 135 - - - Gyro - - - groupBox3 - - - System.Windows.Forms.GroupBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - tabHeli - - - 2 - True @@ -4261,6 +2794,30 @@ will work with hexa's etc 3 + + 433, 271 + + + 101, 63 + + + 135 + + + Gyro + + + groupBox3 + + + System.Windows.Forms.GroupBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tabHeli + + + 2 + True @@ -4351,75 +2908,6 @@ will work with hexa's etc 5 - - label24 - - - System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - groupBox2 - - - 0 - - - HS4_MIN - - - System.Windows.Forms.TextBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - groupBox2 - - - 1 - - - HS4_MAX - - - System.Windows.Forms.TextBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - groupBox2 - - - 2 - - - label40 - - - System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - groupBox2 - - - 3 - - - 433, 143 - - - 169, 78 - - - 130 - - - groupBox2 - - - System.Windows.Forms.GroupBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - tabHeli - - - 6 - True @@ -4534,98 +3022,26 @@ will work with hexa's etc 3 - - label41 + + 433, 143 - - System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + 169, 78 - - groupBox1 + + 130 - - 0 + + groupBox2 - - label21 - - - System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - groupBox1 - - - 1 - - - COL_MIN_ - - - System.Windows.Forms.TextBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - groupBox1 - - - 2 - - - COL_MID_ - - - System.Windows.Forms.TextBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - groupBox1 - - - 3 - - - COL_MAX_ - - - System.Windows.Forms.TextBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - groupBox1 - - - 4 - - - BUT_0collective - - - ArdupilotMega.MyButton, ArdupilotMegaPlanner, Version=1.0.0.0, Culture=neutral, PublicKeyToken=38326cb7e06851fc - - - groupBox1 - - - 5 - - - 293, 52 - - - 80, 209 - - - 129 - - - groupBox1 - - + System.Windows.Forms.GroupBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + tabHeli - - 7 + + 6 True @@ -4790,7 +3206,7 @@ will work with hexa's etc BUT_0collective - ArdupilotMega.MyButton, ArdupilotMegaPlanner, Version=1.0.0.0, Culture=neutral, PublicKeyToken=38326cb7e06851fc + ArdupilotMega.MyButton, ArdupilotMegaPlanner, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null groupBox1 @@ -4798,6 +3214,27 @@ will work with hexa's etc 5 + + 293, 52 + + + 80, 209 + + + 129 + + + groupBox1 + + + System.Windows.Forms.GroupBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tabHeli + + + 7 + 535, 241 @@ -5483,7 +3920,7 @@ will work with hexa's etc HS4 - ArdupilotMega.HorizontalProgressBar2, ArdupilotMegaPlanner, Version=1.0.0.0, Culture=neutral, PublicKeyToken=38326cb7e06851fc + ArdupilotMega.HorizontalProgressBar2, ArdupilotMegaPlanner, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null tabHeli @@ -5504,7 +3941,7 @@ will work with hexa's etc HS3 - ArdupilotMega.VerticalProgressBar2, ArdupilotMegaPlanner, Version=1.0.0.0, Culture=neutral, PublicKeyToken=38326cb7e06851fc + ArdupilotMega.VerticalProgressBar2, ArdupilotMegaPlanner, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null tabHeli @@ -5534,7 +3971,7 @@ will work with hexa's etc Gservoloc - AGaugeApp.AGauge, ArdupilotMegaPlanner, Version=1.0.0.0, Culture=neutral, PublicKeyToken=38326cb7e06851fc + AGaugeApp.AGauge, ArdupilotMegaPlanner, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null tabHeli @@ -5542,11 +3979,74 @@ will work with hexa's etc 35 + + 4, 22 + + + 666, 393 + + + 5 + + + AC2 Heli + + + tabHeli + + + System.Windows.Forms.TabPage, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tabControl1 + + + 5 + + + Fill + + + 0, 0 + + + 674, 419 + + + 93 + + + tabControl1 + + + System.Windows.Forms.TabControl, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 0 + + + NoControl + + + 214, 161 + + + 195, 23 + + + 0 + + + Reset APM Hardware to Default + BUT_reset - ArdupilotMega.MyButton, ArdupilotMegaPlanner, Version=1.0.0.0, Culture=neutral, PublicKeyToken=38326cb7e06851fc + ArdupilotMega.MyButton, ArdupilotMegaPlanner, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null tabReset @@ -5572,33 +4072,6 @@ will work with hexa's etc System.Windows.Forms.TabPage, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - NoControl - - - 214, 161 - - - 195, 23 - - - 0 - - - Reset APM Hardware to Default - - - BUT_reset - - - ArdupilotMega.MyButton, ArdupilotMegaPlanner, Version=1.0.0.0, Culture=neutral, PublicKeyToken=38326cb7e06851fc - - - tabReset - - - 0 - True diff --git a/Tools/ArdupilotMegaPlanner/ThemeManager.cs b/Tools/ArdupilotMegaPlanner/ThemeManager.cs index 7723eb9dd3..47bf8b5c24 100644 --- a/Tools/ArdupilotMegaPlanner/ThemeManager.cs +++ b/Tools/ArdupilotMegaPlanner/ThemeManager.cs @@ -61,10 +61,14 @@ namespace ArdupilotMega private static void ApplyBurntKermitTheme(Control temp, int level) { + Color BGColor = Color.FromArgb(0x26, 0x27, 0x28); // background + Color ControlBGColor = Color.FromArgb(0x43, 0x44, 0x45); // editable bg color + Color TextColor = Color.White; + if (level == 0) { - temp.BackColor = Color.FromArgb(0x26, 0x27, 0x28); - temp.ForeColor = Color.White;// Color.FromArgb(0xe6, 0xe8, 0xea); + temp.BackColor = BGColor; + temp.ForeColor = TextColor;// Color.FromArgb(0xe6, 0xe8, 0xea); } //temp.Font = new Font("Lucida Console", 8.25f); @@ -75,24 +79,34 @@ namespace ArdupilotMega { ctl.ForeColor = Color.Black; } + else if (ctl.GetType() == typeof(MyButton)) + { + Color PrimeColor = Color.FromArgb(0x94, 0xc1, 0x1f); + + MyButton but = (MyButton)ctl; + //but.BGGradTop = Color.FromArgb(PrimeColor.R, PrimeColor.G, PrimeColor.B); + //but.BGGradBot = Color.FromArgb(255 - (int)(PrimeColor.R * 0.27), 255 - (int)(PrimeColor.G * 0.14), 255 - (int)(PrimeColor.B * 0.79)); + //but.ForeColor = Color.FromArgb(0x40, 0x57, 0x04); //Color.FromArgb(255 - (int)(PrimeColor.R * 0.7), 255 - (int)(PrimeColor.G * 0.8), 255 - (int)(PrimeColor.B * 0.1)); + //but.Outline = ControlBGColor; + } else if (ctl.GetType() == typeof(TextBox)) { - ctl.BackColor = Color.FromArgb(0x43, 0x44, 0x45); - ctl.ForeColor = Color.White;// Color.FromArgb(0xe6, 0xe8, 0xea); + ctl.BackColor = ControlBGColor; + ctl.ForeColor = TextColor;// Color.FromArgb(0xe6, 0xe8, 0xea); TextBox txt = (TextBox)ctl; txt.BorderStyle = BorderStyle.None; } else if (ctl.GetType() == typeof(DomainUpDown)) { - ctl.BackColor = Color.FromArgb(0x43, 0x44, 0x45); - ctl.ForeColor = Color.White;// Color.FromArgb(0xe6, 0xe8, 0xea); + ctl.BackColor = ControlBGColor; + ctl.ForeColor = TextColor;// Color.FromArgb(0xe6, 0xe8, 0xea); DomainUpDown txt = (DomainUpDown)ctl; txt.BorderStyle = BorderStyle.None; } else if (ctl.GetType() == typeof(GroupBox)) { - ctl.BackColor = Color.FromArgb(0x26, 0x27, 0x28); - ctl.ForeColor = Color.White;// Color.FromArgb(0xe6, 0xe8, 0xea); + ctl.BackColor = BGColor; + ctl.ForeColor = TextColor;// Color.FromArgb(0xe6, 0xe8, 0xea); } else if (ctl.GetType() == typeof(ZedGraph.ZedGraphControl)) { @@ -103,7 +117,7 @@ namespace ArdupilotMega foreach (ZedGraph.LineItem li in zg1.GraphPane.CurveList) li.Line.Width = 4; - zg1.GraphPane.Title.FontSpec.FontColor = Color.White; + zg1.GraphPane.Title.FontSpec.FontColor = TextColor; zg1.GraphPane.XAxis.MajorTic.Color = Color.White; zg1.GraphPane.XAxis.MinorTic.Color = Color.White; @@ -120,95 +134,95 @@ namespace ArdupilotMega zg1.GraphPane.XAxis.Title.FontSpec.FontColor = Color.White; zg1.GraphPane.Legend.Fill = new ZedGraph.Fill(Color.FromArgb(0x85, 0x84, 0x83)); - zg1.GraphPane.Legend.FontSpec.FontColor = Color.White; + zg1.GraphPane.Legend.FontSpec.FontColor = TextColor; } else if (ctl.GetType() == typeof(BSE.Windows.Forms.Panel) || ctl.GetType() == typeof(SplitterPanel)) { - ctl.BackColor = Color.FromArgb(0x26, 0x27, 0x28); - ctl.ForeColor = Color.White;// Color.FromArgb(0xe6, 0xe8, 0xea); + ctl.BackColor = BGColor; + ctl.ForeColor = TextColor;// Color.FromArgb(0xe6, 0xe8, 0xea); } else if (ctl.GetType() == typeof(Form)) { - ctl.BackColor = Color.FromArgb(0x26, 0x27, 0x28); - ctl.ForeColor = Color.White;// Color.FromArgb(0xe6, 0xe8, 0xea); + ctl.BackColor = BGColor; + ctl.ForeColor = TextColor;// Color.FromArgb(0xe6, 0xe8, 0xea); } else if (ctl.GetType() == typeof(RichTextBox)) { - ctl.BackColor = Color.FromArgb(0x43, 0x44, 0x45); - ctl.ForeColor = Color.White; + ctl.BackColor = ControlBGColor; + ctl.ForeColor = TextColor; RichTextBox txtr = (RichTextBox)ctl; txtr.BorderStyle = BorderStyle.None; } else if (ctl.GetType() == typeof(CheckedListBox)) { - ctl.BackColor = Color.FromArgb(0x43, 0x44, 0x45); - ctl.ForeColor = Color.White; + ctl.BackColor = ControlBGColor; + ctl.ForeColor = TextColor; CheckedListBox txtr = (CheckedListBox)ctl; txtr.BorderStyle = BorderStyle.None; } else if (ctl.GetType() == typeof(TabPage)) { - ctl.BackColor = Color.FromArgb(0x26, 0x27, 0x28); //Color.FromArgb(0x43, 0x44, 0x45); - ctl.ForeColor = Color.White; + ctl.BackColor = BGColor; //ControlBGColor + ctl.ForeColor = TextColor; TabPage txtr = (TabPage)ctl; txtr.BorderStyle = BorderStyle.None; } else if (ctl.GetType() == typeof(TabControl)) { - ctl.BackColor = Color.FromArgb(0x26, 0x27, 0x28); //Color.FromArgb(0x43, 0x44, 0x45); - ctl.ForeColor = Color.White; + ctl.BackColor = BGColor; //ControlBGColor + ctl.ForeColor = TextColor; TabControl txtr = (TabControl)ctl; } else if (ctl.GetType() == typeof(DataGridView)) { - ctl.ForeColor = Color.White; + ctl.ForeColor = TextColor; DataGridView dgv = (DataGridView)ctl; dgv.EnableHeadersVisualStyles = false; dgv.BorderStyle = BorderStyle.None; - dgv.BackgroundColor = Color.FromArgb(0x26, 0x27, 0x28); + dgv.BackgroundColor = BGColor; DataGridViewCellStyle rs = new DataGridViewCellStyle(); - rs.BackColor = Color.FromArgb(0x43, 0x44, 0x45); - rs.ForeColor = Color.White; + rs.BackColor = ControlBGColor; + rs.ForeColor = TextColor; dgv.RowsDefaultCellStyle = rs; DataGridViewCellStyle hs = new DataGridViewCellStyle(dgv.ColumnHeadersDefaultCellStyle); - hs.BackColor = Color.FromArgb(0x26, 0x27, 0x28); - hs.ForeColor = Color.White; + hs.BackColor = BGColor; + hs.ForeColor = TextColor; dgv.ColumnHeadersDefaultCellStyle = hs; dgv.RowHeadersDefaultCellStyle = hs; } else if (ctl.GetType() == typeof(ComboBox)) { - ctl.BackColor = Color.FromArgb(0x43, 0x44, 0x45); - ctl.ForeColor = Color.White; + ctl.BackColor = ControlBGColor; + ctl.ForeColor = TextColor; ComboBox CMB = (ComboBox)ctl; CMB.FlatStyle = FlatStyle.Flat; } else if (ctl.GetType() == typeof(NumericUpDown)) { - ctl.BackColor = Color.FromArgb(0x43, 0x44, 0x45); - ctl.ForeColor = Color.White; + ctl.BackColor = ControlBGColor; + ctl.ForeColor = TextColor; } else if (ctl.GetType() == typeof(TrackBar)) { - ctl.BackColor = Color.FromArgb(0x26, 0x27, 0x28); - ctl.ForeColor = Color.White; + ctl.BackColor = BGColor; + ctl.ForeColor = TextColor; } else if (ctl.GetType() == typeof(LinkLabel)) { - ctl.BackColor = Color.FromArgb(0x26, 0x27, 0x28); - ctl.ForeColor = Color.White; + ctl.BackColor = BGColor; + ctl.ForeColor = TextColor; LinkLabel LNK = (LinkLabel)ctl; - LNK.ActiveLinkColor = Color.White; - LNK.LinkColor = Color.White; - LNK.VisitedLinkColor = Color.White; + LNK.ActiveLinkColor = TextColor; + LNK.LinkColor = TextColor; + LNK.VisitedLinkColor = TextColor; } else if (ctl.GetType() == typeof(HorizontalProgressBar2) || ctl.GetType() == typeof(VerticalProgressBar2)) { - ((HorizontalProgressBar2)ctl).BackgroundColor = Color.FromArgb(0x43, 0x44, 0x45); + ((HorizontalProgressBar2)ctl).BackgroundColor = ControlBGColor; ((HorizontalProgressBar2)ctl).ValueColor = Color.FromArgb(148, 193, 31); } diff --git a/Tools/ArdupilotMegaPlanner/bin/Release/.gitignore b/Tools/ArdupilotMegaPlanner/bin/Release/.gitignore index f792876120..7ddb7730c7 100644 --- a/Tools/ArdupilotMegaPlanner/bin/Release/.gitignore +++ b/Tools/ArdupilotMegaPlanner/bin/Release/.gitignore @@ -1,2 +1,3 @@ *.pdb -*.etag \ No newline at end of file +*.etag +*.new \ No newline at end of file diff --git a/Tools/ArdupilotMegaPlanner/bin/Release/ArdupilotMegaPlanner.pdb b/Tools/ArdupilotMegaPlanner/bin/Release/ArdupilotMegaPlanner.pdb index ae1895b403c936d8e5fe53069f471c0fd129fc26..2f372e4f1d72a1432f363f72a37cd83be899bb1b 100644 GIT binary patch delta 273459 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 CJ3b!( delta 260742 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%0D!8JoS+QbP1&)6^R(uD?%Wad^p*`pVx{b;OF_xjO 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�Hs*V6t!%0A_PLryFIKQPSU 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 z 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 Date: Tue, 6 Mar 2012 20:55:15 -0800 Subject: [PATCH 012/178] Updated on Barometer - increased the Temp filtering and decreased the pressure filtering to and get less temp noise, faster response from pressure. I'm filtering the Climb rate differently now, so this higher pressure noise should not hurt the derivative calcs at all now. --- libraries/AP_Baro/AP_Baro_BMP085.cpp | 32 ++++++---------------------- libraries/AP_Baro/AP_Baro_BMP085.h | 5 +---- 2 files changed, 8 insertions(+), 29 deletions(-) diff --git a/libraries/AP_Baro/AP_Baro_BMP085.cpp b/libraries/AP_Baro/AP_Baro_BMP085.cpp index cf2b1bd527..d5790feb0d 100644 --- a/libraries/AP_Baro/AP_Baro_BMP085.cpp +++ b/libraries/AP_Baro/AP_Baro_BMP085.cpp @@ -67,7 +67,7 @@ extern "C" { bool AP_Baro_BMP085::init( AP_PeriodicProcess * scheduler ) { byte buff[22]; - + pinMode(BMP085_EOC, INPUT); // End Of Conversion (PC7) input BMP085_State = 0; // Initial state @@ -207,6 +207,7 @@ void AP_Baro_BMP085::Command_ReadTemp() void AP_Baro_BMP085::ReadTemp() { uint8_t buf[2]; + int32_t _temp_sensor; if (!healthy && millis() < _retry_time) { return; @@ -218,32 +219,13 @@ void AP_Baro_BMP085::ReadTemp() healthy = false; return; } - RawTemp = buf[0]; - RawTemp = (RawTemp << 8) | buf[1]; + _temp_sensor = buf[0]; + _temp_sensor = (_temp_sensor << 8) | buf[1]; - if (_offset_temp == 0){ - _offset_temp = RawTemp; - RawTemp = 0; - } else { - RawTemp -= _offset_temp; - } + if (RawTemp == 0) + RawTemp = _temp_sensor; - // filter - _temp_filter[_temp_index++] = RawTemp; - - if(_temp_index >= TEMP_FILTER_SIZE) - _temp_index = 0; - - RawTemp = 0; - // sum our filter - for(uint8_t i = 0; i < TEMP_FILTER_SIZE; i++){ - RawTemp += _temp_filter[i]; - } - - // grab result - RawTemp /= TEMP_FILTER_SIZE; - //RawTemp >>= 4; - RawTemp += _offset_temp; + RawTemp = (float)_temp_sensor * .01 + (float)RawTemp * .99; } // Calculate Temperature and Pressure in real units. diff --git a/libraries/AP_Baro/AP_Baro_BMP085.h b/libraries/AP_Baro/AP_Baro_BMP085.h index b7d5ede9b5..b7b329edd9 100644 --- a/libraries/AP_Baro/AP_Baro_BMP085.h +++ b/libraries/AP_Baro/AP_Baro_BMP085.h @@ -2,8 +2,7 @@ #ifndef __AP_BARO_BMP085_H__ #define __AP_BARO_BMP085_H__ -#define TEMP_FILTER_SIZE 4 -#define PRESS_FILTER_SIZE 8 +#define PRESS_FILTER_SIZE 2 #include "AP_Baro.h" @@ -41,9 +40,7 @@ class AP_Baro_BMP085 : public AP_Baro int16_t ac1, ac2, ac3, b1, b2, mb, mc, md; uint16_t ac4, ac5, ac6; - int16_t _temp_filter[TEMP_FILTER_SIZE]; int32_t _press_filter[PRESS_FILTER_SIZE]; - int32_t _offset_temp; uint8_t _temp_index; uint8_t _press_index; From c26eb6afcc101e826c2b245f12c8572274083fe5 Mon Sep 17 00:00:00 2001 From: Jason Short Date: Tue, 6 Mar 2012 22:12:24 -0800 Subject: [PATCH 013/178] ACM: Updated config values --- ArduCopter/config.h | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/ArduCopter/config.h b/ArduCopter/config.h index 3435cec68c..78376add1c 100644 --- a/ArduCopter/config.h +++ b/ArduCopter/config.h @@ -578,7 +578,7 @@ # define STABILIZE_ROLL_P 4.5 #endif #ifndef STABILIZE_ROLL_I -# define STABILIZE_ROLL_I 0.0 +# define STABILIZE_ROLL_I 0.1 #endif #ifndef STABILIZE_ROLL_IMAX # define STABILIZE_ROLL_IMAX 40 // degrees @@ -588,7 +588,7 @@ # define STABILIZE_PITCH_P 4.5 #endif #ifndef STABILIZE_PITCH_I -# define STABILIZE_PITCH_I 0.0 +# define STABILIZE_PITCH_I 0.1 #endif #ifndef STABILIZE_PITCH_IMAX # define STABILIZE_PITCH_IMAX 40 // degrees @@ -615,7 +615,7 @@ # define RATE_ROLL_I 0.0 #endif #ifndef RATE_ROLL_D -# define RATE_ROLL_D 0.002 +# define RATE_ROLL_D 0.000 //.002 #endif #ifndef RATE_ROLL_IMAX # define RATE_ROLL_IMAX 5 // degrees @@ -628,7 +628,7 @@ # define RATE_PITCH_I 0.0 #endif #ifndef RATE_PITCH_D -# define RATE_PITCH_D 0.002 +# define RATE_PITCH_D 0.00 #endif #ifndef RATE_PITCH_IMAX # define RATE_PITCH_IMAX 5 // degrees @@ -641,7 +641,7 @@ # define RATE_YAW_I 0.0 #endif #ifndef RATE_YAW_D -# define RATE_YAW_D .000 +# define RATE_YAW_D 0.000 #endif #ifndef RATE_YAW_IMAX # define RATE_YAW_IMAX 50 // degrees @@ -649,18 +649,18 @@ #ifndef STABILIZE_D -# define STABILIZE_D 0.1 +# define STABILIZE_D 0.15 #endif #ifndef STABILIZE_D_SCHEDULE -# define STABILIZE_D_SCHEDULE 0.0 +# define STABILIZE_D_SCHEDULE 0.5 #endif ////////////////////////////////////////////////////////////////////////////// // Loiter control gains // #ifndef LOITER_P -# define LOITER_P .8 +# define LOITER_P .4 #endif #ifndef LOITER_I # define LOITER_I 0.0 @@ -677,10 +677,10 @@ #endif #ifndef LOITER_RATE_P -# define LOITER_RATE_P 3.5 // +# define LOITER_RATE_P 3.0 // #endif #ifndef LOITER_RATE_I -# define LOITER_RATE_I 0.2 // Wind control +# define LOITER_RATE_I 0.25 // Wind control #endif #ifndef LOITER_RATE_D # define LOITER_RATE_D 0.0 // try 2 or 3 for LOITER_RATE 1 @@ -693,10 +693,10 @@ // WP Navigation control gains // #ifndef NAV_P -# define NAV_P 3.5 // +# define NAV_P 3.0 // #endif #ifndef NAV_I -# define NAV_I 0.2 // Wind control +# define NAV_I 0.25 // Wind control #endif #ifndef NAV_D # define NAV_D 0.00 // @@ -727,10 +727,10 @@ #endif #ifndef ALT_HOLD_P -# define ALT_HOLD_P 0.4 // +# define ALT_HOLD_P 0.2 // #endif #ifndef ALT_HOLD_I -# define ALT_HOLD_I 0.04 +# define ALT_HOLD_I 0.015 #endif #ifndef ALT_HOLD_IMAX # define ALT_HOLD_IMAX 300 @@ -738,7 +738,7 @@ // RATE control #ifndef THROTTLE_P -# define THROTTLE_P 0.35 // +# define THROTTLE_P 0.45 // #endif #ifndef THROTTLE_I # define THROTTLE_I 0.0 // From 730476fdfd343981deda6f712dcbee0d3cf23727 Mon Sep 17 00:00:00 2001 From: Jason Short Date: Tue, 6 Mar 2012 22:22:14 -0800 Subject: [PATCH 014/178] ACM - Implemented automatic ranging of Alt Hold gains. Works well in simulator and testing. - alt hold estimation moved to 50 hz - simple fixed observer calc for smooth and accurate climb rates useful for derivative calcs - auto-reset of the I term by moving I value into throttle value. This recalcs the gain every 20seconds for battery drainage compensation in long flights. - remove filtering for Nav_throttle - added a way to lower the gain on nav_throttle for descents by / climb_rate error by 2 - seems to work OK and keeps copter from dropping like a rock when the Baro drifts quickly lower. - removed old throttle hold set point code - made throttle override for alt hold +- 200 vs 250 --- ArduCopter/ArduCopter.pde | 110 ++++++++++++++++++++--------------- ArduCopter/Attitude.pde | 16 ++--- ArduCopter/config.h | 2 +- ArduCopter/control_modes.pde | 3 - ArduCopter/system.pde | 26 ++------- 5 files changed, 78 insertions(+), 79 deletions(-) diff --git a/ArduCopter/ArduCopter.pde b/ArduCopter/ArduCopter.pde index f59fe98a26..ad3dcefb28 100644 --- a/ArduCopter/ArduCopter.pde +++ b/ArduCopter/ArduCopter.pde @@ -568,7 +568,11 @@ static int32_t ground_pressure; static int16_t ground_temperature; // The cm we are off in altitude from next_WP.alt – Positive value means we are below the WP static int32_t altitude_error; -// The cm/s we are moving up or down - Positive = UP +// The cm/s we are moving up or down based on sensor data - Positive = UP +static int16_t climb_rate_actual; +// Used to dither our climb_rate over 50hz +static int16_t climb_rate_error; +// The cm/s we are moving up or down based on filtered data - Positive = UP static int16_t climb_rate; // The altitude as reported by Sonar in cm – Values are 20 to 700 generally. static int16_t sonar_alt; @@ -578,8 +582,10 @@ static int16_t sonar_rate; static int32_t baro_alt; // The climb_rate as reported by Baro in cm/s static int16_t baro_rate; -// +// used to switch out of Manual Boost static boolean reset_throttle_flag; +// used to track when to read sensors vs estimate alt +static boolean alt_sensor_flag; //////////////////////////////////////////////////////////////////////////////// @@ -690,13 +696,6 @@ static int16_t nav_throttle; // 0-1000 for throttle control // This is a simple counter to track the amount of throttle used during flight // This could be useful later in determining and debuging current usage and predicting battery life static uint32_t throttle_integrator; -// This is a future value for replacing the throttle_cruise setup procedure. It's an average of throttle control -// that is generated when the climb rate is within a certain threshold -//static float throttle_avg = THROTTLE_CRUISE; -// This is a flag used to trigger the updating of nav_throttle at 10hz -static bool invalid_throttle; -// Used to track the altitude offset for climbrate control -//static int32_t target_altitude; //////////////////////////////////////////////////////////////////////////////// // Climb rate control @@ -1005,8 +1004,9 @@ static void medium_loop() // ----------------------------- update_navigation(); - if (g.log_bitmask & MASK_LOG_NTUN) + if (g.log_bitmask & MASK_LOG_NTUN && motor_armed){ Log_Write_Nav_Tuning(); + } } } break; @@ -1018,13 +1018,10 @@ static void medium_loop() // Read altitude from sensors // -------------------------- - #if HIL_MODE != HIL_MODE_ATTITUDE // don't execute in HIL mode - update_altitude(); - #endif - - // invalidate the throttle hold value - // ---------------------------------- - invalid_throttle = true; + //#if HIL_MODE != HIL_MODE_ATTITUDE // don't execute in HIL mode + //update_altitude(); + //#endif + alt_sensor_flag = true; break; @@ -1045,16 +1042,13 @@ static void medium_loop() if (g.log_bitmask & MASK_LOG_ATTITUDE_MED) Log_Write_Attitude(); - if (g.log_bitmask & MASK_LOG_CTUN) - Log_Write_Control_Tuning(); + if (g.log_bitmask & MASK_LOG_MOTORS) + Log_Write_Motors(); } - // send all requested output streams with rates requested - // between 5 and 45 Hz - gcs_data_stream_send(5,45); - - if (g.log_bitmask & MASK_LOG_MOTORS) - Log_Write_Motors(); + // send all requested output streams with rates requested + // between 5 and 45 Hz + gcs_data_stream_send(5,45); break; @@ -1102,6 +1096,10 @@ static void medium_loop() // --------------------------- static void fifty_hz_loop() { + // read altitude sensors or estimate altitude + // ------------------------------------------ + update_altitude_est(); + // moved to slower loop // -------------------- update_throttle_mode(); @@ -1162,6 +1160,11 @@ static void slow_loop() slow_loopCounter++; superslow_loopCounter++; + // update throttle hold every 20 seconds + if(superslow_loopCounter > 60){ + update_throttle_cruise(); + } + if(superslow_loopCounter > 1200){ #if HIL_MODE != HIL_MODE_ATTITUDE if(g.rc_3.control_in == 0 && control_mode == STABILIZE && g.compass_enabled){ @@ -1219,13 +1222,14 @@ static void slow_loop() // 1Hz loop static void super_slow_loop() { - if (g.log_bitmask & MASK_LOG_CUR) + if (g.log_bitmask & MASK_LOG_CUR && motor_armed) Log_Write_Current(); // this function disarms the copter if it has been sitting on the ground for any moment of time greater than 30s // but only of the control mode is manual if((control_mode <= ACRO) && (g.rc_3.control_in == 0)){ auto_disarming_counter++; + if(auto_disarming_counter == AUTO_ARMING_DELAY){ init_disarm_motors(); }else if (auto_disarming_counter > AUTO_ARMING_DELAY){ @@ -1234,8 +1238,10 @@ static void super_slow_loop() }else{ auto_disarming_counter = 0; } + gcs_send_message(MSG_HEARTBEAT); gcs_data_stream_send(1,3); + // agmatthews - USERHOOKS #ifdef USERHOOK_SUPERSLOWLOOP USERHOOK_SUPERSLOWLOOP @@ -1359,12 +1365,13 @@ static void update_GPS(void) current_loc.lng = g_gps->longitude; // Lon * 10 * *7 current_loc.lat = g_gps->latitude; // Lat * 10 * *7 - if (g.log_bitmask & MASK_LOG_GPS){ + if (g.log_bitmask & MASK_LOG_GPS && motor_armed){ Log_Write_GPS(); } #if HIL_MODE == HIL_MODE_ATTITUDE // only execute in HIL mode - update_altitude(); + //update_altitude(); + alt_sensor_flag = true; #endif } @@ -1635,10 +1642,10 @@ void update_throttle_mode(void) if(reset_throttle_flag) { set_new_altitude(max(current_loc.alt, 100)); reset_throttle_flag = false; + update_throttle_cruise(); } - // 10hz, don't run up i term - if(invalid_throttle && motor_auto_armed == true){ + if(motor_auto_armed == true){ // how far off are we altitude_error = get_altitude_error(); @@ -1646,8 +1653,6 @@ void update_throttle_mode(void) // get the AP throttle nav_throttle = get_nav_throttle(altitude_error); - // clear the new data flag - invalid_throttle = false; /* Serial.printf("tar_alt: %d, actual_alt: %d \talt_err: %d, \tnav_thr: %d, \talt Int: %d\n", next_WP.alt, @@ -1656,6 +1661,7 @@ void update_throttle_mode(void) nav_throttle, (int16_t)g.pi_alt_hold.get_integrator()); //*/ + } // hack to remove the influence of the ground effect @@ -1864,7 +1870,6 @@ static void update_altitude() { static int16_t old_sonar_alt = 0; static int32_t old_baro_alt = 0; - static int16_t old_climb_rate = 0; #if HIL_MODE == HIL_MODE_ATTITUDE // we are in the SIM, fake out the baro and Sonar @@ -1889,7 +1894,6 @@ static void update_altitude() // Note: sonar_alt is calculated in a faster loop and filtered with a mode filter #endif - if(g.sonar_enabled){ // filter out offset float scale; @@ -1921,35 +1925,47 @@ static void update_altitude() current_loc.alt = ((float)sonar_alt * (1.0 - scale)) + ((float)baro_alt * scale) + home.alt; // solve for a blended climb_rate - climb_rate = ((float)sonar_rate * (1.0 - scale)) + (float)baro_rate * scale; + climb_rate_actual = ((float)sonar_rate * (1.0 - scale)) + (float)baro_rate * scale; }else{ // we must be higher than sonar (>800), don't get tricked by bad sonar reads current_loc.alt = baro_alt + home.alt; // home alt = 0 // dont blend, go straight baro - climb_rate = baro_rate; + climb_rate_actual = baro_rate; } }else{ // NO Sonar case current_loc.alt = baro_alt + home.alt; - climb_rate = baro_rate; + climb_rate_actual = baro_rate; } - // simple smoothing - climb_rate = (climb_rate + old_climb_rate)>>1; - - // manage bad data - climb_rate = constrain(climb_rate, -800, 800); - - // save for filtering - old_climb_rate = climb_rate; - // update the target altitude next_WP.alt = get_new_altitude(); + + // calc error + climb_rate_error = (climb_rate_actual - climb_rate) / 5; } -#define THROTTLE_ADJUST 250 +static void update_altitude_est() +{ + if(alt_sensor_flag){ + update_altitude(); + alt_sensor_flag = false; + + if(g.log_bitmask & MASK_LOG_CTUN && motor_armed){ + Log_Write_Control_Tuning(); + } + + }else{ + // simple dithering of climb rate + climb_rate += climb_rate_error; + current_loc.alt += (climb_rate / 50); + } + //Serial.printf(" %d, %d, %d, %d\n", climb_rate_actual, climb_rate_error, climb_rate, current_loc.alt); +} + +#define THROTTLE_ADJUST 200 static void adjust_altitude() { diff --git a/ArduCopter/Attitude.pde b/ArduCopter/Attitude.pde index a986a3ccaa..dba7ce508d 100644 --- a/ArduCopter/Attitude.pde +++ b/ArduCopter/Attitude.pde @@ -186,7 +186,7 @@ get_rate_yaw(int32_t target_rate) static int16_t get_nav_throttle(int32_t z_error) { - static int16_t old_output = 0; + //static int16_t old_output = 0; int16_t rate_error = 0; int16_t output = 0; @@ -198,19 +198,23 @@ get_nav_throttle(int32_t z_error) z_error = constrain(z_error, -400, 400); // compensates throttle setpoint error for hovering - int16_t iterm = g.pi_alt_hold.get_i(z_error, .1); + int16_t iterm = g.pi_alt_hold.get_i(z_error, .02); // calculate rate error rate_error = rate_error - climb_rate; + // hack to see if we can smooth out oscillations + if(rate_error < 0) + rate_error = rate_error >> 1; + // limit the rate - output = constrain(g.pid_throttle.get_pid(rate_error, .1), -160, 180); + output = constrain(g.pid_throttle.get_pid(rate_error, .02), -80, 120); // light filter of output - output = (old_output + output) / 2; + //output = (old_output + output) / 2; // save our output - old_output = output; + //old_output = output; // output control: return output + iterm; @@ -219,8 +223,6 @@ get_nav_throttle(int32_t z_error) // Keeps old data out of our calculation / logs static void reset_nav_params(void) { - // forces us to update nav throttle - invalid_throttle = true; nav_throttle = 0; // always start Circle mode at same angle diff --git a/ArduCopter/config.h b/ArduCopter/config.h index 78376add1c..fd5be47917 100644 --- a/ArduCopter/config.h +++ b/ArduCopter/config.h @@ -741,7 +741,7 @@ # define THROTTLE_P 0.45 // #endif #ifndef THROTTLE_I -# define THROTTLE_I 0.0 // +# define THROTTLE_I 0.0 // Don't edit #endif #ifndef THROTTLE_D # define THROTTLE_D 0.02 // diff --git a/ArduCopter/control_modes.pde b/ArduCopter/control_modes.pde index bb820aca74..cbfc5615bd 100644 --- a/ArduCopter/control_modes.pde +++ b/ArduCopter/control_modes.pde @@ -186,9 +186,6 @@ static void auto_trim() //Serial.println("Done"); auto_level_counter = 0; - - // set TC - init_throttle_cruise(); } } } diff --git a/ArduCopter/system.pde b/ArduCopter/system.pde index fdea7be828..a3c43799b4 100644 --- a/ArduCopter/system.pde +++ b/ArduCopter/system.pde @@ -532,16 +532,8 @@ static void set_mode(byte mode) motor_auto_armed = true; } - if(throttle_mode == THROTTLE_MANUAL){ - // reset all of the throttle iterms - update_throttle_cruise(); - - // reset auto_throttle - nav_throttle = 0; - }else { - // an automatic throttle - init_throttle_cruise(); - } + // called to calculate gain for alt hold + update_throttle_cruise(); if(roll_pitch_mode <= ROLL_PITCH_ACRO){ // We are under manual attitude control @@ -594,18 +586,10 @@ static void update_throttle_cruise() g.throttle_cruise += tmp; reset_throttle_I(); } -} -static void -init_throttle_cruise() -{ -#if AUTO_THROTTLE_HOLD == 0 - // are we moving from manual throttle to auto_throttle? - if((old_control_mode <= STABILIZE) && (g.rc_3.control_in > MINIMUM_THROTTLE)){ - reset_throttle_I(); - g.throttle_cruise.set_and_save(g.rc_3.control_in); - } -#endif + // recalc kp + g.pid_throttle.kP((float)g.throttle_cruise.get() / 981.0); + //Serial.printf("kp:%1.4f\n",kp); } #if CLI_SLIDER_ENABLED == ENABLED && CLI_ENABLED == ENABLED From c8e9d5756753eb66af3718daa13909cca349b75b Mon Sep 17 00:00:00 2001 From: Jason Short Date: Tue, 6 Mar 2012 22:23:06 -0800 Subject: [PATCH 015/178] temp remove filter for quad motors during testing. It's unlikely this filter did anything at all to be honest. --- ArduCopter/motors_quad.pde | 31 +++++++++++++++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/ArduCopter/motors_quad.pde b/ArduCopter/motors_quad.pde index 54992683bd..8066a382d7 100644 --- a/ArduCopter/motors_quad.pde +++ b/ArduCopter/motors_quad.pde @@ -102,7 +102,7 @@ static void output_motors_armed() // this filter slows the acceleration of motors vs the deceleration // Idea by Denny Rowland to help with his Yaw issue - for(int8_t i = MOT_1; i <= MOT_4; i++){ + /*for(int8_t i = MOT_1; i <= MOT_4; i++){ if(motor_filtered[i] < motor_out[i]){ motor_filtered[i] = (motor_out[i] + motor_filtered[i]) / 2; }else{ @@ -110,11 +110,38 @@ static void output_motors_armed() motor_filtered[i] = motor_out[i]; } } - APM_RC.OutputCh(MOT_1, motor_filtered[MOT_1]); APM_RC.OutputCh(MOT_2, motor_filtered[MOT_2]); APM_RC.OutputCh(MOT_3, motor_filtered[MOT_3]); APM_RC.OutputCh(MOT_4, motor_filtered[MOT_4]); + */ + + + /* + if(g.rc_7.radio_in > 1700){ + for(int8_t i = MOT_1; i <= MOT_4; i++){ + motor_out[i] = (motor_previous[i] * 3 + motor_out[i]) / 4; + motor_previous[i] = motor_out[i]; + } + + APM_RC.OutputCh(MOT_1, motor_out[MOT_1]); + APM_RC.OutputCh(MOT_2, motor_out[MOT_2]); + APM_RC.OutputCh(MOT_3, motor_out[MOT_3]); + APM_RC.OutputCh(MOT_4, motor_out[MOT_4]); + }else{ + APM_RC.OutputCh(MOT_1, motor_out[MOT_1]); + APM_RC.OutputCh(MOT_2, motor_out[MOT_2]); + APM_RC.OutputCh(MOT_3, motor_out[MOT_3]); + APM_RC.OutputCh(MOT_4, motor_out[MOT_4]); + } + //*/ + + + APM_RC.OutputCh(MOT_1, motor_out[MOT_1]); + APM_RC.OutputCh(MOT_2, motor_out[MOT_2]); + APM_RC.OutputCh(MOT_3, motor_out[MOT_3]); + APM_RC.OutputCh(MOT_4, motor_out[MOT_4]); + #if INSTANT_PWM == 1 // InstantPWM From 486c56ce417999c559433e4a30e1f919a748646c Mon Sep 17 00:00:00 2001 From: Jason Short Date: Thu, 8 Mar 2012 23:13:04 -0800 Subject: [PATCH 016/178] Consolidated Barometer pressure sensing to a single filter based on Randy's new filter class. --- ArduCopter/ArduCopter.pde | 11 +++++--- ArduCopter/sensors.pde | 22 ++++++++++----- libraries/AP_Baro/AP_Baro_BMP085.cpp | 40 +++++++++++++++------------- 3 files changed, 46 insertions(+), 27 deletions(-) diff --git a/ArduCopter/ArduCopter.pde b/ArduCopter/ArduCopter.pde index ad3dcefb28..1a31602067 100644 --- a/ArduCopter/ArduCopter.pde +++ b/ArduCopter/ArduCopter.pde @@ -502,10 +502,14 @@ static int32_t initial_simple_bearing; // Used to control Axis lock int32_t roll_axis; int32_t pitch_axis; + // Filters AverageFilterInt32_Size3 roll_rate_d_filter; // filtered acceleration AverageFilterInt32_Size3 pitch_rate_d_filter; // filtered pitch acceleration +// Barometer filter +AverageFilterInt32_Size5 baro_filter; // filtered pitch acceleration + //////////////////////////////////////////////////////////////////////////////// // Circle Mode / Loiter control //////////////////////////////////////////////////////////////////////////////// @@ -1070,8 +1074,8 @@ static void medium_loop() // ----------------------- arm_motors(); - // Do an extra baro read - // --------------------- + // Do an extra baro read for Temp sensing + // --------------------------------------- #if HIL_MODE != HIL_MODE_ATTITUDE barometer.read(); #endif @@ -1884,7 +1888,8 @@ static void update_altitude() // This is real life // read in Actual Baro Altitude - baro_alt = (baro_alt + read_barometer()) >> 1; + baro_alt = read_barometer(); + //Serial.printf("baro_alt: %d \n", baro_alt); // calc the vertical accel rate int temp = (baro_alt - old_baro_alt) * 10; diff --git a/ArduCopter/sensors.pde b/ArduCopter/sensors.pde index 4c901b6357..cb0da8bb03 100644 --- a/ArduCopter/sensors.pde +++ b/ArduCopter/sensors.pde @@ -35,7 +35,7 @@ static void init_barometer(void) //Serial.printf("init %ld, %d, -, %ld, %ld\n", barometer.RawTemp, barometer.Temp, barometer.RawPress, barometer.Press); } - for(i = 0; i < 20; i++){ + for(i = 0; i < 40; i++){ delay(20); #if HIL_MODE == HIL_MODE_SENSORS @@ -44,15 +44,25 @@ static void init_barometer(void) // Get initial data from absolute pressure sensor barometer.read(); - ground_pressure = barometer.get_pressure(); - ground_temperature = (ground_temperature * 7 + barometer.get_temperature()) / 8; - //Serial.printf("init %ld, %d, -, %ld, %ld, -, %d, %ld\n", barometer.RawTemp, barometer.Temp, barometer.RawPress, barometer.Press, ground_temperature, ground_pressure); + ground_pressure = baro_filter.apply(barometer.get_pressure()); + + //Serial.printf("t: %ld, p: %d\n", ground_pressure, ground_temperature); + + /*Serial.printf("init %d, %d, -, %d, %d, -, %d, %d\n", + barometer.RawTemp, + barometer.Temp, + barometer.RawPress, + barometer.Press, + ground_temperature, + ground_pressure);*/ } + // save our ground temp + ground_temperature = barometer.get_temperature(); } static void reset_baro(void) { - ground_pressure = barometer.get_pressure(); + ground_pressure = baro_filter.apply(barometer.get_pressure()); ground_temperature = barometer.get_temperature(); } @@ -61,7 +71,7 @@ static int32_t read_barometer(void) float x, scaling, temp; barometer.read(); - float abs_pressure = barometer.get_pressure(); + float abs_pressure = baro_filter.apply(barometer.get_pressure()); //Serial.printf("%ld, %ld, %ld, %ld\n", barometer.RawTemp, barometer.RawPress, barometer.Press, abs_pressure); diff --git a/libraries/AP_Baro/AP_Baro_BMP085.cpp b/libraries/AP_Baro/AP_Baro_BMP085.cpp index d5790feb0d..e6755ffdc1 100644 --- a/libraries/AP_Baro/AP_Baro_BMP085.cpp +++ b/libraries/AP_Baro/AP_Baro_BMP085.cpp @@ -94,6 +94,9 @@ bool AP_Baro_BMP085::init( AP_PeriodicProcess * scheduler ) Command_ReadTemp(); BMP085_State = 1; + // init raw temo + RawTemp = 0; + healthy = true; return true; } @@ -170,29 +173,29 @@ void AP_Baro_BMP085::ReadPress() RawPress = (((uint32_t)buf[0] << 16) | ((uint32_t)buf[1] << 8) | ((uint32_t)buf[2])) >> (8 - OVERSAMPLING); - if (_offset_press == 0){ - _offset_press = RawPress; - RawPress = 0; - } else{ - RawPress -= _offset_press; - } + //if (_offset_press == 0){ + // _offset_press = RawPress; + // RawPress = 0; + //} else{ + // RawPress -= _offset_press; + //} // filter - _press_filter[_press_index++] = RawPress; + //_press_filter[_press_index++] = RawPress; - if(_press_index >= PRESS_FILTER_SIZE) - _press_index = 0; + //if(_press_index >= PRESS_FILTER_SIZE) + // _press_index = 0; - RawPress = 0; + //RawPress = 0; // sum our filter - for (uint8_t i = 0; i < PRESS_FILTER_SIZE; i++){ - RawPress += _press_filter[i]; - } + //for (uint8_t i = 0; i < PRESS_FILTER_SIZE; i++){ + // RawPress += _press_filter[i]; + //} // grab result - RawPress /= PRESS_FILTER_SIZE; - RawPress += _offset_press; + //RawPress /= PRESS_FILTER_SIZE; + //RawPress += _offset_press; } // Send Command to Read Temperature @@ -222,10 +225,11 @@ void AP_Baro_BMP085::ReadTemp() _temp_sensor = buf[0]; _temp_sensor = (_temp_sensor << 8) | buf[1]; - if (RawTemp == 0) + if (RawTemp == 0){ RawTemp = _temp_sensor; - - RawTemp = (float)_temp_sensor * .01 + (float)RawTemp * .99; + }else{ + RawTemp = (float)_temp_sensor * .01 + (float)RawTemp * .99; + } } // Calculate Temperature and Pressure in real units. From 986f1675ad46580ddc86dca215660b5a7762e8f1 Mon Sep 17 00:00:00 2001 From: Michael Oborne Date: Fri, 9 Mar 2012 23:18:12 +0800 Subject: [PATCH 017/178] APM Planner 1.1.50 rename messagebox to custommessagebox mag calibration now working. > hardware setup tab --- Tools/ArdupilotMegaPlanner/Antenna/Maestro.cs | 6 +- Tools/ArdupilotMegaPlanner/Antenna/Tracker.cs | 4 +- Tools/ArdupilotMegaPlanner/ArduinoDetect.cs | 2 +- .../ArdupilotMegaPlanner/ArdupilotMega.csproj | 7 +- Tools/ArdupilotMegaPlanner/Camera.cs | 4 +- Tools/ArdupilotMegaPlanner/Capture.cs | 2 +- Tools/ArdupilotMegaPlanner/Common.cs | 8 +- Tools/ArdupilotMegaPlanner/CommsUdpSerial.cs | 2 +- .../Controls/CustomMessageBox.cs | 242 ++ .../ArdupilotMegaPlanner/Controls/MyButton.cs | 5 +- .../Controls/ProgressReporterDialogue.cs | 2 +- .../ArdupilotMegaPlanner/ElevationProfile.cs | 6 +- .../GCSViews/Configuration.cs | 16 +- .../ArdupilotMegaPlanner/GCSViews/Firmware.cs | 40 +- .../GCSViews/FlightData.cs | 38 +- .../GCSViews/FlightPlanner.Designer.cs | 6 - .../GCSViews/FlightPlanner.cs | 108 +- .../GCSViews/Simulation.cs | 2 +- .../ArdupilotMegaPlanner/GCSViews/Terminal.cs | 2 +- Tools/ArdupilotMegaPlanner/Joystick.cs | 12 +- Tools/ArdupilotMegaPlanner/JoystickSetup.cs | 4 +- Tools/ArdupilotMegaPlanner/Log.cs | 6 +- Tools/ArdupilotMegaPlanner/LogBrowse.cs | 10 +- Tools/ArdupilotMegaPlanner/MAVLink.cs | 9 +- Tools/ArdupilotMegaPlanner/MagCalib.cs | 324 +- Tools/ArdupilotMegaPlanner/MainV2.cs | 37 +- Tools/ArdupilotMegaPlanner/Program.cs | 18 +- .../Properties/AssemblyInfo.cs | 2 +- Tools/ArdupilotMegaPlanner/RAW_Sensor.cs | 45 +- .../Radio/3DRradio.Designer.cs | 37 +- Tools/ArdupilotMegaPlanner/Radio/3DRradio.cs | 26 +- .../ArdupilotMegaPlanner/Radio/3DRradio.resx | 120 + Tools/ArdupilotMegaPlanner/ResEdit.cs | 10 +- Tools/ArdupilotMegaPlanner/Script.cs | 2 +- Tools/ArdupilotMegaPlanner/SerialInput.cs | 8 +- Tools/ArdupilotMegaPlanner/SerialOutput.cs | 6 +- .../Setup/Setup.Designer.cs | 66 +- Tools/ArdupilotMegaPlanner/Setup/Setup.cs | 180 +- Tools/ArdupilotMegaPlanner/Setup/Setup.resx | 2805 +++++++++++++---- .../bin/Release/ArdupilotMegaPlanner.pdb | Bin 1000960 -> 1003008 bytes Tools/ArdupilotMegaPlanner/georefimage.cs | 2 +- Tools/ArdupilotMegaPlanner/temp.cs | 64 +- Tools/ArdupilotMegaPlanner/test.cs | 1 + 43 files changed, 3173 insertions(+), 1123 deletions(-) create mode 100644 Tools/ArdupilotMegaPlanner/Controls/CustomMessageBox.cs create mode 100644 Tools/ArdupilotMegaPlanner/test.cs diff --git a/Tools/ArdupilotMegaPlanner/Antenna/Maestro.cs b/Tools/ArdupilotMegaPlanner/Antenna/Maestro.cs index f69c713875..635b5048bb 100644 --- a/Tools/ArdupilotMegaPlanner/Antenna/Maestro.cs +++ b/Tools/ArdupilotMegaPlanner/Antenna/Maestro.cs @@ -36,13 +36,13 @@ namespace ArdupilotMega.Antenna if ((PanStartRange - PanEndRange) == 0) { - System.Windows.Forms.MessageBox.Show("Invalid Pan Range", "Error"); + System.Windows.Forms.CustomMessageBox.Show("Invalid Pan Range", "Error"); return false; } if ((TiltStartRange - TiltEndRange) == 0) { - System.Windows.Forms.MessageBox.Show("Invalid Tilt Range", "Error"); + System.Windows.Forms.CustomMessageBox.Show("Invalid Tilt Range", "Error"); return false; } @@ -50,7 +50,7 @@ namespace ArdupilotMega.Antenna { ComPort.Open(); } - catch (Exception ex) { System.Windows.Forms.MessageBox.Show("Connect failed " + ex.Message,"Error"); return false; } + catch (Exception ex) { System.Windows.Forms.CustomMessageBox.Show("Connect failed " + ex.Message,"Error"); return false; } return true; } diff --git a/Tools/ArdupilotMegaPlanner/Antenna/Tracker.cs b/Tools/ArdupilotMegaPlanner/Antenna/Tracker.cs index 65f2f8c242..5c1ee337bc 100644 --- a/Tools/ArdupilotMegaPlanner/Antenna/Tracker.cs +++ b/Tools/ArdupilotMegaPlanner/Antenna/Tracker.cs @@ -54,7 +54,7 @@ namespace ArdupilotMega.Antenna BaudRate = int.Parse(CMB_baudrate.Text) }; } - catch (Exception ex) { MessageBox.Show("Bad Port settings " + ex.Message); return; } + catch (Exception ex) { CustomMessageBox.Show("Bad Port settings " + ex.Message); return; } try { @@ -67,7 +67,7 @@ namespace ArdupilotMega.Antenna tracker.TrimTilt = TRK_tilttrim.Value; } - catch (Exception ex) { MessageBox.Show("Bad User input " + ex.Message); return; } + catch (Exception ex) { CustomMessageBox.Show("Bad User input " + ex.Message); return; } if (tracker.Init()) { diff --git a/Tools/ArdupilotMegaPlanner/ArduinoDetect.cs b/Tools/ArdupilotMegaPlanner/ArduinoDetect.cs index 62e86d3639..bbd132643b 100644 --- a/Tools/ArdupilotMegaPlanner/ArduinoDetect.cs +++ b/Tools/ArdupilotMegaPlanner/ArduinoDetect.cs @@ -178,7 +178,7 @@ namespace ArdupilotMega } else { - if (DialogResult.Yes == MessageBox.Show("Is this a APM 2?", "APM 2", MessageBoxButtons.YesNo)) + if (DialogResult.Yes == CustomMessageBox.Show("Is this a APM 2?", "APM 2", MessageBoxButtons.YesNo)) { return "2560-2"; } diff --git a/Tools/ArdupilotMegaPlanner/ArdupilotMega.csproj b/Tools/ArdupilotMegaPlanner/ArdupilotMega.csproj index 2846b45652..80b938dd1c 100644 --- a/Tools/ArdupilotMegaPlanner/ArdupilotMega.csproj +++ b/Tools/ArdupilotMegaPlanner/ArdupilotMega.csproj @@ -166,6 +166,10 @@ False + + False + Lib\netDxf.dll + False @@ -218,7 +222,7 @@ Tracker.cs - + Form @@ -442,6 +446,7 @@ + Tracker.cs diff --git a/Tools/ArdupilotMegaPlanner/Camera.cs b/Tools/ArdupilotMegaPlanner/Camera.cs index 6964565f1c..f1aaa912d2 100644 --- a/Tools/ArdupilotMegaPlanner/Camera.cs +++ b/Tools/ArdupilotMegaPlanner/Camera.cs @@ -182,7 +182,7 @@ namespace ArdupilotMega xmlwriter.Close(); } - catch (Exception ex) { MessageBox.Show(ex.ToString()); } + catch (Exception ex) { CustomMessageBox.Show(ex.ToString()); } } else { @@ -279,7 +279,7 @@ namespace ArdupilotMega camera.sensorheight = float.Parse(TXT_sensheight.Text); camera.sensorwidth = float.Parse(TXT_senswidth.Text); } - catch { MessageBox.Show("One of your entries is not a valid number"); return; } + catch { CustomMessageBox.Show("One of your entries is not a valid number"); return; } cameras[CMB_camera.Text] = camera; diff --git a/Tools/ArdupilotMegaPlanner/Capture.cs b/Tools/ArdupilotMegaPlanner/Capture.cs index bb1c5b0863..022f40fe37 100644 --- a/Tools/ArdupilotMegaPlanner/Capture.cs +++ b/Tools/ArdupilotMegaPlanner/Capture.cs @@ -227,7 +227,7 @@ namespace WebCamService camimage(image); } } - catch { Console.WriteLine("Grab bmp failed"); timer1.Enabled = false; this.CloseInterfaces(); System.Windows.Forms.MessageBox.Show("Problem with capture device, grabbing frame took longer than 5 sec"); } + catch { Console.WriteLine("Grab bmp failed"); timer1.Enabled = false; this.CloseInterfaces(); System.Windows.Forms.CustomMessageBox.Show("Problem with capture device, grabbing frame took longer than 5 sec"); } } ///

build the capture graph for grabber. diff --git a/Tools/ArdupilotMegaPlanner/Common.cs b/Tools/ArdupilotMegaPlanner/Common.cs index 74f101f290..5f8e8df3ff 100644 --- a/Tools/ArdupilotMegaPlanner/Common.cs +++ b/Tools/ArdupilotMegaPlanner/Common.cs @@ -525,7 +525,7 @@ namespace ArdupilotMega mode.mode = (byte)MAVLink.MAV_MODE.MAV_MODE_TEST2; break; default: - MessageBox.Show("No Mode Changed " + (int)Enum.Parse(Common.getModes(), modein)); + CustomMessageBox.Show("No Mode Changed " + (int)Enum.Parse(Common.getModes(), modein)); return false; } } @@ -553,12 +553,12 @@ namespace ArdupilotMega mode.mode = (byte)MAVLink.MAV_MODE.MAV_MODE_AUTO; break; default: - MessageBox.Show("No Mode Changed " + (int)Enum.Parse(Common.getModes(), modein)); + CustomMessageBox.Show("No Mode Changed " + (int)Enum.Parse(Common.getModes(), modein)); return false; } } } - catch { System.Windows.Forms.MessageBox.Show("Failed to find Mode"); return false; } + catch { System.Windows.Forms.CustomMessageBox.Show("Failed to find Mode"); return false; } return true; } @@ -574,7 +574,7 @@ namespace ArdupilotMega // Create a request using a URL that can receive a post. WebRequest request = WebRequest.Create(url); - request.Timeout = 5000; + request.Timeout = 10000; // Set the Method property of the request to POST. request.Method = "GET"; // Get the response. diff --git a/Tools/ArdupilotMegaPlanner/CommsUdpSerial.cs b/Tools/ArdupilotMegaPlanner/CommsUdpSerial.cs index 628a3616ec..3556c12f67 100644 --- a/Tools/ArdupilotMegaPlanner/CommsUdpSerial.cs +++ b/Tools/ArdupilotMegaPlanner/CommsUdpSerial.cs @@ -143,7 +143,7 @@ namespace System.IO.Ports client.Close(); } log.Info(ex.ToString()); - System.Windows.Forms.MessageBox.Show("Please check your Firewall settings\nPlease try running this command\n1. Run the following command in an elevated command prompt to disable Windows Firewall temporarily:\n \nNetsh advfirewall set allprofiles state off\n \nNote: This is just for test; please turn it back on with the command 'Netsh advfirewall set allprofiles state on'.\n"); + System.Windows.Forms.CustomMessageBox.Show("Please check your Firewall settings\nPlease try running this command\n1. Run the following command in an elevated command prompt to disable Windows Firewall temporarily:\n \nNetsh advfirewall set allprofiles state off\n \nNote: This is just for test; please turn it back on with the command 'Netsh advfirewall set allprofiles state on'.\n"); throw new Exception("The socket/serialproxy is closed " + e); } } diff --git a/Tools/ArdupilotMegaPlanner/Controls/CustomMessageBox.cs b/Tools/ArdupilotMegaPlanner/Controls/CustomMessageBox.cs new file mode 100644 index 0000000000..fda4573224 --- /dev/null +++ b/Tools/ArdupilotMegaPlanner/Controls/CustomMessageBox.cs @@ -0,0 +1,242 @@ +using System; +using System.Drawing; +using System.Windows.Forms; +using ArdupilotMega.Controls; +using System.Text; +using ArdupilotMega; + +namespace System.Windows.Forms +{ + public static class CustomMessageBox + { + const int FORM_Y_MARGIN = 10; + const int FORM_X_MARGIN = 16; + + static DialogResult _state = DialogResult.None; + + public static DialogResult Show(string text) + { + return Show(text, string.Empty, MessageBoxButtons.OK, MessageBoxIcon.None); + } + + public static DialogResult Show(string text, string caption) + { + return Show(text, caption, MessageBoxButtons.OK, MessageBoxIcon.None); + } + + public static DialogResult Show(string text, string caption, MessageBoxButtons buttons) + { + return Show(text, caption, buttons, MessageBoxIcon.None); + } + + public static DialogResult Show(string text, string caption, MessageBoxButtons buttons, MessageBoxIcon icon) + { + if (text == null) + text = ""; + + if (caption == null) + caption = ""; + + // ensure we are always in a known state + _state = DialogResult.None; + + // convert to nice wrapped lines. + text = AddNewLinesToText(text); + // get pixel width and height + Size textSize = TextRenderer.MeasureText(text, SystemFonts.DefaultFont); + // allow for icon + if (icon != MessageBoxIcon.None) + textSize.Width += SystemIcons.Question.Width; + + var msgBoxFrm = new Form + { + FormBorderStyle = FormBorderStyle.FixedDialog, + ShowInTaskbar = false, + StartPosition = FormStartPosition.CenterScreen, + Text = caption, + MaximizeBox = false, + MinimizeBox = false, + Width = textSize.Width + 50, + Height = textSize.Height + 100, + TopMost = true, + }; + + Rectangle screenRectangle = msgBoxFrm.RectangleToScreen(msgBoxFrm.ClientRectangle); + int titleHeight = screenRectangle.Top - msgBoxFrm.Top; + + var lblMessage = new Label + { + Left = 58, + Top = 15, + Width = textSize.Width + 10, + Height = textSize.Height + 10, + Text = text + }; + + msgBoxFrm.Controls.Add(lblMessage); + + var actualIcon = getMessageBoxIcon(icon); + + if (actualIcon == null) + { + lblMessage.Location = new Point(FORM_X_MARGIN, FORM_Y_MARGIN); + } + else + { + var iconPbox = new PictureBox + { + Image = actualIcon.ToBitmap(), + Location = new Point(FORM_X_MARGIN, FORM_Y_MARGIN) + }; + msgBoxFrm.Controls.Add(iconPbox); + } + + + AddButtonsToForm(msgBoxFrm, buttons); + + // display even if theme fails + try + { + ThemeManager.ApplyThemeTo(msgBoxFrm); + } + catch { } + + if (System.Windows.Forms.Application.OpenForms.Count > 0) + { + msgBoxFrm.StartPosition = FormStartPosition.Manual; + Form parentForm = System.Windows.Forms.Application.OpenForms[0]; + // center of first form + msgBoxFrm.Location = new Point(parentForm.Location.X + parentForm.Width / 2 - msgBoxFrm.Width / 2, + parentForm.Location.Y + parentForm.Height / 2 - msgBoxFrm.Height / 2); + DialogResult test = msgBoxFrm.ShowDialog(); + } + else + { + DialogResult test = msgBoxFrm.ShowDialog(); + } + + DialogResult answer = _state; + + return answer; + } + + static void msgBoxFrm_FormClosing(object sender, FormClosingEventArgs e) + { + throw new NotImplementedException(); + } + + // from http://stackoverflow.com/questions/2512781/winforms-big-paragraph-tooltip/2512895#2512895 + private static int maximumSingleLineTooltipLength = 85; + + private static string AddNewLinesToText(string text) + { + if (text.Length < maximumSingleLineTooltipLength) + return text; + int lineLength = maximumSingleLineTooltipLength; + StringBuilder sb = new StringBuilder(); + int currentLinePosition = 0; + for (int textIndex = 0; textIndex < text.Length; textIndex++) + { + // If we have reached the target line length and the next + // character is whitespace then begin a new line. + if (currentLinePosition >= lineLength && + char.IsWhiteSpace(text[textIndex])) + { + sb.Append(Environment.NewLine); + currentLinePosition = 0; + } + // If we have just started a new line, skip all the whitespace. + if (currentLinePosition == 0) + while (textIndex < text.Length && char.IsWhiteSpace(text[textIndex])) + textIndex++; + // Append the next character. + if (textIndex < text.Length) sb.Append(text[textIndex]); + currentLinePosition++; + } + return sb.ToString(); + } + + private static void AddButtonsToForm(Form msgBoxFrm, MessageBoxButtons buttons) + { + Rectangle screenRectangle = msgBoxFrm.RectangleToScreen(msgBoxFrm.ClientRectangle); + int titleHeight = screenRectangle.Top - msgBoxFrm.Top; + + var t = Type.GetType("Mono.Runtime"); + if ((t != null)) + titleHeight = 25; + + switch (buttons) + { + case MessageBoxButtons.OK: + var but = new MyButton + { + Size = new Size(75, 23), + Text = "OK", + Left = msgBoxFrm.Width - 75 - FORM_X_MARGIN, + Top = msgBoxFrm.Height - 23 - FORM_Y_MARGIN - titleHeight + }; + + but.Click += delegate { _state = DialogResult.OK; msgBoxFrm.Close(); }; + msgBoxFrm.Controls.Add(but); + msgBoxFrm.AcceptButton = but; + break; + + case MessageBoxButtons.YesNo: + + if (msgBoxFrm.Width < (75 * 2 + FORM_X_MARGIN * 3)) + msgBoxFrm.Width = (75 * 2 + FORM_X_MARGIN * 3); + + var butyes = new MyButton + { + Size = new Size(75, 23), + Text = "Yes", + Left = msgBoxFrm.Width - 75 * 2 - FORM_X_MARGIN * 2, + Top = msgBoxFrm.Height - 23 - FORM_Y_MARGIN - titleHeight + }; + + butyes.Click += delegate { _state = DialogResult.Yes; msgBoxFrm.Close(); }; + msgBoxFrm.Controls.Add(butyes); + msgBoxFrm.AcceptButton = butyes; + + var butno = new MyButton + { + Size = new Size(75, 23), + Text = "No", + Left = msgBoxFrm.Width - 75 - FORM_X_MARGIN, + Top = msgBoxFrm.Height - 23 - FORM_Y_MARGIN - titleHeight + }; + + butno.Click += delegate { _state = DialogResult.No; msgBoxFrm.Close(); }; + msgBoxFrm.Controls.Add(butno); + msgBoxFrm.CancelButton = butno; + break; + + default: + throw new NotImplementedException("Only MessageBoxButtons.OK and YesNo supported at this time"); + } + } + + /// + /// Get system icon for MessageBoxIcon. + /// + /// The MessageBoxIcon value. + /// SystemIcon type Icon. + private static Icon getMessageBoxIcon(MessageBoxIcon icon) + { + switch (icon) + { + case MessageBoxIcon.Asterisk: + return SystemIcons.Asterisk; + case MessageBoxIcon.Error: + return SystemIcons.Error; + case MessageBoxIcon.Exclamation: + return SystemIcons.Exclamation; + case MessageBoxIcon.Question: + return SystemIcons.Question; + default: + return null; + } + } + + } +} \ No newline at end of file diff --git a/Tools/ArdupilotMegaPlanner/Controls/MyButton.cs b/Tools/ArdupilotMegaPlanner/Controls/MyButton.cs index 8eb9d97e84..9faaeb8441 100644 --- a/Tools/ArdupilotMegaPlanner/Controls/MyButton.cs +++ b/Tools/ArdupilotMegaPlanner/Controls/MyButton.cs @@ -23,7 +23,8 @@ namespace ArdupilotMega public Color BGGradBot = Color.FromArgb(0xcd, 0xe2, 0x96); - public new Color ForeColor = Color.FromArgb(0x40, 0x57, 0x04); + // i want to ignore forecolor + public Color TextColor = Color.FromArgb(0x40, 0x57, 0x04); public Color Outline = Color.FromArgb(0x79, 0x94, 0x29); @@ -79,7 +80,7 @@ namespace ArdupilotMega gr.DrawRectangle(mypen, outside); - SolidBrush mybrush = new SolidBrush(ForeColor); + SolidBrush mybrush = new SolidBrush(TextColor); if (mouseover) { diff --git a/Tools/ArdupilotMegaPlanner/Controls/ProgressReporterDialogue.cs b/Tools/ArdupilotMegaPlanner/Controls/ProgressReporterDialogue.cs index 85757abd5e..683b995004 100644 --- a/Tools/ArdupilotMegaPlanner/Controls/ProgressReporterDialogue.cs +++ b/Tools/ArdupilotMegaPlanner/Controls/ProgressReporterDialogue.cs @@ -211,7 +211,7 @@ namespace ArdupilotMega.Controls + Environment.NewLine + Environment.NewLine + this.workerException.StackTrace; - MessageBox.Show(message,"Exception Details",MessageBoxButtons.OK,MessageBoxIcon.Information); + CustomMessageBox.Show(message,"Exception Details",MessageBoxButtons.OK,MessageBoxIcon.Information); } } diff --git a/Tools/ArdupilotMegaPlanner/ElevationProfile.cs b/Tools/ArdupilotMegaPlanner/ElevationProfile.cs index cae52f80a4..ca7d702ff1 100644 --- a/Tools/ArdupilotMegaPlanner/ElevationProfile.cs +++ b/Tools/ArdupilotMegaPlanner/ElevationProfile.cs @@ -28,7 +28,7 @@ namespace ArdupilotMega if (planlocs.Count <= 1) { - MessageBox.Show("Please plan something first"); + CustomMessageBox.Show("Please plan something first"); return; } @@ -113,7 +113,7 @@ namespace ArdupilotMega if (list.Count <= 2 || coords.Length > (2048 - 256) || distance > 50000) { - MessageBox.Show("To many/few WP's or to Big a Distance " + (distance/1000) + "km"); + CustomMessageBox.Show("To many/few WP's or to Big a Distance " + (distance/1000) + "km"); return answer; } @@ -145,7 +145,7 @@ namespace ArdupilotMega } } } - catch { MessageBox.Show("Error getting GE data"); } + catch { CustomMessageBox.Show("Error getting GE data"); } return answer; } diff --git a/Tools/ArdupilotMegaPlanner/GCSViews/Configuration.cs b/Tools/ArdupilotMegaPlanner/GCSViews/Configuration.cs index 04287df16e..08f7cf31c4 100644 --- a/Tools/ArdupilotMegaPlanner/GCSViews/Configuration.cs +++ b/Tools/ArdupilotMegaPlanner/GCSViews/Configuration.cs @@ -590,7 +590,7 @@ namespace ArdupilotMega.GCSViews string line = sr.ReadLine(); if (line.Contains("NOTE:")) - MessageBox.Show(line, "Saved Note"); + CustomMessageBox.Show(line, "Saved Note"); int index = line.IndexOf(','); @@ -711,7 +711,7 @@ namespace ArdupilotMega.GCSViews catch { } } - catch { MessageBox.Show("Set " + value + " Failed"); } + catch { CustomMessageBox.Show("Set " + value + " Failed"); } } } @@ -724,7 +724,7 @@ namespace ArdupilotMega.GCSViews { if (!MainV2.comPort.BaseStream.IsOpen) { - MessageBox.Show("Please Connect First"); + CustomMessageBox.Show("Please Connect First"); ConfigTabs.SelectedIndex = 0; } else @@ -764,7 +764,7 @@ namespace ArdupilotMega.GCSViews BUT_videostart.Enabled = false; } - catch (Exception ex) { MessageBox.Show("Camera Fail: " + ex.Message); } + catch (Exception ex) { CustomMessageBox.Show("Camera Fail: " + ex.Message); } } @@ -818,7 +818,7 @@ namespace ArdupilotMega.GCSViews } catch (Exception ex) { - MessageBox.Show("Can not add video source\n" + ex.ToString()); + CustomMessageBox.Show("Can not add video source\n" + ex.ToString()); return; } @@ -951,7 +951,7 @@ namespace ArdupilotMega.GCSViews } - catch { MessageBox.Show("Error: getting param list"); } + catch { CustomMessageBox.Show("Error: getting param list"); } ((MyButton)sender).Enabled = true; @@ -1122,7 +1122,7 @@ namespace ArdupilotMega.GCSViews string line = sr.ReadLine(); if (line.Contains("NOTE:")) - MessageBox.Show(line, "Saved Note"); + CustomMessageBox.Show(line, "Saved Note"); int index = line.IndexOf(','); @@ -1155,7 +1155,7 @@ namespace ArdupilotMega.GCSViews { if (startup) return; - MessageBox.Show("You need to restart the planner for this to take effect"); + CustomMessageBox.Show("You need to restart the planner for this to take effect"); MainV2.config["CHK_GDIPlus"] = CHK_GDIPlus.Checked.ToString(); } diff --git a/Tools/ArdupilotMegaPlanner/GCSViews/Firmware.cs b/Tools/ArdupilotMegaPlanner/GCSViews/Firmware.cs index ab5651f73a..643994b2db 100644 --- a/Tools/ArdupilotMegaPlanner/GCSViews/Firmware.cs +++ b/Tools/ArdupilotMegaPlanner/GCSViews/Firmware.cs @@ -141,7 +141,7 @@ namespace ArdupilotMega.GCSViews } catch (Exception ex) { - MessageBox.Show("Failed to get Firmware List : " + ex.Message); + CustomMessageBox.Show("Failed to get Firmware List : " + ex.Message); } log.Info("FW load done"); @@ -211,12 +211,12 @@ namespace ArdupilotMega.GCSViews // none found if (items.Count == 0) { - MessageBox.Show("The requested firmware was not found."); + CustomMessageBox.Show("The requested firmware was not found."); return; } else if (items.Count == 1) // 1 found so accept it { - DialogResult dr = MessageBox.Show("Are you sure you want to upload " + items[0].name + "?", "Continue", MessageBoxButtons.YesNo); + DialogResult dr = CustomMessageBox.Show("Are you sure you want to upload " + items[0].name + "?", "Continue", MessageBoxButtons.YesNo); if (dr == System.Windows.Forms.DialogResult.Yes) { update(items[0]); @@ -239,7 +239,7 @@ namespace ArdupilotMega.GCSViews { if (select.frame == "+" && temp.name.Contains("Plus")) { - DialogResult dr = MessageBox.Show("Are you sure you want to upload " + items[a].name + "?", "Continue", MessageBoxButtons.YesNo); + DialogResult dr = CustomMessageBox.Show("Are you sure you want to upload " + items[a].name + "?", "Continue", MessageBoxButtons.YesNo); if (dr == System.Windows.Forms.DialogResult.Yes) { update(items[a]); @@ -248,7 +248,7 @@ namespace ArdupilotMega.GCSViews } else if (select.frame == "X" && temp.name.Contains("X")) { - DialogResult dr = MessageBox.Show("Are you sure you want to upload " + items[a].name + "?", "Continue", MessageBoxButtons.YesNo); + DialogResult dr = CustomMessageBox.Show("Are you sure you want to upload " + items[a].name + "?", "Continue", MessageBoxButtons.YesNo); if (dr == System.Windows.Forms.DialogResult.Yes) { update(items[a]); @@ -261,7 +261,7 @@ namespace ArdupilotMega.GCSViews } else { - MessageBox.Show("Something has gone wrong, to many firmware choices"); + CustomMessageBox.Show("Something has gone wrong, to many firmware choices"); return; } } @@ -318,7 +318,7 @@ namespace ArdupilotMega.GCSViews { if (softwares.Count == 0) { - MessageBox.Show("No valid options"); + CustomMessageBox.Show("No valid options"); return; } @@ -330,7 +330,7 @@ namespace ArdupilotMega.GCSViews if (board == "") { - MessageBox.Show("Cant detect your APM version. Please check your cabling"); + CustomMessageBox.Show("Cant detect your APM version. Please check your cabling"); return; } @@ -344,9 +344,9 @@ namespace ArdupilotMega.GCSViews if (apmformat_version != -1 && apmformat_version != temp.k_format_version) { - if (DialogResult.No == MessageBox.Show("Epprom changed, all your setting will be lost during the update,\nDo you wish to continue?", "Epprom format changed (" + apmformat_version + " vs " + temp.k_format_version + ")", MessageBoxButtons.YesNo)) + if (DialogResult.No == CustomMessageBox.Show("Epprom changed, all your setting will be lost during the update,\nDo you wish to continue?", "Epprom format changed (" + apmformat_version + " vs " + temp.k_format_version + ")", MessageBoxButtons.YesNo)) { - MessageBox.Show("Please connect and backup your config in the configuration tab."); + CustomMessageBox.Show("Please connect and backup your config in the configuration tab."); return; } } @@ -370,7 +370,7 @@ namespace ArdupilotMega.GCSViews } else { - MessageBox.Show("Invalid Board Type"); + CustomMessageBox.Show("Invalid Board Type"); return; } @@ -426,7 +426,7 @@ namespace ArdupilotMega.GCSViews this.Refresh(); log.Info("Downloaded"); } - catch (Exception ex) { lbl_status.Text = "Failed download"; MessageBox.Show("Failed to download new firmware : " + ex.ToString()); return; } + catch (Exception ex) { lbl_status.Text = "Failed download"; CustomMessageBox.Show("Failed to download new firmware : " + ex.ToString()); return; } UploadFlash(Path.GetDirectoryName(Application.ExecutablePath) + Path.DirectorySeparatorChar + @"firmware.hex", board); } @@ -451,7 +451,7 @@ namespace ArdupilotMega.GCSViews sr.Dispose(); } lbl_status.Text = "Failed read HEX"; - MessageBox.Show("Failed to read firmware.hex : " + ex.Message); + CustomMessageBox.Show("Failed to read firmware.hex : " + ex.Message); return; } ArduinoComms port = new ArduinoSTK(); @@ -460,7 +460,7 @@ namespace ArdupilotMega.GCSViews { if (FLASH.Length > 126976) { - MessageBox.Show("Firmware is to big for a 1280, Please upgrade!!"); + CustomMessageBox.Show("Firmware is to big for a 1280, Please upgrade!!"); return; } //port = new ArduinoSTK(); @@ -539,7 +539,7 @@ namespace ArdupilotMega.GCSViews { if (FLASH[s] != flashverify[s]) { - MessageBox.Show("Upload succeeded, but verify failed: exp " + FLASH[s].ToString("X") + " got " + flashverify[s].ToString("X") + " at " + s); + CustomMessageBox.Show("Upload succeeded, but verify failed: exp " + FLASH[s].ToString("X") + " got " + flashverify[s].ToString("X") + " at " + s); break; } } @@ -549,7 +549,7 @@ namespace ArdupilotMega.GCSViews else { lbl_status.Text = "Failed upload"; - MessageBox.Show("Communication Error - no connection"); + CustomMessageBox.Show("Communication Error - no connection"); } port.Close(); @@ -588,7 +588,7 @@ namespace ArdupilotMega.GCSViews catch (Exception ex) { lbl_status.Text = "Failed upload"; - MessageBox.Show("Check port settings or Port in use? " + ex); + CustomMessageBox.Show("Check port settings or Port in use? " + ex); port.Close(); } flashing = false; @@ -655,7 +655,7 @@ namespace ArdupilotMega.GCSViews if (checksumact != checksum) { - MessageBox.Show("The hex file loaded is invalid, please try again."); + CustomMessageBox.Show("The hex file loaded is invalid, please try again."); throw new Exception("Checksum Failed - Invalid Hex"); } } @@ -664,7 +664,7 @@ namespace ArdupilotMega.GCSViews if (!hitend) { - MessageBox.Show("The hex file did no contain an end flag. aborting"); + CustomMessageBox.Show("The hex file did no contain an end flag. aborting"); throw new Exception("No end flag in file"); } @@ -678,7 +678,7 @@ namespace ArdupilotMega.GCSViews if (flashing == true) { e.Cancel = true; - MessageBox.Show("Cant exit while updating"); + CustomMessageBox.Show("Cant exit while updating"); } } diff --git a/Tools/ArdupilotMegaPlanner/GCSViews/FlightData.cs b/Tools/ArdupilotMegaPlanner/GCSViews/FlightData.cs index 2e55ef0f2f..f6a6c224c9 100644 --- a/Tools/ArdupilotMegaPlanner/GCSViews/FlightData.cs +++ b/Tools/ArdupilotMegaPlanner/GCSViews/FlightData.cs @@ -781,7 +781,7 @@ namespace ArdupilotMega.GCSViews Directory.CreateDirectory(Path.GetDirectoryName(Application.ExecutablePath) + Path.DirectorySeparatorChar + @"logs"); swlog = new StreamWriter(Path.GetDirectoryName(Application.ExecutablePath) + Path.DirectorySeparatorChar + @"logs" + Path.DirectorySeparatorChar + DateTime.Now.ToString("yyyy-MM-dd hh-mm") + " telem.log"); } - catch { MessageBox.Show("Log creation error"); } + catch { CustomMessageBox.Show("Log creation error"); } } private void BUTactiondo_Click(object sender, EventArgs e) @@ -795,7 +795,7 @@ namespace ArdupilotMega.GCSViews comPort.doAction((MAVLink.MAV_ACTION)Enum.Parse(typeof(MAVLink.MAV_ACTION), "MAV_ACTION_" + CMB_action.Text)); #endif } - catch { MessageBox.Show("The Command failed to execute"); } + catch { CustomMessageBox.Show("The Command failed to execute"); } ((Button)sender).Enabled = true; } @@ -811,7 +811,7 @@ namespace ArdupilotMega.GCSViews //System.Threading.Thread.Sleep(100); //comPort.doAction(MAVLink.MAV_ACTION.MAV_ACTION_SET_AUTO); // set auto } - catch { MessageBox.Show("The command failed to execute"); } + catch { CustomMessageBox.Show("The command failed to execute"); } ((Button)sender).Enabled = true; } @@ -872,7 +872,7 @@ namespace ArdupilotMega.GCSViews { if (!MainV2.comPort.BaseStream.IsOpen) { - MessageBox.Show("Please Connect First"); + CustomMessageBox.Show("Please Connect First"); return; } @@ -892,13 +892,13 @@ namespace ArdupilotMega.GCSViews int intalt = (int)(100 * MainV2.cs.multiplierdist); if (!int.TryParse(alt, out intalt)) { - MessageBox.Show("Bad Alt"); + CustomMessageBox.Show("Bad Alt"); return; } if (gotolocation.Lat == 0 || gotolocation.Lng == 0) { - MessageBox.Show("Bad Lat/Long"); + CustomMessageBox.Show("Bad Lat/Long"); return; } @@ -919,7 +919,7 @@ namespace ArdupilotMega.GCSViews MainV2.givecomport = false; } - catch (Exception ex) { MainV2.givecomport = false; MessageBox.Show("Error sending command : " + ex.Message); } + catch (Exception ex) { MainV2.givecomport = false; CustomMessageBox.Show("Error sending command : " + ex.Message); } } @@ -1009,7 +1009,7 @@ namespace ArdupilotMega.GCSViews tracklog.Minimum = 0; tracklog.Maximum = 100; } - catch { MessageBox.Show("Error: Failed to write log file"); } + catch { CustomMessageBox.Show("Error: Failed to write log file"); } } } @@ -1112,7 +1112,7 @@ namespace ArdupilotMega.GCSViews ((Button)sender).Enabled = false; comPort.setWPCurrent((ushort)CMB_setwp.SelectedIndex); // set nav to } - catch { MessageBox.Show("The command failed to execute"); } + catch { CustomMessageBox.Show("The command failed to execute"); } ((Button)sender).Enabled = true; } @@ -1143,7 +1143,7 @@ namespace ArdupilotMega.GCSViews comPort.doAction(MAVLink.MAV_ACTION.MAV_ACTION_SET_AUTO); #endif } - catch { MessageBox.Show("The Command failed to execute"); } + catch { CustomMessageBox.Show("The Command failed to execute"); } ((Button)sender).Enabled = true; } @@ -1158,7 +1158,7 @@ namespace ArdupilotMega.GCSViews comPort.doAction(MAVLink.MAV_ACTION.MAV_ACTION_RETURN); #endif } - catch { MessageBox.Show("The Command failed to execute"); } + catch { CustomMessageBox.Show("The Command failed to execute"); } ((Button)sender).Enabled = true; } @@ -1173,7 +1173,7 @@ namespace ArdupilotMega.GCSViews comPort.doAction(MAVLink.MAV_ACTION.MAV_ACTION_SET_MANUAL); #endif } - catch { MessageBox.Show("The Command failed to execute"); } + catch { CustomMessageBox.Show("The Command failed to execute"); } ((Button)sender).Enabled = true; } @@ -1356,7 +1356,7 @@ namespace ArdupilotMega.GCSViews { stopRecordToolStripMenuItem_Click(sender, e); - MessageBox.Show("Output avi will be saved to the log folder"); + CustomMessageBox.Show("Output avi will be saved to the log folder"); aviwriter = new AviWriter(); Directory.CreateDirectory(Path.GetDirectoryName(Application.ExecutablePath) + Path.DirectorySeparatorChar + @"logs"); @@ -1552,7 +1552,7 @@ namespace ArdupilotMega.GCSViews } else { - MessageBox.Show("Max 10 at a time."); + CustomMessageBox.Show("Max 10 at a time."); ((CheckBox)sender).Checked = false; } ThemeManager.ApplyThemeTo(this); @@ -1635,7 +1635,7 @@ namespace ArdupilotMega.GCSViews { if (!MainV2.comPort.BaseStream.IsOpen) { - MessageBox.Show("Please Connect First"); + CustomMessageBox.Show("Please Connect First"); return; } @@ -1645,13 +1645,13 @@ namespace ArdupilotMega.GCSViews int intalt = (int)(100 * MainV2.cs.multiplierdist); if (!int.TryParse(alt, out intalt)) { - MessageBox.Show("Bad Alt"); + CustomMessageBox.Show("Bad Alt"); return; } if (gotolocation.Lat == 0 || gotolocation.Lng == 0) { - MessageBox.Show("Bad Lat/Long"); + CustomMessageBox.Show("Bad Lat/Long"); return; } @@ -1735,7 +1735,7 @@ print 'Roll complete' "; - MessageBox.Show("This is Very ALPHA"); + CustomMessageBox.Show("This is Very ALPHA"); Form scriptedit = new Form(); @@ -1757,7 +1757,7 @@ print 'Roll complete' scriptedit.ShowDialog(); - if (DialogResult.Yes == MessageBox.Show("Run Script", "Run this script?", MessageBoxButtons.YesNo)) + if (DialogResult.Yes == CustomMessageBox.Show("Run Script", "Run this script?", MessageBoxButtons.YesNo)) { Script scr = new Script(); diff --git a/Tools/ArdupilotMegaPlanner/GCSViews/FlightPlanner.Designer.cs b/Tools/ArdupilotMegaPlanner/GCSViews/FlightPlanner.Designer.cs index 4f77a22a7e..acadb4b905 100644 --- a/Tools/ArdupilotMegaPlanner/GCSViews/FlightPlanner.Designer.cs +++ b/Tools/ArdupilotMegaPlanner/GCSViews/FlightPlanner.Designer.cs @@ -339,7 +339,6 @@ // // BUT_write // - this.BUT_write.ForeColor = System.Drawing.SystemColors.ControlText; resources.ApplyResources(this.BUT_write, "BUT_write"); this.BUT_write.Name = "BUT_write"; this.BUT_write.UseVisualStyleBackColor = true; @@ -347,7 +346,6 @@ // // BUT_read // - this.BUT_read.ForeColor = System.Drawing.SystemColors.ControlText; resources.ApplyResources(this.BUT_read, "BUT_read"); this.BUT_read.Name = "BUT_read"; this.BUT_read.UseVisualStyleBackColor = true; @@ -355,7 +353,6 @@ // // SaveFile // - this.SaveFile.ForeColor = System.Drawing.SystemColors.ControlText; resources.ApplyResources(this.SaveFile, "SaveFile"); this.SaveFile.Name = "SaveFile"; this.SaveFile.UseVisualStyleBackColor = true; @@ -363,7 +360,6 @@ // // BUT_loadwpfile // - this.BUT_loadwpfile.ForeColor = System.Drawing.SystemColors.ControlText; resources.ApplyResources(this.BUT_loadwpfile, "BUT_loadwpfile"); this.BUT_loadwpfile.Name = "BUT_loadwpfile"; this.BUT_loadwpfile.UseVisualStyleBackColor = true; @@ -608,7 +604,6 @@ // // button1 // - this.button1.ForeColor = System.Drawing.SystemColors.ControlText; resources.ApplyResources(this.button1, "button1"); this.button1.Name = "button1"; this.toolTip1.SetToolTip(this.button1, resources.GetString("button1.ToolTip")); @@ -617,7 +612,6 @@ // // BUT_Add // - this.BUT_Add.ForeColor = System.Drawing.SystemColors.ControlText; resources.ApplyResources(this.BUT_Add, "BUT_Add"); this.BUT_Add.Name = "BUT_Add"; this.toolTip1.SetToolTip(this.BUT_Add, resources.GetString("BUT_Add.ToolTip")); diff --git a/Tools/ArdupilotMegaPlanner/GCSViews/FlightPlanner.cs b/Tools/ArdupilotMegaPlanner/GCSViews/FlightPlanner.cs index 5aac614ce6..b6aeb84394 100644 --- a/Tools/ArdupilotMegaPlanner/GCSViews/FlightPlanner.cs +++ b/Tools/ArdupilotMegaPlanner/GCSViews/FlightPlanner.cs @@ -98,13 +98,13 @@ namespace ArdupilotMega.GCSViews // if (!hashdefines.ContainsKey("WP_START_BYTE")) { - MessageBox.Show("Your Ardupilot Mega project defines.h is Invalid"); + CustomMessageBox.Show("Your Ardupilot Mega project defines.h is Invalid"); //return false; } } catch (Exception) { - MessageBox.Show("Can't open file!"); + CustomMessageBox.Show("Can't open file!"); return false; } return true; @@ -180,7 +180,7 @@ namespace ArdupilotMega.GCSViews } if (wp_count == byte.MaxValue) { - MessageBox.Show("To many Waypoints!!!"); + CustomMessageBox.Show("To many Waypoints!!!"); break; } } @@ -200,7 +200,7 @@ namespace ArdupilotMega.GCSViews } catch (Exception ex) { - MessageBox.Show("Can't open file! " + ex.ToString()); + CustomMessageBox.Show("Can't open file! " + ex.ToString()); return false; } return true; @@ -260,7 +260,7 @@ namespace ArdupilotMega.GCSViews { if (selectedrow > Commands.RowCount) { - MessageBox.Show("Invalid coord, How did you do this?"); + CustomMessageBox.Show("Invalid coord, How did you do this?"); return; } DataGridViewTextBoxCell cell; @@ -286,13 +286,13 @@ namespace ArdupilotMega.GCSViews if (result == 0 || pass == false) { - MessageBox.Show("You must have a home altitude"); + CustomMessageBox.Show("You must have a home altitude"); return; } int results1; if (!int.TryParse(TXT_DefaultAlt.Text, out results1)) { - MessageBox.Show("Your default alt is not valid"); + CustomMessageBox.Show("Your default alt is not valid"); return; } } @@ -332,7 +332,7 @@ namespace ArdupilotMega.GCSViews if (float.Parse(TXT_homealt.Text) + int.Parse(TXT_DefaultAlt.Text) < alt) // calced height is less that GE ground height { - MessageBox.Show("Altitude appears to be low!! (you will fly into a hill)\nGoogle Ground height: " + alt + " Meters\nYour height: " + ((float.Parse(TXT_homealt.Text) + int.Parse(TXT_DefaultAlt.Text))) + " Meters"); + CustomMessageBox.Show("Altitude appears to be low!! (you will fly into a hill)\nGoogle Ground height: " + alt + " Meters\nYour height: " + ((float.Parse(TXT_homealt.Text) + int.Parse(TXT_DefaultAlt.Text))) + " Meters"); cell.Style.BackColor = Color.Red; } else @@ -346,7 +346,7 @@ namespace ArdupilotMega.GCSViews } else { - MessageBox.Show("Invalid Home or wp Alt"); + CustomMessageBox.Show("Invalid Home or wp Alt"); cell.Style.BackColor = Color.Red; } @@ -772,7 +772,7 @@ namespace ArdupilotMega.GCSViews for (int i = 1; i <= 7; i++) Commands.Columns[i].HeaderText = "setme"; } - catch (Exception ex) { MessageBox.Show(ex.ToString()); } + catch (Exception ex) { CustomMessageBox.Show(ex.ToString()); } } /// @@ -797,7 +797,7 @@ namespace ArdupilotMega.GCSViews //Console.WriteLine("editformat " + option + " value " + cmd); ChangeColumnHeader(cmd); } - catch (Exception ex) { MessageBox.Show(ex.ToString()); } + catch (Exception ex) { CustomMessageBox.Show(ex.ToString()); } } private void Commands_RowsAdded(object sender, DataGridViewRowsAddedEventArgs e) @@ -1179,7 +1179,7 @@ namespace ArdupilotMega.GCSViews } sw.Close(); } - catch (Exception) { MessageBox.Show("Error writing file"); } + catch (Exception) { CustomMessageBox.Show("Error writing file"); } } } @@ -1248,7 +1248,7 @@ namespace ArdupilotMega.GCSViews log.Info("Done"); } - catch (Exception ex) { error = 1; MessageBox.Show("Error : " + ex.ToString()); } + catch (Exception ex) { error = 1; CustomMessageBox.Show("Error : " + ex.ToString()); } try { this.BeginInvoke((MethodInvoker)delegate() @@ -1282,7 +1282,7 @@ namespace ArdupilotMega.GCSViews { if (CHK_altmode.Checked) { - if (DialogResult.No == MessageBox.Show("Absolute Alt is ticked are you sure?", "Alt Mode", MessageBoxButtons.YesNo)) + if (DialogResult.No == CustomMessageBox.Show("Absolute Alt is ticked are you sure?", "Alt Mode", MessageBoxButtons.YesNo)) { CHK_altmode.Checked = false; } @@ -1298,7 +1298,7 @@ namespace ArdupilotMega.GCSViews { if (!double.TryParse(Commands[b, a].Value.ToString(), out answer)) { - MessageBox.Show("There are errors in your mission"); + CustomMessageBox.Show("There are errors in your mission"); return; } } @@ -1501,7 +1501,7 @@ namespace ArdupilotMega.GCSViews { if (cellhome.Value.ToString() != TXT_homelat.Text && cellhome.Value.ToString() != "0") { - DialogResult dr = MessageBox.Show("Reset Home to loaded coords", "Reset Home Coords", MessageBoxButtons.YesNo); + DialogResult dr = CustomMessageBox.Show("Reset Home to loaded coords", "Reset Home Coords", MessageBoxButtons.YesNo); if (dr == DialogResult.Yes) { @@ -1633,7 +1633,7 @@ namespace ArdupilotMega.GCSViews } if (isNumber > 127) { - MessageBox.Show("The value can only be between 0 and 127"); + CustomMessageBox.Show("The value can only be between 0 and 127"); TXT_WPRad.Text = "127"; } writeKML(); @@ -1656,7 +1656,7 @@ namespace ArdupilotMega.GCSViews } if (isNumber > 127) { - MessageBox.Show("The value can only be between 0 and 127"); + CustomMessageBox.Show("The value can only be between 0 and 127"); TXT_loiterrad.Text = "127"; } } @@ -1712,7 +1712,7 @@ namespace ArdupilotMega.GCSViews writeKML(); } } - catch (Exception) { MessageBox.Show("Row error"); } + catch (Exception) { CustomMessageBox.Show("Row error"); } } private void Commands_DefaultValuesNeeded(object sender, DataGridViewRowEventArgs e) @@ -1792,7 +1792,7 @@ namespace ArdupilotMega.GCSViews string header = sr.ReadLine(); if (header == null || !header.Contains("QGC WPL 110")) { - MessageBox.Show("Invalid Waypoint file"); + CustomMessageBox.Show("Invalid Waypoint file"); return; } while (!error && !sr.EndOfStream) @@ -1839,11 +1839,11 @@ namespace ArdupilotMega.GCSViews wp_count++; } - catch { MessageBox.Show("Line invalid\n" + line); } + catch { CustomMessageBox.Show("Line invalid\n" + line); } if (wp_count == byte.MaxValue) { - MessageBox.Show("To many Waypoints!!!"); + CustomMessageBox.Show("To many Waypoints!!!"); break; } @@ -1859,7 +1859,7 @@ namespace ArdupilotMega.GCSViews } catch (Exception ex) { - MessageBox.Show("Can't open file! " + ex.ToString()); + CustomMessageBox.Show("Can't open file! " + ex.ToString()); } } @@ -2252,7 +2252,7 @@ namespace ArdupilotMega.GCSViews FlightData.mymap.MapType = (MapType)comboBoxMapType.SelectedItem; MainV2.config["MapType"] = comboBoxMapType.Text; } - catch { MessageBox.Show("Map change failed. try zomming out first."); } + catch { CustomMessageBox.Show("Map change failed. try zomming out first."); } } private void Commands_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e) @@ -2324,7 +2324,7 @@ namespace ArdupilotMega.GCSViews private void TXT_homelat_Enter(object sender, EventArgs e) { sethome = true; - MessageBox.Show("Click on the Map to set Home "); + CustomMessageBox.Show("Click on the Map to set Home "); } private void Planner_Resize(object sender, EventArgs e) @@ -2345,7 +2345,7 @@ namespace ArdupilotMega.GCSViews private void CHK_altmode_CheckedChanged(object sender, EventArgs e) { if (Commands.RowCount > 0 && !quickadd) - MessageBox.Show("You will need to change your altitudes"); + CustomMessageBox.Show("You will need to change your altitudes"); } protected override void OnPaint(PaintEventArgs pe) @@ -2391,7 +2391,7 @@ namespace ArdupilotMega.GCSViews RectLatLng area = MainMap.SelectedArea; if (area.IsEmpty) { - DialogResult res = MessageBox.Show("No ripp area defined, ripp displayed on screen?", "Rip", MessageBoxButtons.YesNo); + DialogResult res = CustomMessageBox.Show("No ripp area defined, ripp displayed on screen?", "Rip", MessageBoxButtons.YesNo); if (res == DialogResult.Yes) { area = MainMap.CurrentViewArea; @@ -2400,7 +2400,7 @@ namespace ArdupilotMega.GCSViews if (!area.IsEmpty) { - DialogResult res = MessageBox.Show("Ready ripp at Zoom = " + (int)MainMap.Zoom + " ?", "GMap.NET", MessageBoxButtons.YesNo); + DialogResult res = CustomMessageBox.Show("Ready ripp at Zoom = " + (int)MainMap.Zoom + " ?", "GMap.NET", MessageBoxButtons.YesNo); for (int i = 1; i <= MainMap.MaxZoom; i++) { @@ -2422,7 +2422,7 @@ namespace ArdupilotMega.GCSViews } else { - MessageBox.Show("Select map area holding ALT", "GMap.NET", MessageBoxButtons.OK, MessageBoxIcon.Exclamation); + CustomMessageBox.Show("Select map area holding ALT", "GMap.NET", MessageBoxButtons.OK, MessageBoxIcon.Exclamation); } } @@ -2485,7 +2485,7 @@ namespace ArdupilotMega.GCSViews if (drawnpolygon == null || drawnpolygon.Points.Count == 0) { - MessageBox.Show("Right click the map to draw a polygon", "Area", MessageBoxButtons.OK, MessageBoxIcon.Exclamation); + CustomMessageBox.Show("Right click the map to draw a polygon", "Area", MessageBoxButtons.OK, MessageBoxIcon.Exclamation); return; } GMapPolygon area = drawnpolygon; @@ -2520,17 +2520,17 @@ namespace ArdupilotMega.GCSViews if (!double.TryParse(angle, out tryme)) { - MessageBox.Show("Invalid Angle"); + CustomMessageBox.Show("Invalid Angle"); return; } if (!double.TryParse(alt, out tryme)) { - MessageBox.Show("Invalid Alt"); + CustomMessageBox.Show("Invalid Alt"); return; } if (!double.TryParse(distance, out tryme)) { - MessageBox.Show("Invalid Distance"); + CustomMessageBox.Show("Invalid Distance"); return; } @@ -2691,7 +2691,7 @@ namespace ArdupilotMega.GCSViews if (Commands.RowCount > 150) { - MessageBox.Show("Stopping at 150 WP's"); + CustomMessageBox.Show("Stopping at 150 WP's"); break; } } @@ -2713,7 +2713,7 @@ namespace ArdupilotMega.GCSViews } else { - MessageBox.Show("If you're at the field, connect to your APM and wait for GPS lock. Then click 'Home Location' link to set home to your location"); + CustomMessageBox.Show("If you're at the field, connect to your APM and wait for GPS lock. Then click 'Home Location' link to set home to your location"); } } @@ -2771,7 +2771,7 @@ namespace ArdupilotMega.GCSViews polygons.Markers.Add(new GMapMarkerGoogleRed(start)); MainMap.Invalidate(); - MessageBox.Show("Distance: " + FormatDistance(MainMap.Manager.GetDistance(startmeasure, start), true) + " AZ: " + (MainMap.Manager.GetBearing(startmeasure, start).ToString("0"))); + CustomMessageBox.Show("Distance: " + FormatDistance(MainMap.Manager.GetDistance(startmeasure, start), true) + " AZ: " + (MainMap.Manager.GetBearing(startmeasure, start).ToString("0"))); polygons.Polygons.Remove(line); polygons.Markers.Clear(); startmeasure = new PointLatLng(); @@ -2794,7 +2794,7 @@ namespace ArdupilotMega.GCSViews { if (polygongridmode == false) { - MessageBox.Show("You will remain in polygon mode until you clear the polygon or create a grid/upload a fence"); + CustomMessageBox.Show("You will remain in polygon mode until you clear the polygon or create a grid/upload a fence"); } polygongridmode = true; @@ -2909,7 +2909,7 @@ namespace ArdupilotMega.GCSViews MainMap.Invalidate(); } catch { - MessageBox.Show("Remove point Failed. Please try again."); + CustomMessageBox.Show("Remove point Failed. Please try again."); } } } @@ -2981,7 +2981,7 @@ namespace ArdupilotMega.GCSViews GeoCoderStatusCode status = MainMap.SetCurrentPositionByKeywords(place); if (status != GeoCoderStatusCode.G_GEO_SUCCESS) { - MessageBox.Show("Google Maps Geocoder can't find: '" + place + "', reason: " + status.ToString(), "GMap.NET", MessageBoxButtons.OK, MessageBoxIcon.Exclamation); + CustomMessageBox.Show("Google Maps Geocoder can't find: '" + place + "', reason: " + status.ToString(), "GMap.NET", MessageBoxButtons.OK, MessageBoxIcon.Exclamation); } else { @@ -3017,7 +3017,7 @@ namespace ArdupilotMega.GCSViews parser.ElementAdded += parser_ElementAdded; parser.ParseString(kml, true); - if (DialogResult.Yes == MessageBox.Show("Do you want to load this into the flight data screen?", "Load data", MessageBoxButtons.YesNo)) + if (DialogResult.Yes == CustomMessageBox.Show("Do you want to load this into the flight data screen?", "Load data", MessageBoxButtons.YesNo)) { foreach (var temp in kmlpolygons.Polygons) { @@ -3030,7 +3030,7 @@ namespace ArdupilotMega.GCSViews } } - catch (Exception ex) { MessageBox.Show("Bad KML File :" + ex.ToString()); } + catch (Exception ex) { CustomMessageBox.Show("Bad KML File :" + ex.ToString()); } } } @@ -3064,25 +3064,25 @@ namespace ArdupilotMega.GCSViews //FENCE_TOTAL if (MainV2.comPort.param["FENCE_ACTION"] == null) { - MessageBox.Show("Not Supported"); + CustomMessageBox.Show("Not Supported"); return; } if (drawnpolygon == null) { - MessageBox.Show("No polygon to upload"); + CustomMessageBox.Show("No polygon to upload"); return; } if (geofence.Markers.Count == 0) { - MessageBox.Show("No return location set"); + CustomMessageBox.Show("No return location set"); return; } if (drawnpolygon.Points.Count == 0) { - MessageBox.Show("No polygon drawn"); + CustomMessageBox.Show("No polygon drawn"); return; } @@ -3093,7 +3093,7 @@ namespace ArdupilotMega.GCSViews // check it if (!pnpoly(plll.ToArray(), geofence.Markers[0].Position.Lat, geofence.Markers[0].Position.Lng)) { - MessageBox.Show("Your return location is outside the polygon"); + CustomMessageBox.Show("Your return location is outside the polygon"); return; } @@ -3108,13 +3108,13 @@ namespace ArdupilotMega.GCSViews if (!int.TryParse(minalts, out minalt)) { - MessageBox.Show("Bad Min Alt"); + CustomMessageBox.Show("Bad Min Alt"); return; } if (!int.TryParse(maxalts, out maxalt)) { - MessageBox.Show("Bad Max Alt"); + CustomMessageBox.Show("Bad Max Alt"); return; } @@ -3125,7 +3125,7 @@ namespace ArdupilotMega.GCSViews } catch { - MessageBox.Show("Failed to set min/max fence alt"); + CustomMessageBox.Show("Failed to set min/max fence alt"); return; } @@ -3136,7 +3136,7 @@ namespace ArdupilotMega.GCSViews } catch { - MessageBox.Show("Failed to set FENCE_ACTION"); + CustomMessageBox.Show("Failed to set FENCE_ACTION"); return; } @@ -3192,13 +3192,13 @@ namespace ArdupilotMega.GCSViews if (MainV2.comPort.param["FENCE_ACTION"] == null || MainV2.comPort.param["FENCE_TOTAL"] == null) { - MessageBox.Show("Not Supported"); + CustomMessageBox.Show("Not Supported"); return; } if (int.Parse(MainV2.comPort.param["FENCE_TOTAL"].ToString()) <= 1) { - MessageBox.Show("Nothing to download"); + CustomMessageBox.Show("Nothing to download"); return; } @@ -3320,7 +3320,7 @@ namespace ArdupilotMega.GCSViews { if (geofence.Markers.Count == 0) { - MessageBox.Show("Please set a return location"); + CustomMessageBox.Show("Please set a return location"); return; } @@ -3362,7 +3362,7 @@ namespace ArdupilotMega.GCSViews sw.Close(); } - catch { MessageBox.Show("Failed to write fence file"); } + catch { CustomMessageBox.Show("Failed to write fence file"); } } } diff --git a/Tools/ArdupilotMegaPlanner/GCSViews/Simulation.cs b/Tools/ArdupilotMegaPlanner/GCSViews/Simulation.cs index 6a313ca07d..e0491361e3 100644 --- a/Tools/ArdupilotMegaPlanner/GCSViews/Simulation.cs +++ b/Tools/ArdupilotMegaPlanner/GCSViews/Simulation.cs @@ -274,7 +274,7 @@ namespace ArdupilotMega.GCSViews if (MainV2.comPort.BaseStream.IsOpen == false) { - MessageBox.Show("Please connect first"); + CustomMessageBox.Show("Please connect first"); return; } diff --git a/Tools/ArdupilotMegaPlanner/GCSViews/Terminal.cs b/Tools/ArdupilotMegaPlanner/GCSViews/Terminal.cs index fb5d258c30..24aeb9fdd1 100644 --- a/Tools/ArdupilotMegaPlanner/GCSViews/Terminal.cs +++ b/Tools/ArdupilotMegaPlanner/GCSViews/Terminal.cs @@ -152,7 +152,7 @@ namespace ArdupilotMega.GCSViews comPort.Write(Encoding.ASCII.GetBytes(cmd + "\r"), 0, cmd.Length + 1); } } - catch { MessageBox.Show("Error writing to com port"); } + catch { CustomMessageBox.Show("Error writing to com port"); } } } /* diff --git a/Tools/ArdupilotMegaPlanner/Joystick.cs b/Tools/ArdupilotMegaPlanner/Joystick.cs index 40ea6ce81d..a79db6ede6 100644 --- a/Tools/ArdupilotMegaPlanner/Joystick.cs +++ b/Tools/ArdupilotMegaPlanner/Joystick.cs @@ -117,7 +117,7 @@ namespace ArdupilotMega joystick.Acquire(); - System.Windows.Forms.MessageBox.Show("Please ensure you have calibrated your joystick in Windows first"); + System.Windows.Forms.CustomMessageBox.Show("Please ensure you have calibrated your joystick in Windows first"); joystick.Poll(); @@ -133,7 +133,7 @@ namespace ArdupilotMega values["Slider1"] = obj.GetSlider()[0]; values["Slider2"] = obj.GetSlider()[1]; - System.Windows.Forms.MessageBox.Show("Please move the joystick axis you want assigned to this function after clicking ok"); + System.Windows.Forms.CustomMessageBox.Show("Please move the joystick axis you want assigned to this function after clicking ok"); DateTime start = DateTime.Now; @@ -178,7 +178,7 @@ namespace ArdupilotMega } } - System.Windows.Forms.MessageBox.Show("No valid option was detected"); + System.Windows.Forms.CustomMessageBox.Show("No valid option was detected"); return joystickaxis.None; } @@ -210,7 +210,7 @@ namespace ArdupilotMega joystick.Poll(); - System.Windows.Forms.MessageBox.Show("Please press the joystick button you want assigned to this function after clicking ok"); + System.Windows.Forms.CustomMessageBox.Show("Please press the joystick button you want assigned to this function after clicking ok"); DateTime start = DateTime.Now; @@ -228,7 +228,7 @@ namespace ArdupilotMega } } - System.Windows.Forms.MessageBox.Show("No valid option was detected"); + System.Windows.Forms.CustomMessageBox.Show("No valid option was detected"); return -1; } @@ -332,7 +332,7 @@ namespace ArdupilotMega MainV2.comPort.setMode(mode); } - catch { System.Windows.Forms.MessageBox.Show("Failed to change Modes"); } + catch { System.Windows.Forms.CustomMessageBox.Show("Failed to change Modes"); } }); } } diff --git a/Tools/ArdupilotMegaPlanner/JoystickSetup.cs b/Tools/ArdupilotMegaPlanner/JoystickSetup.cs index 012475894d..9d491c7a68 100644 --- a/Tools/ArdupilotMegaPlanner/JoystickSetup.cs +++ b/Tools/ArdupilotMegaPlanner/JoystickSetup.cs @@ -34,7 +34,7 @@ namespace ArdupilotMega CMB_joysticks.Items.Add(device.ProductName); } } - catch { MessageBox.Show("Error geting joystick list: do you have the directx redist installed?"); this.Close(); return; } + catch { CustomMessageBox.Show("Error geting joystick list: do you have the directx redist installed?"); this.Close(); return; } if (CMB_joysticks.Items.Count > 0) CMB_joysticks.SelectedIndex = 0; @@ -134,7 +134,7 @@ namespace ArdupilotMega { joy.setButton(f, int.Parse(this.Controls.Find("cmbbutton" + name, false)[0].Text), this.Controls.Find("cmbaction" + name, false)[0].Text); } - catch { MessageBox.Show("Set Button "+ name + " Failed"); } + catch { CustomMessageBox.Show("Set Button "+ name + " Failed"); } } joy.start(CMB_joysticks.Text); diff --git a/Tools/ArdupilotMegaPlanner/Log.cs b/Tools/ArdupilotMegaPlanner/Log.cs index 17f5c72f74..53953f1449 100644 --- a/Tools/ArdupilotMegaPlanner/Log.cs +++ b/Tools/ArdupilotMegaPlanner/Log.cs @@ -77,7 +77,7 @@ namespace ArdupilotMega catch (Exception ex) { log.Error("Error opening comport", ex); - MessageBox.Show("Error opening comport"); + CustomMessageBox.Show("Error opening comport"); } var t11 = new System.Threading.Thread(delegate() @@ -312,7 +312,7 @@ namespace ArdupilotMega log.Info("exit while"); } - catch (Exception ex) { MessageBox.Show("Error reading data" + ex.ToString()); } + catch (Exception ex) { CustomMessageBox.Show("Error reading data" + ex.ToString()); } } string lastline = ""; @@ -899,7 +899,7 @@ namespace ArdupilotMega tr.Close(); } - catch (Exception ex) { MessageBox.Show("Error processing log. Is it still downloading? " + ex.Message); continue; } + catch (Exception ex) { CustomMessageBox.Show("Error processing log. Is it still downloading? " + ex.Message); continue; } writeKMLFirstPerson(logfile + ".kml"); diff --git a/Tools/ArdupilotMegaPlanner/LogBrowse.cs b/Tools/ArdupilotMegaPlanner/LogBrowse.cs index df1f7e349c..8d9dfa0b57 100644 --- a/Tools/ArdupilotMegaPlanner/LogBrowse.cs +++ b/Tools/ArdupilotMegaPlanner/LogBrowse.cs @@ -52,7 +52,7 @@ namespace ArdupilotMega dataGridView1.DataSource = m_dtCSV; } - catch (Exception ex) { MessageBox.Show("Failed to read File: " + ex.ToString()); } + catch (Exception ex) { CustomMessageBox.Show("Failed to read File: " + ex.ToString()); } foreach (DataGridViewColumn column in dataGridView1.Columns) { @@ -256,7 +256,7 @@ namespace ArdupilotMega { if (dataGridView1.RowCount == 0 || dataGridView1.ColumnCount == 0) { - MessageBox.Show("Please load a valid file"); + CustomMessageBox.Show("Please load a valid file"); return; } @@ -267,7 +267,7 @@ namespace ArdupilotMega if (col == 0) { - MessageBox.Show("Please pick another column, Highlight the cell you wish to graph"); + CustomMessageBox.Show("Please pick another column, Highlight the cell you wish to graph"); return; } @@ -307,11 +307,11 @@ namespace ArdupilotMega } else { - MessageBox.Show("Max of 5"); + CustomMessageBox.Show("Max of 5"); break; } } - catch { error++; log.Info("Bad Data : " + type + " " + col + " " + a); if (error >= 500) { MessageBox.Show("There is to much bad data - failing"); break; } } + catch { error++; log.Info("Bad Data : " + type + " " + col + " " + a); if (error >= 500) { CustomMessageBox.Show("There is to much bad data - failing"); break; } } } a++; } diff --git a/Tools/ArdupilotMegaPlanner/MAVLink.cs b/Tools/ArdupilotMegaPlanner/MAVLink.cs index 576cdead7f..2b181fbf75 100644 --- a/Tools/ArdupilotMegaPlanner/MAVLink.cs +++ b/Tools/ArdupilotMegaPlanner/MAVLink.cs @@ -472,13 +472,6 @@ namespace ArdupilotMega return true; } - public bool setParam(string paramname, object flag) - { - int value = (int)(float)param[paramname]; - - return setParam(paramname, value | (int)flag); - } - /// /// Set parameter on apm /// @@ -1917,7 +1910,7 @@ namespace ArdupilotMega MainV2.comPort.generatePacket((byte)MAVLink.MAVLINK_MSG_ID_SET_MODE, mode); } } - catch { System.Windows.Forms.MessageBox.Show("Failed to change Modes"); } + catch { System.Windows.Forms.CustomMessageBox.Show("Failed to change Modes"); } #endif } diff --git a/Tools/ArdupilotMegaPlanner/MagCalib.cs b/Tools/ArdupilotMegaPlanner/MagCalib.cs index 3db2921682..ca36613cfd 100644 --- a/Tools/ArdupilotMegaPlanner/MagCalib.cs +++ b/Tools/ArdupilotMegaPlanner/MagCalib.cs @@ -5,23 +5,24 @@ using System.Text; using System.Windows.Forms; using System.IO; using System.Collections; +using netDxf; +using netDxf.Entities; +using netDxf.Tables; +using netDxf.Header; +using System.Reflection; +using log4net; namespace ArdupilotMega { public class MagCalib { + private static readonly ILog log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - //alglib.lsfit. - - public static void doWork() + /// + /// Self contained process tlog and save/display offsets + /// + public static void ProcessLog() { - // based of tridge's work - - Tuple offset = new Tuple(0, 0, 0); - List> data = new List>(); - - Hashtable filter = new Hashtable(); - OpenFileDialog openFileDialog1 = new OpenFileDialog(); openFileDialog1.Filter = "*.tlog|*.tlog"; openFileDialog1.FilterIndex = 2; @@ -37,100 +38,225 @@ namespace ArdupilotMega if (openFileDialog1.ShowDialog() == DialogResult.OK) { - foreach (string logfile in openFileDialog1.FileNames) - { - MAVLink mine = new MAVLink(); - mine.logplaybackfile = new BinaryReader(File.Open(logfile, FileMode.Open, FileAccess.Read, FileShare.Read)); - mine.logreadmode = true; + double[] ans = getOffsets(openFileDialog1.FileName); - mine.packets.Initialize(); // clear - - // gather data - while (mine.logplaybackfile.BaseStream.Position < mine.logplaybackfile.BaseStream.Length) - { - // bar moves to 100 % in this step - //progressBar1.Value = (int)((float)mine.logplaybackfile.BaseStream.Position / (float)mine.logplaybackfile.BaseStream.Length * 100.0f / 1.0f); - - //progressBar1.Refresh(); - //Application.DoEvents(); - - byte[] packetraw = mine.readPacket(); - - var packet = mine.DebugPacket(packetraw); - - if (packet == null) - continue; - - if (packet.GetType() == typeof(MAVLink.__mavlink_sensor_offsets_t)) - { - offset = new Tuple( - ((MAVLink.__mavlink_sensor_offsets_t)packet).mag_ofs_x, - ((MAVLink.__mavlink_sensor_offsets_t)packet).mag_ofs_y, - ((MAVLink.__mavlink_sensor_offsets_t)packet).mag_ofs_z); - } - else if (packet.GetType() == typeof(MAVLink.__mavlink_raw_imu_t)) - { - int div = 20; - - string item = (int)(((MAVLink.__mavlink_raw_imu_t)packet).xmag / div) + "," + - (int)(((MAVLink.__mavlink_raw_imu_t)packet).ymag / div) + "," + - (int)(((MAVLink.__mavlink_raw_imu_t)packet).zmag / div); - - if (filter.ContainsKey(item)) - { - filter[item] = (int)filter[item] + 1; - - if ((int)filter[item] > 3) - continue; - } - else - { - filter[item] = 1; - } - - - data.Add(new Tuple( - ((MAVLink.__mavlink_raw_imu_t)packet).xmag - offset.Item1, - ((MAVLink.__mavlink_raw_imu_t)packet).ymag - offset.Item2, - ((MAVLink.__mavlink_raw_imu_t)packet).zmag - offset.Item3)); - } - - } - - Console.WriteLine("Extracted " + data.Count + " data points"); - Console.WriteLine("Current offset: " + offset); - - mine.logreadmode = false; - mine.logplaybackfile.Close(); - mine.logplaybackfile = null; - - double[] x = new double[] { 0, 0, 0, 0 }; - double epsg = 0.0000000001; - double epsf = 0; - double epsx = 0; - int maxits = 0; - alglib.minlmstate state; - alglib.minlmreport rep; - - alglib.minlmcreatev(data.Count, x, 100, out state); - alglib.minlmsetcond(state, epsg, epsf, epsx, maxits); - alglib.minlmoptimize(state, sphere_error, null, data); - alglib.minlmresults(state, out x, out rep); - - System.Console.WriteLine("{0}", rep.terminationtype); // EXPECTED: 4 - System.Console.WriteLine("{0}", alglib.ap.format(x, 2)); // EXPECTED: [-3,+3] - //System.Console.ReadLine(); - - - // return; - - - } + SaveOffsets(ans); } } - public static void sphere_error(double[] xi, double[] fi, object obj) + /// + /// Processes a tlog to get the offsets - creates dxf of data + /// + /// Filename + /// Offsets + public static double[] getOffsets(string fn) + { + // based of tridge's work + string logfile = fn; + + // old method + float minx = 0; + float maxx = 0; + float miny = 0; + float maxy = 0; + float minz = 0; + float maxz = 0; + + // this is for a dxf + Polyline3dVertex vertex; + List vertexes = new List(); + + // data storage + Tuple offset = new Tuple(0, 0, 0); + List> data = new List>(); + + Hashtable filter = new Hashtable(); + + log.Info("Start log: " + DateTime.Now); + + MAVLink mine = new MAVLink(); + mine.logplaybackfile = new BinaryReader(File.Open(logfile, FileMode.Open, FileAccess.Read, FileShare.Read)); + mine.logreadmode = true; + + mine.packets.Initialize(); // clear + + // gather data + while (mine.logplaybackfile.BaseStream.Position < mine.logplaybackfile.BaseStream.Length) + { + byte[] packetraw = mine.readPacket(); + + var packet = mine.DebugPacket(packetraw, false); + + // this is for packets we dont know about + if (packet == null) + continue; + + if (packet.GetType() == typeof(MAVLink.__mavlink_sensor_offsets_t)) + { + offset = new Tuple( + ((MAVLink.__mavlink_sensor_offsets_t)packet).mag_ofs_x, + ((MAVLink.__mavlink_sensor_offsets_t)packet).mag_ofs_y, + ((MAVLink.__mavlink_sensor_offsets_t)packet).mag_ofs_z); + } + else if (packet.GetType() == typeof(MAVLink.__mavlink_raw_imu_t)) + { + int div = 20; + + // fox dxf + vertex = new Polyline3dVertex(new Vector3f( + ((MAVLink.__mavlink_raw_imu_t)packet).xmag - offset.Item1, + ((MAVLink.__mavlink_raw_imu_t)packet).ymag - offset.Item2, + ((MAVLink.__mavlink_raw_imu_t)packet).zmag - offset.Item3) + ); + vertexes.Add(vertex); + + + // for old method + setMinorMax(((MAVLink.__mavlink_raw_imu_t)packet).xmag - offset.Item1, ref minx, ref maxx); + setMinorMax(((MAVLink.__mavlink_raw_imu_t)packet).ymag - offset.Item2, ref miny, ref maxy); + setMinorMax(((MAVLink.__mavlink_raw_imu_t)packet).zmag - offset.Item3, ref minz, ref maxz); + + // for new lease sq + string item = (int)(((MAVLink.__mavlink_raw_imu_t)packet).xmag / div) + "," + + (int)(((MAVLink.__mavlink_raw_imu_t)packet).ymag / div) + "," + + (int)(((MAVLink.__mavlink_raw_imu_t)packet).zmag / div); + + if (filter.ContainsKey(item)) + { + filter[item] = (int)filter[item] + 1; + + if ((int)filter[item] > 3) + continue; + } + else + { + filter[item] = 1; + } + + + data.Add(new Tuple( + ((MAVLink.__mavlink_raw_imu_t)packet).xmag - offset.Item1, + ((MAVLink.__mavlink_raw_imu_t)packet).ymag - offset.Item2, + ((MAVLink.__mavlink_raw_imu_t)packet).zmag - offset.Item3)); + + } + + } + + log.Info("Log Processed " + DateTime.Now); + + Console.WriteLine("Extracted " + data.Count + " data points"); + Console.WriteLine("Current offset: " + offset); + + mine.logreadmode = false; + mine.logplaybackfile.Close(); + mine.logplaybackfile = null; + + double[] x = LeastSq(data); + + System.Console.WriteLine("Old Method {0} {1} {2}", -(maxx + minx) / 2, -(maxy + miny) / 2, -(maxz + minz) / 2); + + log.Info("Least Sq Done " + DateTime.Now); + + // create a dxf for those who want to "see" the calibration + DxfDocument dxf = new DxfDocument(); + + Polyline3d polyline = new Polyline3d(vertexes, true); + polyline.Layer = new Layer("polyline3d"); + polyline.Layer.Color.Index = 24; + dxf.AddEntity(polyline); + + Point pnt = new Point(new Vector3f(-offset.Item1, -offset.Item2, -offset.Item3)); + pnt.Layer = new Layer("old offset"); + pnt.Layer.Color.Index = 22; + dxf.AddEntity(pnt); + + pnt = new Point(new Vector3f(-(float)x[0], -(float)x[1], -(float)x[2])); + pnt.Layer = new Layer("new offset"); + pnt.Layer.Color.Index = 21; + dxf.AddEntity(pnt); + + dxf.Save("magoffset.dxf", DxfVersion.AutoCad2000); + + log.Info("dxf Done " + DateTime.Now); + + Array.Resize(ref x, 3); + + return x; + } + + /// + /// Does the least sq adjustment to find the center of the sphere + /// + /// list of x,y,z data + /// offsets + public static double[] LeastSq(List> data) + { + double[] x = new double[] { 0, 0, 0, 0 }; + double epsg = 0.0000000001; + double epsf = 0; + double epsx = 0; + int maxits = 0; + alglib.minlmstate state; + alglib.minlmreport rep; + + alglib.minlmcreatev(data.Count, x, 100, out state); + alglib.minlmsetcond(state, epsg, epsf, epsx, maxits); + alglib.minlmoptimize(state, sphere_error, null, data); + alglib.minlmresults(state, out x, out rep); + + log.InfoFormat("{0}", rep.terminationtype); + log.InfoFormat("{0}", alglib.ap.format(x, 2)); + + return x; + } + + /// + /// saves the offests to eeprom, os displays if cant + /// + /// offsets + public static void SaveOffsets(double[] ofs) + { + if (MainV2.comPort.param.ContainsKey("COMPASS_OFS_X")) + { + try + { + // disable learning + MainV2.comPort.setParam("COMPASS_LEARN", 0); + // set values + MainV2.comPort.setParam("COMPASS_OFS_X", (float)ofs[0]); + MainV2.comPort.setParam("COMPASS_OFS_Y", (float)ofs[1]); + MainV2.comPort.setParam("COMPASS_OFS_Z", (float)ofs[2]); + } + catch { + CustomMessageBox.Show("Set Compass offset failed"); + return; + } + + CustomMessageBox.Show("New offsets are " + ofs[0].ToString("0") + " " + ofs[1].ToString("0") + " " + ofs[2].ToString("0") +"\nThese have been saved for you.", "New Mag Offsets"); + } + else + { + CustomMessageBox.Show("New offsets are " + ofs[0].ToString("0") + " " + ofs[1].ToString("0") + " " + ofs[2].ToString("0") + "\n\nPlease write these down for manual entry", "New Mag Offsets"); + } + } + /// + /// Min or max finder + /// + /// value to process + /// current min + /// current max + private static void setMinorMax(float value, ref float min, ref float max) + { + if (value > max) + max = value; + if (value < min) + min = value; + } + + + static void sphere_error(double[] xi, double[] fi, object obj) { double xofs = xi[0]; double yofs = xi[1]; diff --git a/Tools/ArdupilotMegaPlanner/MainV2.cs b/Tools/ArdupilotMegaPlanner/MainV2.cs index f7cb7c990e..26e42632e2 100644 --- a/Tools/ArdupilotMegaPlanner/MainV2.cs +++ b/Tools/ArdupilotMegaPlanner/MainV2.cs @@ -171,7 +171,7 @@ namespace ArdupilotMega // preload Python.CreateEngine(); } - catch (Exception e) { MessageBox.Show("A Major error has occured : " + e.ToString()); this.Close(); } + catch (Exception e) { CustomMessageBox.Show("A Major error has occured : " + e.ToString()); this.Close(); } if (MainV2.config["CHK_GDIPlus"] != null) GCSViews.FlightData.myhud.UseOpenGL = !bool.Parse(MainV2.config["CHK_GDIPlus"].ToString()); @@ -232,7 +232,7 @@ namespace ArdupilotMega if (cs.rateattitude == 0) // initilised to 10, configured above from save { - MessageBox.Show("NOTE: your attitude rate is 0, the hud will not work\nChange in Configuration > Planner > Telemetry Rates"); + CustomMessageBox.Show("NOTE: your attitude rate is 0, the hud will not work\nChange in Configuration > Planner > Telemetry Rates"); } @@ -249,7 +249,7 @@ namespace ArdupilotMega if (Framework < 3.5) { - MessageBox.Show("This program requires .NET Framework 3.5. You currently have " + Framework); + CustomMessageBox.Show("This program requires .NET Framework 3.5. You currently have " + Framework); } } @@ -303,7 +303,7 @@ namespace ArdupilotMega } string name = "ss" + DateTime.Now.ToString("hhmmss") + ".jpg"; bitmap.Save(Path.GetDirectoryName(Application.ExecutablePath) + Path.DirectorySeparatorChar + name, System.Drawing.Imaging.ImageFormat.Jpeg); - MessageBox.Show("Screenshot saved to " + name); + CustomMessageBox.Show("Screenshot saved to " + name); } } @@ -475,7 +475,7 @@ namespace ArdupilotMega if (comPort.BaseStream.IsOpen && cs.groundspeed > 4) { - if (DialogResult.No == MessageBox.Show("Your model is still moving are you sure you want to disconnect?", "Disconnect", MessageBoxButtons.YesNo)) + if (DialogResult.No == CustomMessageBox.Show("Your model is still moving are you sure you want to disconnect?", "Disconnect", MessageBoxButtons.YesNo)) { return; } @@ -538,9 +538,9 @@ namespace ArdupilotMega try { Directory.CreateDirectory(Path.GetDirectoryName(Application.ExecutablePath) + Path.DirectorySeparatorChar + @"logs"); - comPort.logfile = new BinaryWriter(File.Open(Path.GetDirectoryName(Application.ExecutablePath) + Path.DirectorySeparatorChar + @"logs" + Path.DirectorySeparatorChar + DateTime.Now.ToString("yyyy-MM-dd hh-mm-ss") + ".tlog", FileMode.CreateNew)); + comPort.logfile = new BinaryWriter(File.Open(Path.GetDirectoryName(Application.ExecutablePath) + Path.DirectorySeparatorChar + @"logs" + Path.DirectorySeparatorChar + DateTime.Now.ToString("yyyy-MM-dd hh-mm-ss") + ".tlog", FileMode.CreateNew,FileAccess.ReadWrite,FileShare.Read)); } - catch { MessageBox.Show("Failed to create log - wont log this session"); } // soft fail + catch { CustomMessageBox.Show("Failed to create log - wont log this session"); } // soft fail comPort.BaseStream.PortName = CMB_serialport.Text; comPort.Open(true); @@ -605,7 +605,7 @@ namespace ArdupilotMega } else { - MessageBox.Show("You dont appear to have uploaded a firmware yet,\n\nPlease goto the firmware page and upload one."); + CustomMessageBox.Show("You dont appear to have uploaded a firmware yet,\n\nPlease goto the firmware page and upload one."); return; } } @@ -733,7 +733,7 @@ namespace ArdupilotMega //appconfig.Save(); } - catch (Exception ex) { MessageBox.Show(ex.ToString()); } + catch (Exception ex) { CustomMessageBox.Show(ex.ToString()); } } else { @@ -1071,6 +1071,9 @@ namespace ArdupilotMega MenuFlightData_Click(sender, e); + // for long running tasks using own threads. + // for short use threadpool + try { listener = new TcpListener(IPAddress.Any, 56781); @@ -1085,7 +1088,7 @@ namespace ArdupilotMega catch (Exception ex) { log.Error("Error starting TCP listener thread: ", ex); - MessageBox.Show(ex.ToString()); + CustomMessageBox.Show(ex.ToString()); } var t12 = new Thread(new ThreadStart(joysticksend)) @@ -1493,7 +1496,7 @@ namespace ArdupilotMega catch (Exception ex) { log.Error("Update Failed", ex); - MessageBox.Show("Update Failed " + ex.Message); + CustomMessageBox.Show("Update Failed " + ex.Message); } } @@ -1556,13 +1559,7 @@ namespace ArdupilotMega if (fi.Length != response.ContentLength || response.Headers[HttpResponseHeader.ETag] != CurrentEtag) { - using (var sw = new StreamWriter(path + ".etag")) - { - sw.WriteLine(response.Headers[HttpResponseHeader.ETag]); - sw.Close(); - } shouldGetFile = true; - log.Info("Newer file found: " + path + " " + fi.Length + " vs " + response.ContentLength); } } else @@ -1576,7 +1573,7 @@ namespace ArdupilotMega if (shouldGetFile) { - var dr = MessageBox.Show("Update Found\n\nDo you wish to update now?", "Update Now", MessageBoxButtons.YesNo); + var dr = CustomMessageBox.Show("Update Found\n\nDo you wish to update now?", "Update Now", MessageBoxButtons.YesNo); if (dr == DialogResult.Yes) { DoUpdate(); @@ -1858,7 +1855,7 @@ namespace ArdupilotMega { MainV2.comPort.Open(false); } - catch (Exception ex) { MessageBox.Show(ex.ToString()); } + catch (Exception ex) { CustomMessageBox.Show(ex.ToString()); } return true; } if (keyData == (Keys.Control | Keys.Y)) // for ryan beall @@ -1871,7 +1868,7 @@ namespace ArdupilotMega #else MainV2.comPort.doAction(MAVLink.MAV_ACTION.MAV_ACTION_STORAGE_WRITE); #endif - MessageBox.Show("Done MAV_ACTION_STORAGE_WRITE"); + CustomMessageBox.Show("Done MAV_ACTION_STORAGE_WRITE"); return true; } if (keyData == (Keys.Control | Keys.J)) // for jani diff --git a/Tools/ArdupilotMegaPlanner/Program.cs b/Tools/ArdupilotMegaPlanner/Program.cs index d80b848cdf..ec406309d2 100644 --- a/Tools/ArdupilotMegaPlanner/Program.cs +++ b/Tools/ArdupilotMegaPlanner/Program.cs @@ -33,9 +33,11 @@ namespace ArdupilotMega CodeGen.runCode("Sin(0.55)"); - //MagCalib.doWork(); + int wt = 0, ct = 0; + ThreadPool.GetMaxThreads(out wt, out ct); + log.Info("Max Threads: " + wt); - //return; + //MagCalib.ProcessLog(); //MessageBox.Show("NOTE: This version may break advanced mission scripting"); @@ -66,17 +68,17 @@ namespace ArdupilotMega log.Debug(ex.ToString()); if (ex.Message == "The port is closed.") { - MessageBox.Show("Serial connection has been lost"); + CustomMessageBox.Show("Serial connection has been lost"); return; } if (ex.Message == "A device attached to the system is not functioning.") { - MessageBox.Show("Serial connection has been lost"); + CustomMessageBox.Show("Serial connection has been lost"); return; } if (e.Exception.GetType() == typeof(MissingMethodException)) { - MessageBox.Show("Please Update - Some older library dlls are causing problems\n" + e.Exception.Message); + CustomMessageBox.Show("Please Update - Some older library dlls are causing problems\n" + e.Exception.Message); return; } if (e.Exception.GetType() == typeof(ObjectDisposedException) || e.Exception.GetType() == typeof(InvalidOperationException)) // something is trying to update while the form, is closing. @@ -85,10 +87,10 @@ namespace ArdupilotMega } if (e.Exception.GetType() == typeof(FileNotFoundException) || e.Exception.GetType() == typeof(BadImageFormatException)) // i get alot of error from people who click the exe from inside a zip file. { - MessageBox.Show("You are missing some DLL's. Please extract the zip file somewhere. OR Use the update feature from the menu"); + CustomMessageBox.Show("You are missing some DLL's. Please extract the zip file somewhere. OR Use the update feature from the menu"); return; } - DialogResult dr = MessageBox.Show("An error has occurred\n"+ex.ToString() + "\n\nReport this Error???", "Send Error", MessageBoxButtons.YesNo); + DialogResult dr = CustomMessageBox.Show("An error has occurred\n"+ex.ToString() + "\n\nReport this Error???", "Send Error", MessageBoxButtons.YesNo); if (DialogResult.Yes == dr) { try @@ -130,7 +132,7 @@ namespace ArdupilotMega } catch { - MessageBox.Show("Error sending Error report!! Youre most likerly are not on the internet"); + CustomMessageBox.Show("Error sending Error report!! Youre most likerly are not on the internet"); } } } diff --git a/Tools/ArdupilotMegaPlanner/Properties/AssemblyInfo.cs b/Tools/ArdupilotMegaPlanner/Properties/AssemblyInfo.cs index 14484783e3..bb1b4de8b3 100644 --- a/Tools/ArdupilotMegaPlanner/Properties/AssemblyInfo.cs +++ b/Tools/ArdupilotMegaPlanner/Properties/AssemblyInfo.cs @@ -34,5 +34,5 @@ using System.Resources; // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.1.49")] +[assembly: AssemblyFileVersion("1.1.50")] [assembly: NeutralResourcesLanguageAttribute("")] diff --git a/Tools/ArdupilotMegaPlanner/RAW_Sensor.cs b/Tools/ArdupilotMegaPlanner/RAW_Sensor.cs index f3109aa829..04c2427d1b 100644 --- a/Tools/ArdupilotMegaPlanner/RAW_Sensor.cs +++ b/Tools/ArdupilotMegaPlanner/RAW_Sensor.cs @@ -190,47 +190,6 @@ namespace ArdupilotMega else { list6.Clear(); } } - public static string CustomMessageBox(string title, string promptText, string buttontext1, string buttontext2) - { - Form form = new Form(); - System.Windows.Forms.Label label = new System.Windows.Forms.Label(); - Button button1 = new Button(); - Button button2 = new Button(); - - form.Text = title; - label.Text = promptText; - - button1.Text = buttontext1; - button2.Text = buttontext2; - button1.DialogResult = DialogResult.OK; - button2.DialogResult = DialogResult.Cancel; - - label.SetBounds(9, 10, 372, 13); - button1.SetBounds(228, 72, 75, 23); - button2.SetBounds(309, 72, 75, 23); - - label.AutoSize = true; - button1.Anchor = AnchorStyles.Bottom | AnchorStyles.Right; - button2.Anchor = AnchorStyles.Bottom | AnchorStyles.Right; - - form.ClientSize = new Size(396, 107); - form.Controls.AddRange(new Control[] { label, button1, button2 }); - form.ClientSize = new Size(Math.Max(300, label.Right + 10), form.ClientSize.Height); - form.FormBorderStyle = FormBorderStyle.FixedDialog; - form.StartPosition = FormStartPosition.CenterScreen; - form.MinimizeBox = false; - form.MaximizeBox = false; - form.AcceptButton = button1; - form.CancelButton = button2; - - DialogResult dialogResult = form.ShowDialog(); - if (dialogResult == DialogResult.OK) - { - return buttontext1; - } - return buttontext2; - } - private void ACM_Setup_Load(object sender, EventArgs e) { @@ -274,7 +233,7 @@ namespace ArdupilotMega if (!comPort.BaseStream.IsOpen && !MainV2.comPort.logreadmode) { - MessageBox.Show("Please connect first"); + CustomMessageBox.Show("Please connect first"); this.Close(); } @@ -292,7 +251,7 @@ namespace ArdupilotMega } catch { - MessageBox.Show("Comport open failed"); + CustomMessageBox.Show("Comport open failed"); return; } timer1.Start(); diff --git a/Tools/ArdupilotMegaPlanner/Radio/3DRradio.Designer.cs b/Tools/ArdupilotMegaPlanner/Radio/3DRradio.Designer.cs index 18605e5c01..62c057b626 100644 --- a/Tools/ArdupilotMegaPlanner/Radio/3DRradio.Designer.cs +++ b/Tools/ArdupilotMegaPlanner/Radio/3DRradio.Designer.cs @@ -29,6 +29,7 @@ private void InitializeComponent() { this.components = new System.ComponentModel.Container(); + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(_3DRradio)); this.Progressbar = new System.Windows.Forms.ProgressBar(); this.S1 = new System.Windows.Forms.ComboBox(); this.label1 = new System.Windows.Forms.Label(); @@ -97,7 +98,7 @@ this.S1.Name = "S1"; this.S1.Size = new System.Drawing.Size(80, 21); this.S1.TabIndex = 4; - this.toolTip1.SetToolTip(this.S1, "Serial Baud Rate 57 = 57600"); + this.toolTip1.SetToolTip(this.S1, "Serial baud rate in rounded kbps. So 57 means 57600. \r\n"); // // label1 // @@ -149,7 +150,9 @@ this.S2.Name = "S2"; this.S2.Size = new System.Drawing.Size(80, 21); this.S2.TabIndex = 9; - this.toolTip1.SetToolTip(this.S2, "the inter-radio data rate in rounded kbps. So 128 means"); + this.toolTip1.SetToolTip(this.S2, "AIR_SPEED is the inter-radio data rate in rounded kbps. So 128 means 128kbps. Max" + + " is 192, min is 2. I would not recommend values below 16 as the frequency hoppin" + + "g and tdm sync times get too long. "); // // label4 // @@ -198,7 +201,7 @@ this.S3.Name = "S3"; this.S3.Size = new System.Drawing.Size(80, 21); this.S3.TabIndex = 11; - this.toolTip1.SetToolTip(this.S3, "a 16 bit \'network ID\'. This is used to seed the frequency"); + this.toolTip1.SetToolTip(this.S3, resources.GetString("S3.ToolTip")); // // label5 // @@ -238,7 +241,8 @@ this.S4.Name = "S4"; this.S4.Size = new System.Drawing.Size(80, 21); this.S4.TabIndex = 13; - this.toolTip1.SetToolTip(this.S4, "the transmit power in dBm. 20dBm is 100mW. It is useful to"); + this.toolTip1.SetToolTip(this.S4, "TXPOWER is the transmit power in dBm. 20dBm is 100mW. It is useful to set this to" + + " lower levels for short range testing.\r\n"); // // label6 // @@ -255,7 +259,7 @@ this.S5.Name = "S5"; this.S5.Size = new System.Drawing.Size(80, 21); this.S5.TabIndex = 15; - this.toolTip1.SetToolTip(this.S5, "to enable/disable the golay error correcting code. It defaults"); + this.toolTip1.SetToolTip(this.S5, resources.GetString("S5.ToolTip")); // // label7 // @@ -272,7 +276,7 @@ this.S6.Name = "S6"; this.S6.Size = new System.Drawing.Size(80, 21); this.S6.TabIndex = 17; - this.toolTip1.SetToolTip(this.S6, "enables/disables MAVLink packet framing. This tries to align"); + this.toolTip1.SetToolTip(this.S6, resources.GetString("S6.ToolTip")); // // label8 // @@ -289,7 +293,7 @@ this.S7.Name = "S7"; this.S7.Size = new System.Drawing.Size(80, 21); this.S7.TabIndex = 19; - this.toolTip1.SetToolTip(this.S7, "enables/disables \"opportunistic resend\". When enabled the"); + this.toolTip1.SetToolTip(this.S7, resources.GetString("S7.ToolTip")); // // RS7 // @@ -297,7 +301,7 @@ this.RS7.Name = "RS7"; this.RS7.Size = new System.Drawing.Size(80, 21); this.RS7.TabIndex = 29; - this.toolTip1.SetToolTip(this.RS7, "enables/disables \"opportunistic resend\". When enabled the"); + this.toolTip1.SetToolTip(this.RS7, resources.GetString("RS7.ToolTip")); // // RS6 // @@ -305,7 +309,7 @@ this.RS6.Name = "RS6"; this.RS6.Size = new System.Drawing.Size(80, 21); this.RS6.TabIndex = 28; - this.toolTip1.SetToolTip(this.RS6, "enables/disables MAVLink packet framing. This tries to align"); + this.toolTip1.SetToolTip(this.RS6, resources.GetString("RS6.ToolTip")); // // RS5 // @@ -313,7 +317,7 @@ this.RS5.Name = "RS5"; this.RS5.Size = new System.Drawing.Size(80, 21); this.RS5.TabIndex = 27; - this.toolTip1.SetToolTip(this.RS5, "to enable/disable the golay error correcting code. It defaults"); + this.toolTip1.SetToolTip(this.RS5, resources.GetString("RS5.ToolTip")); // // RS4 // @@ -344,7 +348,8 @@ this.RS4.Name = "RS4"; this.RS4.Size = new System.Drawing.Size(80, 21); this.RS4.TabIndex = 26; - this.toolTip1.SetToolTip(this.RS4, "the transmit power in dBm. 20dBm is 100mW. It is useful to"); + this.toolTip1.SetToolTip(this.RS4, "TXPOWER is the transmit power in dBm. 20dBm is 100mW. It is useful to set this to" + + " lower levels for short range testing.\r\n"); // // RS3 // @@ -384,7 +389,7 @@ this.RS3.Name = "RS3"; this.RS3.Size = new System.Drawing.Size(80, 21); this.RS3.TabIndex = 25; - this.toolTip1.SetToolTip(this.RS3, "a 16 bit \'network ID\'. This is used to seed the frequency"); + this.toolTip1.SetToolTip(this.RS3, resources.GetString("RS3.ToolTip")); // // RS2 // @@ -401,7 +406,9 @@ this.RS2.Name = "RS2"; this.RS2.Size = new System.Drawing.Size(80, 21); this.RS2.TabIndex = 24; - this.toolTip1.SetToolTip(this.RS2, "the inter-radio data rate in rounded kbps. So 128 means"); + this.toolTip1.SetToolTip(this.RS2, "AIR_SPEED is the inter-radio data rate in rounded kbps. So 128 means 128kbps. Max" + + " is 192, min is 2. I would not recommend values below 16 as the frequency hoppin" + + "g and tdm sync times get too long. "); // // RS1 // @@ -420,7 +427,7 @@ this.RS1.Name = "RS1"; this.RS1.Size = new System.Drawing.Size(80, 21); this.RS1.TabIndex = 22; - this.toolTip1.SetToolTip(this.RS1, "Serial Baud Rate 57 = 57600"); + this.toolTip1.SetToolTip(this.RS1, "Serial baud rate in rounded kbps. So 57 means 57600. \r\n"); // // RS0 // @@ -472,6 +479,7 @@ this.RSSI.ReadOnly = true; this.RSSI.Size = new System.Drawing.Size(194, 58); this.RSSI.TabIndex = 34; + this.toolTip1.SetToolTip(this.RSSI, resources.GetString("RSSI.ToolTip")); // // label11 // @@ -605,6 +613,7 @@ this.Controls.Add(this.lbl_status); this.Controls.Add(this.Progressbar); this.Controls.Add(this.BUT_upload); + this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); this.MaximizeBox = false; this.MinimizeBox = false; this.MinimumSize = new System.Drawing.Size(334, 482); diff --git a/Tools/ArdupilotMegaPlanner/Radio/3DRradio.cs b/Tools/ArdupilotMegaPlanner/Radio/3DRradio.cs index b0bb0a8a93..cd1791859a 100644 --- a/Tools/ArdupilotMegaPlanner/Radio/3DRradio.cs +++ b/Tools/ArdupilotMegaPlanner/Radio/3DRradio.cs @@ -59,7 +59,7 @@ namespace ArdupilotMega comPort.Open(); } - catch { MessageBox.Show("Invalid ComPort or in use"); return; } + catch { CustomMessageBox.Show("Invalid ComPort or in use"); return; } bool bootloadermode = false; @@ -99,7 +99,7 @@ namespace ArdupilotMega { iHex.load(firmwarefile); } - catch { MessageBox.Show("Bad Firmware File"); goto exit; } + catch { CustomMessageBox.Show("Bad Firmware File"); goto exit; } if (!bootloadermode) { @@ -118,16 +118,16 @@ namespace ArdupilotMega { uploader.upload(comPort, iHex); } - catch (Exception ex) { MessageBox.Show("Upload Failed " + ex.Message); } + catch (Exception ex) { CustomMessageBox.Show("Upload Failed " + ex.Message); } } else { - MessageBox.Show("Failed to download new firmware"); + CustomMessageBox.Show("Failed to download new firmware"); } } else { - MessageBox.Show("Failed to identify Radio"); + CustomMessageBox.Show("Failed to identify Radio"); } exit: @@ -198,7 +198,7 @@ namespace ArdupilotMega } - catch { MessageBox.Show("Invalid ComPort or in use"); return; } + catch { CustomMessageBox.Show("Invalid ComPort or in use"); return; } lbl_status.Text = "Connecting"; @@ -242,7 +242,7 @@ namespace ArdupilotMega } else { - MessageBox.Show("Set Command error"); + CustomMessageBox.Show("Set Command error"); } } } @@ -258,7 +258,7 @@ namespace ArdupilotMega } else { - MessageBox.Show("Set Command error"); + CustomMessageBox.Show("Set Command error"); } } } @@ -309,7 +309,7 @@ namespace ArdupilotMega } else { - MessageBox.Show("Set Command error"); + CustomMessageBox.Show("Set Command error"); } } } @@ -325,7 +325,7 @@ namespace ArdupilotMega } else { - MessageBox.Show("Set Command error"); + CustomMessageBox.Show("Set Command error"); } } } @@ -351,7 +351,7 @@ namespace ArdupilotMega doCommand(comPort, "ATZ"); lbl_status.Text = "Fail"; - MessageBox.Show("Failed to enter command mode"); + CustomMessageBox.Show("Failed to enter command mode"); } @@ -374,7 +374,7 @@ namespace ArdupilotMega } - catch { MessageBox.Show("Invalid ComPort or in use"); return; } + catch { CustomMessageBox.Show("Invalid ComPort or in use"); return; } lbl_status.Text = "Connecting"; @@ -479,7 +479,7 @@ namespace ArdupilotMega doCommand(comPort, "ATO"); lbl_status.Text = "Fail"; - MessageBox.Show("Failed to enter command mode"); + CustomMessageBox.Show("Failed to enter command mode"); } comPort.Close(); diff --git a/Tools/ArdupilotMegaPlanner/Radio/3DRradio.resx b/Tools/ArdupilotMegaPlanner/Radio/3DRradio.resx index 271670364a..5194d642e6 100644 --- a/Tools/ArdupilotMegaPlanner/Radio/3DRradio.resx +++ b/Tools/ArdupilotMegaPlanner/Radio/3DRradio.resx @@ -120,4 +120,124 @@ 17, 17 + + 17, 17 + + + NETID is a 16 bit 'network ID'. This is used to seed the frequency hopping sequence and to identify packets as coming from the right radio. Make sure you use a different NETID from anyone else running the same sort of radio in the area. + + + ECC is to enable/disable the golay error correcting code. It defaults to off. If you enable it then you packets take twice as many bytes to send, so you lose half your air bandwidth, but it can correct up to 3 bit errors per 12 bits of data. Use this for long range, usually in combination with a lower air data rate. The golay decode takes 20 microsecond per transmitted byte (40 microseconds per user data byte) which means you will also be a bit CPU constrained at the highest air data rates. So you usually use golay at 128kbps or less. + + + + MAVLINK enables/disables MAVLink packet framing. This tries to align radio packets to MAVLink packet boundaries, which makes a big difference to what happens to the MAVLink stream when you lose a packet. + + + + OPPRESEND enables/disables "opportunistic resend". When enabled the radio will send a packet twice if the serial input buffer has less than 256 bytes in it. The 2nd send is marked as a resend and discarded by the receiving radio if it got the first packet OK. This makes a big difference to the link quality, especially for uplink commands. + + + + OPPRESEND enables/disables "opportunistic resend". When enabled the radio will send a packet twice if the serial input buffer has less than 256 bytes in it. The 2nd send is marked as a resend and discarded by the receiving radio if it got the first packet OK. This makes a big difference to the link quality, especially for uplink commands. + + + + MAVLINK enables/disables MAVLink packet framing. This tries to align radio packets to MAVLink packet boundaries, which makes a big difference to what happens to the MAVLink stream when you lose a packet. + + + + ECC is to enable/disable the golay error correcting code. It defaults to off. If you enable it then you packets take twice as many bytes to send, so you lose half your air bandwidth, but it can correct up to 3 bit errors per 12 bits of data. Use this for long range, usually in combination with a lower air data rate. The golay decode takes 20 microsecond per transmitted byte (40 microseconds per user data byte) which means you will also be a bit CPU constrained at the highest air data rates. So you usually use golay at 128kbps or less. + + + + NETID is a 16 bit 'network ID'. This is used to seed the frequency hopping sequence and to identify packets as coming from the right radio. Make sure you use a different NETID from anyone else running the same sort of radio in the area. + + + see the spec for a RSSI to dBm graph. The numbers at the end are: +txe: number of transmit errors (eg. transmit timeouts) +rxe: number of receive errors (crc error, framing error etc) +stx: number of serial transmit overflows +rrx: number of serial receive overflows +ecc: number of 12 bit words successfully corrected by the golay code +which result in a valid packet CRC + + + + + + AAABAAEAICAAAAEAIACoEAAAFgAAACgAAAAgAAAAQAAAAAEAIAAAAAAAABAAABILAAASCwAAAAAAAAAA + AAD///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADOxkjAtnoOAKpJ4vyiK + c+8nh3D/J4Zv/yeHcP8oi3PvKpJ4vy6fg4AzsZIwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAP///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADjGo2AyspPfLZ+D/yiQ + d/8hlXj/G6F9/xeqg/8XqYL/GKqD/xuhfv8ilnn/KZB3/y2fhP8yspPfN8ajYAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAA////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADvRrDA1vpzfL6uN/yel + hP8XvJD/DMyY/wfQl/8FzJP/A8qS/wPJkf8EypL/BsyU/wnRmP8PzZn/Gb2R/yemhP8tqoz/Mb2a3zbQ + qkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///8AAAAAAAAAAAAAAAAAAAAAAAAAAAA4y6ZgMbWV/yin + iP8WwZP/Btqf/wDPlf8AyI7/A8aP/yfNnv9T2LP/UNax/03XsP8506b/G8ya/wHKkf8F0Zf/CNuf/xLB + kv8fpYT/J7KQ/y7IomAAAAAAAAAAAAAAAAAAAAAAAAAAAP///wAAAAAAAAAAAAAAAAAAAAAANcajny+w + kf8hqoj/CNSd/wDRlf8Axor/Hcyd/3Lhwf+p7Nj/o+vV/57m0/+X5dD/k+TN/4/jzf+K5Mz/fuHH/0PW + rf8HzJT/ANCT/wDRlv8OpX//HayI/yrFn58AAAAAAAAAAAAAAAAAAAAA////AAAAAAAAAAAAAAAAADDC + nmAtro7/H62J/wPWmv8Ay47/AMaO/3XhxP+e6tT/mObP/5Pjy/+Q4sr/jODJ/4ffx/+C3MT/f9vC/3nb + wf9y2r7/adq7/2DauP8ZzZv/Fdae/8T/9/9WxKj/HKuI/y7IomAAAAAAAAAAAAAAAAD///8AAAAAAAAA + AAAiuZMwKKyM/x6ohf8C1Zr/AMmL/wHGjv+49OL///////////9+3ML/f9zD/4Dcwv9+28L/e9rA/3bZ + vv9w1rr/Z9S4/17Rs/9Qz63/Qcyn/3LewP////////////n///8MpH7/JbKP/zXQqUAAAAAAAAAAAP// + /wAAAAAAAAAAABymhN8dnn//BNGa/wDKjP8AxY3/sfHf/////////////////2nXt/9w1rv/c9e8/3TX + vP9x17z/a9W5/2TTtf9Y0K//SMyp/zXFoP9i07X/////////////////f/LR/wDQlf8epYT/Mb2a3wAA + AAAAAAAA////AAAAAAADlnJgFZR1/wq4iv8AzpH/AMCD/4rmzf//////////////////////WdGv/2PU + tf9p1rf/atS4/2nUtv9i0rT/Vc+u/0fKpv8zxZz/Ws+w//////////////////////8GyJL/ANCS/xLB + kv8tq4z/OMajYAAAAAD///8AAAAAAACHZt8NkW//ANKV/wDChP9i27r//////////////////////9Dx + 6P9MzKn/Vc+v/17Rsv9g0rP/XNCx/1XNrv9Fyaf/McSd/1fPr///////////////////////QM2m/ynK + oP8JzJX/C9yh/ymmhf80spPfAAAAAP///wAAcUwwAHtc/wCrfP8AyIv/AMKK//////////////////// + /////////////5Dgyv9Gyqb/TMyq/07Nq/9MzKn/Qcmj/y/Fnf9Wzq3//////////////////////57k + 0v8av5T/Lceg/yzOo/8M05v/Hr6T/zCghf80spIw////AABoRYAAclT/AL2H/wDBhf9R1rL///////// + ////////4vfw//////////////////H8+P9KzKn/Ocah/zTFnv8qwpj/Us2t//////////////////// + ////////DLqM/yDBlv8wxp//OM6m/xPPm/8Xz53/LZF5/y+fg4////8AAGNAvwB7Wf8Aw4j/ALyC/4bj + yP+g5tL/g93E/2HSsv9Pzqz/Us6s//////////////////////9Yzq//Gr2S/0jLp/////////////// + /////////////yrDm/8SvI//JMGY/zDHn/81zKT/Is2e/xTUnf8nl3v/LJJ5v////wAAXz3vAIlg/wDA + hf8AuoD/quzZ/5Hjyv9628D/ada2/1jRsP9Jy6f/a9a4//////////////////////+Y4s7///////// + //////////////////+c4tD/AbaH/xW8kf8jwZj/LcWd/y/Jn/8kzJ3/E9Ca/yGjgf8ri3Tv////AABd + PP8Ak2b/AL6D/w/Ekv+m6tf/j+HJ/3vawP9p1rf/W9Gx/0rNqf85yJ//Nsaf//////////////////// + /////////////////////////////wCwe/8AtoT/ELqP/xu+k/8jwZj/KMeb/yHKm/8QzZf/HqyG/ymI + cf////8AAF07/wCSZP8AvYL/GMWU/6Dn1P+K38f/ddi+/27Wuf+E3MX/leHN/6fm1f+l5tX/neLQ//// + ////////////////////////////////////////j9/J/27Vuv9Tzq7/JsKY/xa/kv8aw5T/FcaW/wvL + lf8aqoT/J4dw/////wAAXTv/AJFk/wC9gP8GwY3/mObQ/5rkz/+26dv/y/Hl/8Dt3/+06tz/pebV/5bg + zP+g5NL//////////////v///f7+//7+/v//////7fn2////////////tOnb/6Ll0v+v6Nj/jeDI/zXK + o/8IxJD/BMqS/xaqgv8lh2//////AABeO+8AgVf/AL1//wDBif/R9uv/1PPq/8Tv5P+36t3/rujY/6Lk + 0v+U4cv/jt7J//j8+///////+/38//f8+//2+/r/+Pz7//3+/v/m9/P/9Pv6//D6+P9/28L/jd7J/5jj + z/+h5dL/qOvX/4Hmyf8f1J//E596/yOJcO////8AAGA8vwB3U/8p06P/hufM/8Ty5f/D7+T/s+vb/6bm + 1P+c4c//j9/K/4vcyP/t+fb///7///j8/P/0+/r/8vr5//P7+f/1+/r/+/39///////i9fL/ZNO1/3HW + vP992sH/htzG/4vhyv+S5dD/mO7W/6X74v80noT/Io90v////wAAZkCAAHla/33ny/945cb/nunV/7Xr + 3v+l5tT/luDN/4ndxv992cL/1vLq//v9/P/1+/n/8vv4//L69//z+/j/9Pv5/7Xo2//x+vn///////// + //+y59n/aNS3/3LWvP932r//fNzD/4Ljyf+J7ND/l/bd/yORdf8knH6A////AABuRzAAdlT/Xc6x/23o + xv9s4MH/qurZ/5jiz/+I3cb/edjA/8ju5f/3/Pv/8vv4//H6+P/y+/j/6/f0/7np3v/7/fz//v7+/6fk + 1f+56tz///////////9h0bT/aNW4/23Wu/9v3L//dOLG/37w0f9m1rn/Hpt8/ymujTD///8AAAAAAACD + X98po4X/Z+7K/1vgvP+A4sf/jOHK/3rZwv+r59f/9Pv6/+/69//v+vf/8vr4/9fy6/9n0rf/VM6t/6Di + 0v/N7+f/adO4/1PMrf9t1Lr/i9zI/1/Rs/9h0rX/ZNe4/2bbvf9s5sb/ePfV/z2ylf8lrozfAAAAAP// + /wAAAAAAAJNsYAWQbf9U1rP/Vee//0rYsf993sb/pebV//P7+v/s+Pb/6/f1/+749v+s5tj/Vc2u/1jP + r/9ZzrD/btW5/1bOr/9Wza//Vs6v/1fOr/9Z0LD/WdCy/1vTtP9d1rX/Xt+8/2btyP9k4L//IaaF/y7D + nmAAAAAA////AAAAAAAAAAAAD6J9zyCjgv9S68L/P9+0/2Pevv/5////7/v6/+v59//j9/L/gtvF/1PN + r/9Wz7D/Wc+x/1nQsf9Zz7H/WM6w/1fPsP9UzrD/VM+w/1TPrv9U0a//U9Oy/1Tatv9Z5sD/Y/LL/zSx + lP8qupbPAAAAAAAAAAD///8AAAAAAAAAAAAYto4wGaeE/y23lP8+5rn/6/////j////w//3/ve/i/2bV + uP9Tzq7/Vc+v/1jPsP9Z0LL/WM+w/1fOsf9Wz7D/Us2w/1HOrf9Qzq3/T9Cu/0zSr/9M2LP/TeC5/1bt + xP9HxaX/KLKQ/zTPqDAAAAAAAAAAAP///wAAAAAAAAAAAAAAAAAkvpdgG6iF/y++m//e/////P///3rl + yf9G0K3/VdKy/1bPsf9Wz7H/Vs6w/1bPsP9Sza//Ucyu/0/Nrf9NzKz/S82s/0fOrP9G0a7/QdWv/0Le + tP9I6L7/Q8Ok/yitjP8yyKJgAAAAAAAAAAAAAAAA////AAAAAAAAAAAAAAAAAAAAAAAmwJlgG6iF/yK3 + kP8k3q7/H9el/x7Pn/8tzKT/Q9Cs/1HQsP9Q0K7/TM6u/0nMrf9Hzaz/RMyp/0LNqf8+zqn/ONGo/zTV + qf833rD/O+S4/zvCof8orIv/MMSfYAAAAAAAAAAAAAAAAAAAAAD///8AAAAAAAAAAAAAAAAAAAAAAAAA + AAAkvpdgG6iE/xukgv8gy53/HNql/xzRn/8czJz/HcmZ/yXJnP8qyp7/Lcqg/yzLn/8nypz/JMqc/yTO + n/8l1KT/KN2r/y3Tpv8nq4n/JaqJ/yzAm2AAAAAAAAAAAAAAAAAAAAAAAAAAAP///wAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAato8wFKN/zxCScv8RnHn/DbqM/wjIlP8GyZT/BsaS/wbFkf8GxZH/B8WR/wfH + k/8IypX/DMmV/xG3jP8WoX3/Fph2/xqkgs8ft5EwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////AAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJVvYACGZM8Aelr/AHlZ/wCFX/8AiWL/AJlr/wCb + bP8AlGf/AI5k/wB/W/8AeFj/AHtb/wCHZd8ClXBgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAD///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABwSzAAaESAAGI/vwBf + Pd8AXTz/AF08/wBdPP8AXz3fAGJAvwBoRIAAcUswAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP// + /wD///8A////AP///wD///8A/+AD//+AAP/+AAA//AAAH/gAAA/wAAAH4AAAA+AAAAPAAAABwAAAAYAA + AACAAAAAgAAAAIAAAACAAAAAgAAAAIAAAACAAAAAgAAAAIAAAACAAAAAwAAAAcAAAAHgAAAD4AAAA/AA + AAf4AAAP/AAAH/4AAD//gAD//+AD//////8= + + \ No newline at end of file diff --git a/Tools/ArdupilotMegaPlanner/ResEdit.cs b/Tools/ArdupilotMegaPlanner/ResEdit.cs index 40e7eed05b..5a1baced21 100644 --- a/Tools/ArdupilotMegaPlanner/ResEdit.cs +++ b/Tools/ArdupilotMegaPlanner/ResEdit.cs @@ -184,21 +184,21 @@ namespace resedit { sw.Write("" + row.Cells[colFile.Index].Value.ToString() + "" + row.Cells[colInternal.Index].Value.ToString() + "" + row.Cells[colOtherLang.Index].Value.ToString() + ""); } - catch (Exception ex) { try { MessageBox.Show("Failed to save " + row.Cells[colOtherLang.Index].Value.ToString() + " " + ex.ToString()); } catch { } } + catch (Exception ex) { try { CustomMessageBox.Show("Failed to save " + row.Cells[colOtherLang.Index].Value.ToString() + " " + ex.ToString()); } catch { } } } if (writer != null) writer.Close(); sw.Write(""); sw.Close(); - MessageBox.Show("Saved"); + CustomMessageBox.Show("Saved"); } private void button3_Click(object sender, EventArgs e) { if (!File.Exists("translation/output.html")) { - MessageBox.Show("No existing translation has been done"); + CustomMessageBox.Show("No existing translation has been done"); return; } @@ -230,7 +230,7 @@ namespace resedit sr1.Close(); - MessageBox.Show("Modified "+a+" entries"); + CustomMessageBox.Show("Modified "+a+" entries"); } private void comboBox1_SelectedIndexChanged(object sender, EventArgs e) @@ -292,7 +292,7 @@ namespace resedit catch { } } - MessageBox.Show("Loaded Existing"); + CustomMessageBox.Show("Loaded Existing"); } } } diff --git a/Tools/ArdupilotMegaPlanner/Script.cs b/Tools/ArdupilotMegaPlanner/Script.cs index 82b7c9346e..60d5ea4fa1 100644 --- a/Tools/ArdupilotMegaPlanner/Script.cs +++ b/Tools/ArdupilotMegaPlanner/Script.cs @@ -82,7 +82,7 @@ namespace ArdupilotMega } catch (Exception e) { - System.Windows.Forms.MessageBox.Show("Error running script " + e.Message); + System.Windows.Forms.CustomMessageBox.Show("Error running script " + e.Message); } } diff --git a/Tools/ArdupilotMegaPlanner/SerialInput.cs b/Tools/ArdupilotMegaPlanner/SerialInput.cs index ba9c84fbd3..4955b4ba3a 100644 --- a/Tools/ArdupilotMegaPlanner/SerialInput.cs +++ b/Tools/ArdupilotMegaPlanner/SerialInput.cs @@ -45,13 +45,13 @@ namespace ArdupilotMega { comPort.PortName = CMB_serialport.Text; } - catch { MessageBox.Show("Invalid PortName"); return; } + catch { CustomMessageBox.Show("Invalid PortName"); return; } try { comPort.BaudRate = int.Parse(CMB_baudrate.Text); - } catch {MessageBox.Show("Invalid BaudRate"); return;} + } catch {CustomMessageBox.Show("Invalid BaudRate"); return;} try { comPort.Open(); - } catch {MessageBox.Show("Error Connecting\nif using com0com please rename the ports to COM??"); return;} + } catch {CustomMessageBox.Show("Error Connecting\nif using com0com please rename the ports to COM??"); return;} string alt = "100"; @@ -70,7 +70,7 @@ namespace ArdupilotMega intalt = (int)(100 * MainV2.cs.multiplierdist); if (!int.TryParse(alt, out intalt)) { - MessageBox.Show("Bad Alt"); + CustomMessageBox.Show("Bad Alt"); return; } diff --git a/Tools/ArdupilotMegaPlanner/SerialOutput.cs b/Tools/ArdupilotMegaPlanner/SerialOutput.cs index 57f0bbe2e2..95f9254c32 100644 --- a/Tools/ArdupilotMegaPlanner/SerialOutput.cs +++ b/Tools/ArdupilotMegaPlanner/SerialOutput.cs @@ -43,13 +43,13 @@ namespace ArdupilotMega { comPort.PortName = CMB_serialport.Text; } - catch { MessageBox.Show("Invalid PortName"); return; } + catch { CustomMessageBox.Show("Invalid PortName"); return; } try { comPort.BaudRate = int.Parse(CMB_baudrate.Text); - } catch {MessageBox.Show("Invalid BaudRate"); return;} + } catch {CustomMessageBox.Show("Invalid BaudRate"); return;} try { comPort.Open(); - } catch {MessageBox.Show("Error Connecting\nif using com0com please rename the ports to COM??"); return;} + } catch {CustomMessageBox.Show("Error Connecting\nif using com0com please rename the ports to COM??"); return;} t12 = new System.Threading.Thread(new System.Threading.ThreadStart(mainloop)) { diff --git a/Tools/ArdupilotMegaPlanner/Setup/Setup.Designer.cs b/Tools/ArdupilotMegaPlanner/Setup/Setup.Designer.cs index fef84a1f1b..41b6ab6aad 100644 --- a/Tools/ArdupilotMegaPlanner/Setup/Setup.Designer.cs +++ b/Tools/ArdupilotMegaPlanner/Setup/Setup.Designer.cs @@ -123,6 +123,9 @@ this.pictureBoxQuad = new System.Windows.Forms.PictureBox(); this.BUT_levelac2 = new ArdupilotMega.MyButton(); this.tabHeli = new System.Windows.Forms.TabPage(); + this.groupBox5 = new System.Windows.Forms.GroupBox(); + this.H1_ENABLE = new System.Windows.Forms.RadioButton(); + this.CCPM = new System.Windows.Forms.RadioButton(); this.BUT_HS4save = new ArdupilotMega.MyButton(); this.BUT_swash_manual = new ArdupilotMega.MyButton(); this.groupBox3 = new System.Windows.Forms.GroupBox(); @@ -176,9 +179,7 @@ this.tabReset = new System.Windows.Forms.TabPage(); this.BUT_reset = new ArdupilotMega.MyButton(); this.toolTip1 = new System.Windows.Forms.ToolTip(this.components); - this.CCPM = new System.Windows.Forms.RadioButton(); - this.groupBox5 = new System.Windows.Forms.GroupBox(); - this.H1_ENABLE = new System.Windows.Forms.RadioButton(); + this.BUT_MagCalibration = new ArdupilotMega.MyButton(); this.tabControl1.SuspendLayout(); this.tabRadioIn.SuspendLayout(); this.groupBoxElevons.SuspendLayout(); @@ -196,6 +197,7 @@ ((System.ComponentModel.ISupportInitialize)(this.pictureBoxQuadX)).BeginInit(); ((System.ComponentModel.ISupportInitialize)(this.pictureBoxQuad)).BeginInit(); this.tabHeli.SuspendLayout(); + this.groupBox5.SuspendLayout(); this.groupBox3.SuspendLayout(); this.groupBox2.SuspendLayout(); this.groupBox1.SuspendLayout(); @@ -204,7 +206,6 @@ ((System.ComponentModel.ISupportInitialize)(this.HS2_TRIM)).BeginInit(); ((System.ComponentModel.ISupportInitialize)(this.HS1_TRIM)).BeginInit(); this.tabReset.SuspendLayout(); - this.groupBox5.SuspendLayout(); this.SuspendLayout(); // // tabControl1 @@ -656,7 +657,8 @@ // // tabHardware // - this.tabHardware.BackColor = System.Drawing.Color.DarkRed; + this.tabHardware.BackColor = System.Drawing.SystemColors.Control; + this.tabHardware.Controls.Add(this.BUT_MagCalibration); this.tabHardware.Controls.Add(this.label27); this.tabHardware.Controls.Add(this.CMB_sonartype); this.tabHardware.Controls.Add(this.CHK_enableoptflow); @@ -1018,6 +1020,29 @@ this.tabHeli.UseVisualStyleBackColor = true; this.tabHeli.Click += new System.EventHandler(this.tabHeli_Click); // + // groupBox5 + // + this.groupBox5.Controls.Add(this.H1_ENABLE); + this.groupBox5.Controls.Add(this.CCPM); + resources.ApplyResources(this.groupBox5, "groupBox5"); + this.groupBox5.Name = "groupBox5"; + this.groupBox5.TabStop = false; + // + // H1_ENABLE + // + resources.ApplyResources(this.H1_ENABLE, "H1_ENABLE"); + this.H1_ENABLE.Name = "H1_ENABLE"; + this.H1_ENABLE.TabStop = true; + this.H1_ENABLE.UseVisualStyleBackColor = true; + this.H1_ENABLE.CheckedChanged += new System.EventHandler(this.H1_ENABLE_CheckedChanged); + // + // CCPM + // + resources.ApplyResources(this.CCPM, "CCPM"); + this.CCPM.Name = "CCPM"; + this.CCPM.TabStop = true; + this.CCPM.UseVisualStyleBackColor = true; + // // BUT_HS4save // resources.ApplyResources(this.BUT_HS4save, "BUT_HS4save"); @@ -1559,28 +1584,12 @@ this.BUT_reset.UseVisualStyleBackColor = true; this.BUT_reset.Click += new System.EventHandler(this.BUT_reset_Click); // - // CCPM + // BUT_MagCalibration // - resources.ApplyResources(this.CCPM, "CCPM"); - this.CCPM.Name = "CCPM"; - this.CCPM.TabStop = true; - this.CCPM.UseVisualStyleBackColor = true; - // - // groupBox5 - // - this.groupBox5.Controls.Add(this.H1_ENABLE); - this.groupBox5.Controls.Add(this.CCPM); - resources.ApplyResources(this.groupBox5, "groupBox5"); - this.groupBox5.Name = "groupBox5"; - this.groupBox5.TabStop = false; - // - // H1_ENABLE - // - resources.ApplyResources(this.H1_ENABLE, "H1_ENABLE"); - this.H1_ENABLE.Name = "H1_ENABLE"; - this.H1_ENABLE.TabStop = true; - this.H1_ENABLE.UseVisualStyleBackColor = true; - this.H1_ENABLE.CheckedChanged += new System.EventHandler(this.H1_ENABLE_CheckedChanged); + resources.ApplyResources(this.BUT_MagCalibration, "BUT_MagCalibration"); + this.BUT_MagCalibration.Name = "BUT_MagCalibration"; + this.BUT_MagCalibration.UseVisualStyleBackColor = true; + this.BUT_MagCalibration.Click += new System.EventHandler(this.BUT_MagCalibration_Click); // // Setup // @@ -1616,6 +1625,8 @@ ((System.ComponentModel.ISupportInitialize)(this.pictureBoxQuad)).EndInit(); this.tabHeli.ResumeLayout(false); this.tabHeli.PerformLayout(); + this.groupBox5.ResumeLayout(false); + this.groupBox5.PerformLayout(); this.groupBox3.ResumeLayout(false); this.groupBox3.PerformLayout(); this.groupBox2.ResumeLayout(false); @@ -1627,8 +1638,6 @@ ((System.ComponentModel.ISupportInitialize)(this.HS2_TRIM)).EndInit(); ((System.ComponentModel.ISupportInitialize)(this.HS1_TRIM)).EndInit(); this.tabReset.ResumeLayout(false); - this.groupBox5.ResumeLayout(false); - this.groupBox5.PerformLayout(); this.ResumeLayout(false); } @@ -1784,6 +1793,7 @@ private System.Windows.Forms.GroupBox groupBox5; private System.Windows.Forms.RadioButton H1_ENABLE; private System.Windows.Forms.RadioButton CCPM; + private MyButton BUT_MagCalibration; } } \ No newline at end of file diff --git a/Tools/ArdupilotMegaPlanner/Setup/Setup.cs b/Tools/ArdupilotMegaPlanner/Setup/Setup.cs index fa9c3992eb..3537a9c809 100644 --- a/Tools/ArdupilotMegaPlanner/Setup/Setup.cs +++ b/Tools/ArdupilotMegaPlanner/Setup/Setup.cs @@ -159,7 +159,7 @@ namespace ArdupilotMega.Setup return; } - MessageBox.Show("Ensure your transmitter is on and receiver is powered and connected\nEnsure your motor does not have power/no props!!!"); + CustomMessageBox.Show("Ensure your transmitter is on and receiver is powered and connected\nEnsure your motor does not have power/no props!!!"); byte oldrc = MainV2.cs.raterc; byte oldatt = MainV2.cs.rateattitude; @@ -245,7 +245,7 @@ namespace ArdupilotMega.Setup } } - MessageBox.Show("Ensure all your sticks are centered and throttle is down, and click ok to continue"); + CustomMessageBox.Show("Ensure all your sticks are centered and throttle is down, and click ok to continue"); MainV2.cs.UpdateCurrentSettings(currentStateBindingSource, true, MainV2.comPort); @@ -274,7 +274,7 @@ namespace ArdupilotMega.Setup if (rctrim[a] < 1195 || rctrim[a] > 1205) MainV2.comPort.setParam("RC" + (a + 1).ToString("0") + "_TRIM", rctrim[a]); } - catch { MessageBox.Show("Failed to set Channel " + (a + 1).ToString()); } + catch { CustomMessageBox.Show("Failed to set Channel " + (a + 1).ToString()); } data = data + "CH" + (a + 1) + " " + rcmin[a] + " | " + rcmax[a] + "\n"; } @@ -299,7 +299,7 @@ namespace ArdupilotMega.Setup Configuration.startup = false; } - MessageBox.Show("Here are the detected radio options\nNOTE Channels not connected are displayed as 1500 +-2\nNormal values are around 1100 | 1900\nChannel:Min | Max \n" + data, "Radio"); + CustomMessageBox.Show("Here are the detected radio options\nNOTE Channels not connected are displayed as 1500 +-2\nNormal values are around 1100 | 1900\nChannel:Min | Max \n" + data, "Radio"); BUT_Calibrateradio.Text = "Please goto the next tab"; } @@ -336,7 +336,7 @@ namespace ArdupilotMega.Setup CHK_revch3.Checked = MainV2.comPort.param["RC3_REV"].ToString() == "-1"; CHK_revch4.Checked = MainV2.comPort.param["RC4_REV"].ToString() == "-1"; } - catch (Exception ex) { MessageBox.Show("Missing RC rev Param "+ex.ToString()); } + catch (Exception ex) { CustomMessageBox.Show("Missing RC rev Param "+ex.ToString()); } startup = false; } @@ -605,7 +605,7 @@ namespace ArdupilotMega.Setup MainV2.comPort.setParam("SIMPLE", value); } } - catch { MessageBox.Show("Failed to set Flight modes"); } + catch { CustomMessageBox.Show("Failed to set Flight modes"); } BUT_SaveModes.Text = "Complete"; } @@ -635,7 +635,7 @@ namespace ArdupilotMega.Setup { if (MainV2.comPort.param["COMPASS_DEC"] == null) { - MessageBox.Show("Not Available"); + CustomMessageBox.Show("Not Available"); } else { @@ -655,14 +655,14 @@ namespace ArdupilotMega.Setup dec -= ((mins) / 60.0f); } } - catch { MessageBox.Show("Invalid input!"); return; } + catch { CustomMessageBox.Show("Invalid input!"); return; } TXT_declination.Text = dec.ToString(); MainV2.comPort.setParam("COMPASS_DEC", dec * deg2rad); } } - catch { MessageBox.Show("Set COMPASS_DEC Failed"); } + catch { CustomMessageBox.Show("Set COMPASS_DEC Failed"); } } @@ -674,14 +674,14 @@ namespace ArdupilotMega.Setup { if (MainV2.comPort.param["MAG_ENABLE"] == null) { - MessageBox.Show("Not Available"); + CustomMessageBox.Show("Not Available"); } else { MainV2.comPort.setParam("MAG_ENABLE", ((CheckBox)sender).Checked == true ? 1 : 0); } } - catch { MessageBox.Show("Set MAG_ENABLE Failed"); } + catch { CustomMessageBox.Show("Set MAG_ENABLE Failed"); } } //((CheckBox)sender).Checked = !((CheckBox)sender).Checked; @@ -695,14 +695,14 @@ namespace ArdupilotMega.Setup { if (MainV2.comPort.param["SONAR_ENABLE"] == null) { - MessageBox.Show("Not Available"); + CustomMessageBox.Show("Not Available"); } else { MainV2.comPort.setParam("SONAR_ENABLE", ((CheckBox)sender).Checked == true ? 1 : 0); } } - catch { MessageBox.Show("Set SONAR_ENABLE Failed"); } + catch { CustomMessageBox.Show("Set SONAR_ENABLE Failed"); } } private void CHK_enableairspeed_CheckedChanged(object sender, EventArgs e) @@ -713,14 +713,14 @@ namespace ArdupilotMega.Setup { if (MainV2.comPort.param["ARSPD_ENABLE"] == null) { - MessageBox.Show("Not Available on " + MainV2.cs.firmware.ToString()); + CustomMessageBox.Show("Not Available on " + MainV2.cs.firmware.ToString()); } else { MainV2.comPort.setParam("ARSPD_ENABLE", ((CheckBox)sender).Checked == true ? 1 : 0); } } - catch { MessageBox.Show("Set ARSPD_ENABLE Failed"); } + catch { CustomMessageBox.Show("Set ARSPD_ENABLE Failed"); } } private void CHK_enablebattmon_CheckedChanged(object sender, EventArgs e) { @@ -738,7 +738,7 @@ namespace ArdupilotMega.Setup CMB_batmontype.SelectedIndex = 1; } } - catch { MessageBox.Show("Set BATT_MONITOR Failed"); } + catch { CustomMessageBox.Show("Set BATT_MONITOR Failed"); } } private void TXT_battcapacity_Validating(object sender, CancelEventArgs e) { @@ -753,14 +753,14 @@ namespace ArdupilotMega.Setup { if (MainV2.comPort.param["BATT_CAPACITY"] == null) { - MessageBox.Show("Not Available"); + CustomMessageBox.Show("Not Available"); } else { MainV2.comPort.setParam("BATT_CAPACITY", float.Parse(TXT_battcapacity.Text)); } } - catch { MessageBox.Show("Set BATT_CAPACITY Failed"); } + catch { CustomMessageBox.Show("Set BATT_CAPACITY Failed"); } } private void CMB_batmontype_SelectedIndexChanged(object sender, EventArgs e) { @@ -770,7 +770,7 @@ namespace ArdupilotMega.Setup { if (MainV2.comPort.param["BATT_MONITOR"] == null) { - MessageBox.Show("Not Available"); + CustomMessageBox.Show("Not Available"); } else { @@ -804,7 +804,7 @@ namespace ArdupilotMega.Setup MainV2.comPort.setParam("BATT_MONITOR", selection); } } - catch { MessageBox.Show("Set BATT_MONITOR Failed"); } + catch { CustomMessageBox.Show("Set BATT_MONITOR Failed"); } } private void TXT_inputvoltage_Validating(object sender, CancelEventArgs e) { @@ -819,14 +819,14 @@ namespace ArdupilotMega.Setup { if (MainV2.comPort.param["INPUT_VOLTS"] == null) { - MessageBox.Show("Not Available"); + CustomMessageBox.Show("Not Available"); } else { MainV2.comPort.setParam("INPUT_VOLTS", float.Parse(TXT_inputvoltage.Text)); } } - catch { MessageBox.Show("Set INPUT_VOLTS Failed"); } + catch { CustomMessageBox.Show("Set INPUT_VOLTS Failed"); } } private void TXT_measuredvoltage_Validating(object sender, CancelEventArgs e) { @@ -847,20 +847,20 @@ namespace ArdupilotMega.Setup float new_divider = (measuredvoltage * divider) / voltage; TXT_divider.Text = new_divider.ToString(); } - catch { MessageBox.Show("Invalid number entered"); return; } + catch { CustomMessageBox.Show("Invalid number entered"); return; } try { if (MainV2.comPort.param["VOLT_DIVIDER"] == null) { - MessageBox.Show("Not Available"); + CustomMessageBox.Show("Not Available"); } else { MainV2.comPort.setParam("VOLT_DIVIDER", float.Parse(TXT_divider.Text)); } } - catch { MessageBox.Show("Set VOLT_DIVIDER Failed"); } + catch { CustomMessageBox.Show("Set VOLT_DIVIDER Failed"); } } private void TXT_divider_Validating(object sender, CancelEventArgs e) { @@ -875,14 +875,14 @@ namespace ArdupilotMega.Setup { if (MainV2.comPort.param["VOLT_DIVIDER"] == null) { - MessageBox.Show("Not Available"); + CustomMessageBox.Show("Not Available"); } else { MainV2.comPort.setParam("VOLT_DIVIDER", float.Parse(TXT_divider.Text)); } } - catch { MessageBox.Show("Set VOLT_DIVIDER Failed"); } + catch { CustomMessageBox.Show("Set VOLT_DIVIDER Failed"); } } private void TXT_ampspervolt_Validating(object sender, CancelEventArgs e) { @@ -897,14 +897,14 @@ namespace ArdupilotMega.Setup { if (MainV2.comPort.param["AMP_PER_VOLT"] == null) { - MessageBox.Show("Not Available"); + CustomMessageBox.Show("Not Available"); } else { MainV2.comPort.setParam("AMP_PER_VOLT", float.Parse(TXT_ampspervolt.Text)); } } - catch { MessageBox.Show("Set AMP_PER_VOLT Failed"); } + catch { CustomMessageBox.Show("Set AMP_PER_VOLT Failed"); } } private void BUT_reset_Click(object sender, EventArgs e) @@ -913,7 +913,7 @@ namespace ArdupilotMega.Setup { MainV2.comPort.setParam("SYSID_SW_MREV", UInt16.MaxValue); } - catch { MessageBox.Show("Set SYSID_SW_MREV Failed"); return; } + catch { CustomMessageBox.Show("Set SYSID_SW_MREV Failed"); return; } MainV2.givecomport = true; @@ -931,7 +931,7 @@ namespace ArdupilotMega.Setup comPortT.DtrEnable = true; comPortT.Open(); } - catch (Exception ex) { MainV2.givecomport = false; MessageBox.Show("Invalid Comport Settings : " + ex.Message); return; } + catch (Exception ex) { MainV2.givecomport = false; CustomMessageBox.Show("Invalid Comport Settings : " + ex.Message); return; } BUT_reset.Text = "Rebooting (17 sec)"; BUT_reset.Refresh(); @@ -958,7 +958,7 @@ namespace ArdupilotMega.Setup } catch { - MessageBox.Show("Failed to re-connect : Please try again"); + CustomMessageBox.Show("Failed to re-connect : Please try again"); this.Close(); } @@ -985,9 +985,9 @@ namespace ArdupilotMega.Setup try { MainV2.comPort.setParam("FRAME", 0f); - MessageBox.Show("Set to +"); + CustomMessageBox.Show("Set to +"); } - catch { MessageBox.Show("Set frame failed"); } + catch { CustomMessageBox.Show("Set frame failed"); } } private void pictureBoxQuadX_Click(object sender, EventArgs e) @@ -995,16 +995,16 @@ namespace ArdupilotMega.Setup try { MainV2.comPort.setParam("FRAME", 1f); - MessageBox.Show("Set to x"); + CustomMessageBox.Show("Set to x"); } - catch { MessageBox.Show("Set frame failed"); } + catch { CustomMessageBox.Show("Set frame failed"); } } private void Setup_Load(object sender, EventArgs e) { if (!MainV2.comPort.BaseStream.IsOpen) { - MessageBox.Show("Please Connect First"); + CustomMessageBox.Show("Please Connect First"); this.Close(); } else @@ -1033,7 +1033,7 @@ namespace ArdupilotMega.Setup MainV2.comPort.setParam("HSV_MAN", 0); // randy request - last } - catch { MessageBox.Show("Set " + ((TextBox)sender).Name + " failed"); } + catch { CustomMessageBox.Show("Set " + ((TextBox)sender).Name + " failed"); } } private void TXT_srvpos2_Validating(object sender, CancelEventArgs e) @@ -1055,7 +1055,7 @@ namespace ArdupilotMega.Setup System.Threading.Thread.Sleep(100); MainV2.comPort.setParam("HSV_MAN", 0); // randy request - last } - catch { MessageBox.Show("Set " + ((TextBox)sender).Name + " failed"); } + catch { CustomMessageBox.Show("Set " + ((TextBox)sender).Name + " failed"); } } private void TXT_srvpos3_Validating(object sender, CancelEventArgs e) @@ -1077,12 +1077,12 @@ namespace ArdupilotMega.Setup System.Threading.Thread.Sleep(100); MainV2.comPort.setParam("HSV_MAN", 0); // randy request - last } - catch { MessageBox.Show("Set " + ((TextBox)sender).Name + " failed"); } + catch { CustomMessageBox.Show("Set " + ((TextBox)sender).Name + " failed"); } } private void BUT_0collective_Click(object sender, EventArgs e) { - MessageBox.Show("Make sure your blades are at 0 degrees"); + CustomMessageBox.Show("Make sure your blades are at 0 degrees"); try { @@ -1091,7 +1091,7 @@ namespace ArdupilotMega.Setup COL_MID.Text = MainV2.comPort.param["COL_MID_"].ToString(); } - catch { MessageBox.Show("Set COL_MID_ failed"); } + catch { CustomMessageBox.Show("Set COL_MID_ failed"); } } private void HS1_REV_CheckedChanged(object sender, EventArgs e) @@ -1191,7 +1191,7 @@ namespace ArdupilotMega.Setup { MainV2.comPort.setParam(((TextBox)sender).Name, test); } - catch { MessageBox.Show("Failed to set Gyro Gain"); } + catch { CustomMessageBox.Show("Failed to set Gyro Gain"); } } private void GYR_ENABLE__CheckedChanged(object sender, EventArgs e) @@ -1216,7 +1216,7 @@ namespace ArdupilotMega.Setup } catch { - MessageBox.Show("Failed to level : ac2 2.0.37+ is required"); + CustomMessageBox.Show("Failed to level : ac2 2.0.37+ is required"); } } @@ -1227,7 +1227,7 @@ namespace ArdupilotMega.Setup //System.Diagnostics.Process.Start("http://www.ngdc.noaa.gov/geomagmodels/Declination.jsp"); System.Diagnostics.Process.Start("http://www.magnetic-declination.com/"); } - catch { MessageBox.Show("Webpage open failed... do you have a virus?\nhttp://www.magnetic-declination.com/"); } + catch { CustomMessageBox.Show("Webpage open failed... do you have a virus?\nhttp://www.magnetic-declination.com/"); } } void reverseChannel(string name, bool normalreverse, Control progressbar) @@ -1252,16 +1252,16 @@ namespace ArdupilotMega.Setup try { MainV2.comPort.setParam("SWITCH_ENABLE", 0); - MessageBox.Show("Disabled Dip Switchs"); + CustomMessageBox.Show("Disabled Dip Switchs"); } - catch { MessageBox.Show("Error Disableing Dip Switch"); } + catch { CustomMessageBox.Show("Error Disableing Dip Switch"); } } try { int i = normalreverse == false ? 1 : -1; MainV2.comPort.setParam(name, i); } - catch { MessageBox.Show("Error Reversing"); } + catch { CustomMessageBox.Show("Error Reversing"); } } private void CHK_revch1_CheckedChanged(object sender, EventArgs e) @@ -1313,7 +1313,7 @@ namespace ArdupilotMega.Setup BUT_0collective.Enabled = true; } } - catch { MessageBox.Show("Failed to set HSV_MAN"); } + catch { CustomMessageBox.Show("Failed to set HSV_MAN"); } } private void BUT_HS4save_Click(object sender, EventArgs e) @@ -1342,7 +1342,7 @@ namespace ArdupilotMega.Setup HS4_MIN.Enabled = true; } } - catch { MessageBox.Show("Failed to set HSV_MAN"); } + catch { CustomMessageBox.Show("Failed to set HSV_MAN"); } } private void tabHeli_Click(object sender, EventArgs e) @@ -1444,14 +1444,14 @@ namespace ArdupilotMega.Setup { if (MainV2.comPort.param["FLOW_ENABLE"] == null) { - MessageBox.Show("Not Available on " + MainV2.cs.firmware.ToString()); + CustomMessageBox.Show("Not Available on " + MainV2.cs.firmware.ToString()); } else { MainV2.comPort.setParam("FLOW_ENABLE", ((CheckBox)sender).Checked == true ? 1 : 0); } } - catch { MessageBox.Show("Set FLOW_ENABLE Failed"); } + catch { CustomMessageBox.Show("Set FLOW_ENABLE Failed"); } } private void CMB_sonartype_SelectedIndexChanged(object sender, EventArgs e) @@ -1462,14 +1462,14 @@ namespace ArdupilotMega.Setup { if (MainV2.comPort.param["SONAR_TYPE"] == null) { - MessageBox.Show("Not Available on " + MainV2.cs.firmware.ToString()); + CustomMessageBox.Show("Not Available on " + MainV2.cs.firmware.ToString()); } else { MainV2.comPort.setParam("SONAR_TYPE", ((ComboBox)sender).SelectedIndex); } } - catch { MessageBox.Show("Set SONAR_TYPE Failed"); } + catch { CustomMessageBox.Show("Set SONAR_TYPE Failed"); } } private void CHK_mixmode_CheckedChanged(object sender, EventArgs e) @@ -1480,14 +1480,14 @@ namespace ArdupilotMega.Setup { if (MainV2.comPort.param["ELEVON_MIXING"] == null) { - MessageBox.Show("Not Available on " + MainV2.cs.firmware.ToString()); + CustomMessageBox.Show("Not Available on " + MainV2.cs.firmware.ToString()); } else { MainV2.comPort.setParam("ELEVON_MIXING", ((CheckBox)sender).Checked == true ? 1 : 0); } } - catch { MessageBox.Show("Set ELEVON_MIXING Failed"); } + catch { CustomMessageBox.Show("Set ELEVON_MIXING Failed"); } } private void CHK_elevonrev_CheckedChanged(object sender, EventArgs e) @@ -1498,14 +1498,14 @@ namespace ArdupilotMega.Setup { if (MainV2.comPort.param["ELEVON_REVERSE"] == null) { - MessageBox.Show("Not Available on " + MainV2.cs.firmware.ToString()); + CustomMessageBox.Show("Not Available on " + MainV2.cs.firmware.ToString()); } else { MainV2.comPort.setParam("ELEVON_REVERSE", ((CheckBox)sender).Checked == true ? 1 : 0); } } - catch { MessageBox.Show("Set ELEVON_REVERSE Failed"); } + catch { CustomMessageBox.Show("Set ELEVON_REVERSE Failed"); } } private void CHK_elevonch1rev_CheckedChanged(object sender, EventArgs e) @@ -1516,14 +1516,14 @@ namespace ArdupilotMega.Setup { if (MainV2.comPort.param["ELEVON_CH1_REV"] == null) { - MessageBox.Show("Not Available on " + MainV2.cs.firmware.ToString()); + CustomMessageBox.Show("Not Available on " + MainV2.cs.firmware.ToString()); } else { MainV2.comPort.setParam("ELEVON_CH1_REV", ((CheckBox)sender).Checked == true ? 1 : 0); } } - catch { MessageBox.Show("Set ELEVON_CH1_REV Failed"); } + catch { CustomMessageBox.Show("Set ELEVON_CH1_REV Failed"); } } private void CHK_elevonch2rev_CheckedChanged(object sender, EventArgs e) @@ -1534,14 +1534,14 @@ namespace ArdupilotMega.Setup { if (MainV2.comPort.param["ELEVON_CH2_REV"] == null) { - MessageBox.Show("Not Available on " + MainV2.cs.firmware.ToString()); + CustomMessageBox.Show("Not Available on " + MainV2.cs.firmware.ToString()); } else { MainV2.comPort.setParam("ELEVON_CH2_REV", ((CheckBox)sender).Checked == true ? 1 : 0); } } - catch { MessageBox.Show("Set ELEVON_CH2_REV Failed"); } + catch { CustomMessageBox.Show("Set ELEVON_CH2_REV Failed"); } } private void CMB_batmonsensortype_SelectedIndexChanged(object sender, EventArgs e) @@ -1625,14 +1625,66 @@ namespace ArdupilotMega.Setup { if (MainV2.comPort.param["H1_ENABLE"] == null) { - MessageBox.Show("Not Available on " + MainV2.cs.firmware.ToString()); + CustomMessageBox.Show("Not Available on " + MainV2.cs.firmware.ToString()); } else { MainV2.comPort.setParam("H1_ENABLE", ((RadioButton)sender).Checked == true ? 1 : 0); } } - catch { MessageBox.Show("Set H1_ENABLE Failed"); } + catch { CustomMessageBox.Show("Set H1_ENABLE Failed"); } + } + + private void BUT_MagCalibration_Click(object sender, EventArgs e) + { + if (DialogResult.Yes == CustomMessageBox.Show("Use live data, or a log\n\nYes for Live data", "Mag Calibration", MessageBoxButtons.YesNo)) + { + List> data = new List>(); + + byte backupratesens = MainV2.cs.ratesensors; + + MainV2.cs.ratesensors = 10; + + MainV2.comPort.requestDatastream((byte)MAVLink.MAV_DATA_STREAM.MAV_DATA_STREAM_RAW_SENSORS, MainV2.cs.ratesensors); // mag captures at 10 hz + + CustomMessageBox.Show("Data will be collected for 30 seconds, Please click ok and move the apm around all axises"); + + DateTime deadline = DateTime.Now.AddSeconds(30); + + float oldmx = 0; + float oldmy = 0; + float oldmz = 0; + + while (deadline > DateTime.Now) + { + Application.DoEvents(); + + if (oldmx != MainV2.cs.mx && + oldmy != MainV2.cs.my && + oldmz != MainV2.cs.mz) + { + data.Add(new Tuple( + MainV2.cs.mx - (float)MainV2.cs.mag_ofs_x, + MainV2.cs.my - (float)MainV2.cs.mag_ofs_y, + MainV2.cs.mz - (float)MainV2.cs.mag_ofs_z)); + + oldmx = MainV2.cs.mx; + oldmy = MainV2.cs.my; + oldmz = MainV2.cs.mz; + } + } + + MainV2.cs.ratesensors = backupratesens; + + double[] ans = MagCalib.LeastSq(data); + + MagCalib.SaveOffsets(ans); + + } + else + { + MagCalib.ProcessLog(); + } } } } \ No newline at end of file diff --git a/Tools/ArdupilotMegaPlanner/Setup/Setup.resx b/Tools/ArdupilotMegaPlanner/Setup/Setup.resx index 6bda482d71..16be1cd25e 100644 --- a/Tools/ArdupilotMegaPlanner/Setup/Setup.resx +++ b/Tools/ArdupilotMegaPlanner/Setup/Setup.resx @@ -117,15 +117,1788 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + groupBoxElevons + + + System.Windows.Forms.GroupBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tabRadioIn + + + 0 + + + CHK_revch3 + + + System.Windows.Forms.CheckBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tabRadioIn + + + 1 + + + CHK_revch4 + + + System.Windows.Forms.CheckBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tabRadioIn + + + 2 + + + CHK_revch2 + + + System.Windows.Forms.CheckBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tabRadioIn + + + 3 + + + CHK_revch1 + + + System.Windows.Forms.CheckBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tabRadioIn + + + 4 + + + BUT_Calibrateradio + + + ArdupilotMega.MyButton, ArdupilotMegaPlanner, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + + + tabRadioIn + + + 5 + + + BAR8 + + + ArdupilotMega.HorizontalProgressBar2, ArdupilotMegaPlanner, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + + + tabRadioIn + + + 6 + + + BAR7 + + + ArdupilotMega.HorizontalProgressBar2, ArdupilotMegaPlanner, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + + + tabRadioIn + + + 7 + + + BAR6 + + + ArdupilotMega.HorizontalProgressBar2, ArdupilotMegaPlanner, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + + + tabRadioIn + + + 8 + + + BAR5 + + + ArdupilotMega.HorizontalProgressBar2, ArdupilotMegaPlanner, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + + + tabRadioIn + + + 9 + + + BARpitch + + + ArdupilotMega.VerticalProgressBar2, ArdupilotMegaPlanner, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + + + tabRadioIn + + + 10 + + + BARthrottle + + + ArdupilotMega.VerticalProgressBar2, ArdupilotMegaPlanner, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + + + tabRadioIn + + + 11 + + + BARyaw + + + ArdupilotMega.HorizontalProgressBar2, ArdupilotMegaPlanner, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + + + tabRadioIn + + + 12 + + + BARroll + + + ArdupilotMega.HorizontalProgressBar2, ArdupilotMegaPlanner, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + + + tabRadioIn + + + 13 + + + + 4, 22 + + + + 3, 3, 3, 3 + + + 666, 393 + + + 0 + + + Radio Input + + + tabRadioIn + + + System.Windows.Forms.TabPage, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tabControl1 + + + 0 + + + CB_simple6 + + + System.Windows.Forms.CheckBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tabModes + + + 0 + + + CB_simple5 + + + System.Windows.Forms.CheckBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tabModes + + + 1 + + + CB_simple4 + + + System.Windows.Forms.CheckBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tabModes + + + 2 + + + CB_simple3 + + + System.Windows.Forms.CheckBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tabModes + + + 3 + + + CB_simple2 + + + System.Windows.Forms.CheckBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tabModes + + + 4 + + + CB_simple1 + + + System.Windows.Forms.CheckBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tabModes + + + 5 + + + label14 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tabModes + + + 6 + + + LBL_flightmodepwm + + + System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tabModes + + + 7 + + + label13 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tabModes + + + 8 + + + lbl_currentmode + + + System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tabModes + + + 9 + + + label12 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tabModes + + + 10 + + + label11 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tabModes + + + 11 + + + label10 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tabModes + + + 12 + + + label9 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tabModes + + + 13 + + + label8 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tabModes + + + 14 + + + label7 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tabModes + + + 15 + + + label6 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tabModes + + + 16 + + + CMB_fmode6 + + + System.Windows.Forms.ComboBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tabModes + + + 17 + + + label5 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tabModes + + + 18 + + + CMB_fmode5 + + + System.Windows.Forms.ComboBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tabModes + + + 19 + + + label4 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tabModes + + + 20 + + + CMB_fmode4 + + + System.Windows.Forms.ComboBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tabModes + + + 21 + + + label3 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tabModes + + + 22 + + + CMB_fmode3 + + + System.Windows.Forms.ComboBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tabModes + + + 23 + + + label2 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tabModes + + + 24 + + + CMB_fmode2 + + + System.Windows.Forms.ComboBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tabModes + + + 25 + + + label1 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tabModes + + + 26 + + + CMB_fmode1 + + + System.Windows.Forms.ComboBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tabModes + + + 27 + + + BUT_SaveModes + + + ArdupilotMega.MyButton, ArdupilotMegaPlanner, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + + + tabModes + + + 28 + + + 4, 22 + + + 666, 393 + + + 3 + + + Modes + + + tabModes + + + System.Windows.Forms.TabPage, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tabControl1 + + + 1 + + + 405, 25 + + + 75, 23 + + + 33 + + + Calibration + + + BUT_MagCalibration + + + ArdupilotMega.MyButton, ArdupilotMegaPlanner, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + + + tabHardware + + + 0 + + + NoControl + + + 510, 57 + + + 150, 20 + + + 32 + + + in Degrees eg 2° 3' W is -2.3 + + + label27 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tabHardware + + + 1 + + + XL-EZ0 + + + LV-EZ0 + + + XL-EZL0 + + + 308, 134 + + + 121, 21 + + + 31 + + + CMB_sonartype + + + System.Windows.Forms.ComboBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tabHardware + + + 2 + + + NoControl + + + 162, 297 + + + 134, 19 + + + 30 + + + Enable Optical Flow + + + CHK_enableoptflow + + + System.Windows.Forms.CheckBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tabHardware + + + 3 + + + Zoom + + + NoControl + + + 78, 271 + + + 75, 75 + + + 29 + + + pictureBox2 + + + System.Windows.Forms.PictureBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tabHardware + + + 4 + + + True + + + NoControl + + + 390, 80 + + + 104, 13 + + + 28 + + + Declination WebSite + + + linkLabelmagdec + + + System.Windows.Forms.LinkLabel, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tabHardware + + + 5 + + + NoControl + + + 305, 57 + + + 72, 16 + + + 23 + + + Declination + + + label100 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tabHardware + + + 6 + + + 383, 57 + + + 121, 20 + + + 20 + + + Magnetic Declination (-20.0 to 20.0) eg 2° 3' W is -2.3 + + + TXT_declination + + + System.Windows.Forms.TextBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tabHardware + + + 7 + + + NoControl + + + 162, 214 + + + 103, 17 + + + 24 + + + Enable Airspeed + + + CHK_enableairspeed + + + System.Windows.Forms.CheckBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tabHardware + + + 8 + + + NoControl + + + 159, 136 + + + 90, 17 + + + 25 + + + Enable Sonar + + + CHK_enablesonar + + + System.Windows.Forms.CheckBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tabHardware + + + 9 + + + NoControl + + + 162, 56 + + + 105, 17 + + + 27 + + + Enable Compass + + + CHK_enablecompass + + + System.Windows.Forms.CheckBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tabHardware + + + 10 + + + Zoom + + + NoControl + + + 78, 188 + + + 75, 75 + + + 3 + + + pictureBox4 + + + System.Windows.Forms.PictureBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tabHardware + + + 11 + + + Zoom + + + NoControl + + + 78, 106 + + + 75, 75 + + + 2 + + + pictureBox3 + + + System.Windows.Forms.PictureBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tabHardware + + + 12 + + + Zoom + + + + + + NoControl + + + + + + 78, 25 + + + 75, 75 + + + 0 + + + pictureBox1 + + + System.Windows.Forms.PictureBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tabHardware + + + 13 + + + 4, 22 + + + 3, 3, 3, 3 + + + 666, 393 + + + 1 + + + Hardware + + + tabHardware + + + System.Windows.Forms.TabPage, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tabControl1 + + + 2 + + + groupBox4 + + + System.Windows.Forms.GroupBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tabBattery + + + 0 + + + label47 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tabBattery + + + 1 + + + CMB_batmonsensortype + + + System.Windows.Forms.ComboBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tabBattery + + + 2 + + + textBox3 + + + System.Windows.Forms.TextBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tabBattery + + + 3 + + + label29 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tabBattery + + + 4 + + + label30 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tabBattery + + + 5 + + + TXT_battcapacity + + + System.Windows.Forms.TextBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tabBattery + + + 6 + + + CMB_batmontype + + + System.Windows.Forms.ComboBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tabBattery + + + 7 + + + pictureBox5 + + + System.Windows.Forms.PictureBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tabBattery + + + 8 + + + 4, 22 + + + 2, 2, 2, 2 + + + 666, 393 + + + 6 + + + Battery + + + tabBattery + + + System.Windows.Forms.TabPage, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tabControl1 + + + 3 + + + label28 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tabArducopter + + + 0 + + + label16 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tabArducopter + + + 1 + + + label15 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tabArducopter + + + 2 + + + pictureBoxQuadX + + + System.Windows.Forms.PictureBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tabArducopter + + + 3 + + + pictureBoxQuad + + + System.Windows.Forms.PictureBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tabArducopter + + + 4 + + + BUT_levelac2 + + + ArdupilotMega.MyButton, ArdupilotMegaPlanner, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + + + tabArducopter + + + 5 + + + 4, 22 + + + 666, 393 + + + 2 + + + ArduCopter2 + + + tabArducopter + + + System.Windows.Forms.TabPage, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tabControl1 + + + 4 + + + groupBox5 + + + System.Windows.Forms.GroupBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tabHeli + + + 0 + + + BUT_HS4save + + + ArdupilotMega.MyButton, ArdupilotMegaPlanner, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + + + tabHeli + + + 1 + + + BUT_swash_manual + + + ArdupilotMega.MyButton, ArdupilotMegaPlanner, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + + + tabHeli + + + 2 + + + groupBox3 + + + System.Windows.Forms.GroupBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tabHeli + + + 3 + + + label44 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tabHeli + + + 4 + + + label43 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tabHeli + + + 5 + + + label42 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tabHeli + + + 6 + + + groupBox2 + + + System.Windows.Forms.GroupBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tabHeli + + + 7 + + + groupBox1 + + + System.Windows.Forms.GroupBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tabHeli + + + 8 + + + HS4_TRIM + + + System.Windows.Forms.NumericUpDown, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tabHeli + + + 9 + + + HS3_TRIM + + + System.Windows.Forms.NumericUpDown, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tabHeli + + + 10 + + + HS2_TRIM + + + System.Windows.Forms.NumericUpDown, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tabHeli + + + 11 + + + HS1_TRIM + + + System.Windows.Forms.NumericUpDown, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tabHeli + + + 12 + + + label39 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tabHeli + + + 13 + + + label38 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tabHeli + + + 14 + + + label37 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tabHeli + + + 15 + + + label36 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tabHeli + + + 16 + + + label26 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tabHeli + + + 17 + + + PIT_MAX + + + System.Windows.Forms.TextBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tabHeli + + + 18 + + + label25 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tabHeli + + + 19 + + + ROL_MAX + + + System.Windows.Forms.TextBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tabHeli + + + 20 + + + label23 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tabHeli + + + 21 + + + label22 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tabHeli + + + 22 + + + HS4_REV + + + System.Windows.Forms.CheckBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tabHeli + + + 23 + + + label20 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tabHeli + + + 24 + + + label19 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tabHeli + + + 25 + + + label18 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tabHeli + + + 26 + + + SV3_POS + + + System.Windows.Forms.TextBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tabHeli + + + 27 + + + SV2_POS + + + System.Windows.Forms.TextBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tabHeli + + + 28 + + + SV1_POS + + + System.Windows.Forms.TextBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tabHeli + + + 29 + + + HS3_REV + + + System.Windows.Forms.CheckBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tabHeli + + + 30 + + + HS2_REV + + + System.Windows.Forms.CheckBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tabHeli + + + 31 + + + HS1_REV + + + System.Windows.Forms.CheckBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tabHeli + + + 32 + + + label17 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tabHeli + + + 33 + + + HS4 + + + ArdupilotMega.HorizontalProgressBar2, ArdupilotMegaPlanner, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + + + tabHeli + + + 34 + + + HS3 + + + ArdupilotMega.VerticalProgressBar2, ArdupilotMegaPlanner, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + + + tabHeli + + + 35 + + + Gservoloc + + + AGaugeApp.AGauge, ArdupilotMegaPlanner, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + + + tabHeli + + + 36 + + + 4, 22 + + + 666, 393 + + + 5 + + + AC2 Heli + + + tabHeli + + + System.Windows.Forms.TabPage, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tabControl1 + + + 5 + + + Fill + + + 0, 0 + + + 674, 419 + + + 93 + + + tabControl1 + + + System.Windows.Forms.TabControl, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 0 + + + CHK_mixmode + + + System.Windows.Forms.CheckBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + groupBoxElevons + + + 0 + + + CHK_elevonch2rev + + + System.Windows.Forms.CheckBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + groupBoxElevons + + + 1 + + + CHK_elevonrev + + + System.Windows.Forms.CheckBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + groupBoxElevons + + + 2 + + + CHK_elevonch1rev + + + System.Windows.Forms.CheckBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + groupBoxElevons + + + 3 + + + 21, 349 + + + 409, 42 + + + 111 + + + Elevon Config + + + groupBoxElevons + + + System.Windows.Forms.GroupBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tabRadioIn + + + 0 + True - NoControl - 13, 19 @@ -255,30 +2028,6 @@ 3 - - 21, 349 - - - 409, 42 - - - 111 - - - Elevon Config - - - groupBoxElevons - - - System.Windows.Forms.GroupBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - tabRadioIn - - - 0 - True @@ -450,6 +2199,9 @@ 6 + + 17, 17 + 446, 185 @@ -597,33 +2349,6 @@ 13 - - 4, 22 - - - 3, 3, 3, 3 - - - 666, 393 - - - 0 - - - Radio Input - - - tabRadioIn - - - System.Windows.Forms.TabPage, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - tabControl1 - - - 0 - True @@ -1455,417 +3180,150 @@ 28 - - 4, 22 + + label31 - - 666, 393 - - - 3 - - - Modes - - - tabModes - - - System.Windows.Forms.TabPage, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - tabControl1 - - - 1 - - - NoControl - - - 510, 57 - - - 150, 20 - - - 32 - - - in Degrees eg 2° 3' W is -2.3 - - - label27 - - + System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - tabHardware + + groupBox4 - + 0 - - XL-EZ0 + + label32 - - LV-EZ0 - - - XL-EZL0 - - - 308, 134 - - - 121, 21 - - - 31 - - - CMB_sonartype - - - System.Windows.Forms.ComboBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - tabHardware - - - 1 - - - NoControl - - - 162, 297 - - - 134, 19 - - - 30 - - - Enable Optical Flow - - - CHK_enableoptflow - - - System.Windows.Forms.CheckBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - tabHardware - - - 2 - - - Zoom - - - NoControl - - - 78, 271 - - - 75, 75 - - - 29 - - - pictureBox2 - - - System.Windows.Forms.PictureBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - tabHardware - - - 3 - - - True - - - NoControl - - - 390, 80 - - - 104, 13 - - - 28 - - - Declination WebSite - - - linkLabelmagdec - - - System.Windows.Forms.LinkLabel, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - tabHardware - - - 4 - - - NoControl - - - 305, 57 - - - 72, 16 - - - 23 - - - Declination - - - label100 - - + System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - tabHardware + + groupBox4 - - 5 + + 1 - - 383, 57 + + label33 - - 121, 20 + + System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - 20 + + groupBox4 - - Magnetic Declination (-20.0 to 20.0) eg 2° 3' W is -2.3 + + 2 - - TXT_declination + + TXT_ampspervolt - + System.Windows.Forms.TextBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - tabHardware + + groupBox4 - - 6 - - - NoControl - - - 162, 214 - - - 103, 17 - - - 24 - - - Enable Airspeed - - - CHK_enableairspeed - - - System.Windows.Forms.CheckBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - tabHardware - - - 7 - - - NoControl - - - 159, 136 - - - 90, 17 - - - 25 - - - Enable Sonar - - - CHK_enablesonar - - - System.Windows.Forms.CheckBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - tabHardware - - - 8 - - - NoControl - - - 162, 56 - - - 105, 17 - - - 27 - - - Enable Compass - - - CHK_enablecompass - - - System.Windows.Forms.CheckBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - tabHardware - - - 9 - - - Zoom - - - NoControl - - - 78, 188 - - - 75, 75 - - + 3 - - pictureBox4 + + label34 - - System.Windows.Forms.PictureBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - tabHardware + + groupBox4 - - 10 + + 4 - - Zoom + + TXT_divider - - NoControl + + System.Windows.Forms.TextBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - 78, 106 + + groupBox4 - - 75, 75 + + 5 - - 2 + + label35 - - pictureBox3 + + System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - System.Windows.Forms.PictureBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + groupBox4 - - tabHardware + + 6 - - 11 + + TXT_voltage - - Zoom + + System.Windows.Forms.TextBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - + + groupBox4 - - NoControl + + 7 - - + + TXT_inputvoltage - - 78, 25 + + System.Windows.Forms.TextBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - 75, 75 + + groupBox4 - + + 8 + + + TXT_measuredvoltage + + + System.Windows.Forms.TextBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + groupBox4 + + + 9 + + + 31, 177 + + + 238, 131 + + + 41 + + + Calibration + + + groupBox4 + + + System.Windows.Forms.GroupBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tabBattery + + 0 - - pictureBox1 - - - System.Windows.Forms.PictureBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - tabHardware - - - 12 - - - 4, 22 - - - 3, 3, 3, 3 - - - 666, 393 - - - 1 - - - Hardware - - - tabHardware - - - System.Windows.Forms.TabPage, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - tabControl1 - - - 2 - True @@ -2151,30 +3609,6 @@ 9 - - 31, 177 - - - 238, 131 - - - 41 - - - Calibration - - - groupBox4 - - - System.Windows.Forms.GroupBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - tabBattery - - - 0 - NoControl @@ -2406,33 +3840,6 @@ Then subtract 0.3v from that value and enter it in field #1 at left. 8 - - 4, 22 - - - 2, 2, 2, 2 - - - 666, 393 - - - 6 - - - Battery - - - tabBattery - - - System.Windows.Forms.TabPage, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - tabControl1 - - - 3 - True @@ -2605,29 +4012,53 @@ will work with hexa's etc 5 - - 4, 22 + + H1_ENABLE - - 666, 393 + + System.Windows.Forms.RadioButton, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - 2 + + groupBox5 - - ArduCopter2 + + 0 - - tabArducopter + + CCPM - - System.Windows.Forms.TabPage, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + System.Windows.Forms.RadioButton, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - tabControl1 + + groupBox5 - - 4 + + 1 + + + 253, 6 + + + 120, 43 + + + 137 + + + Swash Type + + + groupBox5 + + + System.Windows.Forms.GroupBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tabHeli + + + 0 True @@ -2686,30 +4117,6 @@ will work with hexa's etc 1 - - 253, 6 - - - 120, 43 - - - 137 - - - Swash Type - - - groupBox5 - - - System.Windows.Forms.GroupBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - tabHeli - - - 0 - NoControl @@ -2764,6 +4171,78 @@ will work with hexa's etc 2 + + label46 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + groupBox3 + + + 0 + + + label45 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + groupBox3 + + + 1 + + + GYR_ENABLE + + + System.Windows.Forms.CheckBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + groupBox3 + + + 2 + + + GYR_GAIN + + + System.Windows.Forms.TextBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + groupBox3 + + + 3 + + + 433, 309 + + + 101, 63 + + + 135 + + + Gyro + + + groupBox3 + + + System.Windows.Forms.GroupBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tabHeli + + + 3 + True @@ -2875,30 +4354,6 @@ will work with hexa's etc 3 - - 433, 309 - - - 101, 63 - - - 135 - - - Gyro - - - groupBox3 - - - System.Windows.Forms.GroupBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - tabHeli - - - 3 - True @@ -2989,6 +4444,75 @@ will work with hexa's etc 6 + + label24 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + groupBox2 + + + 0 + + + HS4_MIN + + + System.Windows.Forms.TextBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + groupBox2 + + + 1 + + + HS4_MAX + + + System.Windows.Forms.TextBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + groupBox2 + + + 2 + + + label40 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + groupBox2 + + + 3 + + + 433, 181 + + + 169, 78 + + + 130 + + + groupBox2 + + + System.Windows.Forms.GroupBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tabHeli + + + 7 + True @@ -3103,26 +4627,98 @@ will work with hexa's etc 3 - - 433, 181 + + label41 - - 169, 78 + + System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - 130 + + groupBox1 - - groupBox2 + + 0 - + + label21 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + groupBox1 + + + 1 + + + COL_MIN + + + System.Windows.Forms.TextBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + groupBox1 + + + 2 + + + COL_MID + + + System.Windows.Forms.TextBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + groupBox1 + + + 3 + + + COL_MAX + + + System.Windows.Forms.TextBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + groupBox1 + + + 4 + + + BUT_0collective + + + ArdupilotMega.MyButton, ArdupilotMegaPlanner, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + + + groupBox1 + + + 5 + + + 293, 90 + + + 80, 209 + + + 129 + + + groupBox1 + + System.Windows.Forms.GroupBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + tabHeli - - 7 + + 8 True @@ -3295,27 +4891,6 @@ will work with hexa's etc 5 - - 293, 90 - - - 80, 209 - - - 129 - - - groupBox1 - - - System.Windows.Forms.GroupBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - tabHeli - - - 8 - 535, 279 @@ -4060,69 +5635,6 @@ will work with hexa's etc 36 - - 4, 22 - - - 666, 393 - - - 5 - - - AC2 Heli - - - tabHeli - - - System.Windows.Forms.TabPage, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - tabControl1 - - - 5 - - - Fill - - - 0, 0 - - - 674, 419 - - - 93 - - - tabControl1 - - - System.Windows.Forms.TabControl, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - $this - - - 0 - - - NoControl - - - 214, 161 - - - 195, 23 - - - 0 - - - Reset APM Hardware to Default - BUT_reset @@ -4153,6 +5665,33 @@ will work with hexa's etc System.Windows.Forms.TabPage, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + NoControl + + + 214, 161 + + + 195, 23 + + + 0 + + + Reset APM Hardware to Default + + + BUT_reset + + + ArdupilotMega.MyButton, ArdupilotMegaPlanner, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + + + tabReset + + + 0 + True diff --git a/Tools/ArdupilotMegaPlanner/bin/Release/ArdupilotMegaPlanner.pdb b/Tools/ArdupilotMegaPlanner/bin/Release/ArdupilotMegaPlanner.pdb index 83ab9bf5e9c3808c65f565d94b26d28beb7dc9f5..3b01042cf479a70bb7fb27fd7e4d21ecb96ad8ef 100644 GIT binary patch delta 220231 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 R7<8LH=$U<_K_P1lM#u38)?h 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

#eJMQ|X>`$P0vehEuHbyNpa(;L|w!d5CfuWa#vl z9aQehBgU>gVsub@1_Q$*A|;gWm0`HI$?5SU;%El-@n<*iU%DhErRk_xy^^xMb$HAA%Ay|?msjeKnM!}d>7g&v z3pIY=88)xf`xn%`1}DQsFbS@LQ_P7b`wuv#<8d0!fH&YA_!!QG@8EoxCogsaFaR!s zRpDaT5H5io;W9V?E{9`a2Al&|!R2r@+yd9YV{mOEj+;0(!e8Mg_;2_vbm!^sX6OUA zz(BYaR)afWUC3va?M>lM*a`BO!#)7+f?vYja5CHn7r^~+6+8sLhlz)A{0qkscn2PZ zf5T(Yi-FQ{SQ4Iqb>T_a8lHkZ;aM05&p|u92vguCxB^~*-@&W!5WER5!dvj34cpDT zI9}j!54!W*`ZrhrK7gg+BNz-H!=~^V>;#{~KJedg7<>T};a_kmd<{3jH*ha}56{34 z@FsLqO!g=F5;2#=@g5H*x$S=WP4Y0Zmw_6r0WGjOw89=R7aR$5!x_*MW<ehq_QDy#+9!eE8tKNCl7JPyNp@Di*K@52UA zE-4iXJz+yw5`G4QU}M-AHi0p)DU5~9;AGemE`X766^w#euoXNFTPqy@_i(hs;{|LF z-MM}400Uu1SP6E5pFz%?_V%zF>RVxC~B)%i&^}0k;(4_-8i3eiVc3;lJQg zcp4_I#c>A5c6b&Zfal;fcpg51mlV_VKFs*s;`f&@8z#YfZ~?pzSHoZ6UiiCWn*0Jj z=C^wwi&Me^@Hs3E{|$rT3wiuU;dq5dcla6(g>T>#_#Q5VAK)6uBWU|R=CZWpsyRp|12Clj6nqJp#kPBu;EYH?>Om%W>@6X4G4^hdsSSH9WctEB9x@SO zUjVrsx37ZSX4}7qbrW%%#=&ii{RZR~!TuOB>bJX>n z`D~VbA{-9|oB+Rtvc>j8J3I@M;59e}K7?OGa~V!N&<1D15^xr*3zK0Jm;xiqByxhm z(Fu?Fa3EX&$HRqi8cc;tpn#j;BA5vm!^3b1JO`J;YcLJ|3e({;xD397%b}$#Cm!en zSHNOHI9B4Q2)}{Ba20F>SHmc{26lmKVGLZKxq7FX?$#ihS9v}|^4o6pP&?Ebg`>(S z1hql`&96h|us!M*in$e^gJvOT1DVP`3@of&BaGXHJ0fK|FQNrzsqyAgT{!wUu()Bj znQEZ`+XLKd5FYyhNIKM6D`cpF6_)RhX)C>tQx+G+s!$eMH@baeC&G zqv|HJxw&X|T&?XDK~{lsfn69OW*%4Daif%dTrE_jA-=(EO1}ISn6tSwih|X8z7y(7 zYhSL>GXMFGce75Y3zWY*X7)eH4NwEUm^*oy9O8Bk{uL)MJWA zkIcL0)ZS*RVe6gq23*Vq-bllyd%^`ZM3Gk6doHS1{6Eth!THMHX?__7)n?OVqjp)B z)HObz#)>x6mwRW%U&i*^TCcBB*bAcgIi|24{iJSEurFTnv-;3#SPFAXWQ1j0Aq-33 zR#z#eIv}&)HMN9?5)+phlC7RF7vM1`f6k)R$E}QFem2qKC#v01%PANecD=)^c!tTK z+0@Z^tMJAhwTIdKxu|zfEv@`BTJ*lBo;FVrRqu1R%o@x0)w;@^F_|;&tNRtDb3$gs zZ|Yb#^E7ezp}J5BpPbqC4_=E=uyI=Qh&S1=P12h_%6J#g`!R3TMT(w}+3SWqlKcd{ z{sv(3W8P=Own&f8Y`lE&?a^bksedG0sZvfg+EWd8Mig>?I#R|wAteSux?fr2UAw(c zc-L-#!>@waR@t5R3I9~z_=L(f$;nOL24me*_$m9FI^257{7TYOwX;%F|1m=8=kSbu zhNqY&0?K;w`S@qN7GoIJm`z<5uD}S*^SL@rc|I*O^|_j1<}>HDU#NY&n(Essz$02e zzOk|Pg<8_b@N({x7$RV;a_a?qp#{SqS*dzP)noo*gP54?`AZ$4U>Q>7rMg*}IVX-;PREA^0Bd6+Ch->4(3m@w!$1{tp{o_@m%IoK`Ss!0`s z{=vS}FjX*{{AC0mG2|b$rGiO<9^sOVU|1kHB2dY<SPA5MN3&rRpf}3M zcf6Z$W?tsk@6-sh^*6?1vNkcset+~{ZR_7wZw_bO$MVZ~if=Zh8nI$O@II>Xv|fL4 zS?~WJ=;Lt<7cS9ODm*O@HEThILUZ3knv(_nprENv`-a#%vyizR7Y3| z<3-l`idMK#%be7*FY&xvPwi#&Lc5}cS&b*%W>aM&#~TVc@?`ssq6PD?Qtqz8BGOHZ zRB8#M?mOHxZ-vLv$K15@wyE^j%AAveI3E?mJzK1G*J^uD$l2@;Hp?U9C+^xFh3C5) zJhWpIzS1Hs{qQC_Id*;;pq(&a4&_ylKaNYm8PpuJ5Q+o7UHAJS;Jrt{JbM+HG2bqOQw) zZ_}!o&Fw_h{A`7%5)t{e8S=RUgEHc^$v*ek-aJ(l#sE zn=@|}(xR2RHE2nBc_;&&Z@N~-UC-e!-*lB%EE(r>eYbh>IeZ&$l@2JZl`JiTWl#__ z-13W)&aX~-neyRoEVdNZ3bE|M@xt18WyJQ(rv5zZ@N#ZBnkaQdry^Q+t1+!B4~^>I z@s#>}5n92RwUq~g{vK~&Q5y5`&dg;+wV`I^{I1MA#k5Ltr`HSA#`rh;q{6ZMGG++n z2~j_7-VW3{D>Z%)A;qs3O{Q4AW3lF=%( zS6nErhC6@scm&4{^cMMiOJ=As>WdQ40<;O8M-Px?v&j^Qnxhz$gwoIv zbOV{T&^9Oxbw)`j4IM!@ko#7qPf%mjZ7YL8JB~$YFS>+YAkS?~U7$!5ho+%T=m>g* z+`pqns6Oh3Mxq616S{;RA@A)>qoDRE7A-)V&<*qg1#;e~lgK{9q0;rio7{q z%Asy(BwB^`qDRPmC$&I9s6C2Bv(PG(g{~m?OyZy*6p7-{G_($7q1!0&75@b8q9mvr z8i^L6t>`qmkKA{Y5eh?{(O8s>cA(SfE%MpJMo?e02yI38(OXpQ2X+@4i;~e^bP2id zW&ao1OG4BaEkaw-dGr8T_E9(#hB~9MC>d=+N6;(ey`Ric3|fS?q7&#g@;N|%Lfz0v zGz+aldy(;%(qd04reW#wK7+<=0`+mWi3=GbzDrSjDPLp;ycNN7lzCSMJK(E#(jI0au+`&^ktE~A8OI6Ot@uGWGN|?yj2b~mOSEU|sLsf0G zGU}u#QH?AooD?0aX&s6BZ8f6WiF)j$_^Fy!rSP$nMy}FG??oQ zl2O%3GLa;APK#yL$qnwQtvSsq<3;frM3_Vbw=*(AfEZXq^HKOQp@vpasd`4F*3hab zwa$oRHMDt@p-WBTPbU7JGh$Lr&H0{aytqn$XA%K^XC1BhZU$C{$&<}aE5mrvA&A6N zh%@%Am=NTW__7T6nt-Qg#e3I)4z&oFNk(lt5fb$XjN$5O zPFn(6nNZJULVy3!QSI?_Fg-j{k3RJKf8OA6% zx+qT7*D5IRWqppfn-@iu2AcB&0r9*`OvL#_TzE-rXrKis@RW>TJdow|5X#mT5aI46 z$JUC^#R9YJ$(&UY;(4w~oQ1^6f7uadg^f7B?ax_=nGV*F4W$yN@nun^q2~O^LA)43 zfTti}q%-lExm0~eL-yv#%OW7$r7(VB#9c((fS(*2@=7LdOc-$ke)=@-QR0f^hMK!_ z;wSMWj9mgh$!&NzMOs2`BYqZ3!nMXZef}32u#|w)Kl1{!OF)-KT1oFT0z9r5+c!0D zS0nW^EhH!D8DgmE#0b42Ub-d?|BQfT1dO>N27l&~=l3#TIRPiHh+D1!clHV-P>AvF3c$J6@y{&vOOwDqeLoO87il|C2bjCTwISak^aj-&((zcUvq4{`g}HCvKi-m|7)MN z_w;7OT|?YNXWSw4y?DXN^~`2&PMo#G+2xG0Z9YbHuh!*!gp#`r;%MuL^XoNtajuk7 zRP1W5eLOwUbN0=5$H$1O1@QgePdAYNRM0ow?8bW6O6)JoVM-7+c~ z;5c#p<6;o?kE^|XyjU1T+V4m^Fk9@8BJIHJ|KDl5v?A?x(%#P&lUlhH=%@_XAq$kv z0%0xz)mszrJpnJWMc39Y0qHVeCjoD>#WB|aYqVC(MwP+>c#$Ybu zygH2{n#gL+LGF25EQ@x@`3@oKZZhz>EpoMS35aS#z#amM+!mu<19r=R9|$OQTik7< zl~G`>wk~I%?rn*%mk9lDi?7?d?4dIRc?OQvBI{b+Q9c5trAH0N3g2l#@**ltsXqQ4CC<5D z-1Tp#_(#?;0@9m&jBtzykBJ}`8z`DV4!%T^5%AQn_G3H#c;w#?rm@C>$%q1}~ zhVNnOE2_*DDTdcJ19xP|Qx;Ycv$|?NBCfmUNql`BWviZ18@Wm{qd)Q-E}aYlaq24s zJT)TY_V@78y)QV|QO@%*R&)LsJKwEUlj z$a*#uMZe^j={rU%r!a<|Ge%3O>MVJ0!ku}B>uzT;>~vvc6fHkI*DHjH;>fYu8(OB> zIIX8o*e8+YW*9HioQ1`uacoDqAl{GD60FYc#2Aey<1r4_!vZzF^#&Id275DY4!-Gye&l4M6Ievf@!=dN%Tq7>M@VMJdsI0hO2uLwHa1pbZX|~ zgDal!{ihha77|$5CI7m*+u7`~{K|h>?6GU@|BqNP#FC@ciIk$Q_=3)KgaIew8-@EhasYiq2-n>K~% zPdN&m!sP3lE27HRu;NuQL6U*vSxLr;0aKZ~WjqKAi%nCt&Tb6;MBX6g9RjCmqyOXJ zkcCVXDM=h0N2X~(ZVc>1!|TNLnXWbUX(j8Eb0Ejy{`Hy|I$dk;A1?!PLh8^XjB%Wt zYcKADVeHfC+LJmB^jJ2=bABedC246YCs}LgZllqR%Zqd0S0jY+U8|WCzS>MC*BR6C zBUoVwr+a2dPlj##@wCpqVeFV@;!b_{{F&afm^}H9$2f1vkTF|@+1k_p2;s4^i9uVH zIoyCTM(a9<$!*44*Pz?|YHIZI{_-(?6&6R6HGj7v&ak(H$-zwF6eiRA>q8W?se)slr?AhHZ_5*5g4KBr9Qg4h z%xEQG8!IrS&2u?Nc6Vvq|9K{67^9z7!{)mr8SIke(^Fs?Aq;TzB==pDeBqL$k?wZx zLYah-&(H;29h_zUzhg5T(l=0Pp-Y+m_as3I776zQ-c zEj#f$jUL6%6Oj27`z`nrd;x!kxya`V41`x!CcUq8@ost2=l_~&>MzBhLiU0FrTz}9fTu4w8KI$1^U7j&=2l|h2cr) z4{yU_@EHt*W>4%Hp%*LxUW!Y(ikc7>bZ=WrM7 z22bQkWZZ${5*|I^eb^JefH5#{UgqCnIoJ=@f&F0*H~^{>C-7NF$l-kIGVtzumhY1d%@{&IGh2;!%cv*9o!EG!2?j5IcLFz@Sr^YH{v)1 z55mLnXLtlYhDV`W0mB5{4<6@tRd@n6fhXbT@Dv;l{{^SQ(=Z*Lf!m=pO+N|G!EAUQ z{sj{+;K*IjWcm>nhZkXOcnLIeeKF|&ez%{TS z+zF)#`f(^t(0_)--~$*4U%^t)>StJ#`$1_rUIA8sA&EGu;Ajb}!p~t%DD9gW8Q2qG z9XK1-h3T*XTn|IxZrBhWg<Hp0LV@{VOIQp>!o;dLqHxrMtza|Q z8g_OGFsuo`fQ?}+Y!BmLKPWA}N5N5WA{-4&xP{qmKXuq7r+H@ z16&BRAT~GlpP)3zmUh&Opi-0*9`uDvWQnTaSPC0MX{p^6ro%Y641Nul!!(!yzk||H z`!HMyFTyqOK3of5z>QGOf^EY5SlUHz<##(M4YK<{X^|5{X6_O{0sgKJ&GHK+6CZiewTr7U=8>W zYy{uJR?vj0Y7c0J!=M7cf^KkTA`W*P0!qv6Z=n?)hPmKXm>d2HrA4<#3B#h>A4-ev z>X45Z*_%Oc*d6i$pM5BlmfjPfwDg_<`Lc~Y1Ny?9P#StCN`vddIPOA!_zD(*d3bOk zEx_eN3~2!#0*gUufE@_?!{TrZECHv&l5jpO3s=E%a0iqY;YXpg2)_)g!(U+yH;(_8 zID+xeN*N~Mg`hMEuLA4BCQw?0cZAX+ygzIN$H33vRM;3UgH7P~P+Eu|gVI9$Cnzn% z-$H32?uA`+G%O0+NSpWaIHZYq22iyvK!sD0o{dAAfTzRJa6Ob3;CrC706zs~yz9^o z|A0yGEt~>9%Nmy6CE-+lhd^oR-4tT!J$V|Gmfnk@wDevN=fNzPn2O^(4r$SS8%m4r zXHZ&nzk|}E+pC;m(d`G9^Sdg{fKA{E_&Hn&hr@5+RJaPJ!_{yzl!n{;;aYeKZiLs% zar|$>@dqAT;aj*3dX{I11&hL+urk~O8^9l66x<7Yz<2Hyui#HG1^x`z!Ygne zyb3SEYw&k?9e#i}V1bH^j9|q?9Jg?U!)(|I-iAZq9XJ`@g^S@mxCP#aN8vBT_$SPSPvIH(4Bms!;cNJBn71-R zFIXD>1?$0=unqhh4uG%VSoj)FgKyvh_z&C&Kft}vhJg zH?+Va&LpNSF+xU;pH$zVHa_2d}~Y@F^Ss%{4d!LK_?e zi^3tW3LFYU;Rx8e2FL%GIC|nS2FAg$&<@8z0psCj$U1%YqfoZkPtXp3g%jaBI0fdZ z$(axaz^SknoCYJ|bl3;Zh9lt|m{gPFe=d$>Jd)vBxB%{g3*Ajg*WnWQ9xlf}PY`E5 zepiR9`Q03@hh5+X{1f07xE$`le+&Gc-#@}V{Qe#8hi~8k{EH^m;tYi&44xz)8lK|! zm+&0FXFyDE>`UP#{P#mlFOu#+p1|9m!EAo}1an^CcSZOB)`!2tNcb3bhfm-T_#94v z|AvWkaQuy9IeZ1Tz_&09zJuqX*@Gb%RNyn{1}(KYJfR=7!1B-&hCnYE0rS9KFdrNN z^TSE75S$NvJvjcq!BGT{9k3`o0t4WASPcFKOTt&M6tvXgFob@vJS-0@!w^^nM!*{I zb66980fXQqSO?CBb>TNK#3PZ*ERIk-{skMt>o5#HhmE0IT?Q5~KWqw%!DcWRwuH@K zB2L7CTs_n!uD`2>;U(}E{QnK;phspVGsBh>c6e1+g2opMw)%Hk1|p6WXDvK8G#zuFvs52}e;pCc_Fa z35LKauqpf+#=xmC7EXf+aJq+S${!FrH~R;OMcb4~4Y=ikMdy5P|Uc7@&G=Wqb*21mf|a02WBXTY9tA&h}( zuy@4pg`}AK=1^ zOj&d{6ojJDK$MKup)2SqvK-_d8Z}1U&@_~RPN3V!`w*8n)H#uV;!pBb3I!gg@1htq7G)4#|Bg`v)9EJ{YZ(0TLo7L$!HfkkDemS84h?< zAGJrZC<&#Zz39@JL`sXp^DIq{8l%1_0WCsX(P?xana)ul6oevCEJ{MF&|dTixu2&% zC>kZ81t<$$L6!^D7)7IjC9hX3z?aM6codIVTloYR;%J?SXSpEmeXpBE2W8;A~B7(V^5#e%H_+|0x$k7s4p8x z`Y|Q^O==xapM3thzwyswEWb{Ki8AN45^g8LJXnyfi&%AD8*J9sqARaHA^cvL2)%$^ zH|%jiD_HdRFh_|THli73tR)doJ!W)!x4WOn zi1f@OD*UA732Dq=K>k%jX*A>xbQ;}8uaM70x)F*-1JNwB3hlkPEqsnS^@>)?++UQw z!q<=c2bsjM73STkSGE2$@URSX0g-T3^R=wwzCrF|G4U9Uu>C5Q&+CFj#7(V&czP8> zzQf|(RgGs#V*EAUA~1;+*R&4G;%Koo8!JT5>*OHq)r=g{v2_l+u9aZ}=Wc3jKn8bp z2JcIk8@R67%w5IN>sq#XomhQCYvPEUdQ(* z^?r;A^(&1&NyjWfosWv*x3%S#*N$LObU7u=zOC8(oL0hpH)Rvuqh9Hv^gXSrHJ#C_EJuLYw$p>v zH|}A#L%ir~#M?_eWm`S*{++dl2)a+Ab0X@#R@IFmuQ-=sZms8dUn_@syGdOhYSMcj zjkmmT?gH%P7QbjSt;WujucNOx&H?-M7j1!6+R91O#d6}A8RM*sU$t`Pa^mE#T5I-$ z-*4LA><8Ne?Q>dv$OG+N{s;=lc!`VCbI3DoQ$XhU-?ctww_j-9EiEm6Yu`T9%(U&h zKeU)g$_M2*v+H8YVr~;%J8zkF^0xdOb1cic(mVdZGo%`YkJyD}ptXIlE=9 zf1iF5g!e*Nc~ zrV(D{FBKG@fp)Cq)2YhU5{g1GXR+-Hs#5n77jFF2n>5wFe+ zvE+qT#;wi_7Lr_Ht}YU8xUqo1kX)WD;HESeF@I^*l&~3M-d~!XjpV(+VN~uV8)-%2 zX(V!4lru_UKf&FbZ&3kH<*%_-RV(QGfc^&#AV{B zU5S&OEZ)E8ItBwi@Is(xO6G_U@=eC#^B2Zjf^8e;e{9WM?5=*F?j{ejrKI{f`MjAg zs+cWh6xh*h*^sJQ>MPCpR=;Ygp`2VGMyQrh<(~!OJJk}b1S}K}Rm)IiN2=(mSwfWl zi$tnsalSkiC4Se)l;c}nwn*f&SnB7Lx`TxPY*^HPEfNzfYz?llSmr2q7KvahTdKBL z47OS}D03Ezg1PvezF0)$vQ$x4E*9~*C_%syu_u>B?&|`%$qF+Vb;A-7n%m-hF)vEY zmH|BpIJ!ja%x$UQc65nZY~1O=tL^JNoQp=#S3HRpL$s?)L=R6(PEfGz^;Ms?OcT0@M7SC4GL0sPRqJ!iiabMzCmx?NRToR9y z0qr^S7Fa4KeB~bGYwTiqns8qBo3r0yCW$9`EUlCYlSF7<%b`r45VuF>%)k)0+vb$$ zpq<{9MIMSg1r)H1P^Qfgc?wz{%47CTK}(F{8%+k>p*n62Dq;zC z<2W*WGoi35R_nZ9#P$tFRqCg)sJm=rX*NY!Yvs_`M__?&@i?Xc<44^`?h2-aPJ}#Cm8-5v0CI92Q6Y|Rd z31uunblc4D%2+BXwjP+*wjxO>LY1*{wNejq>5p{EHfZz)r#K~5=Uu5?O0 zS05urTzN~7+f_QM-k@3KX%2edt@1R|GpBF03i!TTB3f0z*Sgf%%+i;xv%i8RB5|-B zd+>J!P2;MQfp(!A=mqj7pd6}?+M_r$4Xs02=mvU$e6O;LQD+o~7NAY&JbHjUuW>0w z%~1?WLTT4beN0Di-1z@EdlUE?uKw}=&b`Ua%w&-eM1&w3ORcS{B_gpEwS=mwHL(T} z5wX@1s;w$2Rr#Pwl&adP_I9zQk4I@Op<1dailWw5ZAJg@Gjngm^L)R**YEeguh-|k zXU;iu_I=KrgWN=de#S8*0qKckA@3q_mR(9vn%J6;t@r$8bWOc{*gdbU!yYLVd^$TPJ#@~wfqXk(O( zd7xa;N3&8hM~%$ll{ik*i{$ZxwFpoHxl&7y0b#YRyD0|(ITf$AuA`K=Kd^*#*Ny^9!%c@XIJI8)_ZEZcKFpMfr(8M7QwT%h;)NMzouLsaTv`CltNTx63rD%sdru~%6j^K!m<8}2QI@A~I7D>ixPvLAwD&53lMJwGe z@QAO{-HfBV{bcb|`j<|!Q1_?xb>%GV9iz?%IH^=7rElSdaJ zn~}Z9S>!$vev$%(v_?{qY-Ik)PwJXqYq@cH1$Q%Q``k>4jnm7!ayfGRQ3q~LoPLPz zTA%ICk}|f59`0_A(a$sGohCG&@XIFpJI-yH(jlIzb4RAU9#4aOFjKycr}?~{DYxSF z-dZzxu_*y=!J}`Dlu1n~4R4LK<5}ffm3jKu-$d3KW%_vvn(D_j=L(KRNYsZoZ;X`4 zW?1??=VLa*(rcq+Ml;&rW^%3>mbS#wW}_vfxnADcY_z9VbA6!8d2zJlw!&=jG4gFI z+V5Ut=y8 z=sA?0nqvD|@>i<<*Q5SWGilj|$68}%%oIs)Q`o#VlP{D;8#Fdfkuz=dSl33T-JyeuCt&yH@+v%$`6-%Q#=uxiF#)VCSPQw*8!Sg{UJ;cwj zgQ+nesJ+ZsYwwGCf|Fo{bS1+Pir!uIFI{+3mc*E4q~1%|^gMUJd=~hOOn*ra>ac;# zwG%mx+(ANrp^`-skZwo@@-DIlDL^hDL8qwEkrqf#BpaEJY&eyZSUxvTs}S%pyJ7$F zkiDyaboP>I-SqH)Rj7piy8Hb$w!aq`yxk01iRIP-@SyH|D)~;Po zJrt$7lZoUEuEWN8tyUE(34+x*J@uI4bBeg=uaq6K_)Gs%5<0@gDLFmqDWVcN!c|_< zdim9Hu6D_!R@6J~dg(##b@)6lP$W5e}8*J?N_NeoYvr1(Rx#l|Ef+mEnS8eIgSY!9)myL46^N0-u0J*JgB+l3b0IV zz*KomMFiWXR4pAK6_c?(^dqAVhecfMP1LT(gKdJPcptr%e;Z{~PA7AsL(e|M%~{LM zl68pY4M-_$>*BLbv=pLnO&>kN|G4#7`xNz9Z#~FgMcrAs(MOL7?i=#Raeo=nSN9#B zx>^P&Q{q@iOc-U9IorRDKu&4 zEH6rh6g?=+DE25mRC9VxI`zhnNw&Gu1GrA(y3DzvZ3q#mVn(IwIhmEBM~7*lkNiv= zqHLXXUSK&}X;|u@3Jh`HXuBubmsx`anHYTBPa`QfDCcCCk24wBjafoFRo)*timp$Jzy%GLVR#b)jKM^s$}my`e`*)yAfr(5A!fs#3AY_kHmUC3 zMf)&>>x1xkyCQljPhV6XFYT|g%0+p=r6i#H75{!z)i*5c_)@|x0)7=m_f`C_R4tn?g0VlOD=OY9p%|1+`o48e`haARjF z`D2J)-3gt;^w{8_5;P6r^k2wHPs%gHuz2iHEN&@-)%6;#owG{I;$eDM2~FeXa%pj< z>$Rkvx_K)?;?oP~2Ug44G@S9^j3+{VOv4#?DP6BDvBUI`;PPc2C5a}9)PZtpFqx?* zSv#zOS5w8GD&v=BV+O}Z%~5)jis-4dyew;}GPTQcdMI`z57#5g%`E9~RG=QKhxUmg z##O$&tV-*X!4o1MWw`*!8D6By%1Nin`W%0+^qLWEEuDlT>3SGboz*hPx|BZ}u;IE} z7G;pN3l?)I%@w;MzhYP9S0rUP8Sh}(N6x4mb>;E;;3v$uzrd**Wo5=Prum~Xs9A5Q zhveW0f^jcvvyoP<bUL|LWHH5oC_UAkOcBy*)@S!GMUQfDvvYDiVwu1QWNE#9>vwKY|VRe`GH zx+eK(d#Y55=RoEuLx0_@-k#3t!|t0wzVom%KGcpdAZtk$sbA5+Ap0} zi;+drZsD<2UgL6lEpu)!Wa(iweM%}wSfIYxv#74yrwmSSpJET3l&}bfQdrx|;BP+fAsK2>dwqnM;9Wx!G<@_iTr-Rq5 z%KXalKjewgg@c;aGGH|3cVIpxT4s+f;@D4U1f(zbiR(Onw0qCp>!BS zCo}XP&*Cw9Z{0~x?crp-nX8ZKlISWyyjEJP`AKp%WjfjPq-X2nHD_L+=h75?x26q~ zPhQnuXwg^s%u$Zri`B0rpJ_juU8%@K$%~GzOcbbJ7_Um6a6E5a``!xNArjjJd)iLZ zvovjhY=2FEp~3&XjXqmgKkt|t@=@E@b*F7fZ5cmZpI`NV_lxgI6%91Kjou_0MumB1 zys0N>!M1npnIy|kPson9DdNtz^oZJz+xY}rRHi##c`Qs>gz0^&iB)@o9z4t5%st=I zlQkMA&$gL5n@Kh)>8UkaPxFS@vb}RXJ7WGj0=p1}qa0%$uRZ2Se}cTTl&94ky@B)p z$D^JI&!%_&-yc=eh$|yK<>%>Rwf~CUG~#0XW1duFYAUpCx%zxhwtf?f~HcW8#8Fqa9<#lH%$y-eO+h?Zz)?3xIPOM`N?uo!?j@S!p=%;X_RzPW4X*ffr z=X}#Q^fsl}-&#z-5-h7d+kWvKZ3m#}N`N_7hc5`J=ICs1vT}KeKEa9mL-O=X29H{L z(Q@#B8qF=$qbm8<3PkX1e?m4EnS-oEb|6R3=OlK{{ean*Tn6y-Ka|)H^h(-%X?e|$562fS*Jl_PK2!nJ9M8#(-v~y+hs+;f@$3)v4_pIR zFfCM_SNrW&=vB*ICjk0y4o3x~HIj^EAv2NXo`Z|@+PoG>$X%&d2r7s3yWX*rMhh{5J6y^dzetX0?$jSYL|$!DwRtnQg- zyQpl?MO#I;%x^V5@u~aT@vZd4oTaVV#jOlJnQ}$N#+22>##VXXMpzmX|9e-H#e3vF z9+<6iFwa+PNF{ZxUPrd9W01UEdz9k+Qin2?U?=T%IkAqI z+OFIxZK$aXf6J-Cm}P7hvB?my9PAy%wf2KFDnog&vI&q~Y z!PG8FogAGVeYk#f8bdaZ@0sVR?x94olA`hF`Y7Xpm95kUKK5kb=S&9H5>Ln%YD%&6 zd{6Z+_5GUj@&dW{6%)Xb3q4P5(T{0Pq9J4(wTAMnwe*Jz8)*w5Pv&em?2HZ!*xgWn|OHHQQC$vXx%#{hmJCeg%6MFrHo`g?^I4zlKgHg#@V|oFjNwL(!-7S zyc(tCw9-gR@eh&>KanokKk0hd%X|&09#a*iYCeCElobEc%0N)qn_fLt-c+6NgG_Og zqc8tN4LDlL9mA7j@yUrZ(&|`Y-7;EUQySyYi2PO79n%xMnR&GQr8LH)(co7p|8wC` zVYCeXS&s>S1&ywJld62<=+doApNy1r>2#bL{ga<5!DvbJMqd1$`nhlheYBK0PMM#; zlheIV%H7WxLG?S%6Da);Pwe4|fMKdcp)09}tUMy|C+HdOI^vmqLf_>! zcAQdv)6_d5bs$B?S-l&P@A>vD*~k$({C!T3@mD?No)U9juV|dGB2aTQkxnHz z86x?-o?%2<9@SVhb-JuN)Z@Hf)oAdzTAknYs?M&zO84JzfBLVoO7Y8I<=$_4+wR$I zRs4_#kyP?xHZmXCf*eLJAZk093P=Ma2}wm}BFmB8$SFj>j2Wagl8lVKyfLw_>VmOy z=MvfY7V$B5u*6>C<H#qB%ijqKOQU{ey274 zc<`gqud1j+B!55q0ftD$Z5#?4BAprqmIbGOr;+E)+kZ9ke%3Q#muckvhuBv68u<`O zyv$J7KGXV^ympx^#n*K1wnJpyWvX$-17?JbSLfVE98l|!u28WRlX6!Ww-=NA#+*Sr zU8%>tV=~`&g+spW;rK1dxkA>si)AN=xTIryqofpEp%`#SvfG7N6_HS@Z{V*=M5u(h zU1ePK8DvVMz>*SwRSyaK(`#O}BXwW^*L@$|)L=_1Y3OgAiqOGW=v^ zV`i!swPiBZ7p(TzdHw;<%TO78ovw=fzdc{`2GR16=YJpSlCqr*2IM!07VZk8MI~}^ z8Sy#Yq~dbpPkIT(CHN*4ZE>l2Q!kzS2j;c3$5XPnq}-%%*HL=9S5HNmO8nxIbCZdc zTe9E}{QeJa-%69O{~&$gwrhH8zIglL|?{uE!UKcHEzO%rg##A#V=z#^tDt zwBafJso~gI+Ms1IX$wggpT3I4|Fi#N!j^dL^5sIy?@YaWmH*4zCvM_x4Nv5zi~BG2 zdNti8fnAMilJpnT7^wFCi~jt6t2=s2KK+Xr9#5Tg0As37^1kC!WzbhAjU`%CIV|>) zF-|RUb9_A5v+5S(1+u)yd53~%*cnxGyd+Csr|&rPu3q3ItM$G|GZ8mbX57=8Imtu& z@9CL_od+~W7ki7oo_|xD{XW$5+272r7`LqCPzSGc+D#<4d!SEuzB$bE;{&BhP)K*R zcb&cM^Qs7>9?}j;MY56k$OdF5avZsd6!~rJkfP-}jmpjv+r1qErxC%*#P^*>ZLO|n zpVK(#Qj1UX+(r!!JK5*vbmwf(6}M4WQ+1hc)MPzwd)=twDu2TvPgd}IUYXvh8#SEw z{*d^cEdC5Kj39LrX&8A*bBlph`{klxJPAsg#;l=s;d|BlYQK?p_thZsp88c+^@8{J z24?>G%U((AXwKS-;ltVw7&$U!(12#cRidkWyFq8o{cgIz945rY#Dq)wGnp1Jba`*R?IG*LPG_*6{SYmY%B7{#)-UCd}+oSx2Uv32a&C z@u1cB25qc2XwP|rr7)eKRl6;ROe2n{Ef#2$jJ)hMHl&ELH!+rRn+0`7i~4rQ*B5VX zy_Tm1+Q#P;d1?kv9lLGEn|-#y@b8>e{=$Q`c*KYbNkRq|d4 zh^_Ou4}2;2Zjk+C^CA|^#DZma!p2)G+Y!#yw-eg|v9y->Z0*asWK{jeD3Wc%TN76oJn zLSFo57l)@{8F&U(gulXAcn(&Dj1IExMQ-X`x+lF74b|63HLLQcL>;cwKq(;VYa}Hx z$a7v%EAcwYfm%VOt5oAsi8}wTF6BclpsQf53s1(M)vU~<=0P|Et3)+wpzL6jsa>+m zK!TQC8Qy@;z&~Ltct@Uj+K4eSyiX5Nhk$jyk0x&!ROZUAqySaqyI=#z_&>V?yn5|n zb`lKWzLWP}C4#|yZ)n27Fi?|SPaE}}$8O8Rr;W%#bS%_nc-F3X)nG~PRic)HjbJ&b zp05P6pmJw4e1iKiunL?CiDxTOsaUe#=Ke`ohQ*6zSaw;CwIGx08Kol9*P^VN_?M8E}|6KQ3jH&F~z%tJF zeK3OiMo?wj#;`7I0-M36(&QPV_TZ;txaOCP1d$|_kvJq78H>zBmLofmqsUDp=sL5E zNDHJtG67kHY(|bE*O3Y&YXc+$nU1XdG>77uTi>YQUckKBuoV(p--vY%TjA+Y-#Ft8 z&i_cYf%dp5K=KG`aoQAu+){#cGRGM;iaT_qunja2GCYcKLCHgJ5*A<;; zR1xOuwrufZXM+`<$Yur$*a+jvR>m#@FP6VFGsJkxuJ1sd7m#=TaBG z6>k62Af~-h&CO!lrZXbsOZ%j@S=Rb~MtR&W+L` ziD-3il&MK1(Qf%E38VWk8n;oLoyY*NdMAu7+9(S_6I$>}>1`ltP$j%sq zuXiy%2&qHKY8_xzH;zjirT&XXrI1sowLpz%bllh|179Qwcgw^Vu;Kt#T-zioUcg)M z+ZT*9Z-08XH0gqY0t^iLLsi>%cuG@oxc_A|h@f@djYG!ajVdpzCD3a3ZqK3~Mw+HVWcD(0@wn%MUIzVSyknV4 zw0p2M`WO?Ocw}*?U!?5pV^r;Wovh?X{T_wXL)szzkqO8gWF@i#If~pwf^L#6kp!eC zl7-AfmLs1d1;~Y)8xyx_xqYcnR?%-be@9~b8s%N*=__=s6gXG)kJQI8*ZWdGtj55V zJ7V@T>Up!+DrwozP)lwMKj+OmlHQM_dF;%$O4g#|UdtnnyYgdEjgtM*ScgW?U5W2s z#IA8@#I8r9#9h1l+YL7gJq0o&u^|a4S7SlQj-L>k4M#2W-%}p3-bXOJ+ zGNPpGK%=;mn?r+)Mv^zo@M9-Jwycn~1C6rUQ?h5E5iJ*n7(sG#pb;AKRFR%;hC@Pz z8l|M_AarM@8bMm7+{n{vdUNwC88ryEKEbVRmRnCTQJ6RwC$9`L0wr}YPc0hAVxpi_ z{*ne8;qvZaBUBn-ldRnB3UYQDF53p&Yw%g`OP@*{98f>s~jvp4K>P2Ph3_zr-WgF^-CHqA!)WdL19HTIt|AONlc@? zVU==FnWB0==iOLQPfiaud@IOTNyQ;J{3#A+{w-~XQ0r&@ZKu2%6DSv-mWe~~h!q9P zhZv#7i-v1_pAIcsFtAV|KdvI)ii_qMc3cDv#UDkDzmVyT2Fu>MLygkf)6!;W5%0V? z6z_b7cN*T8O+$^?Y7OZy`I=MZ9XeQranU@*wod6kBU+kKx=c~+7rfeJS+wh-tvw@c z(u}g@ikf=4Pexiw`hddqV9&^uG{d)KVwLjdY{O7WjSrl}+QUp^-7vMEbU0E2NkFNW+`RS1 ztG?VArIodkvA%?j=2DfZ`cjumIi=o-)t64){LALPXOP+ zyMzj$FP|i1fI!OnA6blD^&E45dE<-(=hO$DGvkcKTF6e~=O}U=3A&S$n3=m*&FfAe z3Q}lwyNr_933L}=hY3chu#8cUUIJh6cb?xOLKlr{>TJm5waQCi=0Jt88Oj#J11#J?sO6_pUK84(GokI z#GAtMmEk4*w&uR#A0Y{U1%yhCH;tRxpGA(a;(CVB$yd5o&LC?ICu^0hC|}PoVxK5m z(Kp-c3Oh;q2RVCu4 zYn%`0m{3ZD_4d46Zd^LZK_mY56&^_$*|dmuQ!q}OJ^G~L8EZt=@{FGQa3O-QZCIl zsusFY=55T3#!Sb@%=CS`h?yK^hV2{O5tY66Si2t_dD{r{x0EDtE`6qgdz$WV;H}%% zt4Hf}rQ6n53)bmMx8-0WtAf+!P+y@uRIPBGW9VF0Tx`^lJ#&meuIpY5d|LDzBQz|= z>zE3iszANwUe2K_)$Ls>x}X=_Au=h)C?57NuTj-%ViKcEbC`CGmyhSt={TNaM1;Lu z#rC@Dkf?_Bw&c{|{aD01Muo8N*(X&+r+QpX)uUI}>09NHFSFhu8Q8VbeWj{=_Kp$j ze?^&>y7LJ0j%Rqo-g6$U^C@*TVV+S;qPzJAOGcX8PZlYSBl|CXmq2_&Agb4vZ{H>RSFdfG^tDfSi?mO7?RUp{swKK> ze|NIOzJAm~-IbKxfo1*Gkp8ZW7)>W-(NdSr!S$rf?s=r~UG=3xNx3x72nqYn>zJ=w zb61vrOcygM*QhS*CTMOv*gh8zvK6SibzK>qiw9fRedNIyT)Ag?&|mdo?%D0<6V|2G ze#Tmt%6I-%tV_#tRjtcTyLel%W2H;?S5sN{B&Qp1ptFUncTc9I(}XVKy4<}Yr8Xrk zYuNDq0}6X#_atAa8t%zYLcg!5$&p#((iqrS>8i5MJqer7DB_;foKFV4C++7Or5}61 z>L!k~y9J@v15<31OYP^j+IJ_olgfE?om7;SvTa^q`JvhZ%jS(4S_%JhmPU%LGR4MH z8~F>2n6L>?*>R|{ol2>D@)ye0=6aQt-KxMA4N)4NQ^rlpc;Z4UG`$x7M=-4D!GtoY zW-*CX+vM7X#*<+k>pjYaB`n>G3-Qg-BFYh#a=G`6=&RWaip!T1m~nrLnXej%`+dXru|Jjn`#d~`>T-+k;rwsZ66g1gM-Oks zjQcwt{dqjOPDEv`~fT! zE_xmn%^05sF{LURj)_#C@?`Y#Qw`*>JnS1w(A3T`AJO9@YK zBX4-dEj3CwBO1xWGo9nA~W_^fn5AoEqabDl6T>WYU9?F{=I#fL&w zRMwxi3stHk`xwQCLX{K|McizlnBF5ow);Yi6RLK?@W;eYj|4j+RDlk$lqt}aIFEc%b+r-XQg=nRnK>-8R@3z! zM~+|E!hSCv?d^H-sIR+y7Dwo=(m&7~3uQzenp0E$qyL$*VxYJeoF(1-)_{`zLl-{6r%atjU*>k z(53ChE^iH@UeM=HqwUL?$5bBAb!D$aO@g?9@S8 zBdJI>vK-lh97k><;r}pofg~ZR$V_B8vIRMe+(AOgHB}v2PU4&PdxrfiF6bst>^GvF z-4f-h+gL5ZI|Er873uWLt>uo8@B_vfhDo;%u&|(vJW;?Jfij*>1uRC;`pT4p#V6NF%K(M%WWo1Fd$m2-h3{FO zaQ`_eb(mp2j6ZB#DnI>X)OJ36Ud&_U z(IJv}%y^4s(ff`Wi3GOT&jhxFH2K+R}>=bc%yo#GeQSge4J53bKWY;renOf{|hA0>$ z2hU(+kla0kktH(aSL1oDitPIpla1uTuf`kBpSsEGXKBabXJ^Uyx4X%Zb4=pK%KPW= zNPqd^oH1Fi+}#_*u>Gt=9CO|XE8|mAOF72UvD%5$A{LTm>3L(aI`{TBT;bGQg;1ID zo1Lfyzp<>OnmqW;XjvGG-7b*d+RKOwILH=L7mUGb0m_a)iQuXi(MprVi$+r|%`@eq z;nB2x((repqoWM_-L^CIXG|9Sj>(R4@pp2-07GKpCL>q$FHpuzvB8ksWvO#g=Pi zhz5PUv85g4kmi4`ks;Va0ia?`Q*QNB2dQtWppY`+*7FOt@`@>`8`D>`WBhe>x-VZc%-L{x@9zV z_3X<`Fbmp!dQrD|^flk3DTi^5$n=-g+jJpblTo)R*E?k2Z97KES>Y0Qhet;D^SZY7 zFukggcZh#h@ZK?|sQ9qTZPZ;{T_w-lB~4bzu)Dr&P?OAc<*w1#wXc7nSC$+jvgX_) z0@;xc{7r3e6EAIh$N1JlEZ39Zd`ORMeH> z)l%0mMJwjnW0>DLU1kS|^f^jXy&=eqA`k8hGM}X;^A9%Pa%nR>IicooO>6GaiktH^ zzL}O1<`iv^r%brnRHORvbT4Uk(Foo8Qf3*gvg|2kzKN+9N}F|!x2@_!^<}I*5A#Z! zQ%iQHu6We5P!o*RdNBDL%Zq@d2s43-ASc4?L7~4AVGhtJ*)K$zgTdBF^I2m+FFRO? zc26U;EDx-ZPG#|MzPwr197GYmQI@c6RAB4FD02d3uwprsw#ygg%p9$mJYU`{M=%GM zH@{bt})*w5Pv&elUiWNfjkZwqZi_`b!bFl$Aj9f-S zSxQwE>4KyodC2F;S>!%agQZ0+kSt^-vIRMe__1$N6w(?=M&=+Zkpkob62TIrI!G5J z4aq}3515RjT=-FL8X!r?G-MG{fLuT#SgTYA>4{_^E0G<@O(cl*OLdUeNER{^*?}BI z?jWJ82a7|xAk&aV$md7_ashFK1Zj@SNF357NZXh=Ld#7vE4VrN!F@hmV$)1sp{M)t zwx@}ldfQ(wvN%0-s21c|o@Vyds6VWC>rv@ucvt~X{*mrSa`Ee!F(AF@Yk&hXBHd(= zikW-qvM}8&?}T5bn_axGa1Thy;TSlCfvLkKez=(wU{^8+WS-LCBntOiydy5EQ8EJ! zj;3(`!V?)-343RlKRS&JsXxNp?>wI=?o6}3^X^EA&oq4l^#go~&VxVjpk&FHnP#jL zp2;*jJKxWe`XkM*+5wq05+grir1mKJY@}Jq36G65Uw1w|O8RD*oiXxh7DkR>WcDaI znT0L0M|s?%%t@Nlf3&37`ejL@|{=nx5 z?{|_?GE>x?ymCk_+U&+N%KQgoIQp0!b=qaKOGiT806)2tr^R-$7gws>P}HFYYE;Va zcgySc^)bxs`d=KHgCl-Cqs;FbBlX9cxgk51XHnz(1jn+ma%`*_8(za3`_{p#15(wmw+-w6XWZU6PPUCRBSYfQ-+(B6)W};^<>3#m8s25KKI>X} z65S8Ro2|WTPkna!ytq@e zSIiRb6Ic^JULs#HBg@U_!8xShbtgOMkGIoYrKy@Y7-WC3x1$B4;fz zF}&DoSWTh0EyJDqIZKCJXX(Tqf0VqqFJTR|D2x=do7q=__%e{i@W+H**4KE6%vPj9-{P7tM#hc`hUqV>V#AE zYiPszKZRE|P4Z@ca^_1(iOru!N9D|;*c!((%KWBDGHH_8y4&Mf(HGbK!)+_Sv0?q6 z#^&E2v$^@G%*+AlS?DU;v#_}imApCsicn;&%WMV_xLWvG{F{CJI5_&cL~JlX5x z{=*adWepylj;^vZ75n0NMw#C(d_D{!&u&;iE_vWpibG6U8&iygp67ebqeE)|V)?yg7Pjq-{|^kqG<^ zJ70UPsGYV?yI|KG%qz36y(YJ&neT*5Lv1E%YjETH*Ch8f>YU2lPe*8?9i3m7Z(lRJ zhWXs}#Z;=KoCqx8=2#>5%s1rf>t;vM#{NgK_Ic%gwEe&@ zMN;N>9{t?*O2`DP-i;Zh|M?r9*y(03*f(^# zodl|$G9+h)87@t-Tmd1c$}_!#nGKkEb-KJh!>k?>&i&^|H`EqQmu)l5*fQ<7-;Aj4 z;O9l`3Q~5JkkGfx*8f#T6DneuU!x)cxlBOhO>cIvYLza-vr^KmEas@-a0Ky;GB0n+ zinq+}J>X@w!p64m{(>G&XDsn&0`^1sO?1U8;v7fX3G9qYRPqpxNAXXHy z^ct3C&6e1=&GO}zV@oJzlz!H1+aWcVuZ)kB8xzfjlOM0FeU)m|6Sj>rY*_!-u{iSW zN3qmiy?5lN>V(!fasg51eP)#U1k}zVF$*P4#~RPb~L&g4(WsQcAy}1MG^a0-j#PGs^t(w>`V&m_KSET~JJ|!l9HrJYtTl zdWZBsfH%M{x+m-u<+rjWg;Z9%Oyc098{9?mm67ly{?mR`elV2RHmcoVlKvQc<0 zeY-n6fA~pG&_W%x4|2`;kUHEKAkU$8V1ZoCH8bk`&mn10)3$bp4eS3eY>!$fvjy9O zaNQ3xN*}e)#60>R1;p30%BW>q@uv;z{}whKUntw=o0UT1uq6&NN*}eW^Ub539xoBT z7OlVPP4e^hHmvJhrdSTV=Z)Q3{jBXaRjg)VV+G7Bv*ll5F^_V$j!8u@w0)A|0E zUDn@iymt1Hg@xO9reawEqRgIsPt5nsq-eXVpuFIF0i-Ns2uO8O_+Dn_duEi2L7w#a zn<<)|+!^=0CZ^k;G~R#DobH-B92061CvOom3ToK4h*8)t!#%eanTK3zwDoPCIY|wv z+AcK@sc}>J56o|!&PikB(sHwHuyWZRyD&(#-UyXHp>Yfz%Ct><1XG{ch{o3UMQVpB zMiz}eG$SWpL@xw0j5e}W^>`UlG_CX7$taE++&>NffC=zV*dD5L++T*bVPE(+910)6 zk?zw!2ur&ATOVkMX5{!g>VH8Y*6k{#Y@Oa-AGXG{ zDs63GXZSqq1>4EQkIWdOm^EV29JQ_au!>3Os-a#ds8X&oq(ZcgbXUcwtDN}AjCL|m zdiW8E*Bfm$>WQtS_X$>F5v3zyYu<90gAE59G{1{GxyJ0rm3#Y={@Kvb#jMHE+d=0AZ`RlM0 zoDQSln@}a*OxOp`f`efWR9_v=h2tST{p=~sM_DJfzlFjA6z0N3a0OfpH^3$EQ@9l7 z!w=#2a5YSDIvi_ZN4O5A!u60?u?}D-l#b2ZzXwOckKlH=0p`QaHMsZ}7YE=@_&xkL zR7(uMfo!B;9i)B{ek=JOo4*?NaFWR}**MBoVlq!o{gC+K$!rh&0e%j#A^R(M4E`Ic zgxCd7a$n%RKL}5A|0~3$?DOy(yzbS%0dYC|Z+IC7JKm?UZ%&OE1qRz#6lqlL2gpHD+YB5-2LqghS<-l2Cc36jY5YAB9-oE=Eeu z8Z&0HJ%ZJ&Q7XDLtUO9OtKYjARi#9rs_GWNvTz}+3g3gO_Iw}4!zHi<%!94qa@ZHH zfCJ%5m<>OMv*9Y2qgD31T&zZ6K3oGA!gVkYu7|7PCb$WH0#z!13b#WKRH^*Aj9Y8= zb21`6xt8?UfwJ=Vzo7CrYbq^&v$)XmH_P9wj}lpVWR+r;1!cFy9IJe+Du-1yR;gya z%CteKALV{9{0U~jlkjzT3eJFM;BxpY#G8GsldF|K&!Mmdo`>7u1-KJlga_bd_#?am zkHc$F<;olIBK#9xgEyhdm3N@374FJU>&(f{)!EX0J>m89b7Y$+yW#UN2u_3{Q00?i zP(?GVYqICTlJFZ?8mht&0Z+n6_zNr#)u+7`psHLd!fG%ER)^JLFIWQ((x}a9a-nLO z+He$n8m@%Tz)i3|+zuPS9WV}Fhw<u_g!Cf1?O&0#9) zDkBVmJzyGCZ4SMT>~xp`RR$O-Z*JsehdqU%c50Zi)L9~t_RK1Iv`kjXdj(d)G!tP~ z$z!g_YCM?RvA*t|0$Za$6?TQMO1VvDZ70(b9X64wZ=tMmaXwVJ_+LQ-pF*ajv%i4MJ6lyI6UEv2+#iE9 zL5&>DEM|X?!bzxd=P78_nUHqdI)_=cP3O1|gcsphxK}EEVh(jO9Wwh9!a={#3dbF& z!conirVBm^V_*%aYLQy70el*^g3rKqus-Yn8^Iwk4ywf9LxAk*uqn)i32+fign5v2 z^s+xtZEXuKR-(`nega#=uV7pFHEaj>!H)0JZ~w@I}Zg8An&Bip5K?0_+BB z!R{~)_JD0+PuLBr6L}A61aS!$s_k3`Rd#Ox|A8MtmEBj$p3UYGg9#p@m4T(z34LNM zx+?wGLHlr-`c@~@s&OAP8vTja=;lJBiI&mI>T#xde%Yg!nf!&N`K+Zu-;PNa+qqxx ziTbIQioT-t+l5(!D|L2nFjPnPs)F+^RE^4aFcR*C(QqGBjvatw;X$a<=6jd}e^4i2 ztD5}?3VHAtRB3S>Zh@+aQ#GTy{|=slKf*KcEIbQU&Bv!FR^H=F6Dv*Ba|QuW_o0vv zNU~M)#W9W9l@!shYUxiVmvM0e4V73*BOd<6{VU%4DNuP}CcFbxm8H%I{ub6x~xhFb*gNh8ucf0q1xEKP_?oBpsE%Iz#VW9+ye*0AK*~<8%%?$R1AZv zCz=kQhQlGd05Gjp?hEr3CsR)gzn~U)9c2~H8Bm3D7F6M!4OKYj!1^!;s_@N)?cqGw z73RVLP@w8j&xfzVg;3?N_uvw^2(E?iLsiHR!GEb*;4l}h@YgZe1)hN2;YrvNo`I_N zItwSj^Dq})f@*Yg8Lom?;5v8}s*dt?s75_Epz0|92~|e93HQS?0V;zucR0#&QHt^v z1sQWW*tjygBCG%zGC3;2`mi#b1KE)hMl55vo!_&>b&wuUut2Q>!P%ZUfeCB;DaG)O$cH zm%gH zXiW!shsis6xRne)2jhY0-1z5`VsWUgfmoolFumP~?JeUbU_Y3>(7U(~hYo^2y7 zZ!d$YFR~o=g)87d_z_eIxEfA{Yas<G{ssS^JQ_e;I^%bU9KXQ8$&{E= zT&NOv8ZxWlI0K{MIjBnBZ%}nJFGAJLyaYSI%djiF3e}kQI{XUWfV<&ssD`W$;5Dc` zegkSc?K*V9$$Ts2@Z%yD{)0h2t#IhvH-{$d0z+Uos4VCXL%HwaWiMEg`xICT4u1|gb72Fx3^szFz&N-IHif(dGx4&`m913oKDhwD5lVDxg8P;{Lz-f#v?hIz0r+ywi>f5UhkEbB;TrDACzgI`xQ_cuI?LBLaY4E}KJhI0+U)2w?1_2J(chkL`vz@v9p6IL z5buLA@Bpj<55a!$u+;oF^KJG-yyoa&cUz93ODs5!!ytG9hQnW=s?|;O}r4yaF@fHTW644!?mnpsH;CfNCuACp@aUEq`&L#;muX8YQ z7v6_zaPklaK~|GxmxN9j16@$fhWf$g&<$0kq)W?P<}1d;1$O6niM0ve{{upx|tjiKsJ z)`0_IGnfTiK-CDggs;Nq;9IZ_oDJK;IaqHw^bQK`QCI;xz*R5_s@9`3`~p4?x4{=> z+-`G_aeSd2uYbzYZbpg8-O*LS=m}LYl3^Lx7pne5f2h1Y5IzS}VMjOwroc3)8ozWn z31+}4a0HwNRdl=#v$$9BItnV^j)8|%FvfE60}A7y8vDHhRiic$o`aL&?=TbIfKz4d z9&?b37bCLd03QO>`PQuJ>@iudgF$|GR59Y0M7ByJ52}1PA6bL! zM2;fYk;+W$#vy6QG-MI787V+6AbugN`9tE6E=Vepjm$?jAiI%M$bBTd7%gu?F;*TT zW05(?W@ImN7P*gvGg7L7v__JVvB(@`1F{=Ai`+*dm}#zqv_twMW05(?8e}JO3b})X zGb*luv__JP56~PFxOf*?iR?g5A$O375?F||Mv{>U$h*j9WG`|7QL~RxNIfJ8NkwKN z%aJX}VdO$MUvBiu-Om!jOMFCBb)dxVX9;1|fi7NG^^gy^VJWG#TWzqM-fvb3OB!f@ z>=fyJe;X`i4wz*zv~jyXr)(WC{kWd8ginal*j3gD8ss(3@?AbfN>lr?=AjW5?bT4L zWN6+T!Ls#$*^Ad=Wedz|?%(lDk3rJ5z)T3RUvXWMoB|f^G12GlHAucJFnt^TT#~zJ zgfa8y?&G!7@j}`F*70u*^lgf8NqQaR;j5S#I7nVUXjZB=&}&w`shjVjo<&r7pIoS3 zAxz~t4nHd6@_k!q=vAv_A3ERjh*{P3J@(aB zB{}a1_7RqCM|fGNr+VU#nv1m_pI5YOcBo2RZO<2u)IgGuRAd^m2-$$_MouAjkZ^{? zHINoaPh>1I2U&^iK#rEuIKgv|mOI|RLI7PtcaN`}Qf0hv)}PT++3EhkM*6La~Y*HoT`HLcDiwhDr3iCzF^ob z`_7nEidQJ|tP1jOhfJF6-sxT6)T{>mr6gQ z6jjS&Oda?-aJaWzwUGs9d43>~vH9PRZF#P8kFOLZ<02U-oDURij9?3-|%w4J~A@wDA5>{}46?X|aJn3Lt_$8}D;+uk;4 zui7i9v>d)}hVo%WnLo_(;<{m$2`jeGwxyIeWABxN<=JS1gQsd}on^!g^4p8J+-{$8 zIX0}F*SKmmRHoP`2XC;G`aZdFgSKgaSJ&4z?UQPMn2FYx(`7mrN!+tMX?vd*)7~6< z(H~}k6IaszG-nhGEkm7yv_O)}Xr8b}u4`J+^bVQ&2(IO}lt;${bdXvY1M=(2-yEO z{SQrs{Y`~fi^|CtwS*nynsG5|r@*Fh-%0K)~e#!JItCUcK63cW6sc_${M-X4U zPY`)i>7Lg{Cfz6V&7;oo*`lg2r&K(J*OMD^yr5Hlz<5|Vm5|SUMW+}K%;@43y~@7$ zb!xKi9Gk}_J+NGQ?Ex+w!=)L|%en_p!s>Y|7A2|b`3s>V5dRmUM)~gFO z7dx+w$LR{>IArCrUtkC4%I7@~{Q|dXjbmF{hOGsjV<`tSk>$v4

rr36G=~inK3#6!Z>Sj< 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 K7&6*9 Date: Thu, 1 Mar 2012 13:48:35 +1100 Subject: [PATCH 018/178] DCM: got rid of _error_roll_pitch from object state this can be a local error variable in common with the yaw code. This saves 12 bytes in the object. --- libraries/AP_DCM/AP_DCM.cpp | 23 ++++++++++++----------- libraries/AP_DCM/AP_DCM.h | 1 - 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/libraries/AP_DCM/AP_DCM.cpp b/libraries/AP_DCM/AP_DCM.cpp index b90e48161b..bce0f1292d 100644 --- a/libraries/AP_DCM/AP_DCM.cpp +++ b/libraries/AP_DCM/AP_DCM.cpp @@ -211,7 +211,6 @@ AP_DCM::matrix_reset(bool recover_eulers) _omega_P = _omega_I; _omega_integ_corr = _omega_I; _omega = _omega_I; - _error_roll_pitch = _omega_I; // if the caller wants us to try to recover to the current // attitude then calculate the dcm matrix from the current @@ -360,7 +359,7 @@ AP_DCM::drift_correction(void) float accel_magnitude; float accel_weight; float integrator_magnitude; - Vector3f error_yaw; + Vector3f error; //static float scaled_omega_P[3]; //static float scaled_omega_I[3]; @@ -377,16 +376,18 @@ AP_DCM::drift_correction(void) _health = constrain(_health+(0.02 * (accel_weight - .5)), 0, 1); // adjust the ground of reference - _error_roll_pitch = _dcm_matrix.c % _accel_vector; // Equation 27 *** sign changed from prev implementation??? + error = _dcm_matrix.c % _accel_vector; // Equation 27 *** sign changed from prev implementation??? // error_roll_pitch are in Accel m/s^2 units // Limit max error_roll_pitch to limit max omega_P and omega_I - _error_roll_pitch.x = constrain(_error_roll_pitch.x, -1.17f, 1.17f); - _error_roll_pitch.y = constrain(_error_roll_pitch.y, -1.17f, 1.17f); - _error_roll_pitch.z = constrain(_error_roll_pitch.z, -1.17f, 1.17f); + float error_norm; + error_norm = error.length(); + if (error_norm > 2) { + error *= (2 / error_norm); + } - _omega_P = _error_roll_pitch * (_kp_roll_pitch * accel_weight); - _omega_I += _error_roll_pitch * (_ki_roll_pitch * accel_weight); + _omega_P = error * (_kp_roll_pitch * accel_weight); + _omega_I += error * (_ki_roll_pitch * accel_weight); //*****YAW*************** @@ -452,10 +453,10 @@ AP_DCM::drift_correction(void) } } - error_yaw = _dcm_matrix.c * error_course; // Equation 24, Applys the yaw correction to the XYZ rotation of the aircraft, depeding the position. + error = _dcm_matrix.c * error_course; // Equation 24, Applys the yaw correction to the XYZ rotation of the aircraft, depeding the position. - _omega_P += error_yaw * _kp_yaw; // Adding yaw correction to proportional correction vector. - _omega_I += error_yaw * _ki_yaw; // adding yaw correction to integrator correction vector. + _omega_P += error * _kp_yaw; // Adding yaw correction to proportional correction vector. + _omega_I += error * _ki_yaw; // adding yaw correction to integrator correction vector. // Here we will place a limit on the integrator so that the integrator cannot ever exceed ~30 degrees/second integrator_magnitude = _omega_I.length(); diff --git a/libraries/AP_DCM/AP_DCM.h b/libraries/AP_DCM/AP_DCM.h index 4a3ba3df7b..3e9946d604 100644 --- a/libraries/AP_DCM/AP_DCM.h +++ b/libraries/AP_DCM/AP_DCM.h @@ -126,7 +126,6 @@ private: Vector3f _omega_I; // Omega Integrator correction Vector3f _omega_integ_corr; // Partially corrected Gyro_Vector data - used for centrepetal correction Vector3f _omega; // Corrected Gyro_Vector data - Vector3f _error_roll_pitch; float _health; bool _centripetal; uint8_t _toggle; From 9df332f0aeb01d750d42e85b6d32aea82b8a9d38 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 1 Mar 2012 15:20:49 +1100 Subject: [PATCH 019/178] MAVLink: import new message types DCM, HWSTATUS and SIMSTATE --- .../include/ardupilotmega/ardupilotmega.h | 9 +- .../include/ardupilotmega/mavlink_msg_dcm.h | 276 +++++++++++++++ .../ardupilotmega/mavlink_msg_hwstatus.h | 166 +++++++++ .../ardupilotmega/mavlink_msg_simstate.h | 320 ++++++++++++++++++ .../include/ardupilotmega/testsuite.h | 162 +++++++++ .../include/ardupilotmega/version.h | 2 +- .../GCS_MAVLink/include/common/version.h | 2 +- .../ardupilotmega/ardupilotmega.h | 8 +- .../ardupilotmega/mavlink_msg_dcm.h | 276 +++++++++++++++ .../ardupilotmega/mavlink_msg_simstate.h | 320 ++++++++++++++++++ .../include_v1.0/ardupilotmega/testsuite.h | 116 +++++++ .../include_v1.0/ardupilotmega/version.h | 2 +- .../GCS_MAVLink/include_v1.0/common/version.h | 2 +- .../message_definitions/ardupilotmega.xml | 32 +- .../ardupilotmega.xml | 24 ++ 15 files changed, 1706 insertions(+), 11 deletions(-) create mode 100644 libraries/GCS_MAVLink/include/ardupilotmega/mavlink_msg_dcm.h create mode 100644 libraries/GCS_MAVLink/include/ardupilotmega/mavlink_msg_hwstatus.h create mode 100644 libraries/GCS_MAVLink/include/ardupilotmega/mavlink_msg_simstate.h create mode 100644 libraries/GCS_MAVLink/include_v1.0/ardupilotmega/mavlink_msg_dcm.h create mode 100644 libraries/GCS_MAVLink/include_v1.0/ardupilotmega/mavlink_msg_simstate.h diff --git a/libraries/GCS_MAVLink/include/ardupilotmega/ardupilotmega.h b/libraries/GCS_MAVLink/include/ardupilotmega/ardupilotmega.h index 9192bacf01..99a5b60d8e 100644 --- a/libraries/GCS_MAVLink/include/ardupilotmega/ardupilotmega.h +++ b/libraries/GCS_MAVLink/include/ardupilotmega/ardupilotmega.h @@ -12,15 +12,15 @@ extern "C" { // MESSAGE LENGTHS AND CRCS #ifndef MAVLINK_MESSAGE_LENGTHS -#define MAVLINK_MESSAGE_LENGTHS {3, 4, 8, 14, 8, 28, 3, 32, 0, 2, 3, 2, 2, 0, 0, 0, 0, 0, 0, 0, 19, 2, 23, 21, 0, 37, 26, 101, 26, 16, 32, 32, 37, 32, 11, 17, 17, 16, 18, 36, 4, 4, 2, 2, 4, 2, 2, 3, 14, 12, 18, 16, 8, 27, 25, 18, 18, 24, 24, 0, 0, 0, 26, 16, 36, 5, 6, 56, 26, 21, 18, 0, 0, 18, 20, 20, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 36, 0, 0, 0, 0, 0, 0, 0, 0, 0, 42, 8, 4, 12, 15, 13, 6, 15, 14, 0, 12, 3, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30, 14, 14, 51, 5} +#define MAVLINK_MESSAGE_LENGTHS {3, 4, 8, 14, 8, 28, 3, 32, 0, 2, 3, 2, 2, 0, 0, 0, 0, 0, 0, 0, 19, 2, 23, 21, 0, 37, 26, 101, 26, 16, 32, 32, 37, 32, 11, 17, 17, 16, 18, 36, 4, 4, 2, 2, 4, 2, 2, 3, 14, 12, 18, 16, 8, 27, 25, 18, 18, 24, 24, 0, 0, 0, 26, 16, 36, 5, 6, 56, 26, 21, 18, 0, 0, 18, 20, 20, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 36, 0, 0, 0, 0, 0, 0, 0, 0, 0, 42, 8, 4, 12, 15, 13, 6, 15, 14, 0, 12, 3, 8, 28, 36, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30, 14, 14, 51, 5} #endif #ifndef MAVLINK_MESSAGE_CRCS -#define MAVLINK_MESSAGE_CRCS {72, 39, 190, 92, 191, 217, 104, 119, 0, 219, 60, 186, 10, 0, 0, 0, 0, 0, 0, 0, 89, 159, 162, 121, 0, 149, 222, 110, 179, 136, 66, 126, 185, 147, 112, 252, 162, 215, 229, 128, 9, 106, 101, 213, 4, 229, 21, 214, 215, 14, 206, 50, 157, 126, 108, 213, 95, 5, 127, 0, 0, 0, 57, 126, 130, 119, 193, 191, 236, 158, 143, 0, 0, 104, 123, 131, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 174, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 155, 0, 0, 0, 0, 0, 0, 0, 0, 0, 143, 29, 208, 188, 118, 242, 19, 97, 233, 0, 18, 68, 136, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 178, 224, 60, 106, 7} +#define MAVLINK_MESSAGE_CRCS {72, 39, 190, 92, 191, 217, 104, 119, 0, 219, 60, 186, 10, 0, 0, 0, 0, 0, 0, 0, 89, 159, 162, 121, 0, 149, 222, 110, 179, 136, 66, 126, 185, 147, 112, 252, 162, 215, 229, 128, 9, 106, 101, 213, 4, 229, 21, 214, 215, 14, 206, 50, 157, 126, 108, 213, 95, 5, 127, 0, 0, 0, 57, 126, 130, 119, 193, 191, 236, 158, 143, 0, 0, 104, 123, 131, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 174, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 155, 0, 0, 0, 0, 0, 0, 0, 0, 0, 143, 29, 208, 188, 118, 242, 19, 97, 233, 0, 18, 68, 136, 205, 42, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 178, 224, 60, 106, 7} #endif #ifndef MAVLINK_MESSAGE_INFO -#define MAVLINK_MESSAGE_INFO {MAVLINK_MESSAGE_INFO_HEARTBEAT, MAVLINK_MESSAGE_INFO_BOOT, MAVLINK_MESSAGE_INFO_SYSTEM_TIME, MAVLINK_MESSAGE_INFO_PING, MAVLINK_MESSAGE_INFO_SYSTEM_TIME_UTC, MAVLINK_MESSAGE_INFO_CHANGE_OPERATOR_CONTROL, MAVLINK_MESSAGE_INFO_CHANGE_OPERATOR_CONTROL_ACK, MAVLINK_MESSAGE_INFO_AUTH_KEY, {NULL}, MAVLINK_MESSAGE_INFO_ACTION_ACK, MAVLINK_MESSAGE_INFO_ACTION, MAVLINK_MESSAGE_INFO_SET_MODE, MAVLINK_MESSAGE_INFO_SET_NAV_MODE, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, MAVLINK_MESSAGE_INFO_PARAM_REQUEST_READ, MAVLINK_MESSAGE_INFO_PARAM_REQUEST_LIST, MAVLINK_MESSAGE_INFO_PARAM_VALUE, MAVLINK_MESSAGE_INFO_PARAM_SET, {NULL}, MAVLINK_MESSAGE_INFO_GPS_RAW_INT, MAVLINK_MESSAGE_INFO_SCALED_IMU, MAVLINK_MESSAGE_INFO_GPS_STATUS, MAVLINK_MESSAGE_INFO_RAW_IMU, MAVLINK_MESSAGE_INFO_RAW_PRESSURE, MAVLINK_MESSAGE_INFO_ATTITUDE, MAVLINK_MESSAGE_INFO_LOCAL_POSITION, MAVLINK_MESSAGE_INFO_GPS_RAW, MAVLINK_MESSAGE_INFO_GLOBAL_POSITION, MAVLINK_MESSAGE_INFO_SYS_STATUS, MAVLINK_MESSAGE_INFO_RC_CHANNELS_RAW, MAVLINK_MESSAGE_INFO_RC_CHANNELS_SCALED, MAVLINK_MESSAGE_INFO_SERVO_OUTPUT_RAW, MAVLINK_MESSAGE_INFO_SCALED_PRESSURE, MAVLINK_MESSAGE_INFO_WAYPOINT, MAVLINK_MESSAGE_INFO_WAYPOINT_REQUEST, MAVLINK_MESSAGE_INFO_WAYPOINT_SET_CURRENT, MAVLINK_MESSAGE_INFO_WAYPOINT_CURRENT, MAVLINK_MESSAGE_INFO_WAYPOINT_REQUEST_LIST, MAVLINK_MESSAGE_INFO_WAYPOINT_COUNT, MAVLINK_MESSAGE_INFO_WAYPOINT_CLEAR_ALL, MAVLINK_MESSAGE_INFO_WAYPOINT_REACHED, MAVLINK_MESSAGE_INFO_WAYPOINT_ACK, MAVLINK_MESSAGE_INFO_GPS_SET_GLOBAL_ORIGIN, MAVLINK_MESSAGE_INFO_GPS_LOCAL_ORIGIN_SET, MAVLINK_MESSAGE_INFO_LOCAL_POSITION_SETPOINT_SET, MAVLINK_MESSAGE_INFO_LOCAL_POSITION_SETPOINT, MAVLINK_MESSAGE_INFO_CONTROL_STATUS, MAVLINK_MESSAGE_INFO_SAFETY_SET_ALLOWED_AREA, MAVLINK_MESSAGE_INFO_SAFETY_ALLOWED_AREA, MAVLINK_MESSAGE_INFO_SET_ROLL_PITCH_YAW_THRUST, MAVLINK_MESSAGE_INFO_SET_ROLL_PITCH_YAW_SPEED_THRUST, MAVLINK_MESSAGE_INFO_ROLL_PITCH_YAW_THRUST_SETPOINT, MAVLINK_MESSAGE_INFO_ROLL_PITCH_YAW_SPEED_THRUST_SETPOINT, {NULL}, {NULL}, {NULL}, MAVLINK_MESSAGE_INFO_NAV_CONTROLLER_OUTPUT, MAVLINK_MESSAGE_INFO_POSITION_TARGET, MAVLINK_MESSAGE_INFO_STATE_CORRECTION, MAVLINK_MESSAGE_INFO_SET_ALTITUDE, MAVLINK_MESSAGE_INFO_REQUEST_DATA_STREAM, MAVLINK_MESSAGE_INFO_HIL_STATE, MAVLINK_MESSAGE_INFO_HIL_CONTROLS, MAVLINK_MESSAGE_INFO_MANUAL_CONTROL, MAVLINK_MESSAGE_INFO_RC_CHANNELS_OVERRIDE, {NULL}, {NULL}, MAVLINK_MESSAGE_INFO_GLOBAL_POSITION_INT, MAVLINK_MESSAGE_INFO_VFR_HUD, MAVLINK_MESSAGE_INFO_COMMAND, MAVLINK_MESSAGE_INFO_COMMAND_ACK, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, MAVLINK_MESSAGE_INFO_OPTICAL_FLOW, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, MAVLINK_MESSAGE_INFO_OBJECT_DETECTION_EVENT, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, MAVLINK_MESSAGE_INFO_SENSOR_OFFSETS, MAVLINK_MESSAGE_INFO_SET_MAG_OFFSETS, MAVLINK_MESSAGE_INFO_MEMINFO, MAVLINK_MESSAGE_INFO_AP_ADC, MAVLINK_MESSAGE_INFO_DIGICAM_CONFIGURE, MAVLINK_MESSAGE_INFO_DIGICAM_CONTROL, MAVLINK_MESSAGE_INFO_MOUNT_CONFIGURE, MAVLINK_MESSAGE_INFO_MOUNT_CONTROL, MAVLINK_MESSAGE_INFO_MOUNT_STATUS, {NULL}, MAVLINK_MESSAGE_INFO_FENCE_POINT, MAVLINK_MESSAGE_INFO_FENCE_FETCH_POINT, MAVLINK_MESSAGE_INFO_FENCE_STATUS, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, MAVLINK_MESSAGE_INFO_DEBUG_VECT, MAVLINK_MESSAGE_INFO_NAMED_VALUE_FLOAT, MAVLINK_MESSAGE_INFO_NAMED_VALUE_INT, MAVLINK_MESSAGE_INFO_STATUSTEXT, MAVLINK_MESSAGE_INFO_DEBUG} +#define MAVLINK_MESSAGE_INFO {MAVLINK_MESSAGE_INFO_HEARTBEAT, MAVLINK_MESSAGE_INFO_BOOT, MAVLINK_MESSAGE_INFO_SYSTEM_TIME, MAVLINK_MESSAGE_INFO_PING, MAVLINK_MESSAGE_INFO_SYSTEM_TIME_UTC, MAVLINK_MESSAGE_INFO_CHANGE_OPERATOR_CONTROL, MAVLINK_MESSAGE_INFO_CHANGE_OPERATOR_CONTROL_ACK, MAVLINK_MESSAGE_INFO_AUTH_KEY, {NULL}, MAVLINK_MESSAGE_INFO_ACTION_ACK, MAVLINK_MESSAGE_INFO_ACTION, MAVLINK_MESSAGE_INFO_SET_MODE, MAVLINK_MESSAGE_INFO_SET_NAV_MODE, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, MAVLINK_MESSAGE_INFO_PARAM_REQUEST_READ, MAVLINK_MESSAGE_INFO_PARAM_REQUEST_LIST, MAVLINK_MESSAGE_INFO_PARAM_VALUE, MAVLINK_MESSAGE_INFO_PARAM_SET, {NULL}, MAVLINK_MESSAGE_INFO_GPS_RAW_INT, MAVLINK_MESSAGE_INFO_SCALED_IMU, MAVLINK_MESSAGE_INFO_GPS_STATUS, MAVLINK_MESSAGE_INFO_RAW_IMU, MAVLINK_MESSAGE_INFO_RAW_PRESSURE, MAVLINK_MESSAGE_INFO_ATTITUDE, MAVLINK_MESSAGE_INFO_LOCAL_POSITION, MAVLINK_MESSAGE_INFO_GPS_RAW, MAVLINK_MESSAGE_INFO_GLOBAL_POSITION, MAVLINK_MESSAGE_INFO_SYS_STATUS, MAVLINK_MESSAGE_INFO_RC_CHANNELS_RAW, MAVLINK_MESSAGE_INFO_RC_CHANNELS_SCALED, MAVLINK_MESSAGE_INFO_SERVO_OUTPUT_RAW, MAVLINK_MESSAGE_INFO_SCALED_PRESSURE, MAVLINK_MESSAGE_INFO_WAYPOINT, MAVLINK_MESSAGE_INFO_WAYPOINT_REQUEST, MAVLINK_MESSAGE_INFO_WAYPOINT_SET_CURRENT, MAVLINK_MESSAGE_INFO_WAYPOINT_CURRENT, MAVLINK_MESSAGE_INFO_WAYPOINT_REQUEST_LIST, MAVLINK_MESSAGE_INFO_WAYPOINT_COUNT, MAVLINK_MESSAGE_INFO_WAYPOINT_CLEAR_ALL, MAVLINK_MESSAGE_INFO_WAYPOINT_REACHED, MAVLINK_MESSAGE_INFO_WAYPOINT_ACK, MAVLINK_MESSAGE_INFO_GPS_SET_GLOBAL_ORIGIN, MAVLINK_MESSAGE_INFO_GPS_LOCAL_ORIGIN_SET, MAVLINK_MESSAGE_INFO_LOCAL_POSITION_SETPOINT_SET, MAVLINK_MESSAGE_INFO_LOCAL_POSITION_SETPOINT, MAVLINK_MESSAGE_INFO_CONTROL_STATUS, MAVLINK_MESSAGE_INFO_SAFETY_SET_ALLOWED_AREA, MAVLINK_MESSAGE_INFO_SAFETY_ALLOWED_AREA, MAVLINK_MESSAGE_INFO_SET_ROLL_PITCH_YAW_THRUST, MAVLINK_MESSAGE_INFO_SET_ROLL_PITCH_YAW_SPEED_THRUST, MAVLINK_MESSAGE_INFO_ROLL_PITCH_YAW_THRUST_SETPOINT, MAVLINK_MESSAGE_INFO_ROLL_PITCH_YAW_SPEED_THRUST_SETPOINT, {NULL}, {NULL}, {NULL}, MAVLINK_MESSAGE_INFO_NAV_CONTROLLER_OUTPUT, MAVLINK_MESSAGE_INFO_POSITION_TARGET, MAVLINK_MESSAGE_INFO_STATE_CORRECTION, MAVLINK_MESSAGE_INFO_SET_ALTITUDE, MAVLINK_MESSAGE_INFO_REQUEST_DATA_STREAM, MAVLINK_MESSAGE_INFO_HIL_STATE, MAVLINK_MESSAGE_INFO_HIL_CONTROLS, MAVLINK_MESSAGE_INFO_MANUAL_CONTROL, MAVLINK_MESSAGE_INFO_RC_CHANNELS_OVERRIDE, {NULL}, {NULL}, MAVLINK_MESSAGE_INFO_GLOBAL_POSITION_INT, MAVLINK_MESSAGE_INFO_VFR_HUD, MAVLINK_MESSAGE_INFO_COMMAND, MAVLINK_MESSAGE_INFO_COMMAND_ACK, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, MAVLINK_MESSAGE_INFO_OPTICAL_FLOW, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, MAVLINK_MESSAGE_INFO_OBJECT_DETECTION_EVENT, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, MAVLINK_MESSAGE_INFO_SENSOR_OFFSETS, MAVLINK_MESSAGE_INFO_SET_MAG_OFFSETS, MAVLINK_MESSAGE_INFO_MEMINFO, MAVLINK_MESSAGE_INFO_AP_ADC, MAVLINK_MESSAGE_INFO_DIGICAM_CONFIGURE, MAVLINK_MESSAGE_INFO_DIGICAM_CONTROL, MAVLINK_MESSAGE_INFO_MOUNT_CONFIGURE, MAVLINK_MESSAGE_INFO_MOUNT_CONTROL, MAVLINK_MESSAGE_INFO_MOUNT_STATUS, {NULL}, MAVLINK_MESSAGE_INFO_FENCE_POINT, MAVLINK_MESSAGE_INFO_FENCE_FETCH_POINT, MAVLINK_MESSAGE_INFO_FENCE_STATUS, MAVLINK_MESSAGE_INFO_DCM, MAVLINK_MESSAGE_INFO_SIMSTATE, MAVLINK_MESSAGE_INFO_HWSTATUS, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, MAVLINK_MESSAGE_INFO_DEBUG_VECT, MAVLINK_MESSAGE_INFO_NAMED_VALUE_FLOAT, MAVLINK_MESSAGE_INFO_NAMED_VALUE_INT, MAVLINK_MESSAGE_INFO_STATUSTEXT, MAVLINK_MESSAGE_INFO_DEBUG} #endif #include "../protocol.h" @@ -143,6 +143,9 @@ enum FENCE_BREACH #include "./mavlink_msg_fence_point.h" #include "./mavlink_msg_fence_fetch_point.h" #include "./mavlink_msg_fence_status.h" +#include "./mavlink_msg_dcm.h" +#include "./mavlink_msg_simstate.h" +#include "./mavlink_msg_hwstatus.h" #ifdef __cplusplus } diff --git a/libraries/GCS_MAVLink/include/ardupilotmega/mavlink_msg_dcm.h b/libraries/GCS_MAVLink/include/ardupilotmega/mavlink_msg_dcm.h new file mode 100644 index 0000000000..60b89c1afd --- /dev/null +++ b/libraries/GCS_MAVLink/include/ardupilotmega/mavlink_msg_dcm.h @@ -0,0 +1,276 @@ +// MESSAGE DCM PACKING + +#define MAVLINK_MSG_ID_DCM 163 + +typedef struct __mavlink_dcm_t +{ + float omegaIx; ///< X gyro drift estimate rad/s + float omegaIy; ///< Y gyro drift estimate rad/s + float omegaIz; ///< Z gyro drift estimate rad/s + float accel_weight; ///< average accel_weight + float renorm_val; ///< average renormalisation value + float error_rp; ///< average error_roll_pitch value + float error_yaw; ///< average error_yaw value +} mavlink_dcm_t; + +#define MAVLINK_MSG_ID_DCM_LEN 28 +#define MAVLINK_MSG_ID_163_LEN 28 + + + +#define MAVLINK_MESSAGE_INFO_DCM { \ + "DCM", \ + 7, \ + { { "omegaIx", NULL, MAVLINK_TYPE_FLOAT, 0, 0, offsetof(mavlink_dcm_t, omegaIx) }, \ + { "omegaIy", NULL, MAVLINK_TYPE_FLOAT, 0, 4, offsetof(mavlink_dcm_t, omegaIy) }, \ + { "omegaIz", NULL, MAVLINK_TYPE_FLOAT, 0, 8, offsetof(mavlink_dcm_t, omegaIz) }, \ + { "accel_weight", NULL, MAVLINK_TYPE_FLOAT, 0, 12, offsetof(mavlink_dcm_t, accel_weight) }, \ + { "renorm_val", NULL, MAVLINK_TYPE_FLOAT, 0, 16, offsetof(mavlink_dcm_t, renorm_val) }, \ + { "error_rp", NULL, MAVLINK_TYPE_FLOAT, 0, 20, offsetof(mavlink_dcm_t, error_rp) }, \ + { "error_yaw", NULL, MAVLINK_TYPE_FLOAT, 0, 24, offsetof(mavlink_dcm_t, error_yaw) }, \ + } \ +} + + +/** + * @brief Pack a dcm message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param omegaIx X gyro drift estimate rad/s + * @param omegaIy Y gyro drift estimate rad/s + * @param omegaIz Z gyro drift estimate rad/s + * @param accel_weight average accel_weight + * @param renorm_val average renormalisation value + * @param error_rp average error_roll_pitch value + * @param error_yaw average error_yaw value + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_dcm_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + float omegaIx, float omegaIy, float omegaIz, float accel_weight, float renorm_val, float error_rp, float error_yaw) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[28]; + _mav_put_float(buf, 0, omegaIx); + _mav_put_float(buf, 4, omegaIy); + _mav_put_float(buf, 8, omegaIz); + _mav_put_float(buf, 12, accel_weight); + _mav_put_float(buf, 16, renorm_val); + _mav_put_float(buf, 20, error_rp); + _mav_put_float(buf, 24, error_yaw); + + memcpy(_MAV_PAYLOAD(msg), buf, 28); +#else + mavlink_dcm_t packet; + packet.omegaIx = omegaIx; + packet.omegaIy = omegaIy; + packet.omegaIz = omegaIz; + packet.accel_weight = accel_weight; + packet.renorm_val = renorm_val; + packet.error_rp = error_rp; + packet.error_yaw = error_yaw; + + memcpy(_MAV_PAYLOAD(msg), &packet, 28); +#endif + + msg->msgid = MAVLINK_MSG_ID_DCM; + return mavlink_finalize_message(msg, system_id, component_id, 28); +} + +/** + * @brief Pack a dcm message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param omegaIx X gyro drift estimate rad/s + * @param omegaIy Y gyro drift estimate rad/s + * @param omegaIz Z gyro drift estimate rad/s + * @param accel_weight average accel_weight + * @param renorm_val average renormalisation value + * @param error_rp average error_roll_pitch value + * @param error_yaw average error_yaw value + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_dcm_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + float omegaIx,float omegaIy,float omegaIz,float accel_weight,float renorm_val,float error_rp,float error_yaw) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[28]; + _mav_put_float(buf, 0, omegaIx); + _mav_put_float(buf, 4, omegaIy); + _mav_put_float(buf, 8, omegaIz); + _mav_put_float(buf, 12, accel_weight); + _mav_put_float(buf, 16, renorm_val); + _mav_put_float(buf, 20, error_rp); + _mav_put_float(buf, 24, error_yaw); + + memcpy(_MAV_PAYLOAD(msg), buf, 28); +#else + mavlink_dcm_t packet; + packet.omegaIx = omegaIx; + packet.omegaIy = omegaIy; + packet.omegaIz = omegaIz; + packet.accel_weight = accel_weight; + packet.renorm_val = renorm_val; + packet.error_rp = error_rp; + packet.error_yaw = error_yaw; + + memcpy(_MAV_PAYLOAD(msg), &packet, 28); +#endif + + msg->msgid = MAVLINK_MSG_ID_DCM; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 28); +} + +/** + * @brief Encode a dcm struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param dcm C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_dcm_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_dcm_t* dcm) +{ + return mavlink_msg_dcm_pack(system_id, component_id, msg, dcm->omegaIx, dcm->omegaIy, dcm->omegaIz, dcm->accel_weight, dcm->renorm_val, dcm->error_rp, dcm->error_yaw); +} + +/** + * @brief Send a dcm message + * @param chan MAVLink channel to send the message + * + * @param omegaIx X gyro drift estimate rad/s + * @param omegaIy Y gyro drift estimate rad/s + * @param omegaIz Z gyro drift estimate rad/s + * @param accel_weight average accel_weight + * @param renorm_val average renormalisation value + * @param error_rp average error_roll_pitch value + * @param error_yaw average error_yaw value + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_dcm_send(mavlink_channel_t chan, float omegaIx, float omegaIy, float omegaIz, float accel_weight, float renorm_val, float error_rp, float error_yaw) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[28]; + _mav_put_float(buf, 0, omegaIx); + _mav_put_float(buf, 4, omegaIy); + _mav_put_float(buf, 8, omegaIz); + _mav_put_float(buf, 12, accel_weight); + _mav_put_float(buf, 16, renorm_val); + _mav_put_float(buf, 20, error_rp); + _mav_put_float(buf, 24, error_yaw); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_DCM, buf, 28); +#else + mavlink_dcm_t packet; + packet.omegaIx = omegaIx; + packet.omegaIy = omegaIy; + packet.omegaIz = omegaIz; + packet.accel_weight = accel_weight; + packet.renorm_val = renorm_val; + packet.error_rp = error_rp; + packet.error_yaw = error_yaw; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_DCM, (const char *)&packet, 28); +#endif +} + +#endif + +// MESSAGE DCM UNPACKING + + +/** + * @brief Get field omegaIx from dcm message + * + * @return X gyro drift estimate rad/s + */ +static inline float mavlink_msg_dcm_get_omegaIx(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 0); +} + +/** + * @brief Get field omegaIy from dcm message + * + * @return Y gyro drift estimate rad/s + */ +static inline float mavlink_msg_dcm_get_omegaIy(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 4); +} + +/** + * @brief Get field omegaIz from dcm message + * + * @return Z gyro drift estimate rad/s + */ +static inline float mavlink_msg_dcm_get_omegaIz(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 8); +} + +/** + * @brief Get field accel_weight from dcm message + * + * @return average accel_weight + */ +static inline float mavlink_msg_dcm_get_accel_weight(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 12); +} + +/** + * @brief Get field renorm_val from dcm message + * + * @return average renormalisation value + */ +static inline float mavlink_msg_dcm_get_renorm_val(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 16); +} + +/** + * @brief Get field error_rp from dcm message + * + * @return average error_roll_pitch value + */ +static inline float mavlink_msg_dcm_get_error_rp(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 20); +} + +/** + * @brief Get field error_yaw from dcm message + * + * @return average error_yaw value + */ +static inline float mavlink_msg_dcm_get_error_yaw(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 24); +} + +/** + * @brief Decode a dcm message into a struct + * + * @param msg The message to decode + * @param dcm C-struct to decode the message contents into + */ +static inline void mavlink_msg_dcm_decode(const mavlink_message_t* msg, mavlink_dcm_t* dcm) +{ +#if MAVLINK_NEED_BYTE_SWAP + dcm->omegaIx = mavlink_msg_dcm_get_omegaIx(msg); + dcm->omegaIy = mavlink_msg_dcm_get_omegaIy(msg); + dcm->omegaIz = mavlink_msg_dcm_get_omegaIz(msg); + dcm->accel_weight = mavlink_msg_dcm_get_accel_weight(msg); + dcm->renorm_val = mavlink_msg_dcm_get_renorm_val(msg); + dcm->error_rp = mavlink_msg_dcm_get_error_rp(msg); + dcm->error_yaw = mavlink_msg_dcm_get_error_yaw(msg); +#else + memcpy(dcm, _MAV_PAYLOAD(msg), 28); +#endif +} diff --git a/libraries/GCS_MAVLink/include/ardupilotmega/mavlink_msg_hwstatus.h b/libraries/GCS_MAVLink/include/ardupilotmega/mavlink_msg_hwstatus.h new file mode 100644 index 0000000000..20fca8139c --- /dev/null +++ b/libraries/GCS_MAVLink/include/ardupilotmega/mavlink_msg_hwstatus.h @@ -0,0 +1,166 @@ +// MESSAGE HWSTATUS PACKING + +#define MAVLINK_MSG_ID_HWSTATUS 165 + +typedef struct __mavlink_hwstatus_t +{ + uint16_t Vcc; ///< board voltage (mV) + uint8_t I2Cerr; ///< I2C error count +} mavlink_hwstatus_t; + +#define MAVLINK_MSG_ID_HWSTATUS_LEN 3 +#define MAVLINK_MSG_ID_165_LEN 3 + + + +#define MAVLINK_MESSAGE_INFO_HWSTATUS { \ + "HWSTATUS", \ + 2, \ + { { "Vcc", NULL, MAVLINK_TYPE_UINT16_T, 0, 0, offsetof(mavlink_hwstatus_t, Vcc) }, \ + { "I2Cerr", NULL, MAVLINK_TYPE_UINT8_T, 0, 2, offsetof(mavlink_hwstatus_t, I2Cerr) }, \ + } \ +} + + +/** + * @brief Pack a hwstatus message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param Vcc board voltage (mV) + * @param I2Cerr I2C error count + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_hwstatus_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint16_t Vcc, uint8_t I2Cerr) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[3]; + _mav_put_uint16_t(buf, 0, Vcc); + _mav_put_uint8_t(buf, 2, I2Cerr); + + memcpy(_MAV_PAYLOAD(msg), buf, 3); +#else + mavlink_hwstatus_t packet; + packet.Vcc = Vcc; + packet.I2Cerr = I2Cerr; + + memcpy(_MAV_PAYLOAD(msg), &packet, 3); +#endif + + msg->msgid = MAVLINK_MSG_ID_HWSTATUS; + return mavlink_finalize_message(msg, system_id, component_id, 3); +} + +/** + * @brief Pack a hwstatus message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param Vcc board voltage (mV) + * @param I2Cerr I2C error count + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_hwstatus_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint16_t Vcc,uint8_t I2Cerr) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[3]; + _mav_put_uint16_t(buf, 0, Vcc); + _mav_put_uint8_t(buf, 2, I2Cerr); + + memcpy(_MAV_PAYLOAD(msg), buf, 3); +#else + mavlink_hwstatus_t packet; + packet.Vcc = Vcc; + packet.I2Cerr = I2Cerr; + + memcpy(_MAV_PAYLOAD(msg), &packet, 3); +#endif + + msg->msgid = MAVLINK_MSG_ID_HWSTATUS; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 3); +} + +/** + * @brief Encode a hwstatus struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param hwstatus C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_hwstatus_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_hwstatus_t* hwstatus) +{ + return mavlink_msg_hwstatus_pack(system_id, component_id, msg, hwstatus->Vcc, hwstatus->I2Cerr); +} + +/** + * @brief Send a hwstatus message + * @param chan MAVLink channel to send the message + * + * @param Vcc board voltage (mV) + * @param I2Cerr I2C error count + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_hwstatus_send(mavlink_channel_t chan, uint16_t Vcc, uint8_t I2Cerr) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[3]; + _mav_put_uint16_t(buf, 0, Vcc); + _mav_put_uint8_t(buf, 2, I2Cerr); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_HWSTATUS, buf, 3); +#else + mavlink_hwstatus_t packet; + packet.Vcc = Vcc; + packet.I2Cerr = I2Cerr; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_HWSTATUS, (const char *)&packet, 3); +#endif +} + +#endif + +// MESSAGE HWSTATUS UNPACKING + + +/** + * @brief Get field Vcc from hwstatus message + * + * @return board voltage (mV) + */ +static inline uint16_t mavlink_msg_hwstatus_get_Vcc(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 0); +} + +/** + * @brief Get field I2Cerr from hwstatus message + * + * @return I2C error count + */ +static inline uint8_t mavlink_msg_hwstatus_get_I2Cerr(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 2); +} + +/** + * @brief Decode a hwstatus message into a struct + * + * @param msg The message to decode + * @param hwstatus C-struct to decode the message contents into + */ +static inline void mavlink_msg_hwstatus_decode(const mavlink_message_t* msg, mavlink_hwstatus_t* hwstatus) +{ +#if MAVLINK_NEED_BYTE_SWAP + hwstatus->Vcc = mavlink_msg_hwstatus_get_Vcc(msg); + hwstatus->I2Cerr = mavlink_msg_hwstatus_get_I2Cerr(msg); +#else + memcpy(hwstatus, _MAV_PAYLOAD(msg), 3); +#endif +} diff --git a/libraries/GCS_MAVLink/include/ardupilotmega/mavlink_msg_simstate.h b/libraries/GCS_MAVLink/include/ardupilotmega/mavlink_msg_simstate.h new file mode 100644 index 0000000000..4d487c99b5 --- /dev/null +++ b/libraries/GCS_MAVLink/include/ardupilotmega/mavlink_msg_simstate.h @@ -0,0 +1,320 @@ +// MESSAGE SIMSTATE PACKING + +#define MAVLINK_MSG_ID_SIMSTATE 164 + +typedef struct __mavlink_simstate_t +{ + float roll; ///< Roll angle (rad) + float pitch; ///< Pitch angle (rad) + float yaw; ///< Yaw angle (rad) + float xacc; ///< X acceleration m/s/s + float yacc; ///< Y acceleration m/s/s + float zacc; ///< Z acceleration m/s/s + float xgyro; ///< Angular speed around X axis rad/s + float ygyro; ///< Angular speed around Y axis rad/s + float zgyro; ///< Angular speed around Z axis rad/s +} mavlink_simstate_t; + +#define MAVLINK_MSG_ID_SIMSTATE_LEN 36 +#define MAVLINK_MSG_ID_164_LEN 36 + + + +#define MAVLINK_MESSAGE_INFO_SIMSTATE { \ + "SIMSTATE", \ + 9, \ + { { "roll", NULL, MAVLINK_TYPE_FLOAT, 0, 0, offsetof(mavlink_simstate_t, roll) }, \ + { "pitch", NULL, MAVLINK_TYPE_FLOAT, 0, 4, offsetof(mavlink_simstate_t, pitch) }, \ + { "yaw", NULL, MAVLINK_TYPE_FLOAT, 0, 8, offsetof(mavlink_simstate_t, yaw) }, \ + { "xacc", NULL, MAVLINK_TYPE_FLOAT, 0, 12, offsetof(mavlink_simstate_t, xacc) }, \ + { "yacc", NULL, MAVLINK_TYPE_FLOAT, 0, 16, offsetof(mavlink_simstate_t, yacc) }, \ + { "zacc", NULL, MAVLINK_TYPE_FLOAT, 0, 20, offsetof(mavlink_simstate_t, zacc) }, \ + { "xgyro", NULL, MAVLINK_TYPE_FLOAT, 0, 24, offsetof(mavlink_simstate_t, xgyro) }, \ + { "ygyro", NULL, MAVLINK_TYPE_FLOAT, 0, 28, offsetof(mavlink_simstate_t, ygyro) }, \ + { "zgyro", NULL, MAVLINK_TYPE_FLOAT, 0, 32, offsetof(mavlink_simstate_t, zgyro) }, \ + } \ +} + + +/** + * @brief Pack a simstate message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param roll Roll angle (rad) + * @param pitch Pitch angle (rad) + * @param yaw Yaw angle (rad) + * @param xacc X acceleration m/s/s + * @param yacc Y acceleration m/s/s + * @param zacc Z acceleration m/s/s + * @param xgyro Angular speed around X axis rad/s + * @param ygyro Angular speed around Y axis rad/s + * @param zgyro Angular speed around Z axis rad/s + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_simstate_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + float roll, float pitch, float yaw, float xacc, float yacc, float zacc, float xgyro, float ygyro, float zgyro) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[36]; + _mav_put_float(buf, 0, roll); + _mav_put_float(buf, 4, pitch); + _mav_put_float(buf, 8, yaw); + _mav_put_float(buf, 12, xacc); + _mav_put_float(buf, 16, yacc); + _mav_put_float(buf, 20, zacc); + _mav_put_float(buf, 24, xgyro); + _mav_put_float(buf, 28, ygyro); + _mav_put_float(buf, 32, zgyro); + + memcpy(_MAV_PAYLOAD(msg), buf, 36); +#else + mavlink_simstate_t packet; + packet.roll = roll; + packet.pitch = pitch; + packet.yaw = yaw; + packet.xacc = xacc; + packet.yacc = yacc; + packet.zacc = zacc; + packet.xgyro = xgyro; + packet.ygyro = ygyro; + packet.zgyro = zgyro; + + memcpy(_MAV_PAYLOAD(msg), &packet, 36); +#endif + + msg->msgid = MAVLINK_MSG_ID_SIMSTATE; + return mavlink_finalize_message(msg, system_id, component_id, 36); +} + +/** + * @brief Pack a simstate message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param roll Roll angle (rad) + * @param pitch Pitch angle (rad) + * @param yaw Yaw angle (rad) + * @param xacc X acceleration m/s/s + * @param yacc Y acceleration m/s/s + * @param zacc Z acceleration m/s/s + * @param xgyro Angular speed around X axis rad/s + * @param ygyro Angular speed around Y axis rad/s + * @param zgyro Angular speed around Z axis rad/s + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_simstate_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + float roll,float pitch,float yaw,float xacc,float yacc,float zacc,float xgyro,float ygyro,float zgyro) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[36]; + _mav_put_float(buf, 0, roll); + _mav_put_float(buf, 4, pitch); + _mav_put_float(buf, 8, yaw); + _mav_put_float(buf, 12, xacc); + _mav_put_float(buf, 16, yacc); + _mav_put_float(buf, 20, zacc); + _mav_put_float(buf, 24, xgyro); + _mav_put_float(buf, 28, ygyro); + _mav_put_float(buf, 32, zgyro); + + memcpy(_MAV_PAYLOAD(msg), buf, 36); +#else + mavlink_simstate_t packet; + packet.roll = roll; + packet.pitch = pitch; + packet.yaw = yaw; + packet.xacc = xacc; + packet.yacc = yacc; + packet.zacc = zacc; + packet.xgyro = xgyro; + packet.ygyro = ygyro; + packet.zgyro = zgyro; + + memcpy(_MAV_PAYLOAD(msg), &packet, 36); +#endif + + msg->msgid = MAVLINK_MSG_ID_SIMSTATE; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 36); +} + +/** + * @brief Encode a simstate struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param simstate C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_simstate_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_simstate_t* simstate) +{ + return mavlink_msg_simstate_pack(system_id, component_id, msg, simstate->roll, simstate->pitch, simstate->yaw, simstate->xacc, simstate->yacc, simstate->zacc, simstate->xgyro, simstate->ygyro, simstate->zgyro); +} + +/** + * @brief Send a simstate message + * @param chan MAVLink channel to send the message + * + * @param roll Roll angle (rad) + * @param pitch Pitch angle (rad) + * @param yaw Yaw angle (rad) + * @param xacc X acceleration m/s/s + * @param yacc Y acceleration m/s/s + * @param zacc Z acceleration m/s/s + * @param xgyro Angular speed around X axis rad/s + * @param ygyro Angular speed around Y axis rad/s + * @param zgyro Angular speed around Z axis rad/s + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_simstate_send(mavlink_channel_t chan, float roll, float pitch, float yaw, float xacc, float yacc, float zacc, float xgyro, float ygyro, float zgyro) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[36]; + _mav_put_float(buf, 0, roll); + _mav_put_float(buf, 4, pitch); + _mav_put_float(buf, 8, yaw); + _mav_put_float(buf, 12, xacc); + _mav_put_float(buf, 16, yacc); + _mav_put_float(buf, 20, zacc); + _mav_put_float(buf, 24, xgyro); + _mav_put_float(buf, 28, ygyro); + _mav_put_float(buf, 32, zgyro); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_SIMSTATE, buf, 36); +#else + mavlink_simstate_t packet; + packet.roll = roll; + packet.pitch = pitch; + packet.yaw = yaw; + packet.xacc = xacc; + packet.yacc = yacc; + packet.zacc = zacc; + packet.xgyro = xgyro; + packet.ygyro = ygyro; + packet.zgyro = zgyro; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_SIMSTATE, (const char *)&packet, 36); +#endif +} + +#endif + +// MESSAGE SIMSTATE UNPACKING + + +/** + * @brief Get field roll from simstate message + * + * @return Roll angle (rad) + */ +static inline float mavlink_msg_simstate_get_roll(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 0); +} + +/** + * @brief Get field pitch from simstate message + * + * @return Pitch angle (rad) + */ +static inline float mavlink_msg_simstate_get_pitch(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 4); +} + +/** + * @brief Get field yaw from simstate message + * + * @return Yaw angle (rad) + */ +static inline float mavlink_msg_simstate_get_yaw(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 8); +} + +/** + * @brief Get field xacc from simstate message + * + * @return X acceleration m/s/s + */ +static inline float mavlink_msg_simstate_get_xacc(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 12); +} + +/** + * @brief Get field yacc from simstate message + * + * @return Y acceleration m/s/s + */ +static inline float mavlink_msg_simstate_get_yacc(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 16); +} + +/** + * @brief Get field zacc from simstate message + * + * @return Z acceleration m/s/s + */ +static inline float mavlink_msg_simstate_get_zacc(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 20); +} + +/** + * @brief Get field xgyro from simstate message + * + * @return Angular speed around X axis rad/s + */ +static inline float mavlink_msg_simstate_get_xgyro(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 24); +} + +/** + * @brief Get field ygyro from simstate message + * + * @return Angular speed around Y axis rad/s + */ +static inline float mavlink_msg_simstate_get_ygyro(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 28); +} + +/** + * @brief Get field zgyro from simstate message + * + * @return Angular speed around Z axis rad/s + */ +static inline float mavlink_msg_simstate_get_zgyro(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 32); +} + +/** + * @brief Decode a simstate message into a struct + * + * @param msg The message to decode + * @param simstate C-struct to decode the message contents into + */ +static inline void mavlink_msg_simstate_decode(const mavlink_message_t* msg, mavlink_simstate_t* simstate) +{ +#if MAVLINK_NEED_BYTE_SWAP + simstate->roll = mavlink_msg_simstate_get_roll(msg); + simstate->pitch = mavlink_msg_simstate_get_pitch(msg); + simstate->yaw = mavlink_msg_simstate_get_yaw(msg); + simstate->xacc = mavlink_msg_simstate_get_xacc(msg); + simstate->yacc = mavlink_msg_simstate_get_yacc(msg); + simstate->zacc = mavlink_msg_simstate_get_zacc(msg); + simstate->xgyro = mavlink_msg_simstate_get_xgyro(msg); + simstate->ygyro = mavlink_msg_simstate_get_ygyro(msg); + simstate->zgyro = mavlink_msg_simstate_get_zgyro(msg); +#else + memcpy(simstate, _MAV_PAYLOAD(msg), 36); +#endif +} diff --git a/libraries/GCS_MAVLink/include/ardupilotmega/testsuite.h b/libraries/GCS_MAVLink/include/ardupilotmega/testsuite.h index 7e91d71da4..957bd99ca5 100644 --- a/libraries/GCS_MAVLink/include/ardupilotmega/testsuite.h +++ b/libraries/GCS_MAVLink/include/ardupilotmega/testsuite.h @@ -668,6 +668,165 @@ static void mavlink_test_fence_status(uint8_t system_id, uint8_t component_id, m MAVLINK_ASSERT(memcmp(&packet1, &packet2, sizeof(packet1)) == 0); } +static void mavlink_test_dcm(uint8_t system_id, uint8_t component_id, mavlink_message_t *last_msg) +{ + mavlink_message_t msg; + uint8_t buffer[MAVLINK_MAX_PACKET_LEN]; + uint16_t i; + mavlink_dcm_t packet_in = { + 17.0, + 45.0, + 73.0, + 101.0, + 129.0, + 157.0, + 185.0, + }; + mavlink_dcm_t packet1, packet2; + memset(&packet1, 0, sizeof(packet1)); + packet1.omegaIx = packet_in.omegaIx; + packet1.omegaIy = packet_in.omegaIy; + packet1.omegaIz = packet_in.omegaIz; + packet1.accel_weight = packet_in.accel_weight; + packet1.renorm_val = packet_in.renorm_val; + packet1.error_rp = packet_in.error_rp; + packet1.error_yaw = packet_in.error_yaw; + + + + memset(&packet2, 0, sizeof(packet2)); + mavlink_msg_dcm_encode(system_id, component_id, &msg, &packet1); + mavlink_msg_dcm_decode(&msg, &packet2); + MAVLINK_ASSERT(memcmp(&packet1, &packet2, sizeof(packet1)) == 0); + + memset(&packet2, 0, sizeof(packet2)); + mavlink_msg_dcm_pack(system_id, component_id, &msg , packet1.omegaIx , packet1.omegaIy , packet1.omegaIz , packet1.accel_weight , packet1.renorm_val , packet1.error_rp , packet1.error_yaw ); + mavlink_msg_dcm_decode(&msg, &packet2); + MAVLINK_ASSERT(memcmp(&packet1, &packet2, sizeof(packet1)) == 0); + + memset(&packet2, 0, sizeof(packet2)); + mavlink_msg_dcm_pack_chan(system_id, component_id, MAVLINK_COMM_0, &msg , packet1.omegaIx , packet1.omegaIy , packet1.omegaIz , packet1.accel_weight , packet1.renorm_val , packet1.error_rp , packet1.error_yaw ); + mavlink_msg_dcm_decode(&msg, &packet2); + MAVLINK_ASSERT(memcmp(&packet1, &packet2, sizeof(packet1)) == 0); + + memset(&packet2, 0, sizeof(packet2)); + mavlink_msg_to_send_buffer(buffer, &msg); + for (i=0; imsgid = MAVLINK_MSG_ID_DCM; + return mavlink_finalize_message(msg, system_id, component_id, 28, 205); +} + +/** + * @brief Pack a dcm message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param omegaIx X gyro drift estimate rad/s + * @param omegaIy Y gyro drift estimate rad/s + * @param omegaIz Z gyro drift estimate rad/s + * @param accel_weight average accel_weight + * @param renorm_val average renormalisation value + * @param error_rp average error_roll_pitch value + * @param error_yaw average error_yaw value + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_dcm_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + float omegaIx,float omegaIy,float omegaIz,float accel_weight,float renorm_val,float error_rp,float error_yaw) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[28]; + _mav_put_float(buf, 0, omegaIx); + _mav_put_float(buf, 4, omegaIy); + _mav_put_float(buf, 8, omegaIz); + _mav_put_float(buf, 12, accel_weight); + _mav_put_float(buf, 16, renorm_val); + _mav_put_float(buf, 20, error_rp); + _mav_put_float(buf, 24, error_yaw); + + memcpy(_MAV_PAYLOAD(msg), buf, 28); +#else + mavlink_dcm_t packet; + packet.omegaIx = omegaIx; + packet.omegaIy = omegaIy; + packet.omegaIz = omegaIz; + packet.accel_weight = accel_weight; + packet.renorm_val = renorm_val; + packet.error_rp = error_rp; + packet.error_yaw = error_yaw; + + memcpy(_MAV_PAYLOAD(msg), &packet, 28); +#endif + + msg->msgid = MAVLINK_MSG_ID_DCM; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 28, 205); +} + +/** + * @brief Encode a dcm struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param dcm C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_dcm_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_dcm_t* dcm) +{ + return mavlink_msg_dcm_pack(system_id, component_id, msg, dcm->omegaIx, dcm->omegaIy, dcm->omegaIz, dcm->accel_weight, dcm->renorm_val, dcm->error_rp, dcm->error_yaw); +} + +/** + * @brief Send a dcm message + * @param chan MAVLink channel to send the message + * + * @param omegaIx X gyro drift estimate rad/s + * @param omegaIy Y gyro drift estimate rad/s + * @param omegaIz Z gyro drift estimate rad/s + * @param accel_weight average accel_weight + * @param renorm_val average renormalisation value + * @param error_rp average error_roll_pitch value + * @param error_yaw average error_yaw value + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_dcm_send(mavlink_channel_t chan, float omegaIx, float omegaIy, float omegaIz, float accel_weight, float renorm_val, float error_rp, float error_yaw) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[28]; + _mav_put_float(buf, 0, omegaIx); + _mav_put_float(buf, 4, omegaIy); + _mav_put_float(buf, 8, omegaIz); + _mav_put_float(buf, 12, accel_weight); + _mav_put_float(buf, 16, renorm_val); + _mav_put_float(buf, 20, error_rp); + _mav_put_float(buf, 24, error_yaw); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_DCM, buf, 28, 205); +#else + mavlink_dcm_t packet; + packet.omegaIx = omegaIx; + packet.omegaIy = omegaIy; + packet.omegaIz = omegaIz; + packet.accel_weight = accel_weight; + packet.renorm_val = renorm_val; + packet.error_rp = error_rp; + packet.error_yaw = error_yaw; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_DCM, (const char *)&packet, 28, 205); +#endif +} + +#endif + +// MESSAGE DCM UNPACKING + + +/** + * @brief Get field omegaIx from dcm message + * + * @return X gyro drift estimate rad/s + */ +static inline float mavlink_msg_dcm_get_omegaIx(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 0); +} + +/** + * @brief Get field omegaIy from dcm message + * + * @return Y gyro drift estimate rad/s + */ +static inline float mavlink_msg_dcm_get_omegaIy(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 4); +} + +/** + * @brief Get field omegaIz from dcm message + * + * @return Z gyro drift estimate rad/s + */ +static inline float mavlink_msg_dcm_get_omegaIz(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 8); +} + +/** + * @brief Get field accel_weight from dcm message + * + * @return average accel_weight + */ +static inline float mavlink_msg_dcm_get_accel_weight(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 12); +} + +/** + * @brief Get field renorm_val from dcm message + * + * @return average renormalisation value + */ +static inline float mavlink_msg_dcm_get_renorm_val(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 16); +} + +/** + * @brief Get field error_rp from dcm message + * + * @return average error_roll_pitch value + */ +static inline float mavlink_msg_dcm_get_error_rp(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 20); +} + +/** + * @brief Get field error_yaw from dcm message + * + * @return average error_yaw value + */ +static inline float mavlink_msg_dcm_get_error_yaw(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 24); +} + +/** + * @brief Decode a dcm message into a struct + * + * @param msg The message to decode + * @param dcm C-struct to decode the message contents into + */ +static inline void mavlink_msg_dcm_decode(const mavlink_message_t* msg, mavlink_dcm_t* dcm) +{ +#if MAVLINK_NEED_BYTE_SWAP + dcm->omegaIx = mavlink_msg_dcm_get_omegaIx(msg); + dcm->omegaIy = mavlink_msg_dcm_get_omegaIy(msg); + dcm->omegaIz = mavlink_msg_dcm_get_omegaIz(msg); + dcm->accel_weight = mavlink_msg_dcm_get_accel_weight(msg); + dcm->renorm_val = mavlink_msg_dcm_get_renorm_val(msg); + dcm->error_rp = mavlink_msg_dcm_get_error_rp(msg); + dcm->error_yaw = mavlink_msg_dcm_get_error_yaw(msg); +#else + memcpy(dcm, _MAV_PAYLOAD(msg), 28); +#endif +} diff --git a/libraries/GCS_MAVLink/include_v1.0/ardupilotmega/mavlink_msg_simstate.h b/libraries/GCS_MAVLink/include_v1.0/ardupilotmega/mavlink_msg_simstate.h new file mode 100644 index 0000000000..aa7e6edfaf --- /dev/null +++ b/libraries/GCS_MAVLink/include_v1.0/ardupilotmega/mavlink_msg_simstate.h @@ -0,0 +1,320 @@ +// MESSAGE SIMSTATE PACKING + +#define MAVLINK_MSG_ID_SIMSTATE 164 + +typedef struct __mavlink_simstate_t +{ + float roll; ///< Roll angle (rad) + float pitch; ///< Pitch angle (rad) + float yaw; ///< Yaw angle (rad) + float xacc; ///< X acceleration m/s/s + float yacc; ///< Y acceleration m/s/s + float zacc; ///< Z acceleration m/s/s + float xgyro; ///< Angular speed around X axis rad/s + float ygyro; ///< Angular speed around Y axis rad/s + float zgyro; ///< Angular speed around Z axis rad/s +} mavlink_simstate_t; + +#define MAVLINK_MSG_ID_SIMSTATE_LEN 36 +#define MAVLINK_MSG_ID_164_LEN 36 + + + +#define MAVLINK_MESSAGE_INFO_SIMSTATE { \ + "SIMSTATE", \ + 9, \ + { { "roll", NULL, MAVLINK_TYPE_FLOAT, 0, 0, offsetof(mavlink_simstate_t, roll) }, \ + { "pitch", NULL, MAVLINK_TYPE_FLOAT, 0, 4, offsetof(mavlink_simstate_t, pitch) }, \ + { "yaw", NULL, MAVLINK_TYPE_FLOAT, 0, 8, offsetof(mavlink_simstate_t, yaw) }, \ + { "xacc", NULL, MAVLINK_TYPE_FLOAT, 0, 12, offsetof(mavlink_simstate_t, xacc) }, \ + { "yacc", NULL, MAVLINK_TYPE_FLOAT, 0, 16, offsetof(mavlink_simstate_t, yacc) }, \ + { "zacc", NULL, MAVLINK_TYPE_FLOAT, 0, 20, offsetof(mavlink_simstate_t, zacc) }, \ + { "xgyro", NULL, MAVLINK_TYPE_FLOAT, 0, 24, offsetof(mavlink_simstate_t, xgyro) }, \ + { "ygyro", NULL, MAVLINK_TYPE_FLOAT, 0, 28, offsetof(mavlink_simstate_t, ygyro) }, \ + { "zgyro", NULL, MAVLINK_TYPE_FLOAT, 0, 32, offsetof(mavlink_simstate_t, zgyro) }, \ + } \ +} + + +/** + * @brief Pack a simstate message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param roll Roll angle (rad) + * @param pitch Pitch angle (rad) + * @param yaw Yaw angle (rad) + * @param xacc X acceleration m/s/s + * @param yacc Y acceleration m/s/s + * @param zacc Z acceleration m/s/s + * @param xgyro Angular speed around X axis rad/s + * @param ygyro Angular speed around Y axis rad/s + * @param zgyro Angular speed around Z axis rad/s + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_simstate_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + float roll, float pitch, float yaw, float xacc, float yacc, float zacc, float xgyro, float ygyro, float zgyro) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[36]; + _mav_put_float(buf, 0, roll); + _mav_put_float(buf, 4, pitch); + _mav_put_float(buf, 8, yaw); + _mav_put_float(buf, 12, xacc); + _mav_put_float(buf, 16, yacc); + _mav_put_float(buf, 20, zacc); + _mav_put_float(buf, 24, xgyro); + _mav_put_float(buf, 28, ygyro); + _mav_put_float(buf, 32, zgyro); + + memcpy(_MAV_PAYLOAD(msg), buf, 36); +#else + mavlink_simstate_t packet; + packet.roll = roll; + packet.pitch = pitch; + packet.yaw = yaw; + packet.xacc = xacc; + packet.yacc = yacc; + packet.zacc = zacc; + packet.xgyro = xgyro; + packet.ygyro = ygyro; + packet.zgyro = zgyro; + + memcpy(_MAV_PAYLOAD(msg), &packet, 36); +#endif + + msg->msgid = MAVLINK_MSG_ID_SIMSTATE; + return mavlink_finalize_message(msg, system_id, component_id, 36, 42); +} + +/** + * @brief Pack a simstate message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param roll Roll angle (rad) + * @param pitch Pitch angle (rad) + * @param yaw Yaw angle (rad) + * @param xacc X acceleration m/s/s + * @param yacc Y acceleration m/s/s + * @param zacc Z acceleration m/s/s + * @param xgyro Angular speed around X axis rad/s + * @param ygyro Angular speed around Y axis rad/s + * @param zgyro Angular speed around Z axis rad/s + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_simstate_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + float roll,float pitch,float yaw,float xacc,float yacc,float zacc,float xgyro,float ygyro,float zgyro) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[36]; + _mav_put_float(buf, 0, roll); + _mav_put_float(buf, 4, pitch); + _mav_put_float(buf, 8, yaw); + _mav_put_float(buf, 12, xacc); + _mav_put_float(buf, 16, yacc); + _mav_put_float(buf, 20, zacc); + _mav_put_float(buf, 24, xgyro); + _mav_put_float(buf, 28, ygyro); + _mav_put_float(buf, 32, zgyro); + + memcpy(_MAV_PAYLOAD(msg), buf, 36); +#else + mavlink_simstate_t packet; + packet.roll = roll; + packet.pitch = pitch; + packet.yaw = yaw; + packet.xacc = xacc; + packet.yacc = yacc; + packet.zacc = zacc; + packet.xgyro = xgyro; + packet.ygyro = ygyro; + packet.zgyro = zgyro; + + memcpy(_MAV_PAYLOAD(msg), &packet, 36); +#endif + + msg->msgid = MAVLINK_MSG_ID_SIMSTATE; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 36, 42); +} + +/** + * @brief Encode a simstate struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param simstate C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_simstate_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_simstate_t* simstate) +{ + return mavlink_msg_simstate_pack(system_id, component_id, msg, simstate->roll, simstate->pitch, simstate->yaw, simstate->xacc, simstate->yacc, simstate->zacc, simstate->xgyro, simstate->ygyro, simstate->zgyro); +} + +/** + * @brief Send a simstate message + * @param chan MAVLink channel to send the message + * + * @param roll Roll angle (rad) + * @param pitch Pitch angle (rad) + * @param yaw Yaw angle (rad) + * @param xacc X acceleration m/s/s + * @param yacc Y acceleration m/s/s + * @param zacc Z acceleration m/s/s + * @param xgyro Angular speed around X axis rad/s + * @param ygyro Angular speed around Y axis rad/s + * @param zgyro Angular speed around Z axis rad/s + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_simstate_send(mavlink_channel_t chan, float roll, float pitch, float yaw, float xacc, float yacc, float zacc, float xgyro, float ygyro, float zgyro) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[36]; + _mav_put_float(buf, 0, roll); + _mav_put_float(buf, 4, pitch); + _mav_put_float(buf, 8, yaw); + _mav_put_float(buf, 12, xacc); + _mav_put_float(buf, 16, yacc); + _mav_put_float(buf, 20, zacc); + _mav_put_float(buf, 24, xgyro); + _mav_put_float(buf, 28, ygyro); + _mav_put_float(buf, 32, zgyro); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_SIMSTATE, buf, 36, 42); +#else + mavlink_simstate_t packet; + packet.roll = roll; + packet.pitch = pitch; + packet.yaw = yaw; + packet.xacc = xacc; + packet.yacc = yacc; + packet.zacc = zacc; + packet.xgyro = xgyro; + packet.ygyro = ygyro; + packet.zgyro = zgyro; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_SIMSTATE, (const char *)&packet, 36, 42); +#endif +} + +#endif + +// MESSAGE SIMSTATE UNPACKING + + +/** + * @brief Get field roll from simstate message + * + * @return Roll angle (rad) + */ +static inline float mavlink_msg_simstate_get_roll(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 0); +} + +/** + * @brief Get field pitch from simstate message + * + * @return Pitch angle (rad) + */ +static inline float mavlink_msg_simstate_get_pitch(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 4); +} + +/** + * @brief Get field yaw from simstate message + * + * @return Yaw angle (rad) + */ +static inline float mavlink_msg_simstate_get_yaw(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 8); +} + +/** + * @brief Get field xacc from simstate message + * + * @return X acceleration m/s/s + */ +static inline float mavlink_msg_simstate_get_xacc(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 12); +} + +/** + * @brief Get field yacc from simstate message + * + * @return Y acceleration m/s/s + */ +static inline float mavlink_msg_simstate_get_yacc(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 16); +} + +/** + * @brief Get field zacc from simstate message + * + * @return Z acceleration m/s/s + */ +static inline float mavlink_msg_simstate_get_zacc(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 20); +} + +/** + * @brief Get field xgyro from simstate message + * + * @return Angular speed around X axis rad/s + */ +static inline float mavlink_msg_simstate_get_xgyro(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 24); +} + +/** + * @brief Get field ygyro from simstate message + * + * @return Angular speed around Y axis rad/s + */ +static inline float mavlink_msg_simstate_get_ygyro(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 28); +} + +/** + * @brief Get field zgyro from simstate message + * + * @return Angular speed around Z axis rad/s + */ +static inline float mavlink_msg_simstate_get_zgyro(const mavlink_message_t* msg) +{ + return _MAV_RETURN_float(msg, 32); +} + +/** + * @brief Decode a simstate message into a struct + * + * @param msg The message to decode + * @param simstate C-struct to decode the message contents into + */ +static inline void mavlink_msg_simstate_decode(const mavlink_message_t* msg, mavlink_simstate_t* simstate) +{ +#if MAVLINK_NEED_BYTE_SWAP + simstate->roll = mavlink_msg_simstate_get_roll(msg); + simstate->pitch = mavlink_msg_simstate_get_pitch(msg); + simstate->yaw = mavlink_msg_simstate_get_yaw(msg); + simstate->xacc = mavlink_msg_simstate_get_xacc(msg); + simstate->yacc = mavlink_msg_simstate_get_yacc(msg); + simstate->zacc = mavlink_msg_simstate_get_zacc(msg); + simstate->xgyro = mavlink_msg_simstate_get_xgyro(msg); + simstate->ygyro = mavlink_msg_simstate_get_ygyro(msg); + simstate->zgyro = mavlink_msg_simstate_get_zgyro(msg); +#else + memcpy(simstate, _MAV_PAYLOAD(msg), 36); +#endif +} diff --git a/libraries/GCS_MAVLink/include_v1.0/ardupilotmega/testsuite.h b/libraries/GCS_MAVLink/include_v1.0/ardupilotmega/testsuite.h index c372c91a1a..d7ce12505c 100644 --- a/libraries/GCS_MAVLink/include_v1.0/ardupilotmega/testsuite.h +++ b/libraries/GCS_MAVLink/include_v1.0/ardupilotmega/testsuite.h @@ -668,6 +668,120 @@ static void mavlink_test_fence_status(uint8_t system_id, uint8_t component_id, m MAVLINK_ASSERT(memcmp(&packet1, &packet2, sizeof(packet1)) == 0); } +static void mavlink_test_dcm(uint8_t system_id, uint8_t component_id, mavlink_message_t *last_msg) +{ + mavlink_message_t msg; + uint8_t buffer[MAVLINK_MAX_PACKET_LEN]; + uint16_t i; + mavlink_dcm_t packet_in = { + 17.0, + 45.0, + 73.0, + 101.0, + 129.0, + 157.0, + 185.0, + }; + mavlink_dcm_t packet1, packet2; + memset(&packet1, 0, sizeof(packet1)); + packet1.omegaIx = packet_in.omegaIx; + packet1.omegaIy = packet_in.omegaIy; + packet1.omegaIz = packet_in.omegaIz; + packet1.accel_weight = packet_in.accel_weight; + packet1.renorm_val = packet_in.renorm_val; + packet1.error_rp = packet_in.error_rp; + packet1.error_yaw = packet_in.error_yaw; + + + + memset(&packet2, 0, sizeof(packet2)); + mavlink_msg_dcm_encode(system_id, component_id, &msg, &packet1); + mavlink_msg_dcm_decode(&msg, &packet2); + MAVLINK_ASSERT(memcmp(&packet1, &packet2, sizeof(packet1)) == 0); + + memset(&packet2, 0, sizeof(packet2)); + mavlink_msg_dcm_pack(system_id, component_id, &msg , packet1.omegaIx , packet1.omegaIy , packet1.omegaIz , packet1.accel_weight , packet1.renorm_val , packet1.error_rp , packet1.error_yaw ); + mavlink_msg_dcm_decode(&msg, &packet2); + MAVLINK_ASSERT(memcmp(&packet1, &packet2, sizeof(packet1)) == 0); + + memset(&packet2, 0, sizeof(packet2)); + mavlink_msg_dcm_pack_chan(system_id, component_id, MAVLINK_COMM_0, &msg , packet1.omegaIx , packet1.omegaIy , packet1.omegaIz , packet1.accel_weight , packet1.renorm_val , packet1.error_rp , packet1.error_yaw ); + mavlink_msg_dcm_decode(&msg, &packet2); + MAVLINK_ASSERT(memcmp(&packet1, &packet2, sizeof(packet1)) == 0); + + memset(&packet2, 0, sizeof(packet2)); + mavlink_msg_to_send_buffer(buffer, &msg); + for (i=0; i0: unlock focus or keep unlocked, 1: lock focus or keep locked, 3: re-lock focus 0: ignore, 1: shot or start filming Command Identity (incremental loop: 0 to 255)//A command sent multiple times will be executed or pooled just once - Extra parameters enumeration (0 means ignore) + Extra parameters enumeration (0 means ignore) Correspondent value to given extra_param @@ -225,5 +225,35 @@ last breach type (see FENCE_BREACH_* enum) time of last breach in milliseconds since boot + + + Status of DCM attitude estimator + X gyro drift estimate rad/s + Y gyro drift estimate rad/s + Z gyro drift estimate rad/s + average accel_weight + average renormalisation value + average error_roll_pitch value + average error_yaw value + + + + Status of simulation environment, if used + Roll angle (rad) + Pitch angle (rad) + Yaw angle (rad) + X acceleration m/s/s + Y acceleration m/s/s + Z acceleration m/s/s + Angular speed around X axis rad/s + Angular speed around Y axis rad/s + Angular speed around Z axis rad/s + + + + Status of key hardware + board voltage (mV) + I2C error count + diff --git a/libraries/GCS_MAVLink/message_definitions_v1.0/ardupilotmega.xml b/libraries/GCS_MAVLink/message_definitions_v1.0/ardupilotmega.xml index 3a71c6c7cf..24841ebc93 100644 --- a/libraries/GCS_MAVLink/message_definitions_v1.0/ardupilotmega.xml +++ b/libraries/GCS_MAVLink/message_definitions_v1.0/ardupilotmega.xml @@ -225,5 +225,29 @@ last breach type (see FENCE_BREACH_* enum) time of last breach in milliseconds since boot + + + Status of DCM attitude estimator + X gyro drift estimate rad/s + Y gyro drift estimate rad/s + Z gyro drift estimate rad/s + average accel_weight + average renormalisation value + average error_roll_pitch value + average error_yaw value + + + + Status of simulation environment, if used + Roll angle (rad) + Pitch angle (rad) + Yaw angle (rad) + X acceleration m/s/s + Y acceleration m/s/s + Z acceleration m/s/s + Angular speed around X axis rad/s + Angular speed around Y axis rad/s + Angular speed around Z axis rad/s + From 772c30ba865a1891ac522a8a3ca1e95bd669c87c Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 1 Mar 2012 15:22:11 +1100 Subject: [PATCH 020/178] SITL: added sitl_simstate_send() used to report simulator state in logs --- libraries/Desktop/support/desktop.h | 2 ++ libraries/Desktop/support/sitl.cpp | 23 +++++++++++++++++++++++ libraries/Desktop/support/sitl_adc.cpp | 17 +++-------------- libraries/Desktop/support/util.cpp | 21 +++++++++++++++++++++ libraries/Desktop/support/util.h | 5 +++++ 5 files changed, 54 insertions(+), 14 deletions(-) diff --git a/libraries/Desktop/support/desktop.h b/libraries/Desktop/support/desktop.h index 710980599e..8ff6756ddf 100644 --- a/libraries/Desktop/support/desktop.h +++ b/libraries/Desktop/support/desktop.h @@ -30,4 +30,6 @@ void sitl_update_adc(float roll, float pitch, float yaw, void sitl_setup_adc(void); void sitl_update_barometer(float altitude); +void sitl_simstate_send(uint8_t chan); + #endif diff --git a/libraries/Desktop/support/sitl.cpp b/libraries/Desktop/support/sitl.cpp index 5e6ecfdbae..cb67d441e6 100644 --- a/libraries/Desktop/support/sitl.cpp +++ b/libraries/Desktop/support/sitl.cpp @@ -25,6 +25,7 @@ #include #include #include +#include #include "sitl_adc.h" #include "sitl_rc.h" #include "desktop.h" @@ -302,3 +303,25 @@ void sitl_setup(void) sitl_update_compass(0, 0, 0, 0); sitl_update_gps(0, 0, 0, 0, 0, false); } + + +/* report SITL state via MAVLink */ +void sitl_simstate_send(uint8_t chan) +{ + double p, q, r; + + // we want the gyro values to be directly comparable to the + // raw_imu message, which is in body frame + convert_body_frame(sim_state.rollDeg, sim_state.pitchDeg, + sim_state.rollRate, sim_state.pitchRate, sim_state.yawRate, + &p, &q, &r); + + mavlink_msg_simstate_send((mavlink_channel_t)chan, + ToRad(sim_state.rollDeg), + ToRad(sim_state.pitchDeg), + ToRad(sim_state.yawDeg), + sim_state.xAccel, + sim_state.yAccel, + sim_state.zAccel, + p, q, r); +} diff --git a/libraries/Desktop/support/sitl_adc.cpp b/libraries/Desktop/support/sitl_adc.cpp index 63e44c2111..05fdaab4d1 100644 --- a/libraries/Desktop/support/sitl_adc.cpp +++ b/libraries/Desktop/support/sitl_adc.cpp @@ -68,27 +68,16 @@ void sitl_update_adc(float roll, float pitch, float yaw, // Relative to earth static const float _sensor_signs[6] = { 1, -1, -1, 1, -1, -1 }; const float accel_offset = 2041; const float gyro_offset = 1658; -#define ToRad(x) (x*0.01745329252) // *pi/180 const float _gyro_gain_x = ToRad(0.4); const float _gyro_gain_y = ToRad(0.41); const float _gyro_gain_z = ToRad(0.41); const float _accel_scale = 9.80665 / 423.8; double adc[7]; - double phi, theta, phiDot, thetaDot, psiDot; double p, q, r; - /* convert the angular velocities from earth frame to - body frame. Thanks to James Goppert for the formula - */ - phi = ToRad(roll); - theta = ToRad(pitch); - phiDot = ToRad(rollRate); - thetaDot = ToRad(pitchRate); - psiDot = ToRad(yawRate); - - p = phiDot - psiDot*sin(theta); - q = cos(phi)*thetaDot + sin(phi)*psiDot*cos(theta); - r = cos(phi)*psiDot*cos(theta) - sin(phi)*thetaDot; + convert_body_frame(roll, pitch, + rollRate, pitchRate, yawRate, + &p, &q, &r); /* work out the ADC channel values */ adc[0] = (p / (_gyro_gain_x * _sensor_signs[0])) + gyro_offset; diff --git a/libraries/Desktop/support/util.cpp b/libraries/Desktop/support/util.cpp index 6232f00aac..7656d36bf1 100644 --- a/libraries/Desktop/support/util.cpp +++ b/libraries/Desktop/support/util.cpp @@ -14,6 +14,7 @@ #include #include #include "desktop.h" +#include "util.h" void set_nonblocking(int fd) @@ -37,3 +38,23 @@ double normalise180(double v) { return normalise(v, -180, 180); } + +/* convert the angular velocities from earth frame to + body frame. Thanks to James Goppert for the formula +*/ +void convert_body_frame(double rollDeg, double pitchDeg, + double rollRate, double pitchRate, double yawRate, + double *p, double *q, double *r) +{ + double phi, theta, phiDot, thetaDot, psiDot; + + phi = ToRad(rollDeg); + theta = ToRad(pitchDeg); + phiDot = ToRad(rollRate); + thetaDot = ToRad(pitchRate); + psiDot = ToRad(yawRate); + + *p = phiDot - psiDot*sin(theta); + *q = cos(phi)*thetaDot + sin(phi)*psiDot*cos(theta); + *r = cos(phi)*psiDot*cos(theta) - sin(phi)*thetaDot; +} diff --git a/libraries/Desktop/support/util.h b/libraries/Desktop/support/util.h index 3cfc729292..7d55f827c6 100644 --- a/libraries/Desktop/support/util.h +++ b/libraries/Desktop/support/util.h @@ -2,8 +2,13 @@ #define ft2m(x) ((x) * 0.3048) #define kt2mps(x) ((x) * 0.514444444) #define sqr(x) ((x)*(x)) +#define ToRad(x) (x*0.01745329252) // *pi/180 void set_nonblocking(int fd); double normalise(double v, double min, double max); double normalise180(double v); void runInterrupt(uint8_t inum); + +void convert_body_frame(double rollDeg, double pitchDeg, + double rollRate, double pitchRate, double yawRate, + double *p, double *q, double *r); From 94d0236b97b62d339b93e137cbbb21d11f3f15e7 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 1 Mar 2012 15:22:39 +1100 Subject: [PATCH 021/178] DCM: added reporting interfaces for DCM state --- libraries/AP_DCM/AP_DCM.cpp | 72 ++++++++++++++++++++++++++++++++++++- libraries/AP_DCM/AP_DCM.h | 16 +++++++++ 2 files changed, 87 insertions(+), 1 deletion(-) diff --git a/libraries/AP_DCM/AP_DCM.cpp b/libraries/AP_DCM/AP_DCM.cpp index bce0f1292d..d338e7577c 100644 --- a/libraries/AP_DCM/AP_DCM.cpp +++ b/libraries/AP_DCM/AP_DCM.cpp @@ -328,6 +328,10 @@ AP_DCM::renorm(Vector3f const &a, int &problem) renorm_val = 1.0 / sqrt(a * a); + // keep the average for reporting + _renorm_val_sum += renorm_val; + _renorm_val_count++; + if (!(renorm_val < 2.0 && renorm_val > 0.5)) { // this is larger than it should get - log it as a warning renorm_range_count++; @@ -360,6 +364,8 @@ AP_DCM::drift_correction(void) float accel_weight; float integrator_magnitude; Vector3f error; + float error_norm; + //static float scaled_omega_P[3]; //static float scaled_omega_I[3]; @@ -380,7 +386,6 @@ AP_DCM::drift_correction(void) // error_roll_pitch are in Accel m/s^2 units // Limit max error_roll_pitch to limit max omega_P and omega_I - float error_norm; error_norm = error.length(); if (error_norm > 2) { error *= (2 / error_norm); @@ -389,6 +394,12 @@ AP_DCM::drift_correction(void) _omega_P = error * (_kp_roll_pitch * accel_weight); _omega_I += error * (_ki_roll_pitch * accel_weight); + // these sums support the reporting of the DCM state via MAVLink + _accel_weight_sum += accel_weight; + _accel_weight_count++; + _error_rp_sum += error_norm; + _error_rp_count++; + //*****YAW*************** @@ -463,6 +474,10 @@ AP_DCM::drift_correction(void) if (integrator_magnitude > radians(30)) { _omega_I *= (radians(30) / integrator_magnitude); } + + _error_yaw_sum += error_course; + _error_yaw_count++; + //Serial.print("*"); } @@ -507,3 +522,58 @@ AP_DCM::euler_yaw(void) if (yaw_sensor < 0) yaw_sensor += 36000; } + + +/* reporting of DCM state for MAVLink */ + +// average accel_weight since last call +float AP_DCM::get_accel_weight(void) +{ + float ret; + if (_accel_weight_count == 0) { + return 0; + } + ret = _accel_weight_sum / _accel_weight_count; + _accel_weight_sum = 0; + _accel_weight_count = 0; + return ret; +} + +// average renorm_val since last call +float AP_DCM::get_renorm_val(void) +{ + float ret; + if (_renorm_val_count == 0) { + return 0; + } + ret = _renorm_val_sum / _renorm_val_count; + _renorm_val_sum = 0; + _renorm_val_count = 0; + return ret; +} + +// average error_roll_pitch since last call +float AP_DCM::get_error_rp(void) +{ + float ret; + if (_error_rp_count == 0) { + return 0; + } + ret = _error_rp_sum / _error_rp_count; + _error_rp_sum = 0; + _error_rp_count = 0; + return ret; +} + +// average error_yaw since last call +float AP_DCM::get_error_yaw(void) +{ + float ret; + if (_error_yaw_count == 0) { + return 0; + } + ret = _error_yaw_sum / _error_yaw_count; + _error_yaw_sum = 0; + _error_yaw_count = 0; + return ret; +} diff --git a/libraries/AP_DCM/AP_DCM.h b/libraries/AP_DCM/AP_DCM.h index 3e9946d604..adcb331901 100644 --- a/libraries/AP_DCM/AP_DCM.h +++ b/libraries/AP_DCM/AP_DCM.h @@ -86,6 +86,11 @@ public: static const float kDCM_kp_rp_low = 0.01; int8_t _clamp; + // status reporting + float get_accel_weight(void); + float get_renorm_val(void); + float get_error_rp(void); + float get_error_yaw(void); private: float _kp_roll_pitch; @@ -129,6 +134,17 @@ private: float _health; bool _centripetal; uint8_t _toggle; + + // state to support status reporting + float _accel_weight_sum; + uint16_t _accel_weight_count; + float _renorm_val_sum; + uint16_t _renorm_val_count; + float _error_rp_sum; + uint16_t _error_rp_count; + float _error_yaw_sum; + uint16_t _error_yaw_count; + }; #endif From b455443e2c5c0ff4896b1dbd281bab6127e6d4b8 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 1 Mar 2012 15:23:00 +1100 Subject: [PATCH 022/178] APM: added logging of DCM, HWSTATUS and SIMSTATE --- ArduPlane/GCS_Mavlink.pde | 59 ++++++++++++++++++++++++++++++++++++++- ArduPlane/defines.h | 3 ++ 2 files changed, 61 insertions(+), 1 deletion(-) diff --git a/ArduPlane/GCS_Mavlink.pde b/ArduPlane/GCS_Mavlink.pde index 312144a886..a2e8a40cb4 100644 --- a/ArduPlane/GCS_Mavlink.pde +++ b/ArduPlane/GCS_Mavlink.pde @@ -485,8 +485,42 @@ static void NOINLINE send_raw_imu3(mavlink_channel_t chan) imu.gx(), imu.gy(), imu.gz(), imu.ax(), imu.ay(), imu.az()); } + +static void NOINLINE send_dcm(mavlink_channel_t chan) +{ + Vector3f omega_I = dcm.get_integrator(); + mavlink_msg_dcm_send( + chan, + omega_I.x, + omega_I.y, + omega_I.z, + dcm.get_accel_weight(), + dcm.get_renorm_val(), + dcm.get_error_rp(), + dcm.get_error_yaw()); +} + #endif // HIL_MODE != HIL_MODE_ATTITUDE +#ifdef DESKTOP_BUILD +// report simulator state +static void NOINLINE send_simstate(mavlink_channel_t chan) +{ + extern void sitl_simstate_send(uint8_t chan); + sitl_simstate_send((uint8_t)chan); +} +#endif + +#ifndef DESKTOP_BUILD +static void NOINLINE send_hwstatus(mavlink_channel_t chan) +{ + mavlink_msg_hwstatus_send( + chan, + board_voltage(), + I2c.lockup_count()); +} +#endif + static void NOINLINE send_gps_status(mavlink_channel_t chan) { mavlink_msg_gps_status_send( @@ -645,6 +679,27 @@ static bool mavlink_try_send_message(mavlink_channel_t chan, enum ap_message id, break; #endif + case MSG_DCM: +#if HIL_MODE != HIL_MODE_ATTITUDE + CHECK_PAYLOAD_SIZE(DCM); + send_dcm(chan); +#endif + break; + + case MSG_SIMSTATE: +#ifdef DESKTOP_BUILD + CHECK_PAYLOAD_SIZE(DCM); + send_simstate(chan); +#endif + break; + + case MSG_HWSTATUS: +#ifndef DESKTOP_BUILD + CHECK_PAYLOAD_SIZE(HWSTATUS); + send_hwstatus(chan); +#endif + break; + case MSG_RETRY_DEFERRED: break; // just here to prevent a warning } @@ -869,6 +924,7 @@ GCS_MAVLINK::data_stream_send(uint16_t freqMin, uint16_t freqMax) if (freqLoopMatch(streamRateExtra1, freqMin, freqMax)){ // Use Extra 1 for AHRS info send_message(MSG_ATTITUDE); + send_message(MSG_SIMSTATE); } if (freqLoopMatch(streamRateExtra2, freqMin, freqMax)){ // Use Extra 2 for additional HIL info @@ -876,7 +932,8 @@ GCS_MAVLINK::data_stream_send(uint16_t freqMin, uint16_t freqMax) } if (freqLoopMatch(streamRateExtra3, freqMin, freqMax)){ - // Available datastream + send_message(MSG_DCM); + send_message(MSG_HWSTATUS); } } } diff --git a/ArduPlane/defines.h b/ArduPlane/defines.h index a5ac6e85a1..8161638686 100644 --- a/ArduPlane/defines.h +++ b/ArduPlane/defines.h @@ -123,6 +123,9 @@ enum ap_message { MSG_NEXT_PARAM, MSG_STATUSTEXT, MSG_FENCE_STATUS, + MSG_DCM, + MSG_SIMSTATE, + MSG_HWSTATUS, MSG_RETRY_DEFERRED // this must be last }; From 4031320f7ca634ea107c576ecfe89d3a5e4f60a0 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 1 Mar 2012 22:52:47 +1100 Subject: [PATCH 023/178] DCM: added a small amount of gyro and accel smoothing possibly not needed, but convenient to be able to test with different values --- libraries/AP_DCM/AP_DCM.cpp | 25 +++++++++++++++++-------- libraries/AP_DCM/AP_DCM.h | 2 ++ 2 files changed, 19 insertions(+), 8 deletions(-) diff --git a/libraries/AP_DCM/AP_DCM.cpp b/libraries/AP_DCM/AP_DCM.cpp index d338e7577c..ac53ca4dfd 100644 --- a/libraries/AP_DCM/AP_DCM.cpp +++ b/libraries/AP_DCM/AP_DCM.cpp @@ -51,10 +51,13 @@ void AP_DCM::update_DCM_fast(void) { float delta_t; + Vector3f accel; _imu->update(); _gyro_vector = _imu->get_gyro(); // Get current values for IMU sensors - _accel_vector = _imu->get_accel(); // Get current values for IMU sensors + + accel = _imu->get_accel(); + _accel_vector = (_accel_vector * 0.0) + (accel * 1.0); delta_t = _imu->get_delta_time(); @@ -96,10 +99,13 @@ void AP_DCM::update_DCM(void) { float delta_t; + Vector3f accel; _imu->update(); _gyro_vector = _imu->get_gyro(); // Get current values for IMU sensors - _accel_vector = _imu->get_accel(); // Get current values for IMU sensors + + accel = _imu->get_accel(); + _accel_vector = (_accel_vector * 0.5) + (accel * 0.5); delta_t = _imu->get_delta_time(); @@ -133,7 +139,8 @@ AP_DCM::matrix_update(float _G_Dt) Matrix3f temp_matrix; _omega_integ_corr = _gyro_vector + _omega_I; // Used for _centripetal correction (theoretically better than _omega) - _omega = _omega_integ_corr + _omega_P; // Equation 16, adding proportional and integral correction terms + _omega = _omega_integ_corr + _omega_P; // Equation 16, adding proportional and integral correction terms + _omega_smoothed = (_omega_smoothed * 0.5) + (_omega_integ_corr * 0.5); if(_centripetal && _gps != NULL && @@ -179,16 +186,17 @@ AP_DCM::matrix_update(float _G_Dt) void AP_DCM::accel_adjust(void) { - Vector3f veloc, temp; + Vector3f temp; + float veloc; - veloc.x = _gps->ground_speed / 100; // We are working with acceleration in m/s^2 units + veloc = _gps->ground_speed / 100; // We are working with acceleration in m/s^2 units // We are working with a modified version of equation 26 as our IMU object reports acceleration in the positive axis direction as positive - //_accel_vector -= _omega_integ_corr % _veloc; // Equation 26 This line is giving the compiler a problem so we break it up below + // _accel_vector -= _omega_integ_corr % veloc; // Equation 26 This line is giving the compiler a problem so we break it up below temp.x = 0; - temp.y = _omega_integ_corr.z * veloc.x; // only computing the non-zero terms - temp.z = -1.0f * _omega_integ_corr.y * veloc.x; // After looking at the compiler issue lets remove _veloc and simlify + temp.y = _omega_smoothed.z * veloc; // only computing the non-zero terms + temp.z = _omega_smoothed.y * (-veloc); // After looking at the compiler issue lets remove _veloc and simlify _accel_vector -= temp; } @@ -210,6 +218,7 @@ AP_DCM::matrix_reset(bool recover_eulers) _omega_I.z = 0.0f; _omega_P = _omega_I; _omega_integ_corr = _omega_I; + _omega_smoothed = _omega_I; _omega = _omega_I; // if the caller wants us to try to recover to the current diff --git a/libraries/AP_DCM/AP_DCM.h b/libraries/AP_DCM/AP_DCM.h index adcb331901..5294b8a06c 100644 --- a/libraries/AP_DCM/AP_DCM.h +++ b/libraries/AP_DCM/AP_DCM.h @@ -126,11 +126,13 @@ private: Matrix3f _dcm_matrix; Vector3f _accel_vector; // Store the acceleration in a vector + Vector3f _accel_smoothed; Vector3f _gyro_vector; // Store the gyros turn rate in a vector Vector3f _omega_P; // Omega Proportional correction Vector3f _omega_I; // Omega Integrator correction Vector3f _omega_integ_corr; // Partially corrected Gyro_Vector data - used for centrepetal correction Vector3f _omega; // Corrected Gyro_Vector data + Vector3f _omega_smoothed; float _health; bool _centripetal; uint8_t _toggle; From 3b1782f369d4133894a40792b531415e4cb937ee Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 1 Mar 2012 22:56:42 +1100 Subject: [PATCH 024/178] DCM: don't use the z accel sensor for drift correction the z accel is the noisest, and seems to do more harm than good. Using just x and y is sufficient for drift correction by assuming the vector length --- libraries/AP_DCM/AP_DCM.cpp | 49 +++++++++++++++++++++++-------------- 1 file changed, 31 insertions(+), 18 deletions(-) diff --git a/libraries/AP_DCM/AP_DCM.cpp b/libraries/AP_DCM/AP_DCM.cpp index ac53ca4dfd..d8bbc708e5 100644 --- a/libraries/AP_DCM/AP_DCM.cpp +++ b/libraries/AP_DCM/AP_DCM.cpp @@ -369,40 +369,53 @@ AP_DCM::drift_correction(void) //float mag_heading_x; //float mag_heading_y; float error_course = 0; - float accel_magnitude; float accel_weight; float integrator_magnitude; Vector3f error; float error_norm; + const float gravity_squared = (9.80665*9.80665); //static float scaled_omega_P[3]; //static float scaled_omega_I[3]; //*****Roll and Pitch*************** - // Calculate the magnitude of the accelerometer vector - accel_magnitude = _accel_vector.length() / 9.80665f; + // calculate the z component of the accel vector assuming it + // has a length of 9.8. This discards the z accelerometer + // sensor reading completely. Logs show that the z accel is + // the noisest, and it seems that using just the x and y accel + // values gives a better attitude estimate than including the + // z accel - // Dynamic weighting of accelerometer info (reliability filter) - // Weight for accelerometer info (<0.5G = 0.0, 1G = 1.0 , >1.5G = 0.0) - accel_weight = constrain(1 - _clamp * fabs(1 - accel_magnitude), 0, 1); // upped to (<0.66G = 0.0, 1G = 1.0 , >1.33G = 0.0) + float zsquared = gravity_squared - ((_accel_vector.x * _accel_vector.x) + (_accel_vector.y * _accel_vector.y)); + if (zsquared < 0) { + accel_weight = 0; + } else { + if (_accel_vector.z > 0) { + _accel_vector.z = sqrt(zsquared); + } else { + _accel_vector.z = -sqrt(zsquared); + } - // We monitor the amount that the accelerometer based drift correction is deweighted for performance reporting - _health = constrain(_health+(0.02 * (accel_weight - .5)), 0, 1); + // this is arbitrary, and can be removed once we get + // ki and kp right + accel_weight = 0.6; - // adjust the ground of reference - error = _dcm_matrix.c % _accel_vector; // Equation 27 *** sign changed from prev implementation??? + _health = constrain(_health+(0.02 * (accel_weight - .5)), 0, 1); - // error_roll_pitch are in Accel m/s^2 units - // Limit max error_roll_pitch to limit max omega_P and omega_I - error_norm = error.length(); - if (error_norm > 2) { - error *= (2 / error_norm); + error = _dcm_matrix.c % _accel_vector; + + // error_roll_pitch are in Accel m/s^2 units + // Limit max error_roll_pitch to limit max omega_P and omega_I + error_norm = error.length(); + if (error_norm > 2) { + error *= (2 / error_norm); + } + + _omega_P = error * (_kp_roll_pitch * accel_weight); + _omega_I += error * (_ki_roll_pitch * accel_weight); } - _omega_P = error * (_kp_roll_pitch * accel_weight); - _omega_I += error * (_ki_roll_pitch * accel_weight); - // these sums support the reporting of the DCM state via MAVLink _accel_weight_sum += accel_weight; _accel_weight_count++; From a0ce202d878c2d5f254f67049b4a479e27d3c690 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 1 Mar 2012 23:36:35 +1100 Subject: [PATCH 025/178] ACM: added SIMSTATE, DCM and HWSTATUS messages to ACM --- ArduCopter/GCS_Mavlink.pde | 62 ++++++++++++++++++++++++++++++++++++-- ArduCopter/defines.h | 3 ++ 2 files changed, 63 insertions(+), 2 deletions(-) diff --git a/ArduCopter/GCS_Mavlink.pde b/ArduCopter/GCS_Mavlink.pde index 4a45b181b2..9ac2fd7e07 100644 --- a/ArduCopter/GCS_Mavlink.pde +++ b/ArduCopter/GCS_Mavlink.pde @@ -124,6 +124,42 @@ static void NOINLINE send_nav_controller_output(mavlink_channel_t chan) crosstrack_error); // was 0 } +#if HIL_MODE != HIL_MODE_ATTITUDE +static void NOINLINE send_dcm(mavlink_channel_t chan) +{ + Vector3f omega_I = dcm.get_integrator(); + mavlink_msg_dcm_send( + chan, + omega_I.x, + omega_I.y, + omega_I.z, + dcm.get_accel_weight(), + dcm.get_renorm_val(), + dcm.get_error_rp(), + dcm.get_error_yaw()); +} +#endif // HIL_MODE != HIL_MODE_ATTITUDE + +#ifdef DESKTOP_BUILD +// report simulator state +static void NOINLINE send_simstate(mavlink_channel_t chan) +{ + extern void sitl_simstate_send(uint8_t chan); + sitl_simstate_send((uint8_t)chan); +} +#endif + +#ifndef DESKTOP_BUILD +static void NOINLINE send_hwstatus(mavlink_channel_t chan) +{ + mavlink_msg_hwstatus_send( + chan, + board_voltage(), + I2c.lockup_count()); +} +#endif + + static void NOINLINE send_gps_raw(mavlink_channel_t chan) { mavlink_msg_gps_raw_send( @@ -435,6 +471,27 @@ static bool mavlink_try_send_message(mavlink_channel_t chan, enum ap_message id, send_statustext(chan); break; + case MSG_DCM: +#if HIL_MODE != HIL_MODE_ATTITUDE + CHECK_PAYLOAD_SIZE(DCM); + send_dcm(chan); +#endif + break; + + case MSG_SIMSTATE: +#ifdef DESKTOP_BUILD + CHECK_PAYLOAD_SIZE(DCM); + send_simstate(chan); +#endif + break; + + case MSG_HWSTATUS: +#ifndef DESKTOP_BUILD + CHECK_PAYLOAD_SIZE(HWSTATUS); + send_hwstatus(chan); +#endif + break; + case MSG_RETRY_DEFERRED: break; // just here to prevent a warning } @@ -669,6 +726,7 @@ GCS_MAVLINK::data_stream_send(uint16_t freqMin, uint16_t freqMax) if (freqLoopMatch(streamRateExtra1, freqMin, freqMax)){ // Use Extra 1 for AHRS info send_message(MSG_ATTITUDE); + send_message(MSG_SIMSTATE); //Serial.printf("mav6 %d\n", (int)streamRateExtra1.get()); } @@ -678,8 +736,8 @@ GCS_MAVLINK::data_stream_send(uint16_t freqMin, uint16_t freqMax) } if (freqLoopMatch(streamRateExtra3, freqMin, freqMax)){ - // Available datastream - //Serial.printf("mav8 %d\n", (int)streamRateExtra3.get()); + send_message(MSG_DCM); + send_message(MSG_HWSTATUS); } } } diff --git a/ArduCopter/defines.h b/ArduCopter/defines.h index 3a22e84eb6..906f960d52 100644 --- a/ArduCopter/defines.h +++ b/ArduCopter/defines.h @@ -234,6 +234,9 @@ enum ap_message { MSG_NEXT_WAYPOINT, MSG_NEXT_PARAM, MSG_STATUSTEXT, + MSG_DCM, + MSG_SIMSTATE, + MSG_HWSTATUS, MSG_RETRY_DEFERRED // this must be last }; From 6ba6e11e7b162450db649e95d6e248fb757ad7b4 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 1 Mar 2012 23:37:18 +1100 Subject: [PATCH 026/178] DCM: added a small amount of accel smoothing to update_DCM_fast() --- libraries/AP_DCM/AP_DCM.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/AP_DCM/AP_DCM.cpp b/libraries/AP_DCM/AP_DCM.cpp index d8bbc708e5..d24426b2c7 100644 --- a/libraries/AP_DCM/AP_DCM.cpp +++ b/libraries/AP_DCM/AP_DCM.cpp @@ -57,7 +57,7 @@ AP_DCM::update_DCM_fast(void) _gyro_vector = _imu->get_gyro(); // Get current values for IMU sensors accel = _imu->get_accel(); - _accel_vector = (_accel_vector * 0.0) + (accel * 1.0); + _accel_vector = (_accel_vector * 0.5) + (accel * 0.5); delta_t = _imu->get_delta_time(); From 5e66d3cecbdaed47fe5ea7649b8061ec2628b3fb Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 2 Mar 2012 16:08:45 +1100 Subject: [PATCH 027/178] autotest: added CMAC test circuit this is what I am using for noise testing --- Tools/autotest/CMAC-circuit.txt | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 Tools/autotest/CMAC-circuit.txt diff --git a/Tools/autotest/CMAC-circuit.txt b/Tools/autotest/CMAC-circuit.txt new file mode 100644 index 0000000000..3a2f7a1623 --- /dev/null +++ b/Tools/autotest/CMAC-circuit.txt @@ -0,0 +1,8 @@ +QGC WPL 110 +0 1 0 16 0 0 0 0 -35.362938 149.165085 650.000000 1 +1 0 3 16 0.000000 0.000000 0.000000 0.000000 -35.359586 149.161398 100.000000 1 +2 0 3 16 0.000000 0.000000 0.000000 0.000000 -35.366463 149.162235 100.000000 1 +3 0 3 16 0.000000 0.000000 0.000000 0.000000 -35.366131 149.164581 100.000000 1 +4 0 3 16 0.000000 0.000000 0.000000 0.000000 -35.359272 149.163757 100.000000 1 +5 0 3 177 1.000000 -1.000000 0.000000 0.000000 -1.000000 0.000000 0.000000 1 +6 0 3 16 0.000000 0.000000 0.000000 0.000000 -35.359272 149.163757 100.000000 1 From accc5dc02fd368e916486ca4accb7164f3f42e8f Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 2 Mar 2012 16:09:24 +1100 Subject: [PATCH 028/178] autotest: run fg viewers with less CPU priority --- Tools/autotest/fg_plane_view.sh | 2 +- Tools/autotest/fg_quad_view.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Tools/autotest/fg_plane_view.sh b/Tools/autotest/fg_plane_view.sh index b70c4f5c58..d0f26bb6b3 100755 --- a/Tools/autotest/fg_plane_view.sh +++ b/Tools/autotest/fg_plane_view.sh @@ -2,7 +2,7 @@ AUTOTESTDIR=$(dirname $0) -fgfs \ +nice fgfs \ --native-fdm=socket,in,10,,5503,udp \ --fdm=external \ --aircraft=Rascal110-JSBSim \ diff --git a/Tools/autotest/fg_quad_view.sh b/Tools/autotest/fg_quad_view.sh index 9b1bb0dd9f..530a59f8a5 100755 --- a/Tools/autotest/fg_quad_view.sh +++ b/Tools/autotest/fg_quad_view.sh @@ -2,7 +2,7 @@ AUTOTESTDIR=$(dirname $0) -fgfs \ +nice fgfs \ --native-fdm=socket,in,10,,5503,udp \ --fdm=external \ --aircraft=arducopter \ From 842460992446e08c05c94bf5f403254d81b0b084 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 2 Mar 2012 18:32:25 +1100 Subject: [PATCH 029/178] SITL: push noise level to 2.0 for DCM testing --- libraries/Desktop/support/sitl_adc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/Desktop/support/sitl_adc.h b/libraries/Desktop/support/sitl_adc.h index da6ab87455..e0624bd724 100644 --- a/libraries/Desktop/support/sitl_adc.h +++ b/libraries/Desktop/support/sitl_adc.h @@ -9,7 +9,7 @@ #include #include -static const float vibration_level = 0.1; +static const float vibration_level = 2.0; // order zgyro, xgyro, ygyro, temp, xacc, yacc, zacc, aspd static const float noise_scale[8] = { 150, 150, 150, 0, 400, 400, 400, 0 }; static const float noise_offset[8]= { 0, 0, 0, 0, 0, 0, 0, 0 }; From fe173227de256cf0d1ed9b8778a54c9b77796235 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 3 Mar 2012 11:10:39 +1100 Subject: [PATCH 030/178] DCM_Test: fixed example code to work with SITL this also fixes the compass setup --- .../AP_DCM/examples/DCM_Test/DCM_Test.pde | 58 ++++++++++++++----- libraries/AP_DCM/examples/DCM_Test/Makefile | 3 + 2 files changed, 46 insertions(+), 15 deletions(-) diff --git a/libraries/AP_DCM/examples/DCM_Test/DCM_Test.pde b/libraries/AP_DCM/examples/DCM_Test/DCM_Test.pde index 3f9c6da226..639bc27a2b 100644 --- a/libraries/AP_DCM/examples/DCM_Test/DCM_Test.pde +++ b/libraries/AP_DCM/examples/DCM_Test/DCM_Test.pde @@ -16,6 +16,11 @@ #include #include #include +#include +#include +#include +#include +#include // uncomment this for a APM2 board // #define APM2_HARDWARE @@ -25,7 +30,11 @@ FastSerialPort(Serial, 0); Arduino_Mega_ISR_Registry isr_registry; AP_TimerProcess scheduler; -AP_Compass_HMC5843 compass(AP_Var::k_key_none); +#ifdef DESKTOP_BUILD +AP_Compass_HIL compass; +#else +AP_Compass_HMC5843 compass; +#endif #ifdef APM2_HARDWARE AP_InertialSensor_MPU6000 ins( 53 ); @@ -36,7 +45,9 @@ AP_Compass_HMC5843 compass(AP_Var::k_key_none); static GPS *g_gps; -AP_IMU_INS imu( &ins, AP_Var::k_key_none ); +AP_Baro_BMP085_HIL barometer; + +AP_IMU_INS imu( &ins); AP_DCM dcm(&imu, g_gps); @@ -69,9 +80,11 @@ void setup(void) isr_registry.init(); scheduler.init(&isr_registry); +#ifndef DESKTOP_BUILD I2c.begin(); I2c.timeOut(5); I2c.setSpeed(true); +#endif SPI.begin(); SPI.setClockDivider(SPI_CLOCK_DIV16); @@ -81,7 +94,7 @@ void setup(void) compass.set_orientation(MAG_ORIENTATION); if (compass.init()) { - printf("Enabling compass\n"); + Serial.printf("Enabling compass\n"); compass.null_offsets_enable(); dcm.set_compass(&compass); } @@ -89,22 +102,37 @@ void setup(void) void loop(void) { - Vector3f accel; - Vector3f gyro; - static uint8_t counter; + static uint16_t counter; + static uint32_t last_t, last_print; + uint32_t now = micros(); + float deltat; - delay(20); + if (last_t == 0) { + last_t = now; + return; + } + deltat = (now - last_t) * 1.0e-6; + last_t = now; + compass.read(); + compass.calculate(dcm.get_dcm_matrix()); dcm.update_DCM(); - if (counter++ == 10) { - counter = 0; + delay(20); + counter++; + + if (now - last_print >= 0.5e6) { + Vector3f accel = imu.get_accel(); + Vector3f gyro = imu.get_gyro(); gyro = imu.get_gyro(); accel = imu.get_accel(); - Serial.printf_P(PSTR("r:%4d p:%4d y:%3d g=(%5.1f %5.1f %5.1f) a=(%5.1f %5.1f %5.1f)\n"), - (int)dcm.roll_sensor / 100, - (int)dcm.pitch_sensor / 100, - (uint16_t)dcm.yaw_sensor / 100, - gyro.x, gyro.y, gyro.z, - accel.x, accel.y, accel.z); + Serial.printf_P(PSTR("r:%4d p:%4d y:%3d g=(%5.1f %5.1f %5.1f) a=(%5.1f %5.1f %5.1f) rate=%.1f\n"), + (int)dcm.roll_sensor / 100, + (int)dcm.pitch_sensor / 100, + (uint16_t)dcm.yaw_sensor / 100, + gyro.x, gyro.y, gyro.z, + accel.x, accel.y, accel.z, + (1.0e6*counter)/(now-last_print)); + last_print = now; + counter = 0; } } diff --git a/libraries/AP_DCM/examples/DCM_Test/Makefile b/libraries/AP_DCM/examples/DCM_Test/Makefile index d1f40fd90f..fcdc8ff8fe 100644 --- a/libraries/AP_DCM/examples/DCM_Test/Makefile +++ b/libraries/AP_DCM/examples/DCM_Test/Makefile @@ -1 +1,4 @@ include ../../../AP_Common/Arduino.mk + +sitl: + make -f ../../../../libraries/Desktop/Desktop.mk From ae5117365674030c6bb25269a7eee20e410db751 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 3 Mar 2012 11:11:14 +1100 Subject: [PATCH 031/178] SITL: fixed delay() to account for signal interrupions when a timer went off we stopped the delay() code --- libraries/Desktop/support/Arduino.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/libraries/Desktop/support/Arduino.cpp b/libraries/Desktop/support/Arduino.cpp index ab4caa7d83..78f123577d 100644 --- a/libraries/Desktop/support/Arduino.cpp +++ b/libraries/Desktop/support/Arduino.cpp @@ -59,7 +59,10 @@ long unsigned int micros(void) void delayMicroseconds(unsigned usec) { - usleep(usec); + uint32_t start = micros(); + while (micros() - start < usec) { + usleep(usec - (micros() - start)); + } } void delay(long unsigned msec) From 145fc91701874b79ff65f5b0912ac6b761b26a60 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 3 Mar 2012 11:52:31 +1100 Subject: [PATCH 032/178] AP_Math: added a .zero() method to Vector3f --- libraries/AP_Math/vector3.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libraries/AP_Math/vector3.h b/libraries/AP_Math/vector3.h index caa1ad5398..af999b95be 100644 --- a/libraries/AP_Math/vector3.h +++ b/libraries/AP_Math/vector3.h @@ -145,6 +145,10 @@ public: void normalize() { *this/=length(); } + // zero the vector + void zero() + { x = y = z = 0.0; } + // returns the normalized version of this vector Vector3 normalized() const { return *this/length(); } From b11b571778e85bc1e696029dfcfd1e3807b558a0 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 3 Mar 2012 11:53:31 +1100 Subject: [PATCH 033/178] DCM: fixed the averaging of accel values for update_DCM_fast() this should improve drift correction for ArduCopter --- libraries/AP_DCM/AP_DCM.cpp | 70 +++++++++++++++++-------------------- libraries/AP_DCM/AP_DCM.h | 12 ++++--- 2 files changed, 41 insertions(+), 41 deletions(-) diff --git a/libraries/AP_DCM/AP_DCM.cpp b/libraries/AP_DCM/AP_DCM.cpp index d24426b2c7..6d79b0c3cd 100644 --- a/libraries/AP_DCM/AP_DCM.cpp +++ b/libraries/AP_DCM/AP_DCM.cpp @@ -56,8 +56,11 @@ AP_DCM::update_DCM_fast(void) _imu->update(); _gyro_vector = _imu->get_gyro(); // Get current values for IMU sensors + // add the current accel vector into our averaging filter accel = _imu->get_accel(); - _accel_vector = (_accel_vector * 0.5) + (accel * 0.5); + _accel_sum += accel; + _accel_sum_count++; + delta_t = _imu->get_delta_time(); @@ -69,16 +72,16 @@ AP_DCM::update_DCM_fast(void) break; case 1: - //drift_correction(); // Normalize the DCM matrix euler_rp(); // Calculate pitch, roll, yaw for stabilization and navigation break; case 2: + _accel_vector = _accel_sum / _accel_sum_count; + _accel_sum_count = 0; drift_correction(); // Normalize the DCM matrix break; case 3: - //drift_correction(); // Normalize the DCM matrix euler_rp(); // Calculate pitch, roll, yaw for stabilization and navigation break; @@ -89,7 +92,6 @@ AP_DCM::update_DCM_fast(void) default: euler_rp(); // Calculate pitch, roll, yaw for stabilization and navigation _toggle = 0; - //drift_correction(); // Normalize the DCM matrix break; } } @@ -104,8 +106,10 @@ AP_DCM::update_DCM(void) _imu->update(); _gyro_vector = _imu->get_gyro(); // Get current values for IMU sensors + // update_DCM() doesn't do averaging over the accel vectors, + // just a mild lowpass filter accel = _imu->get_accel(); - _accel_vector = (_accel_vector * 0.5) + (accel * 0.5); + _accel_vector = (accel * 0.5) + (_accel_vector * 0.5); delta_t = _imu->get_delta_time(); @@ -142,13 +146,6 @@ AP_DCM::matrix_update(float _G_Dt) _omega = _omega_integ_corr + _omega_P; // Equation 16, adding proportional and integral correction terms _omega_smoothed = (_omega_smoothed * 0.5) + (_omega_integ_corr * 0.5); - if(_centripetal && - _gps != NULL && - _gps->status() == GPS::GPS_OK) { - // Remove _centripetal acceleration. - accel_adjust(); - } - #if OUTPUTMODE == 1 float tmp = _G_Dt * _omega.x; update_matrix.b.z = -tmp; // -delta Theta x @@ -182,23 +179,22 @@ AP_DCM::matrix_update(float _G_Dt) } -/**************************************************/ +// adjust an accelerometer vector for centripetal force void -AP_DCM::accel_adjust(void) +AP_DCM::accel_adjust(Vector3f &accel) { - Vector3f temp; float veloc; veloc = _gps->ground_speed / 100; // We are working with acceleration in m/s^2 units - // We are working with a modified version of equation 26 as our IMU object reports acceleration in the positive axis direction as positive + // We are working with a modified version of equation 26 as + // our IMU object reports acceleration in the positive axis + // direction as positive - // _accel_vector -= _omega_integ_corr % veloc; // Equation 26 This line is giving the compiler a problem so we break it up below - temp.x = 0; - temp.y = _omega_smoothed.z * veloc; // only computing the non-zero terms - temp.z = _omega_smoothed.y * (-veloc); // After looking at the compiler issue lets remove _veloc and simlify + // Equation 26 broken up into separate pieces - _accel_vector -= temp; + accel.y -= _omega_smoothed.z * veloc; + accel.z += _omega_smoothed.y * veloc; } /* @@ -365,18 +361,24 @@ AP_DCM::renorm(Vector3f const &a, int &problem) void AP_DCM::drift_correction(void) { - //Compensation the Roll, Pitch and Yaw drift. - //float mag_heading_x; - //float mag_heading_y; float error_course = 0; float accel_weight; float integrator_magnitude; + Vector3f accel; Vector3f error; float error_norm; const float gravity_squared = (9.80665*9.80665); - //static float scaled_omega_P[3]; - //static float scaled_omega_I[3]; + accel = _accel_vector; + + // if enabled, use the GPS to correct our accelerometer vector + // for centripetal forces + if(_centripetal && + _gps != NULL && + _gps->status() == GPS::GPS_OK) { + accel_adjust(accel); + } + //*****Roll and Pitch*************** @@ -387,14 +389,14 @@ AP_DCM::drift_correction(void) // values gives a better attitude estimate than including the // z accel - float zsquared = gravity_squared - ((_accel_vector.x * _accel_vector.x) + (_accel_vector.y * _accel_vector.y)); + float zsquared = gravity_squared - ((accel.x * accel.x) + (accel.y * accel.y)); if (zsquared < 0) { accel_weight = 0; } else { - if (_accel_vector.z > 0) { - _accel_vector.z = sqrt(zsquared); + if (accel.z > 0) { + accel.z = sqrt(zsquared); } else { - _accel_vector.z = -sqrt(zsquared); + accel.z = -sqrt(zsquared); } // this is arbitrary, and can be removed once we get @@ -403,7 +405,7 @@ AP_DCM::drift_correction(void) _health = constrain(_health+(0.02 * (accel_weight - .5)), 0, 1); - error = _dcm_matrix.c % _accel_vector; + error = _dcm_matrix.c % accel; // error_roll_pitch are in Accel m/s^2 units // Limit max error_roll_pitch to limit max omega_P and omega_I @@ -510,13 +512,7 @@ AP_DCM::euler_angles(void) { check_matrix(); - #if (OUTPUTMODE == 2) // Only accelerometer info (debugging purposes) - roll = atan2(_accel_vector.y, -_accel_vector.z); // atan2(acc_y, acc_z) - pitch = safe_asin((_accel_vector.x) / (double)9.81); // asin(acc_x) - yaw = 0; - #else calculate_euler_angles(_dcm_matrix, &roll, &pitch, &yaw); - #endif roll_sensor = degrees(roll) * 100; pitch_sensor = degrees(pitch) * 100; diff --git a/libraries/AP_DCM/AP_DCM.h b/libraries/AP_DCM/AP_DCM.h index 5294b8a06c..6d9f091703 100644 --- a/libraries/AP_DCM/AP_DCM.h +++ b/libraries/AP_DCM/AP_DCM.h @@ -42,7 +42,6 @@ public: // Accessors Vector3f get_gyro(void) {return _omega_integ_corr; } // We return the raw gyro vector corrected for bias - Vector3f get_accel(void) { return _accel_vector; } Matrix3f get_dcm_matrix(void) {return _dcm_matrix; } Matrix3f get_dcm_transposed(void) {Matrix3f temp = _dcm_matrix; return temp.transpose();} Vector3f get_integrator(void) {return _omega_I; } // We return the current drift correction integrator values @@ -101,7 +100,7 @@ private: // Methods void read_adc_raw(void); - void accel_adjust(void); + void accel_adjust(Vector3f &accel); float read_adc(int select); void matrix_update(float _G_Dt); void normalize(void); @@ -125,8 +124,13 @@ private: Matrix3f _dcm_matrix; - Vector3f _accel_vector; // Store the acceleration in a vector - Vector3f _accel_smoothed; + // sum of accel vectors between drift_correction() calls + // this allows the drift correction to run at a different rate + // to the main DCM update code + Vector3f _accel_vector; + Vector3f _accel_sum; + uint8_t _accel_sum_count; + Vector3f _gyro_vector; // Store the gyros turn rate in a vector Vector3f _omega_P; // Omega Proportional correction Vector3f _omega_I; // Omega Integrator correction From 25cad0974652d098b55a794b7c9e98b4a4ae5745 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 3 Mar 2012 11:54:19 +1100 Subject: [PATCH 034/178] SITL: added a drift_level multiplier this makes it easier to experiment with different gyro drift levels --- libraries/Desktop/support/sitl_adc.h | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/libraries/Desktop/support/sitl_adc.h b/libraries/Desktop/support/sitl_adc.h index e0624bd724..e92fded895 100644 --- a/libraries/Desktop/support/sitl_adc.h +++ b/libraries/Desktop/support/sitl_adc.h @@ -10,6 +10,7 @@ #include static const float vibration_level = 2.0; +static const float drift_level = 1.0; // order zgyro, xgyro, ygyro, temp, xacc, yacc, zacc, aspd static const float noise_scale[8] = { 150, 150, 150, 0, 400, 400, 400, 0 }; static const float noise_offset[8]= { 0, 0, 0, 0, 0, 0, 0, 0 }; @@ -25,11 +26,11 @@ static double rand_float(void) static inline float gyro_drift(uint8_t chan) { - if (drift_rate[chan] == 0) { + if (drift_rate[chan] * drift_level == 0.0) { return 0; } extern long unsigned int micros(void); - double period = 10*drift_rate[chan]; + double period = 10*drift_rate[chan] * drift_level; double minutes = fmod(micros() / 60.0e6, period); if (minutes < period/2) { return minutes; @@ -57,7 +58,7 @@ static inline float noise_generator(uint8_t chan) } } if (noise_count == 0) { - return rand_float() * base_noise; + return rand_float() * base_noise * vibration_level; } return gyro_drift(chan) + noise/noise_count; } From bddc6ba24149c465d06c766b90220e8c71b14bc0 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 3 Mar 2012 12:21:12 +1100 Subject: [PATCH 035/178] SITL: separate out drift speed and drift level --- libraries/Desktop/support/sitl_adc.h | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/libraries/Desktop/support/sitl_adc.h b/libraries/Desktop/support/sitl_adc.h index e92fded895..9bf6876a55 100644 --- a/libraries/Desktop/support/sitl_adc.h +++ b/libraries/Desktop/support/sitl_adc.h @@ -10,6 +10,7 @@ #include static const float vibration_level = 2.0; +static const float drift_speed = 1.0; static const float drift_level = 1.0; // order zgyro, xgyro, ygyro, temp, xacc, yacc, zacc, aspd static const float noise_scale[8] = { 150, 150, 150, 0, 400, 400, 400, 0 }; @@ -30,12 +31,12 @@ static inline float gyro_drift(uint8_t chan) return 0; } extern long unsigned int micros(void); - double period = 10*drift_rate[chan] * drift_level; + double period = 10*drift_rate[chan] * drift_speed; double minutes = fmod(micros() / 60.0e6, period); if (minutes < period/2) { - return minutes; + return minutes * drift_level; } - return period - minutes; + return (period - minutes) * drift_level; } From 511f65e2ef5c0a749d782078976a8077ad1c953e Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 3 Mar 2012 12:50:46 +1100 Subject: [PATCH 036/178] APM: fixed reset of control switch when short_fs_action is disabled When FS_SHORT_ACTN is 0, we should not re-read the control switch unless we changed mode on the initial short fs action --- ArduPlane/events.pde | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/ArduPlane/events.pde b/ArduPlane/events.pde index 412c67ec5d..c219d38f39 100644 --- a/ArduPlane/events.pde +++ b/ArduPlane/events.pde @@ -71,7 +71,10 @@ static void failsafe_short_off_event() // re-read the switch so we can return to our preferred mode // -------------------------------------------------------- - reset_control_switch(); + if (control_mode == CIRCLE || + (g.short_fs_action == 1 && control_mode == RTL)) { + reset_control_switch(); + } // Reset control integrators // --------------------- From 64cc04ae09a4cfc6b45184f5eafaf74f9aef9eb0 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 3 Mar 2012 13:27:29 +1100 Subject: [PATCH 037/178] ACM: adjust yaw drift correction constants this should give the compass a bit more authority --- ArduCopter/system.pde | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ArduCopter/system.pde b/ArduCopter/system.pde index a3c43799b4..92c679a000 100644 --- a/ArduCopter/system.pde +++ b/ArduCopter/system.pde @@ -311,8 +311,8 @@ static void init_ardupilot() #if HIL_MODE != HIL_MODE_ATTITUDE dcm.kp_roll_pitch(0.130000); dcm.ki_roll_pitch(0.00001278), // 50 hz I term - dcm.kp_yaw(0.08); - dcm.ki_yaw(0.00004); + dcm.kp_yaw(0.12); + dcm.ki_yaw(0.00002); dcm._clamp = 5; #endif From 367947fd3347c6a6dda35729b5eb0f3e11446b8e Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 3 Mar 2012 13:29:26 +1100 Subject: [PATCH 038/178] HWSTATUS: if we don't know the voltage, report it as zero this will tell us if board_voltage() is really working --- ArduCopter/system.pde | 18 ++++++++++-------- ArduPlane/system.pde | 18 ++++++++++-------- 2 files changed, 20 insertions(+), 16 deletions(-) diff --git a/ArduCopter/system.pde b/ArduCopter/system.pde index 92c679a000..d3e9814d20 100644 --- a/ArduCopter/system.pde +++ b/ArduCopter/system.pde @@ -659,7 +659,6 @@ void flash_leds(bool on) */ uint16_t board_voltage(void) { - static uint16_t vcc = 5000; const uint8_t mux = (_BV(REFS0)|_BV(MUX4)|_BV(MUX3)|_BV(MUX2)|_BV(MUX1)); if (ADMUX == mux) { @@ -669,14 +668,17 @@ uint16_t board_voltage(void) counter--; if (counter == 0) { // we don't actually expect this timeout to happen, - // but we don't want any more code that could hang - return vcc; + // but we don't want any more code that could hang. We + // report 0V so it is clear in the logs that we don't know + // the value + return 0; } uint32_t result = ADCL | ADCH<<8; - vcc = 1126400L / result; // Read and back-calculate Vcc in mV - } else { - ADMUX = mux; // switch mux, settle time is needed - } - return vcc; // in mV + return 1126400UL / result; // Read and back-calculate Vcc in mV + } + // switch mux, settle time is needed. We don't want to delay + // waiting for the settle, so report 0 as a "don't know" value + ADMUX = mux; + return 0; // we don't know the current voltage } #endif diff --git a/ArduPlane/system.pde b/ArduPlane/system.pde index 571006aa15..28b74098fd 100644 --- a/ArduPlane/system.pde +++ b/ArduPlane/system.pde @@ -577,7 +577,6 @@ void flash_leds(bool on) */ uint16_t board_voltage(void) { - static uint16_t vcc = 5000; const uint8_t mux = (_BV(REFS0)|_BV(MUX4)|_BV(MUX3)|_BV(MUX2)|_BV(MUX1)); if (ADMUX == mux) { @@ -587,14 +586,17 @@ uint16_t board_voltage(void) counter--; if (counter == 0) { // we don't actually expect this timeout to happen, - // but we don't want any more code that could hang - return vcc; + // but we don't want any more code that could hang. We + // report 0V so it is clear in the logs that we don't know + // the value + return 0; } uint32_t result = ADCL | ADCH<<8; - vcc = 1126400L / result; // Read and back-calculate Vcc in mV - } else { - ADMUX = mux; // switch mux, settle time is needed - } - return vcc; // in mV + return 1126400UL / result; // Read and back-calculate Vcc in mV + } + // switch mux, settle time is needed. We don't want to delay + // waiting for the settle, so report 0 as a "don't know" value + ADMUX = mux; + return 0; // we don't know the current voltage } #endif From fd2a24f8ed81b64b85fd539456a17ef680892004 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 3 Mar 2012 14:15:26 +1100 Subject: [PATCH 039/178] SITL: reduce the simulated compass offsets this was causing us problems in getting DCM right --- libraries/Desktop/support/sitl_compass.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/Desktop/support/sitl_compass.cpp b/libraries/Desktop/support/sitl_compass.cpp index 0040652671..46a3653def 100644 --- a/libraries/Desktop/support/sitl_compass.cpp +++ b/libraries/Desktop/support/sitl_compass.cpp @@ -16,8 +16,8 @@ #include "desktop.h" #include "util.h" -#define MAG_OFS_X 17.0 -#define MAG_OFS_Y 125.0 +#define MAG_OFS_X 5.0 +#define MAG_OFS_Y 13.0 #define MAG_OFS_Z -18.0 /* From 74eef7018a85d189f61a9fd0eb6d871ccf9b6767 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 3 Mar 2012 15:49:38 +1100 Subject: [PATCH 040/178] Quaternion: added an AP_Quaternion library this is for experimenting with the Madgwick quaternion system, to see if it is more or less noise sensitive than DCM --- libraries/AP_Quaternion/AP_Quaternion.cpp | 296 ++++++++++++++++++ libraries/AP_Quaternion/AP_Quaternion.h | 98 ++++++ .../examples/Quaternion/Makefile | 4 + .../examples/Quaternion/Quaternion.pde | 149 +++++++++ 4 files changed, 547 insertions(+) create mode 100644 libraries/AP_Quaternion/AP_Quaternion.cpp create mode 100644 libraries/AP_Quaternion/AP_Quaternion.h create mode 100644 libraries/AP_Quaternion/examples/Quaternion/Makefile create mode 100644 libraries/AP_Quaternion/examples/Quaternion/Quaternion.pde diff --git a/libraries/AP_Quaternion/AP_Quaternion.cpp b/libraries/AP_Quaternion/AP_Quaternion.cpp new file mode 100644 index 0000000000..646b44806a --- /dev/null +++ b/libraries/AP_Quaternion/AP_Quaternion.cpp @@ -0,0 +1,296 @@ +/* + AP_Quaternion code, based on quaternion code from Jeb Madgwick + + See http://www.x-io.co.uk/res/doc/madgwick_internal_report.pdf + + adapted to APM by Andrew Tridgell + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later + version. +*/ +#include + +#define ToRad(x) (x*0.01745329252) // *pi/180 +#define ToDeg(x) (x*57.2957795131) // *180/pi + +// this is the speed in cm/s above which we first get a yaw lock with +// the GPS +#define GPS_SPEED_MIN 300 + +// this is the speed in cm/s at which we stop using drift correction +// from the GPS and wait for the ground speed to get above GPS_SPEED_MIN +#define GPS_SPEED_RESET 100 + +void +AP_Quaternion::set_compass(Compass *compass) +{ + _compass = compass; +} + +// Function to compute one quaternion iteration without magnetometer +void AP_Quaternion::update_IMU(float deltat, Vector3f &gyro, Vector3f &accel) +{ + // Local system variables + float norm; // vector norm + float SEqDot_omega_1, SEqDot_omega_2, SEqDot_omega_3, SEqDot_omega_4; // quaternion derrivative from gyroscopes elements + float f_1, f_2, f_3; // objective function elements + float J_11or24, J_12or23, J_13or22, J_14or21, J_32, J_33; // objective function Jacobian elements + float SEqHatDot_1, SEqHatDot_2, SEqHatDot_3, SEqHatDot_4; // estimated direction of the gyroscope error + + // Axulirary variables to avoid reapeated calcualtions + float halfSEq_1 = 0.5f * SEq_1; + float halfSEq_2 = 0.5f * SEq_2; + float halfSEq_3 = 0.5f * SEq_3; + float halfSEq_4 = 0.5f * SEq_4; + float twoSEq_1 = 2.0f * SEq_1; + float twoSEq_2 = 2.0f * SEq_2; + float twoSEq_3 = 2.0f * SEq_3; + + // estimated direction of the gyroscope error (radians) + Vector3f w_err; + + // normalise accelerometer vector + accel.normalize(); + + // Compute the objective function and Jacobian + f_1 = twoSEq_2 * SEq_4 - twoSEq_1 * SEq_3 - accel.x; + f_2 = twoSEq_1 * SEq_2 + twoSEq_3 * SEq_4 - accel.y; + f_3 = 1.0f - twoSEq_2 * SEq_2 - twoSEq_3 * SEq_3 - accel.z; + J_11or24 = twoSEq_3; // J_11 negated in matrix multiplication + J_12or23 = 2.0f * SEq_4; + J_13or22 = twoSEq_1; // J_12 negated in matrix multiplication + J_14or21 = twoSEq_2; + J_32 = 2.0f * J_14or21; // negated in matrix multiplication + J_33 = 2.0f * J_11or24; // negated in matrix multiplication + + // Compute the gradient (matrix multiplication) + SEqHatDot_1 = J_14or21 * f_2 - J_11or24 * f_1; + SEqHatDot_2 = J_12or23 * f_1 + J_13or22 * f_2 - J_32 * f_3; + SEqHatDot_3 = J_12or23 * f_2 - J_33 * f_3 - J_13or22 * f_1; + SEqHatDot_4 = J_14or21 * f_1 + J_11or24 * f_2; + + // Normalise the gradient + norm = 1.0/sqrt(SEqHatDot_1 * SEqHatDot_1 + SEqHatDot_2 * SEqHatDot_2 + SEqHatDot_3 * SEqHatDot_3 + SEqHatDot_4 * SEqHatDot_4); + if (!isinf(norm)) { + SEqHatDot_1 *= norm; + SEqHatDot_2 *= norm; + SEqHatDot_3 *= norm; + SEqHatDot_4 *= norm; + } + + // Compute the quaternion derrivative measured by gyroscopes + SEqDot_omega_1 = -halfSEq_2 * gyro.x - halfSEq_3 * gyro.y - halfSEq_4 * gyro.z; + SEqDot_omega_2 = halfSEq_1 * gyro.x + halfSEq_3 * gyro.z - halfSEq_4 * gyro.y; + SEqDot_omega_3 = halfSEq_1 * gyro.y - halfSEq_2 * gyro.z + halfSEq_4 * gyro.x; + SEqDot_omega_4 = halfSEq_1 * gyro.z + halfSEq_2 * gyro.y - halfSEq_3 * gyro.x; + + // Compute then integrate the estimated quaternion derrivative + SEq_1 += (SEqDot_omega_1 - (beta * SEqHatDot_1)) * deltat; + SEq_2 += (SEqDot_omega_2 - (beta * SEqHatDot_2)) * deltat; + SEq_3 += (SEqDot_omega_3 - (beta * SEqHatDot_3)) * deltat; + SEq_4 += (SEqDot_omega_4 - (beta * SEqHatDot_4)) * deltat; + + // Normalise quaternion + norm = 1.0/sqrt(SEq_1 * SEq_1 + SEq_2 * SEq_2 + SEq_3 * SEq_3 + SEq_4 * SEq_4); + if (!isinf(norm)) { + SEq_1 *= norm; + SEq_2 *= norm; + SEq_3 *= norm; + SEq_4 *= norm; + } +} + + +// Function to compute one quaternion iteration including magnetometer +void AP_Quaternion::update_MARG(float deltat, Vector3f &gyro, Vector3f &accel, Vector3f &mag) +{ + // local system variables + float norm; // vector norm + float SEqDot_omega_1, SEqDot_omega_2, SEqDot_omega_3, SEqDot_omega_4; // quaternion rate from gyroscopes elements + float f_1, f_2, f_3, f_4, f_5, f_6; // objective function elements + float J_11or24, J_12or23, J_13or22, J_14or21, J_32, J_33, // objective function Jacobian elements + J_41, J_42, J_43, J_44, J_51, J_52, J_53, J_54, J_61, J_62, J_63, J_64; // + float SEqHatDot_1, SEqHatDot_2, SEqHatDot_3, SEqHatDot_4; // estimated direction of the gyroscope error + + // computed flux in the earth frame + Vector3f flux; + + // estimated direction of the gyroscope error (radians) + Vector3f w_err; + + // normalise accelerometer vector + accel.normalize(); + + // normalise the magnetometer measurement + mag.normalize(); + + // auxiliary variables to avoid repeated calculations + float halfSEq_1 = 0.5f * SEq_1; + float halfSEq_2 = 0.5f * SEq_2; + float halfSEq_3 = 0.5f * SEq_3; + float halfSEq_4 = 0.5f * SEq_4; + float twoSEq_1 = 2.0f * SEq_1; + float twoSEq_2 = 2.0f * SEq_2; + float twoSEq_3 = 2.0f * SEq_3; + float twoSEq_4 = 2.0f * SEq_4; + float twob_x = 2.0f * b_x; + float twob_z = 2.0f * b_z; + float twob_xSEq_1 = 2.0f * b_x * SEq_1; + float twob_xSEq_2 = 2.0f * b_x * SEq_2; + float twob_xSEq_3 = 2.0f * b_x * SEq_3; + float twob_xSEq_4 = 2.0f * b_x * SEq_4; + float twob_zSEq_1 = 2.0f * b_z * SEq_1; + float twob_zSEq_2 = 2.0f * b_z * SEq_2; + float twob_zSEq_3 = 2.0f * b_z * SEq_3; + float twob_zSEq_4 = 2.0f * b_z * SEq_4; + float SEq_1SEq_2; + float SEq_1SEq_3 = SEq_1 * SEq_3; + float SEq_1SEq_4; + float SEq_2SEq_3; + float SEq_2SEq_4 = SEq_2 * SEq_4; + float SEq_3SEq_4; + Vector3f twom = mag * 2.0; + + // compute the objective function and Jacobian + f_1 = twoSEq_2 * SEq_4 - twoSEq_1 * SEq_3 - accel.x; + f_2 = twoSEq_1 * SEq_2 + twoSEq_3 * SEq_4 - accel.y; + f_3 = 1.0f - twoSEq_2 * SEq_2 - twoSEq_3 * SEq_3 - accel.z; + f_4 = twob_x * (0.5f - SEq_3 * SEq_3 - SEq_4 * SEq_4) + twob_z * (SEq_2SEq_4 - SEq_1SEq_3) - mag.x; + f_5 = twob_x * (SEq_2 * SEq_3 - SEq_1 * SEq_4) + twob_z * (SEq_1 * SEq_2 + SEq_3 * SEq_4) - mag.y; + f_6 = twob_x * (SEq_1SEq_3 + SEq_2SEq_4) + twob_z * (0.5f - SEq_2 * SEq_2 - SEq_3 * SEq_3) - mag.z; + J_11or24 = twoSEq_3; // J_11 negated in matrix multiplication + J_12or23 = 2.0f * SEq_4; + J_13or22 = twoSEq_1; // J_12 negated in matrix multiplication + J_14or21 = twoSEq_2; + J_32 = 2.0f * J_14or21; // negated in matrix multiplication + J_33 = 2.0f * J_11or24; // negated in matrix multiplication + J_41 = twob_zSEq_3; // negated in matrix multiplication + J_42 = twob_zSEq_4; + J_43 = 2.0f * twob_xSEq_3 + twob_zSEq_1; // negated in matrix multiplication + J_44 = 2.0f * twob_xSEq_4 - twob_zSEq_2; // negated in matrix multiplication + J_51 = twob_xSEq_4 - twob_zSEq_2; // negated in matrix multiplication + J_52 = twob_xSEq_3 + twob_zSEq_1; + J_53 = twob_xSEq_2 + twob_zSEq_4; + J_54 = twob_xSEq_1 - twob_zSEq_3; // negated in matrix multiplication + J_61 = twob_xSEq_3; + J_62 = twob_xSEq_4 - 2.0f * twob_zSEq_2; + J_63 = twob_xSEq_1 - 2.0f * twob_zSEq_3; + J_64 = twob_xSEq_2; + + // compute the gradient (matrix multiplication) + SEqHatDot_1 = J_14or21 * f_2 - J_11or24 * f_1 - J_41 * f_4 - J_51 * f_5 + J_61 * f_6; + SEqHatDot_2 = J_12or23 * f_1 + J_13or22 * f_2 - J_32 * f_3 + J_42 * f_4 + J_52 * f_5 + J_62 * f_6; + SEqHatDot_3 = J_12or23 * f_2 - J_33 * f_3 - J_13or22 * f_1 - J_43 * f_4 + J_53 * f_5 + J_63 * f_6; + SEqHatDot_4 = J_14or21 * f_1 + J_11or24 * f_2 - J_44 * f_4 - J_54 * f_5 + J_64 * f_6; + + // normalise the gradient to estimate direction of the gyroscope error + norm = 1.0 / sqrt(SEqHatDot_1 * SEqHatDot_1 + SEqHatDot_2 * SEqHatDot_2 + SEqHatDot_3 * SEqHatDot_3 + SEqHatDot_4 * SEqHatDot_4); + SEqHatDot_1 *= norm; + SEqHatDot_2 *= norm; + SEqHatDot_3 *= norm; + SEqHatDot_4 *= norm; + + // compute angular estimated direction of the gyroscope error + w_err.x = twoSEq_1 * SEqHatDot_2 - twoSEq_2 * SEqHatDot_1 - twoSEq_3 * SEqHatDot_4 + twoSEq_4 * SEqHatDot_3; + w_err.y = twoSEq_1 * SEqHatDot_3 + twoSEq_2 * SEqHatDot_4 - twoSEq_3 * SEqHatDot_1 - twoSEq_4 * SEqHatDot_2; + w_err.z = twoSEq_1 * SEqHatDot_4 - twoSEq_2 * SEqHatDot_3 + twoSEq_3 * SEqHatDot_2 - twoSEq_4 * SEqHatDot_1; + + // compute and remove the gyroscope baises + gyro_bias += w_err * (deltat * zeta); + gyro -= gyro_bias; + + // compute the quaternion rate measured by gyroscopes + SEqDot_omega_1 = -halfSEq_2 * gyro.x - halfSEq_3 * gyro.y - halfSEq_4 * gyro.z; + SEqDot_omega_2 = halfSEq_1 * gyro.x + halfSEq_3 * gyro.z - halfSEq_4 * gyro.y; + SEqDot_omega_3 = halfSEq_1 * gyro.y - halfSEq_2 * gyro.z + halfSEq_4 * gyro.x; + SEqDot_omega_4 = halfSEq_1 * gyro.z + halfSEq_2 * gyro.y - halfSEq_3 * gyro.x; + + // compute then integrate the estimated quaternion rate + SEq_1 += (SEqDot_omega_1 - (beta * SEqHatDot_1)) * deltat; + SEq_2 += (SEqDot_omega_2 - (beta * SEqHatDot_2)) * deltat; + SEq_3 += (SEqDot_omega_3 - (beta * SEqHatDot_3)) * deltat; + SEq_4 += (SEqDot_omega_4 - (beta * SEqHatDot_4)) * deltat; + + // normalise quaternion + norm = 1.0/sqrt(SEq_1 * SEq_1 + SEq_2 * SEq_2 + SEq_3 * SEq_3 + SEq_4 * SEq_4); + if (!isinf(norm)) { + SEq_1 *= norm; + SEq_2 *= norm; + SEq_3 *= norm; + SEq_4 *= norm; + } + + // compute flux in the earth frame + // recompute axulirary variables + SEq_1SEq_2 = SEq_1 * SEq_2; + SEq_1SEq_3 = SEq_1 * SEq_3; + SEq_1SEq_4 = SEq_1 * SEq_4; + SEq_3SEq_4 = SEq_3 * SEq_4; + SEq_2SEq_3 = SEq_2 * SEq_3; + SEq_2SEq_4 = SEq_2 * SEq_4; + flux.x = twom.x * (0.5f - SEq_3 * SEq_3 - SEq_4 * SEq_4) + twom.y * (SEq_2SEq_3 - SEq_1SEq_4) + twom.z * (SEq_2SEq_4 + SEq_1SEq_3); + flux.y = twom.x * (SEq_2SEq_3 + SEq_1SEq_4) + twom.y * (0.5f - SEq_2 * SEq_2 - SEq_4 * SEq_4) + twom.z * (SEq_3SEq_4 - SEq_1SEq_2); + flux.z = twom.x * (SEq_2SEq_4 - SEq_1SEq_3) + twom.y * (SEq_3SEq_4 + SEq_1SEq_2) + twom.z * (0.5f - SEq_2 * SEq_2 - SEq_3 * SEq_3); + + // normalise the flux vector to have only components in the x and z + b_x = sqrt((flux.x * flux.x) + (flux.y * flux.y)); + b_z = flux.z; +} + + +// Function to compute one quaternion iteration +void AP_Quaternion::update(float deltat) +{ + Vector3f gyro, accel; + + _imu->update(); + + // get current IMU state + gyro = _imu->get_gyro(); + gyro.x = -gyro.x; + gyro.y = -gyro.y; + + accel = _imu->get_accel(); + accel.z = -accel.z; + + if (_compass == NULL) { + update_IMU(deltat, gyro, accel); + } else { + Vector3f mag = Vector3f(_compass->mag_x, _compass->mag_y, - _compass->mag_z); + update_MARG(deltat, gyro, accel, mag); + } + + // compute the Eulers + float test = (SEq_1*SEq_3 - SEq_4*SEq_2); + const float singularity = 0.499; // 86.3 degrees? + if (test > singularity) { + // singularity at south pole + // this one is ok.. + yaw = 2.0 * atan2(SEq_4, SEq_1); + pitch = ToRad(-90.0); + roll = 0.0; + } else if (test < -singularity) { + // singularity at north pole + // this one is invalid :( .. fix it. + yaw = -2.0 * atan2(SEq_4, SEq_1); + pitch = ToRad(90.0); + roll = 0.0; + } else { + roll = -(atan2(2.0*(SEq_1*SEq_2 + SEq_3*SEq_4), + 1 - 2.0*(SEq_2*SEq_2 + SEq_3*SEq_3))); + pitch = -safe_asin(2.0*test); + yaw = atan2(2.0*(SEq_1*SEq_4 + SEq_2*SEq_3), + 1 - 2.0*(SEq_3*SEq_3 + SEq_4*SEq_4)); + } + + // and integer Eulers + roll_sensor = 100 * ToDeg(roll); + pitch_sensor = 100 * ToDeg(pitch); + yaw_sensor = 100 * ToDeg(yaw); + if (yaw_sensor < 0) { + yaw_sensor += 36000; + } +} diff --git a/libraries/AP_Quaternion/AP_Quaternion.h b/libraries/AP_Quaternion/AP_Quaternion.h new file mode 100644 index 0000000000..4d3cb03356 --- /dev/null +++ b/libraries/AP_Quaternion/AP_Quaternion.h @@ -0,0 +1,98 @@ +#ifndef AP_Quaternion_h +#define AP_Quaternion_h + +#include +#include +#include +#include +#include + +#if defined(ARDUINO) && ARDUINO >= 100 + #include "Arduino.h" +#else + #include "WProgram.h" +#endif + +class AP_Quaternion +{ +public: + // Constructor + AP_Quaternion(IMU *imu, GPS *&gps, Compass *compass = NULL) : + _imu(imu), + _gps(gps), + _compass(compass) + { + // initial quaternion + SEq_1 = 1; + SEq_2 = 0; + SEq_3 = 0; + SEq_4 = 0; + + // reference direction of flux in earth frame + b_x = 0; + b_z = -1; + + // scaled gyro drift limits + beta = sqrt(3.0f / 4.0f) * gyroMeasError; + zeta = sqrt(3.0f / 4.0f) * gyroMeasDrift; + } + + // Accessors + void set_centripetal(bool b) {_centripetal = b;} + bool get_centripetal(void) {return _centripetal;} + void set_compass(Compass *compass); + + // Methods + void update(float deltat); + + // Euler angles (radians) + float roll; + float pitch; + float yaw; + + // integer Euler angles (Degrees * 100) + int32_t roll_sensor; + int32_t pitch_sensor; + int32_t yaw_sensor; + + +private: + void update_IMU(float deltat, Vector3f &gyro, Vector3f &accel); + void update_MARG(float deltat, Vector3f &gyro, Vector3f &accel, Vector3f &mag); + + bool _have_initial_yaw; + + // Methods + void accel_adjust(void); + + // members + Compass * _compass; + + // note: we use ref-to-pointer here so that our caller can change the GPS without our noticing + // IMU under us without our noticing. + GPS *&_gps; + IMU *_imu; + + // true if we are doing centripetal acceleration correction + bool _centripetal; + + // maximum gyroscope measurement error in rad/s (set to 5 degrees/second) + static const float gyroMeasError = 5.0 * (M_PI/180.0); + + // maximum gyroscope drift rate in radians/s/s (set to 0.2 degrees/s/s) + static const float gyroMeasDrift = 0.2 * (PI/180.0); + + float beta; + float zeta; + + // quaternion elements + float SEq_1, SEq_2, SEq_3, SEq_4; + + float b_x; + float b_z; + + // estimate gyroscope biases error + Vector3f gyro_bias; +}; + +#endif diff --git a/libraries/AP_Quaternion/examples/Quaternion/Makefile b/libraries/AP_Quaternion/examples/Quaternion/Makefile new file mode 100644 index 0000000000..fcdc8ff8fe --- /dev/null +++ b/libraries/AP_Quaternion/examples/Quaternion/Makefile @@ -0,0 +1,4 @@ +include ../../../AP_Common/Arduino.mk + +sitl: + make -f ../../../../libraries/Desktop/Desktop.mk diff --git a/libraries/AP_Quaternion/examples/Quaternion/Quaternion.pde b/libraries/AP_Quaternion/examples/Quaternion/Quaternion.pde new file mode 100644 index 0000000000..e5a5157db1 --- /dev/null +++ b/libraries/AP_Quaternion/examples/Quaternion/Quaternion.pde @@ -0,0 +1,149 @@ +// -*- tab-width: 4; Mode: C++; c-basic-offset: 4; indent-tabs-mode: t -*- + +// +// Simple test for the AP_Quaternion library +// + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// uncomment this for a APM2 board +//#define APM2_HARDWARE + +FastSerialPort(Serial, 0); + +Arduino_Mega_ISR_Registry isr_registry; +AP_TimerProcess scheduler; + +#ifdef DESKTOP_BUILD +AP_Compass_HIL compass; +#else +AP_Compass_HMC5843 compass; +#endif + +#ifdef APM2_HARDWARE + AP_InertialSensor_MPU6000 ins( 53 ); +# else + AP_ADC_ADS7844 adc; + AP_InertialSensor_Oilpan ins( &adc ); +#endif // CONFIG_IMU_TYPE + +static GPS *g_gps; + +AP_IMU_INS imu(&ins); +AP_Quaternion quaternion(&imu, g_gps); + +AP_Baro_BMP085_HIL barometer; + + +#ifdef APM2_HARDWARE +# define A_LED_PIN 27 +# define C_LED_PIN 25 +# define LED_ON LOW +# define LED_OFF HIGH +# define MAG_ORIENTATION AP_COMPASS_APM2_SHIELD +#else +# define A_LED_PIN 37 +# define C_LED_PIN 35 +# define LED_ON HIGH +# define LED_OFF LOW +# define MAG_ORIENTATION AP_COMPASS_COMPONENTS_DOWN_PINS_FORWARD +#endif + + +static void flash_leds(bool on) +{ + digitalWrite(A_LED_PIN, on?LED_OFF:LED_ON); + digitalWrite(C_LED_PIN, on?LED_ON:LED_OFF); +} + +void setup(void) +{ + Serial.begin(115200); + Serial.println("Starting up..."); + +#ifndef DESKTOP_BUILD + I2c.begin(); + I2c.timeOut(5); + I2c.setSpeed(true); +#endif + + SPI.begin(); + SPI.setClockDivider(SPI_CLOCK_DIV16); + +#ifdef APM2_HARDWARE + // we need to stop the barometer from holding the SPI bus + pinMode(40, OUTPUT); + digitalWrite(40, HIGH); +#endif + + isr_registry.init(); + scheduler.init(&isr_registry); + + imu.init(IMU::COLD_START, delay, flash_leds, &scheduler); + imu.init_accel(delay, flash_leds); + + compass.set_orientation(MAG_ORIENTATION); + if (compass.init()) { + Serial.printf("Enabling compass\n"); + compass.null_offsets_enable(); + quaternion.set_compass(&compass); + } +} + +void loop(void) +{ + static uint16_t counter; + static uint32_t last_t, last_print, last_compass; + uint32_t now = micros(); + float deltat; + static uint32_t compass_reads; + static uint32_t compass_time; + + if (last_t == 0) { + last_t = now; + return; + } + deltat = (now - last_t) * 1.0e-6; + last_t = now; + + if (now - last_compass > 100*1000UL) { + // read compass at 10Hz + compass.read(); + last_compass = now; + } + + quaternion.update(deltat); + counter++; + + if (now - last_print >= 0.5e6) { + Vector3f accel = imu.get_accel(); + Vector3f gyro = imu.get_gyro(); + Serial.printf_P(PSTR("r:%4.1f p:%4.1f y:%4.1f g=(%5.1f %5.1f %5.1f) a=(%5.1f %5.1f %5.1f) rate=%.1f\n"), + ToDeg(quaternion.roll), + ToDeg(quaternion.pitch), + ToDeg(quaternion.yaw), + gyro.x, gyro.y, gyro.z, + accel.x, accel.y, accel.z, + (1.0e6*counter)/(now-last_print)); + last_print = now; + counter = 0; + compass_reads=0; + compass_time = 0; + } +} From a791224d07df3dc30a3e96366a513408fd9ab3cd Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 3 Mar 2012 15:49:57 +1100 Subject: [PATCH 041/178] SITL: make SITL not depend on DCM --- libraries/Desktop/support/sitl_adc.cpp | 26 -------------------------- 1 file changed, 26 deletions(-) diff --git a/libraries/Desktop/support/sitl_adc.cpp b/libraries/Desktop/support/sitl_adc.cpp index 05fdaab4d1..be857ab88d 100644 --- a/libraries/Desktop/support/sitl_adc.cpp +++ b/libraries/Desktop/support/sitl_adc.cpp @@ -10,7 +10,6 @@ #include #include #include -#include #include #include "wiring.h" #include "sitl_adc.h" @@ -100,31 +99,6 @@ void sitl_update_adc(float roll, float pitch, float yaw, // Relative to earth /* FIX: rubbish value for temperature for now */ UDR2.set(3, 2000); - -#if 0 - extern AP_DCM_HIL dcm; - dcm.setHil(ToRad(roll), ToRad(pitch), ToRad(yaw), - ToRad(rollRate), ToRad(pitchRate), ToRad(yawRate)); - -#endif - - static uint32_t last_report; - uint32_t tnow = millis(); - extern AP_DCM dcm; - Vector3f omega = dcm.get_gyro(); - // report roll/pitch discrepancies - if (tnow - last_report > 5000 || - (tnow - last_report > 1000 && - (fabs(roll - dcm.roll_sensor/100.0) > 5.0 || - fabs(pitch - dcm.pitch_sensor/100.0) > 5.0))) { - last_report = tnow; - /*printf("roll=%5.1f / %5.1f pitch=%5.1f / %5.1f rr=%5.2f / %5.2f pr=%5.2f / %5.2f\n", - roll, dcm.roll_sensor/100.0, - pitch, dcm.pitch_sensor/100.0, - rollRate, ToDeg(omega.x), - pitchRate, ToDeg(omega.y)); - */ - } } From c8a459ab0db6e8a41a6b4ac76219929ab5147ccc Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 3 Mar 2012 16:00:57 +1100 Subject: [PATCH 042/178] fixed deltat in quaternion --- libraries/AP_Quaternion/AP_Quaternion.cpp | 5 ++++- libraries/AP_Quaternion/AP_Quaternion.h | 2 +- libraries/AP_Quaternion/examples/Quaternion/Quaternion.pde | 4 +--- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/libraries/AP_Quaternion/AP_Quaternion.cpp b/libraries/AP_Quaternion/AP_Quaternion.cpp index 646b44806a..aedf1cd78b 100644 --- a/libraries/AP_Quaternion/AP_Quaternion.cpp +++ b/libraries/AP_Quaternion/AP_Quaternion.cpp @@ -242,12 +242,15 @@ void AP_Quaternion::update_MARG(float deltat, Vector3f &gyro, Vector3f &accel, V // Function to compute one quaternion iteration -void AP_Quaternion::update(float deltat) +void AP_Quaternion::update(void) { Vector3f gyro, accel; + float deltat; _imu->update(); + delta_t = _imu->get_delta_time(); + // get current IMU state gyro = _imu->get_gyro(); gyro.x = -gyro.x; diff --git a/libraries/AP_Quaternion/AP_Quaternion.h b/libraries/AP_Quaternion/AP_Quaternion.h index 4d3cb03356..41c76904c3 100644 --- a/libraries/AP_Quaternion/AP_Quaternion.h +++ b/libraries/AP_Quaternion/AP_Quaternion.h @@ -43,7 +43,7 @@ public: void set_compass(Compass *compass); // Methods - void update(float deltat); + void update(void); // Euler angles (radians) float roll; diff --git a/libraries/AP_Quaternion/examples/Quaternion/Quaternion.pde b/libraries/AP_Quaternion/examples/Quaternion/Quaternion.pde index e5a5157db1..1296a7fbd3 100644 --- a/libraries/AP_Quaternion/examples/Quaternion/Quaternion.pde +++ b/libraries/AP_Quaternion/examples/Quaternion/Quaternion.pde @@ -111,7 +111,6 @@ void loop(void) static uint16_t counter; static uint32_t last_t, last_print, last_compass; uint32_t now = micros(); - float deltat; static uint32_t compass_reads; static uint32_t compass_time; @@ -119,7 +118,6 @@ void loop(void) last_t = now; return; } - deltat = (now - last_t) * 1.0e-6; last_t = now; if (now - last_compass > 100*1000UL) { @@ -128,7 +126,7 @@ void loop(void) last_compass = now; } - quaternion.update(deltat); + quaternion.update(); counter++; if (now - last_print >= 0.5e6) { From c80ec9a55cf1591f74a49c7e2deee152ae6b1c02 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 3 Mar 2012 18:31:09 +1100 Subject: [PATCH 043/178] AP_ADC: added new_data_available() interface returns true if more samples are available --- libraries/AP_ADC/AP_ADC.h | 3 +++ libraries/AP_ADC/AP_ADC_ADS7844.cpp | 14 ++++++++++++++ libraries/AP_ADC/AP_ADC_ADS7844.h | 4 ++++ libraries/AP_ADC/AP_ADC_HIL.cpp | 6 ++++++ libraries/AP_ADC/AP_ADC_HIL.h | 3 +++ 5 files changed, 30 insertions(+) diff --git a/libraries/AP_ADC/AP_ADC.h b/libraries/AP_ADC/AP_ADC.h index 8bebead3fc..5e6b2d0909 100644 --- a/libraries/AP_ADC/AP_ADC.h +++ b/libraries/AP_ADC/AP_ADC.h @@ -40,6 +40,9 @@ class AP_ADC */ virtual uint32_t Ch6(const uint8_t *channel_numbers, uint16_t *result) = 0; + // check if Ch6() can return new data + virtual bool new_data_available(const uint8_t *channel_numbers) = 0; + private: }; diff --git a/libraries/AP_ADC/AP_ADC_ADS7844.cpp b/libraries/AP_ADC/AP_ADC_ADS7844.cpp index 6e65527519..f216f5a895 100644 --- a/libraries/AP_ADC/AP_ADC_ADS7844.cpp +++ b/libraries/AP_ADC/AP_ADC_ADS7844.cpp @@ -185,6 +185,20 @@ float AP_ADC_ADS7844::Ch(uint8_t ch_num) return ((float)sum)/count; } +// see if Ch6() can return new data +bool AP_ADC_ADS7844::new_data_available(const uint8_t *channel_numbers) +{ + uint8_t i; + + for (i=0; i<6; i++) { + if (_count[channel_numbers[i]] == 0) { + return false; + } + } + return true; +} + + // Read 6 channel values // this assumes that the counts for all of the 6 channels are // equal. This will only be true if we always consistently access a diff --git a/libraries/AP_ADC/AP_ADC_ADS7844.h b/libraries/AP_ADC/AP_ADC_ADS7844.h index 2bd8235b57..73be670b3b 100644 --- a/libraries/AP_ADC/AP_ADC_ADS7844.h +++ b/libraries/AP_ADC/AP_ADC_ADS7844.h @@ -29,6 +29,10 @@ class AP_ADC_ADS7844 : public AP_ADC // Read 6 sensors at once uint32_t Ch6(const uint8_t *channel_numbers, uint16_t *result); + + // check if Ch6 would block + bool new_data_available(const uint8_t *channel_numbers); + bool filter_result; private: diff --git a/libraries/AP_ADC/AP_ADC_HIL.cpp b/libraries/AP_ADC/AP_ADC_HIL.cpp index 80488682ab..e443941642 100644 --- a/libraries/AP_ADC/AP_ADC_HIL.cpp +++ b/libraries/AP_ADC/AP_ADC_HIL.cpp @@ -82,3 +82,9 @@ void AP_ADC_HIL::setHIL(int16_t p, int16_t q, int16_t r, int16_t gyroTemp, // differential pressure setPressure(diffPress); } + +// see if new data is available +bool AP_ADC_HIL::new_data_available(const uint8_t *channel_numbers) +{ + return true; +} diff --git a/libraries/AP_ADC/AP_ADC_HIL.h b/libraries/AP_ADC/AP_ADC_HIL.h index f7bcde465c..d9c53f6fdb 100644 --- a/libraries/AP_ADC/AP_ADC_HIL.h +++ b/libraries/AP_ADC/AP_ADC_HIL.h @@ -38,6 +38,9 @@ class AP_ADC_HIL : public AP_ADC // Read 6 sensors at once uint32_t Ch6(const uint8_t *channel_numbers, uint16_t *result); + // see if Ch6 would block + bool new_data_available(const uint8_t *channel_numbers); + /// // Set the adc raw values given the current rotations rates, // temps, accels, and pressures From a9dea35310bffea4d02f9b961eeaa5a9cdff7e09 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 3 Mar 2012 18:31:31 +1100 Subject: [PATCH 044/178] AP_InertialSensor: added new_data_available() interface --- libraries/AP_InertialSensor/AP_InertialSensor.h | 3 +++ libraries/AP_InertialSensor/AP_InertialSensor_MPU6000.cpp | 5 +++++ libraries/AP_InertialSensor/AP_InertialSensor_MPU6000.h | 1 + libraries/AP_InertialSensor/AP_InertialSensor_Oilpan.cpp | 5 +++++ libraries/AP_InertialSensor/AP_InertialSensor_Oilpan.h | 1 + libraries/AP_InertialSensor/AP_InertialSensor_Stub.cpp | 1 + libraries/AP_InertialSensor/AP_InertialSensor_Stub.h | 1 + 7 files changed, 17 insertions(+) diff --git a/libraries/AP_InertialSensor/AP_InertialSensor.h b/libraries/AP_InertialSensor/AP_InertialSensor.h index 1227122280..08067b8e1d 100644 --- a/libraries/AP_InertialSensor/AP_InertialSensor.h +++ b/libraries/AP_InertialSensor/AP_InertialSensor.h @@ -20,6 +20,9 @@ class AP_InertialSensor */ virtual bool update() = 0; + // check if the sensors have new data + virtual bool new_data_available(void) = 0; + /* Getters for individual gyro axes. * Gyros have correct coordinate frame and units (degrees per second). */ diff --git a/libraries/AP_InertialSensor/AP_InertialSensor_MPU6000.cpp b/libraries/AP_InertialSensor/AP_InertialSensor_MPU6000.cpp index 3cfd3aefeb..500bfe464d 100644 --- a/libraries/AP_InertialSensor/AP_InertialSensor_MPU6000.cpp +++ b/libraries/AP_InertialSensor/AP_InertialSensor_MPU6000.cpp @@ -159,6 +159,11 @@ bool AP_InertialSensor_MPU6000::update( void ) return true; } +bool AP_InertialSensor_MPU6000::new_data_available( void ) +{ + return _count != 0; +} + float AP_InertialSensor_MPU6000::gx() { return _gyro.x; } float AP_InertialSensor_MPU6000::gy() { return _gyro.y; } float AP_InertialSensor_MPU6000::gz() { return _gyro.z; } diff --git a/libraries/AP_InertialSensor/AP_InertialSensor_MPU6000.h b/libraries/AP_InertialSensor/AP_InertialSensor_MPU6000.h index b6044c36d5..fe48070ca8 100644 --- a/libraries/AP_InertialSensor/AP_InertialSensor_MPU6000.h +++ b/libraries/AP_InertialSensor/AP_InertialSensor_MPU6000.h @@ -20,6 +20,7 @@ class AP_InertialSensor_MPU6000 : public AP_InertialSensor /* Concrete implementation of AP_InertialSensor functions: */ bool update(); + bool new_data_available(); float gx(); float gy(); float gz(); diff --git a/libraries/AP_InertialSensor/AP_InertialSensor_Oilpan.cpp b/libraries/AP_InertialSensor/AP_InertialSensor_Oilpan.cpp index 3f5e45fd0a..cbdf80fb30 100644 --- a/libraries/AP_InertialSensor/AP_InertialSensor_Oilpan.cpp +++ b/libraries/AP_InertialSensor/AP_InertialSensor_Oilpan.cpp @@ -71,6 +71,11 @@ bool AP_InertialSensor_Oilpan::update() return true; } +bool AP_InertialSensor_Oilpan::new_data_available( void ) +{ + return _adc->new_data_available(_sensors); +} + float AP_InertialSensor_Oilpan::gx() { return _gyro.x; } float AP_InertialSensor_Oilpan::gy() { return _gyro.y; } float AP_InertialSensor_Oilpan::gz() { return _gyro.z; } diff --git a/libraries/AP_InertialSensor/AP_InertialSensor_Oilpan.h b/libraries/AP_InertialSensor/AP_InertialSensor_Oilpan.h index 5995dcfde5..48f43b1694 100644 --- a/libraries/AP_InertialSensor/AP_InertialSensor_Oilpan.h +++ b/libraries/AP_InertialSensor/AP_InertialSensor_Oilpan.h @@ -19,6 +19,7 @@ class AP_InertialSensor_Oilpan : public AP_InertialSensor /* Concrete implementation of AP_InertialSensor functions: */ void init(AP_PeriodicProcess * scheduler); bool update(); + bool new_data_available(); float gx(); float gy(); float gz(); diff --git a/libraries/AP_InertialSensor/AP_InertialSensor_Stub.cpp b/libraries/AP_InertialSensor/AP_InertialSensor_Stub.cpp index 4c917ae3b0..e88785e1c6 100644 --- a/libraries/AP_InertialSensor/AP_InertialSensor_Stub.cpp +++ b/libraries/AP_InertialSensor/AP_InertialSensor_Stub.cpp @@ -7,6 +7,7 @@ void AP_InertialSensor_Stub::init( AP_PeriodicProcess * scheduler ) {} /*================ AP_INERTIALSENSOR PUBLIC INTERFACE ==================== */ bool AP_InertialSensor_Stub::update( void ) { return true; } +bool AP_InertialSensor_Stub::new_data_available( void ) { return true; } float AP_InertialSensor_Stub::gx() { return 0.0f; } diff --git a/libraries/AP_InertialSensor/AP_InertialSensor_Stub.h b/libraries/AP_InertialSensor/AP_InertialSensor_Stub.h index a78b995d16..aae2bd1393 100644 --- a/libraries/AP_InertialSensor/AP_InertialSensor_Stub.h +++ b/libraries/AP_InertialSensor/AP_InertialSensor_Stub.h @@ -19,6 +19,7 @@ class AP_InertialSensor_Stub : public AP_InertialSensor /* Concrete implementation of AP_InertialSensor functions: */ bool update(); + bool new_data_available(); float gx(); float gy(); float gz(); From 6138f31cec5d43f1895b734d1e2d65793f886b78 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 3 Mar 2012 18:31:55 +1100 Subject: [PATCH 045/178] AP_IMU: added new_data_available() interface --- libraries/AP_IMU/AP_IMU_INS.cpp | 4 ++++ libraries/AP_IMU/AP_IMU_INS.h | 1 + libraries/AP_IMU/AP_IMU_Shim.h | 2 ++ libraries/AP_IMU/IMU.cpp | 1 + libraries/AP_IMU/IMU.h | 3 +++ 5 files changed, 11 insertions(+) diff --git a/libraries/AP_IMU/AP_IMU_INS.cpp b/libraries/AP_IMU/AP_IMU_INS.cpp index bb24f36248..fca618f13a 100644 --- a/libraries/AP_IMU/AP_IMU_INS.cpp +++ b/libraries/AP_IMU/AP_IMU_INS.cpp @@ -235,3 +235,7 @@ AP_IMU_INS::update(void) // always updated return true; } + +bool AP_IMU_INS::new_data_available(void) { + return _ins->new_data_available(); +} diff --git a/libraries/AP_IMU/AP_IMU_INS.h b/libraries/AP_IMU/AP_IMU_INS.h index 6e5311ab7b..54a0b54c80 100644 --- a/libraries/AP_IMU/AP_IMU_INS.h +++ b/libraries/AP_IMU/AP_IMU_INS.h @@ -51,6 +51,7 @@ public: virtual void init_gyro(void (*delay_cb)(unsigned long t) = delay, void (*flash_leds_cb)(bool on) = NULL); virtual bool update(void); + virtual bool new_data_available(void); // for jason virtual float gx() { return _sensor_cal[0]; } diff --git a/libraries/AP_IMU/AP_IMU_Shim.h b/libraries/AP_IMU/AP_IMU_Shim.h index 02aa86ee29..c9c1ce22b8 100644 --- a/libraries/AP_IMU/AP_IMU_Shim.h +++ b/libraries/AP_IMU/AP_IMU_Shim.h @@ -36,6 +36,8 @@ public: return updated; } //@} + + virtual bool new_data_available(void) { return true; } float gx() { return 0; } float gy() { return 0; } diff --git a/libraries/AP_IMU/IMU.cpp b/libraries/AP_IMU/IMU.cpp index 913020235b..2fabe704b8 100644 --- a/libraries/AP_IMU/IMU.cpp +++ b/libraries/AP_IMU/IMU.cpp @@ -30,6 +30,7 @@ void IMU::init_gyro(void (*delay_cb)(unsigned long t), void (*flash_leds_cb)(boo { } bool IMU::update(void) { return false; } +bool IMU::new_data_available(void) { return true; } float IMU::gx(void) { return 0.0; } float IMU::gy(void) { return 0.0; } diff --git a/libraries/AP_IMU/IMU.h b/libraries/AP_IMU/IMU.h index 8691e2663b..da259e5370 100644 --- a/libraries/AP_IMU/IMU.h +++ b/libraries/AP_IMU/IMU.h @@ -62,6 +62,9 @@ public: /// virtual bool update(void); + // true if new data is available from the sensors + virtual bool new_data_available(void); + /// Fetch the current gyro values /// /// @returns vector of rotational rates in radians/sec From c369d9f60a3c29e58f7b4f1db1b882a443543caa Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 3 Mar 2012 18:32:50 +1100 Subject: [PATCH 046/178] AP_Quaternion: added DCM compatibility interfaces useful for getting the code going quickly --- libraries/AP_Quaternion/AP_Quaternion.cpp | 25 +++++++++++++++++++++-- libraries/AP_Quaternion/AP_Quaternion.h | 18 ++++++++++++++++ 2 files changed, 41 insertions(+), 2 deletions(-) diff --git a/libraries/AP_Quaternion/AP_Quaternion.cpp b/libraries/AP_Quaternion/AP_Quaternion.cpp index aedf1cd78b..7a809b3f39 100644 --- a/libraries/AP_Quaternion/AP_Quaternion.cpp +++ b/libraries/AP_Quaternion/AP_Quaternion.cpp @@ -249,19 +249,36 @@ void AP_Quaternion::update(void) _imu->update(); - delta_t = _imu->get_delta_time(); + deltat = _imu->get_delta_time(); // get current IMU state gyro = _imu->get_gyro(); + accel = _imu->get_accel(); + + // keep a smoothed gyro vector for centripetal and reporting + // to mainline code + _gyro_smoothed = (_gyro_smoothed * 0.95) + (gyro * 0.05); + + // Quaternion code uses opposite x and y gyro sense gyro.x = -gyro.x; gyro.y = -gyro.y; - accel = _imu->get_accel(); + + if (_centripetal && _gps && _gps->status() == GPS::GPS_OK) { + // compensate for centripetal acceleration + float veloc; + veloc = _gps->ground_speed / 100; + accel.y -= _gyro_smoothed.z * veloc; + accel.z += _gyro_smoothed.y * veloc; + } + + // Quaternion code uses opposite z accel accel.z = -accel.z; if (_compass == NULL) { update_IMU(deltat, gyro, accel); } else { + // mag.z is reversed in quaternion code Vector3f mag = Vector3f(_compass->mag_x, _compass->mag_y, - _compass->mag_z); update_MARG(deltat, gyro, accel, mag); } @@ -289,6 +306,10 @@ void AP_Quaternion::update(void) 1 - 2.0*(SEq_3*SEq_3 + SEq_4*SEq_4)); } + if (_compass != NULL) { + yaw += _compass->get_declination(); + } + // and integer Eulers roll_sensor = 100 * ToDeg(roll); pitch_sensor = 100 * ToDeg(pitch); diff --git a/libraries/AP_Quaternion/AP_Quaternion.h b/libraries/AP_Quaternion/AP_Quaternion.h index 41c76904c3..7d0f11d783 100644 --- a/libraries/AP_Quaternion/AP_Quaternion.h +++ b/libraries/AP_Quaternion/AP_Quaternion.h @@ -56,6 +56,21 @@ public: int32_t yaw_sensor; + // compatibility methods with DCM + void update_DCM(void) { update(); } + void update_DCM_fast(void) { update(); } + Vector3f get_gyro(void) { return _gyro_smoothed; } + Vector3f get_integrator(void) { return Vector3f(0,0,0); } + float get_accel_weight(void) { return 0; } + float get_renorm_val(void) { return 0; } + float get_error_rp(void) { return 0; } + float get_error_yaw(void) { return 0; } + float get_health(void) { return 0; } + void matrix_reset(void) { } + uint8_t gyro_sat_count; + uint8_t renorm_range_count; + uint8_t renorm_blowup_count; + private: void update_IMU(float deltat, Vector3f &gyro, Vector3f &accel); void update_MARG(float deltat, Vector3f &gyro, Vector3f &accel, Vector3f &mag); @@ -93,6 +108,9 @@ private: // estimate gyroscope biases error Vector3f gyro_bias; + + // smoothed gyro estimate + Vector3f _gyro_smoothed; }; #endif From e39c3cb9d28a5c568d190c880064ed944c51e839 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 3 Mar 2012 18:33:40 +1100 Subject: [PATCH 047/178] APM: make it possible to build ArduPlane with quaternion support --- ArduPlane/ArduPlane.pde | 20 +++++++++++++++++--- ArduPlane/GCS_Mavlink.pde | 2 ++ ArduPlane/Makefile | 3 +++ ArduPlane/config.h | 5 +++++ ArduPlane/test.pde | 14 ++++++++++++-- 5 files changed, 39 insertions(+), 5 deletions(-) diff --git a/ArduPlane/ArduPlane.pde b/ArduPlane/ArduPlane.pde index 4643de01b1..b7ff74cb80 100644 --- a/ArduPlane/ArduPlane.pde +++ b/ArduPlane/ArduPlane.pde @@ -41,6 +41,7 @@ version 2.1 of the License, or (at your option) any later version. #include // Inertial Sensor (uncalibated IMU) Library #include // ArduPilot Mega IMU Library #include // ArduPilot Mega DCM Library +#include // Madgwick quaternion system #include // PID library #include // RC Channel Library #include // Range finder library @@ -186,7 +187,15 @@ AP_GPS_None g_gps_driver(NULL); AP_InertialSensor_Oilpan ins( &adc ); #endif // CONFIG_IMU_TYPE AP_IMU_INS imu( &ins ); -AP_DCM dcm(&imu, g_gps); + +#if QUATERNION_ENABLE == ENABLED + // this shouldn't be called dcm of course, but until we + // decide to actually use something else, I don't want the patch + // size to be huge + AP_Quaternion dcm(&imu, g_gps); +#else + AP_DCM dcm(&imu, g_gps); +#endif #elif HIL_MODE == HIL_MODE_SENSORS // sensor emulators @@ -709,7 +718,7 @@ static void fast_loop() gcs_update(); #endif - dcm.update_DCM(); + dcm.update_DCM(); // uses the yaw from the DCM to give more accurate turns calc_bearing_error(); @@ -771,8 +780,13 @@ static void medium_loop() #if HIL_MODE != HIL_MODE_ATTITUDE if (g.compass_enabled && compass.read()) { dcm.set_compass(&compass); - compass.calculate(dcm.get_dcm_matrix()); // Calculate heading + // Calculate heading +#if QUATERNION_ENABLE == ENABLED + compass.calculate(dcm.roll, dcm.pitch); +#else + compass.calculate(dcm.get_dcm_matrix()); compass.null_offsets(dcm.get_dcm_matrix()); +#endif } else { dcm.set_compass(NULL); } diff --git a/ArduPlane/GCS_Mavlink.pde b/ArduPlane/GCS_Mavlink.pde index a2e8a40cb4..183a049c45 100644 --- a/ArduPlane/GCS_Mavlink.pde +++ b/ArduPlane/GCS_Mavlink.pde @@ -306,6 +306,7 @@ static void NOINLINE send_meminfo(mavlink_channel_t chan) static void NOINLINE send_location(mavlink_channel_t chan) { +#if QUATERNION_ENABLE == DISABLED Matrix3f rot = dcm.get_dcm_matrix(); // neglecting angle of attack for now mavlink_msg_global_position_int_send( chan, @@ -318,6 +319,7 @@ static void NOINLINE send_location(mavlink_channel_t chan) g_gps->ground_speed * rot.b.x, // Y speed cm/s g_gps->ground_speed * rot.c.x, g_gps->ground_course); // course in 1/100 degree +#endif } static void NOINLINE send_nav_controller_output(mavlink_channel_t chan) diff --git a/ArduPlane/Makefile b/ArduPlane/Makefile index 84b05b1e04..8efe6bba47 100644 --- a/ArduPlane/Makefile +++ b/ArduPlane/Makefile @@ -30,6 +30,9 @@ mavlink10: sitl: make -f ../libraries/Desktop/Makefile.desktop +sitl-quaternion: + make -f ../libraries/Desktop/Makefile.desktop EXTRAFLAGS="-DQUATERNION_ENABLE=ENABLED" + etags: cd .. && etags -f ArduPlane/TAGS --langmap=C++:.pde.cpp.h $$(git ls-files ArduPlane libraries) diff --git a/ArduPlane/config.h b/ArduPlane/config.h index 227dc0f63c..435676d94c 100644 --- a/ArduPlane/config.h +++ b/ArduPlane/config.h @@ -833,3 +833,8 @@ #ifndef RESET_SWITCH_CHAN_PWM # define RESET_SWITCH_CHAN_PWM 1750 #endif + +// experimental quaternion code +#ifndef QUATERNION_ENABLE +# define QUATERNION_ENABLE DISABLED +#endif diff --git a/ArduPlane/test.pde b/ArduPlane/test.pde index 2b0b726b07..fedb2fdb50 100644 --- a/ArduPlane/test.pde +++ b/ArduPlane/test.pde @@ -534,7 +534,12 @@ test_imu(uint8_t argc, const Menu::arg *argv) medium_loopCounter++; if(medium_loopCounter == 5){ if (compass.read()) { - compass.calculate(dcm.get_dcm_matrix()); // Calculate heading + // Calculate heading +#if QUATERNION_ENABLE == ENABLED + compass.calculate(dcm.roll, dcm.pitch); +#else + compass.calculate(dcm.get_dcm_matrix()); +#endif } medium_loopCounter = 0; } @@ -599,8 +604,13 @@ test_mag(uint8_t argc, const Menu::arg *argv) medium_loopCounter++; if(medium_loopCounter == 5){ if (compass.read()) { - compass.calculate(dcm.get_dcm_matrix()); // Calculate heading + // Calculate heading +#if QUATERNION_ENABLE == ENABLED + compass.calculate(dcm.roll, dcm.pitch); +#else + compass.calculate(dcm.get_dcm_matrix()); compass.null_offsets(dcm.get_dcm_matrix()); +#endif } medium_loopCounter = 0; } From 9bff4e2c4c36de6f614b23a6d6585c30bef4d5e1 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 3 Mar 2012 18:34:24 +1100 Subject: [PATCH 048/178] ACM: only call the fast loop if the imu has new data this prevents us spinning waiting for the sensors to gather some data --- ArduCopter/ArduCopter.pde | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ArduCopter/ArduCopter.pde b/ArduCopter/ArduCopter.pde index 1a31602067..7578d4ca16 100644 --- a/ArduCopter/ArduCopter.pde +++ b/ArduCopter/ArduCopter.pde @@ -844,7 +844,7 @@ void loop() uint32_t timer = micros(); // We want this to execute fast // ---------------------------- - if ((timer - fast_loopTimer) >= 4000) { + if ((timer - fast_loopTimer) >= 4000 && imu.new_data_available()) { //Log_Write_Data(13, (int32_t)(timer - fast_loopTimer)); //PORTK |= B00010000; From 7e4c8592ff13950c8f547f3c514c2b4dcabb8923 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 3 Mar 2012 18:35:39 +1100 Subject: [PATCH 049/178] ACM: make it possible to build ArduCopter with quaternions --- ArduCopter/ArduCopter.pde | 39 ++++++++++++++++++++++++++++++++++++-- ArduCopter/GCS_Mavlink.pde | 2 ++ ArduCopter/Makefile | 3 +++ ArduCopter/config.h | 4 ++++ ArduCopter/system.pde | 2 ++ ArduCopter/test.pde | 17 +++++++++++++++-- 6 files changed, 63 insertions(+), 4 deletions(-) diff --git a/ArduCopter/ArduCopter.pde b/ArduCopter/ArduCopter.pde index 7578d4ca16..15a5e6682d 100644 --- a/ArduCopter/ArduCopter.pde +++ b/ArduCopter/ArduCopter.pde @@ -72,6 +72,7 @@ http://code.google.com/p/ardupilot-mega/downloads/list #include // Parent header of Timer // (only included for makefile libpath to work) #include // TimerProcess is the scheduler for MPU6000 reads. +#include // Madgwick quaternion system #include // ArduPilot Mega DCM Library #include // PI library #include // PID library @@ -222,10 +223,20 @@ AP_InertialSensor_MPU6000 ins( CONFIG_MPU6000_CHIP_SELECT_PIN ); AP_InertialSensor_Oilpan ins(&adc); #endif AP_IMU_INS imu(&ins); + // we don't want to use gps for yaw correction on ArduCopter, so pass // a NULL GPS object pointer static GPS *g_gps_null; -AP_DCM dcm(&imu, g_gps_null); + +#if QUATERNION_ENABLE == ENABLED + // this shouldn't be called dcm of course, but until we + // decide to actually use something else, I don't want the patch + // size to be huge + AP_Quaternion dcm(&imu, g_gps_null); +#else + AP_DCM dcm(&imu, g_gps_null); +#endif + AP_TimerProcess timer_scheduler; #elif HIL_MODE == HIL_MODE_SENSORS @@ -842,6 +853,7 @@ void setup() { void loop() { uint32_t timer = micros(); + // We want this to execute fast // ---------------------------- if ((timer - fast_loopTimer) >= 4000 && imu.new_data_available()) { @@ -960,8 +972,13 @@ static void medium_loop() #if HIL_MODE != HIL_MODE_ATTITUDE // don't execute in HIL mode if(g.compass_enabled){ if (compass.read()) { - compass.calculate(dcm.get_dcm_matrix()); // Calculate heading + // Calculate heading +#if QUATERNION_ENABLE == ENABLED + compass.calculate(dcm.roll, dcm.pitch); +#else + compass.calculate(dcm.get_dcm_matrix()); compass.null_offsets(dcm.get_dcm_matrix()); +#endif } } #endif @@ -1844,6 +1861,7 @@ static void read_AHRS(void) } static void update_trig(void){ +#if QUATERNION_ENABLE == DISABLED Vector2f yawvector; Matrix3f temp = dcm.get_dcm_matrix(); @@ -1862,6 +1880,23 @@ static void update_trig(void){ sin_yaw_y = yawvector.x; // 1y = north cos_yaw_x = yawvector.y; // 0x = north +#else + // we need a cheaper way to calculate this .... + Vector2f yawvector; + float cp = cos(dcm.pitch); + float cr = cos(dcm.roll); + float sy = sin(dcm.yaw); + float cy = cos(dcm.yaw); + + yawvector.x = cp * cy; + yawvector.y = cp * sy; + yawvector.normalize(); + + cos_pitch_x = cp; + cos_roll_x = cr; + sin_yaw_y = yawvector.x; + cos_yaw_x = yawvector.y; +#endif //flat: // 0 ° = cos_yaw: 0.00, sin_yaw: 1.00, // 90° = cos_yaw: 1.00, sin_yaw: 0.00, diff --git a/ArduCopter/GCS_Mavlink.pde b/ArduCopter/GCS_Mavlink.pde index 9ac2fd7e07..78fc8f2530 100644 --- a/ArduCopter/GCS_Mavlink.pde +++ b/ArduCopter/GCS_Mavlink.pde @@ -99,6 +99,7 @@ static void NOINLINE send_meminfo(mavlink_channel_t chan) static void NOINLINE send_location(mavlink_channel_t chan) { +#if QUATERNION_ENABLE == DISABLED Matrix3f rot = dcm.get_dcm_matrix(); // neglecting angle of attack for now mavlink_msg_global_position_int_send( chan, @@ -108,6 +109,7 @@ static void NOINLINE send_location(mavlink_channel_t chan) g_gps->ground_speed * rot.a.x, g_gps->ground_speed * rot.b.x, g_gps->ground_speed * rot.c.x); +#endif } static void NOINLINE send_nav_controller_output(mavlink_channel_t chan) diff --git a/ArduCopter/Makefile b/ArduCopter/Makefile index 5d4f5f3732..39784e4912 100644 --- a/ArduCopter/Makefile +++ b/ArduCopter/Makefile @@ -42,6 +42,9 @@ sitl-hexa: sitl-y6: make -f ../libraries/Desktop/Makefile.desktop y6 +sitl-quaternion: + make -f ../libraries/Desktop/Makefile.desktop EXTRAFLAGS="-DQUATERNION_ENABLE=ENABLED" + etags: cd .. && etags -f ArduCopter/TAGS --langmap=C++:.pde.cpp.h $$(git ls-files ArduCopter libraries) diff --git a/ArduCopter/config.h b/ArduCopter/config.h index fd5be47917..a7b3baf794 100644 --- a/ArduCopter/config.h +++ b/ArduCopter/config.h @@ -939,5 +939,9 @@ #endif +// experimental quaternion code +#ifndef QUATERNION_ENABLE +# define QUATERNION_ENABLE DISABLED +#endif #endif // __ARDUCOPTER_CONFIG_H__ diff --git a/ArduCopter/system.pde b/ArduCopter/system.pde index d3e9814d20..1391643a85 100644 --- a/ArduCopter/system.pde +++ b/ArduCopter/system.pde @@ -309,11 +309,13 @@ static void init_ardupilot() reset_control_switch(); #if HIL_MODE != HIL_MODE_ATTITUDE +#if QUATERNION_ENABLE == DISABLED dcm.kp_roll_pitch(0.130000); dcm.ki_roll_pitch(0.00001278), // 50 hz I term dcm.kp_yaw(0.12); dcm.ki_yaw(0.00002); dcm._clamp = 5; +#endif #endif // init the Z damopener diff --git a/ArduCopter/test.pde b/ArduCopter/test.pde index 766b23205d..00a3dcb89d 100644 --- a/ArduCopter/test.pde +++ b/ArduCopter/test.pde @@ -330,8 +330,12 @@ test_radio(uint8_t argc, const Menu::arg *argv) medium_loopCounter++; if(medium_loopCounter == 5){ compass.read(); // Read magnetometer - compass.calculate(dcm.roll, dcm.pitch); // Calculate heading - compass.null_offsets(dcm.get_dcm_matrix()); +#if QUATERNION_ENABLE == ENABLED + compass.calculate(dcm.roll, dcm.pitch); +#else + compass.calculate(dcm.get_dcm_matrix()); + compass.null_offsets(dcm.get_dcm_matrix()); +#endif medium_loopCounter = 0; } } @@ -548,7 +552,12 @@ test_imu(uint8_t argc, const Menu::arg *argv) if(g.compass_enabled){ compass.read(); // Read magnetometer +#if QUATERNION_ENABLE == ENABLED + compass.calculate(dcm.roll, dcm.pitch); +#else compass.calculate(dcm.get_dcm_matrix()); + compass.null_offsets(dcm.get_dcm_matrix()); +#endif } } fast_loopTimer = millis(); @@ -932,7 +941,11 @@ test_mag(uint8_t argc, const Menu::arg *argv) while(1){ delay(100); if (compass.read()) { +#if QUATERNION_ENABLE == ENABLED + compass.calculate(dcm.roll, dcm.pitch); +#else compass.calculate(dcm.get_dcm_matrix()); +#endif Vector3f maggy = compass.get_offsets(); Serial.printf_P(PSTR("Heading: %ld, XYZ: %d, %d, %d\n"), (wrap_360(ToDeg(compass.heading) * 100)) /100, From 25e5ddeaa4632435039ab7a2c93e3fedb270b66c Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 3 Mar 2012 20:12:28 +1100 Subject: [PATCH 050/178] AP_Quaternion: fixed build on Arduino 1.0 --- libraries/AP_Quaternion/AP_Quaternion.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/libraries/AP_Quaternion/AP_Quaternion.cpp b/libraries/AP_Quaternion/AP_Quaternion.cpp index 7a809b3f39..1e7f2ffcdb 100644 --- a/libraries/AP_Quaternion/AP_Quaternion.cpp +++ b/libraries/AP_Quaternion/AP_Quaternion.cpp @@ -11,6 +11,7 @@ version 2.1 of the License, or (at your option) any later version. */ +#include #include #define ToRad(x) (x*0.01745329252) // *pi/180 From bee4bd94748b1ee8b3ea869d4e5e9b9751ecf50f Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 3 Mar 2012 20:23:23 +1100 Subject: [PATCH 051/178] DCM: fixed bug in accel averaging sorry Randy! --- libraries/AP_DCM/AP_DCM.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/libraries/AP_DCM/AP_DCM.cpp b/libraries/AP_DCM/AP_DCM.cpp index 6d79b0c3cd..7d9551da47 100644 --- a/libraries/AP_DCM/AP_DCM.cpp +++ b/libraries/AP_DCM/AP_DCM.cpp @@ -78,6 +78,7 @@ AP_DCM::update_DCM_fast(void) case 2: _accel_vector = _accel_sum / _accel_sum_count; _accel_sum_count = 0; + _accel_sum.zero(); drift_correction(); // Normalize the DCM matrix break; From ffa678669726189b3571e45cbaecde9fe72e4700 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 3 Mar 2012 20:47:15 +1100 Subject: [PATCH 052/178] Quaternion: drop the gyro drift rates down this should allow us to cope with noise more readily --- libraries/AP_Quaternion/AP_Quaternion.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libraries/AP_Quaternion/AP_Quaternion.h b/libraries/AP_Quaternion/AP_Quaternion.h index 7d0f11d783..44ec9a238c 100644 --- a/libraries/AP_Quaternion/AP_Quaternion.h +++ b/libraries/AP_Quaternion/AP_Quaternion.h @@ -91,11 +91,11 @@ private: // true if we are doing centripetal acceleration correction bool _centripetal; - // maximum gyroscope measurement error in rad/s (set to 5 degrees/second) - static const float gyroMeasError = 5.0 * (M_PI/180.0); + // maximum gyroscope measurement error in rad/s (set to 2 degrees/second) + static const float gyroMeasError = 2.0 * (M_PI/180.0); - // maximum gyroscope drift rate in radians/s/s (set to 0.2 degrees/s/s) - static const float gyroMeasDrift = 0.2 * (PI/180.0); + // maximum gyroscope drift rate in radians/s/s (set to 0.03 degrees/s/s) + static const float gyroMeasDrift = 0.03 * (PI/180.0); float beta; float zeta; From cc887949c965617d2527c758b775130431816966 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 3 Mar 2012 22:19:13 +1100 Subject: [PATCH 053/178] AP_IMU: improved the gyro calibration code this should give a much more accurate result --- libraries/AP_IMU/AP_IMU_INS.cpp | 98 ++++++++++++++++++--------------- libraries/AP_IMU/AP_IMU_INS.h | 4 +- 2 files changed, 55 insertions(+), 47 deletions(-) diff --git a/libraries/AP_IMU/AP_IMU_INS.cpp b/libraries/AP_IMU/AP_IMU_INS.cpp index fca618f13a..164e12b3d8 100644 --- a/libraries/AP_IMU/AP_IMU_INS.cpp +++ b/libraries/AP_IMU/AP_IMU_INS.cpp @@ -56,18 +56,15 @@ AP_IMU_INS::init_gyro(void (*delay_cb)(unsigned long t), void (*flash_leds_cb)(b void AP_IMU_INS::_init_gyro(void (*delay_cb)(unsigned long t), void (*flash_leds_cb)(bool on)) { - int flashcount = 0; - float adc_in; - float prev[3] = {0,0,0}; - float total_change; - float max_offset; - float ins_gyro[6]; + Vector3f last_average, best_avg; + float ins_gyro[3]; + float best_diff; // cold start - delay_cb(500); + delay_cb(100); Serial.printf_P(PSTR("Init Gyro")); - for(int c = 0; c < 25; c++){ + for(int c = 0; c < 25; c++) { // Mostly we are just flashing the LED's here // to tell the user to keep the IMU still FLASH_LEDS(true); @@ -80,49 +77,62 @@ AP_IMU_INS::_init_gyro(void (*delay_cb)(unsigned long t), void (*flash_leds_cb)( delay_cb(20); } - for (int j = 0; j <= 2; j++) - _sensor_cal[j] = 500; // Just a large value to load prev[j] the first time + // the strategy is to average 100 points, then do it again and + // see if the 2nd average is within a small margin of the first - do { + last_average.zero(); - _ins->update(); - _ins->get_gyros(ins_gyro); + // we try to get a good calibration estimate for up to 10 seconds + // if the gyros are stable, we should get it in 2 seconds + for (int j = 0; j <= 10; j++) { + Vector3f gyro_sum, gyro_avg, gyro_diff; + float diff_norm; + uint8_t i; - for (int j = 0; j <= 2; j++){ - prev[j] = _sensor_cal[j]; - adc_in = ins_gyro[j]; - _sensor_cal[j] = adc_in; - } + Serial.printf_P(PSTR("*")); - for(int i = 0; i < 50; i++){ - - _ins->update(); - _ins->get_gyros(ins_gyro); - - for (int j = 0; j < 3; j++){ - adc_in = ins_gyro[j]; - // filter - _sensor_cal[j] = _sensor_cal[j] * 0.9 + adc_in * 0.1; - } - - delay_cb(20); - if(flashcount == 5) { - Serial.printf_P(PSTR("*")); + gyro_sum.zero(); + for (i=0; i<200; i++) { + _ins->update(); + _ins->get_gyros(ins_gyro); + gyro_sum += Vector3f(ins_gyro[0], ins_gyro[1], ins_gyro[2]); + if (i % 40 == 20) { FLASH_LEDS(true); - } - - if(flashcount >= 10) { - flashcount = 0; + } else if (i % 40 == 20) { FLASH_LEDS(false); - } - flashcount++; - } + } + delay_cb(5); + } + gyro_avg = gyro_sum / i; - total_change = fabs(prev[0] - _sensor_cal[0]) + fabs(prev[1] - _sensor_cal[1]) +fabs(prev[2] - _sensor_cal[2]); - max_offset = (_sensor_cal[0] > _sensor_cal[1]) ? _sensor_cal[0] : _sensor_cal[1]; - max_offset = (max_offset > _sensor_cal[2]) ? max_offset : _sensor_cal[2]; - delay_cb(500); - } while ( total_change > _gyro_total_cal_change || max_offset > _gyro_max_cal_offset); + gyro_diff = last_average - gyro_avg; + diff_norm = gyro_diff.length(); + + if (j == 0) { + best_diff = diff_norm; + best_avg = gyro_avg; + } else if (gyro_diff.length() < ToRad(0.04)) { + // we want the average to be within 0.1 bit, which is 0.04 degrees/s + last_average = (gyro_avg * 0.5) + (last_average * 0.5); + _sensor_cal[0] = last_average.x; + _sensor_cal[1] = last_average.y; + _sensor_cal[2] = last_average.z; + // all done + return; + } else if (diff_norm < best_diff) { + best_diff = diff_norm; + best_avg = (gyro_avg * 0.5) + (last_average * 0.5); + } + last_average = gyro_avg; + } + + // we've kept the user waiting long enough - use the best pair we + // found so far + Serial.printf_P(PSTR("\ngyro did not converge: diff=%f dps\n"), ToDeg(best_diff)); + + _sensor_cal[0] = best_avg.x; + _sensor_cal[1] = best_avg.y; + _sensor_cal[2] = best_avg.z; } void diff --git a/libraries/AP_IMU/AP_IMU_INS.h b/libraries/AP_IMU/AP_IMU_INS.h index 54a0b54c80..c9f461f04a 100644 --- a/libraries/AP_IMU/AP_IMU_INS.h +++ b/libraries/AP_IMU/AP_IMU_INS.h @@ -75,10 +75,8 @@ private: float _calibrated(uint8_t channel, float ins_value); - // Gyro and Accelerometer calibration criterial + // Gyro and Accelerometer calibration criteria // - static const float _gyro_total_cal_change = 4.0; // Experimentally derived - allows for some minor motion - static const float _gyro_max_cal_offset = 320.0; static const float _accel_total_cal_change = 4.0; static const float _accel_max_cal_offset = 250.0; From d8234882d48095d490aa05d0f50db354d18a1533 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 3 Mar 2012 22:19:30 +1100 Subject: [PATCH 054/178] Quaternion: tweak the quaternion gains a bit --- libraries/AP_Quaternion/AP_Quaternion.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libraries/AP_Quaternion/AP_Quaternion.h b/libraries/AP_Quaternion/AP_Quaternion.h index 44ec9a238c..359fe088cd 100644 --- a/libraries/AP_Quaternion/AP_Quaternion.h +++ b/libraries/AP_Quaternion/AP_Quaternion.h @@ -91,11 +91,11 @@ private: // true if we are doing centripetal acceleration correction bool _centripetal; - // maximum gyroscope measurement error in rad/s (set to 2 degrees/second) - static const float gyroMeasError = 2.0 * (M_PI/180.0); + // maximum gyroscope measurement error in rad/s (set to 5 degrees/second) + static const float gyroMeasError = 5.0 * (M_PI/180.0); - // maximum gyroscope drift rate in radians/s/s (set to 0.03 degrees/s/s) - static const float gyroMeasDrift = 0.03 * (PI/180.0); + // maximum gyroscope drift rate in radians/s/s (set to 0.02 degrees/s/s) + static const float gyroMeasDrift = 0.02 * (PI/180.0); float beta; float zeta; From c73c55aa902c6c3a151b78e46414feff5ad2aa54 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 3 Mar 2012 22:19:50 +1100 Subject: [PATCH 055/178] DCM: fixed an uninitialised variable warning --- libraries/AP_DCM/AP_DCM.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/AP_DCM/AP_DCM.cpp b/libraries/AP_DCM/AP_DCM.cpp index 7d9551da47..e87a6d0110 100644 --- a/libraries/AP_DCM/AP_DCM.cpp +++ b/libraries/AP_DCM/AP_DCM.cpp @@ -367,7 +367,7 @@ AP_DCM::drift_correction(void) float integrator_magnitude; Vector3f accel; Vector3f error; - float error_norm; + float error_norm = 0; const float gravity_squared = (9.80665*9.80665); accel = _accel_vector; From 2a8b167d95f9103c6a2455ec9c384eb7f75139b4 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 3 Mar 2012 22:23:10 +1100 Subject: [PATCH 056/178] fixed comment --- libraries/AP_IMU/AP_IMU_INS.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/libraries/AP_IMU/AP_IMU_INS.cpp b/libraries/AP_IMU/AP_IMU_INS.cpp index 164e12b3d8..500f4e0c88 100644 --- a/libraries/AP_IMU/AP_IMU_INS.cpp +++ b/libraries/AP_IMU/AP_IMU_INS.cpp @@ -77,8 +77,9 @@ AP_IMU_INS::_init_gyro(void (*delay_cb)(unsigned long t), void (*flash_leds_cb)( delay_cb(20); } - // the strategy is to average 100 points, then do it again and - // see if the 2nd average is within a small margin of the first + // the strategy is to average 200 points over 1 second, then do it + // again and see if the 2nd average is within a small margin of + // the first last_average.zero(); From 7a9b3d33887cf669ce45facf60fca181be3fb2f9 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 3 Mar 2012 22:38:34 +1100 Subject: [PATCH 057/178] Quaternion: show "Quaternion test" on startup if enabled --- ArduCopter/setup.pde | 3 +++ ArduPlane/system.pde | 4 ++++ 2 files changed, 7 insertions(+) diff --git a/ArduCopter/setup.pde b/ArduCopter/setup.pde index 367761968f..8d804de75b 100644 --- a/ArduCopter/setup.pde +++ b/ArduCopter/setup.pde @@ -1162,6 +1162,9 @@ static void report_gps() static void report_version() { Serial.printf_P(PSTR("FW Ver: %d\n"),(int)g.format_version.get()); +#if QUATERNION_ENABLE == ENABLED + Serial.printf_P(PSTR("Quaternion test\n")); +#endif print_divider(); print_blanks(2); } diff --git a/ArduPlane/system.pde b/ArduPlane/system.pde index 28b74098fd..9bcc101e4f 100644 --- a/ArduPlane/system.pde +++ b/ArduPlane/system.pde @@ -103,6 +103,10 @@ static void init_ardupilot() "\n\nFree RAM: %u\n"), memcheck_available_memory()); +#if QUATERNION_ENABLE == ENABLED + Serial.printf_P(PSTR("Quaternion test\n")); +#endif + // // Initialize Wire and SPI libraries // From e699e9ace09695a6f5e96f0c98ed1feabf1f1333 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 3 Mar 2012 23:32:31 +1100 Subject: [PATCH 058/178] Quaternion: added in reporting of gyro drift and rp/yaw errors --- libraries/AP_Quaternion/AP_Quaternion.cpp | 32 +++++++++++++++++++++++ libraries/AP_Quaternion/AP_Quaternion.h | 12 ++++++--- 2 files changed, 41 insertions(+), 3 deletions(-) diff --git a/libraries/AP_Quaternion/AP_Quaternion.cpp b/libraries/AP_Quaternion/AP_Quaternion.cpp index 1e7f2ffcdb..cb6cf426c5 100644 --- a/libraries/AP_Quaternion/AP_Quaternion.cpp +++ b/libraries/AP_Quaternion/AP_Quaternion.cpp @@ -199,6 +199,12 @@ void AP_Quaternion::update_MARG(float deltat, Vector3f &gyro, Vector3f &accel, V w_err.y = twoSEq_1 * SEqHatDot_3 + twoSEq_2 * SEqHatDot_4 - twoSEq_3 * SEqHatDot_1 - twoSEq_4 * SEqHatDot_2; w_err.z = twoSEq_1 * SEqHatDot_4 - twoSEq_2 * SEqHatDot_3 + twoSEq_3 * SEqHatDot_2 - twoSEq_4 * SEqHatDot_1; + // keep track of the error rates + _error_rp_sum += 0.5*(fabs(w_err.x) + fabs(w_err.y)); + _error_yaw_sum += fabs(w_err.z); + _error_rp_count++; + _error_yaw_count++; + // compute and remove the gyroscope baises gyro_bias += w_err * (deltat * zeta); gyro -= gyro_bias; @@ -319,3 +325,29 @@ void AP_Quaternion::update(void) yaw_sensor += 36000; } } + +// average error in roll/pitch since last call +float AP_Quaternion::get_error_rp(void) +{ + float ret; + if (_error_rp_count == 0) { + return 0; + } + ret = _error_rp_sum / _error_rp_count; + _error_rp_sum = 0; + _error_rp_count = 0; + return ret; +} + +// average error in yaw since last call +float AP_Quaternion::get_error_yaw(void) +{ + float ret; + if (_error_yaw_count == 0) { + return 0; + } + ret = _error_yaw_sum / _error_yaw_count; + _error_yaw_sum = 0; + _error_yaw_count = 0; + return ret; +} diff --git a/libraries/AP_Quaternion/AP_Quaternion.h b/libraries/AP_Quaternion/AP_Quaternion.h index 359fe088cd..4550a62dd2 100644 --- a/libraries/AP_Quaternion/AP_Quaternion.h +++ b/libraries/AP_Quaternion/AP_Quaternion.h @@ -60,16 +60,16 @@ public: void update_DCM(void) { update(); } void update_DCM_fast(void) { update(); } Vector3f get_gyro(void) { return _gyro_smoothed; } - Vector3f get_integrator(void) { return Vector3f(0,0,0); } + Vector3f get_integrator(void) { return gyro_bias; } float get_accel_weight(void) { return 0; } float get_renorm_val(void) { return 0; } - float get_error_rp(void) { return 0; } - float get_error_yaw(void) { return 0; } float get_health(void) { return 0; } void matrix_reset(void) { } uint8_t gyro_sat_count; uint8_t renorm_range_count; uint8_t renorm_blowup_count; + float get_error_rp(void); + float get_error_yaw(void); private: void update_IMU(float deltat, Vector3f &gyro, Vector3f &accel); @@ -111,6 +111,12 @@ private: // smoothed gyro estimate Vector3f _gyro_smoothed; + + // estimate of error + float _error_rp_sum; + uint16_t _error_rp_count; + float _error_yaw_sum; + uint16_t _error_yaw_count; }; #endif From 7fbfcc2721b2125286356a352a4434425a92ed32 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 4 Mar 2012 20:32:56 +1100 Subject: [PATCH 059/178] GPS: fixed some stdint types --- libraries/AP_GPS/AP_GPS_Auto.cpp | 4 ++-- libraries/AP_GPS/AP_GPS_NMEA.cpp | 6 +++--- libraries/AP_GPS/AP_GPS_NMEA.h | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/libraries/AP_GPS/AP_GPS_Auto.cpp b/libraries/AP_GPS/AP_GPS_Auto.cpp index 55807f4c52..78c8411f30 100644 --- a/libraries/AP_GPS/AP_GPS_Auto.cpp +++ b/libraries/AP_GPS/AP_GPS_Auto.cpp @@ -55,7 +55,7 @@ AP_GPS_Auto::read(void) { GPS *gps; uint8_t i; - unsigned long then; + uint32_t then; // Loop through possible baudrates trying to detect a GPS at one of them. // @@ -96,7 +96,7 @@ AP_GPS_Auto::read(void) GPS * AP_GPS_Auto::_detect(void) { - unsigned long then; + uint32_t then; uint8_t fingerprint[4]; uint8_t tries; uint16_t charcount; diff --git a/libraries/AP_GPS/AP_GPS_NMEA.cpp b/libraries/AP_GPS/AP_GPS_NMEA.cpp index 473601b9d6..15bc788d5a 100644 --- a/libraries/AP_GPS/AP_GPS_NMEA.cpp +++ b/libraries/AP_GPS/AP_GPS_NMEA.cpp @@ -184,10 +184,10 @@ int AP_GPS_NMEA::_from_hex(char a) return a - '0'; } -unsigned long AP_GPS_NMEA::_parse_decimal() +uint32_t AP_GPS_NMEA::_parse_decimal() { char *p = _term; - unsigned long ret = 100UL * atol(p); + uint32_t ret = 100UL * atol(p); while (isdigit(*p)) ++p; if (*p == '.') { @@ -200,7 +200,7 @@ unsigned long AP_GPS_NMEA::_parse_decimal() return ret; } -unsigned long AP_GPS_NMEA::_parse_degrees() +uint32_t AP_GPS_NMEA::_parse_degrees() { char *p, *q; uint8_t deg = 0, min = 0; diff --git a/libraries/AP_GPS/AP_GPS_NMEA.h b/libraries/AP_GPS/AP_GPS_NMEA.h index 546480e97e..23be743ba8 100644 --- a/libraries/AP_GPS/AP_GPS_NMEA.h +++ b/libraries/AP_GPS/AP_GPS_NMEA.h @@ -96,7 +96,7 @@ private: /// @returns The value expressed by the string in _term, /// multiplied by 100. /// - unsigned long _parse_decimal(); + uint32_t _parse_decimal(); /// Parses the current term as a NMEA-style degrees + minutes /// value with up to four decimal digits. @@ -106,7 +106,7 @@ private: /// @returns The value expressed by the string in _term, /// multiplied by 10000. /// - unsigned long _parse_degrees(); + uint32_t _parse_degrees(); /// Processes the current term when it has been deemed to be /// complete. From 57f67ca6e3e815a465e888dda33425b1e5e8ce0b Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 4 Mar 2012 20:33:12 +1100 Subject: [PATCH 060/178] GPS: added an acceleration estimate to the GPS driver This uses the GPS ground speed to estimate acceleration --- libraries/AP_GPS/GPS.cpp | 18 ++++++++++++++++++ libraries/AP_GPS/GPS.h | 15 +++++++++++++-- 2 files changed, 31 insertions(+), 2 deletions(-) diff --git a/libraries/AP_GPS/GPS.cpp b/libraries/AP_GPS/GPS.cpp index 87c4c8f2e3..6fcde0429a 100644 --- a/libraries/AP_GPS/GPS.cpp +++ b/libraries/AP_GPS/GPS.cpp @@ -33,6 +33,24 @@ GPS::update(void) // reset the idle timer _idleTimer = millis(); + + if (_status == GPS_OK) { + // update our acceleration + float deltat = 1.0e-3 * (_idleTimer - _last_fix_time); + float deltav = 1.0e-2 * ((float)ground_speed - (float)_last_ground_speed); + _last_fix_time = _idleTimer; + _last_ground_speed = ground_speed; + + if (deltat > 2.0 || deltat == 0) { + // we didn't get a fix for 2 seconds - set + // acceleration to zero, as the estimate will be too + // far out + _acceleration = 0; + } else { + // calculate a mildly smoothed acceleration value + _acceleration = (0.7 * _acceleration) + (0.3 * (deltav/deltat)); + } + } } } diff --git a/libraries/AP_GPS/GPS.h b/libraries/AP_GPS/GPS.h index 397fbfad5b..9889f96a02 100644 --- a/libraries/AP_GPS/GPS.h +++ b/libraries/AP_GPS/GPS.h @@ -108,7 +108,10 @@ public: /// 1200ms allows a small amount of slack over the worst-case 1Hz update /// rate. /// - unsigned long idleTimeout; + uint32_t idleTimeout; + + // our approximate linear acceleration in m/s/s + float acceleration(void) { return _acceleration; } protected: Stream *_port; ///< port the GPS is attached to @@ -165,11 +168,19 @@ private: /// Last time that the GPS driver got a good packet from the GPS /// - unsigned long _idleTimer; + uint32_t _idleTimer; /// Our current status GPS_Status _status; + // the time we got our last fix in system milliseconds + uint32_t _last_fix_time; + + // previous ground speed in cm/s + uint32_t _last_ground_speed; + + // smoothed estimate of our acceleration + float _acceleration; }; inline long From ebc55bb494edc1bd7be058f0f8cdcb6c8c84907a Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 4 Mar 2012 20:34:24 +1100 Subject: [PATCH 061/178] RC: disable interrupts when reading the RC registers this prevents getting bogus values which could cause a flight mode change --- libraries/APM_RC/APM_RC_APM1.cpp | 30 +++++++++++++++--------------- libraries/APM_RC/APM_RC_APM2.cpp | 25 +++++++++++++------------ 2 files changed, 28 insertions(+), 27 deletions(-) diff --git a/libraries/APM_RC/APM_RC_APM1.cpp b/libraries/APM_RC/APM_RC_APM1.cpp index add4693172..4370378178 100644 --- a/libraries/APM_RC/APM_RC_APM1.cpp +++ b/libraries/APM_RC/APM_RC_APM1.cpp @@ -193,24 +193,24 @@ void APM_RC_APM1::disable_out(uint8_t ch) uint16_t APM_RC_APM1::InputCh(uint8_t ch) { - uint16_t result; + uint16_t result; - if (_HIL_override[ch] != 0) { - return _HIL_override[ch]; - } + if (_HIL_override[ch] != 0) { + return _HIL_override[ch]; + } - // Because servo pulse variables are 16 bits and the interrupts are running values could be corrupted. - // We dont want to stop interrupts to read radio channels so we have to do two readings to be sure that the value is correct... - result = _PWM_RAW[ch]; - if (result != _PWM_RAW[ch]) { - result = _PWM_RAW[ch]; // if the results are different we make a third reading (this should be fine) - } - result >>= 1; // Because timer runs at 0.5us we need to do value/2 + // we need to stop interrupts to be sure we get a correct 16 bit value + cli(); + result = _PWM_RAW[ch]; + sei(); - // Limit values to a valid range - result = constrain(result,MIN_PULSEWIDTH,MAX_PULSEWIDTH); - _radio_status=0; // Radio channel read - return(result); + // Because timer runs at 0.5us we need to do value/2 + result >>= 1; + + // Limit values to a valid range + result = constrain(result,MIN_PULSEWIDTH,MAX_PULSEWIDTH); + _radio_status = 0; // Radio channel read + return result; } uint8_t APM_RC_APM1::GetState(void) diff --git a/libraries/APM_RC/APM_RC_APM2.cpp b/libraries/APM_RC/APM_RC_APM2.cpp index c76c71c08c..0a728cf4f4 100644 --- a/libraries/APM_RC/APM_RC_APM2.cpp +++ b/libraries/APM_RC/APM_RC_APM2.cpp @@ -20,6 +20,7 @@ */ #include "APM_RC_APM2.h" +#include #if defined(ARDUINO) && ARDUINO >= 100 #include "Arduino.h" #else @@ -194,24 +195,24 @@ void APM_RC_APM2::disable_out(uint8_t ch) uint16_t APM_RC_APM2::InputCh(unsigned char ch) { - uint16_t result; - uint16_t result2; + uint16_t result; if (_HIL_override[ch] != 0) { return _HIL_override[ch]; } - // Because servo pulse variables are 16 bits and the interrupts are running values could be corrupted. - // We dont want to stop interrupts to read radio channels so we have to do two readings to be sure that the value is correct... - result = _PWM_RAW[ch]>>1; // Because timer runs at 0.5us we need to do value/2 - result2 = _PWM_RAW[ch]>>1; - if (result != result2) - result = _PWM_RAW[ch]>>1; // if the results are different we make a third reading (this should be fine) + // we need to block interrupts during the read of a 16 bit + // value + cli(); + result = _PWM_RAW[ch]; + sei(); + // Because timer runs at 0.5us we need to do value/2 + result >>= 1; - // Limit values to a valid range - result = constrain(result,MIN_PULSEWIDTH,MAX_PULSEWIDTH); - _radio_status=0; // Radio channel read - return(result); + // Limit values to a valid range + result = constrain(result,MIN_PULSEWIDTH,MAX_PULSEWIDTH); + _radio_status = 0; // Radio channel read + return result; } unsigned char APM_RC_APM2::GetState(void) From 6d356b6c6ee11527232a25f9cdad5eb5e182a21f Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 4 Mar 2012 20:34:44 +1100 Subject: [PATCH 062/178] Compass: fixed last_update time for HIL compass --- libraries/AP_Compass/AP_Compass_HIL.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/libraries/AP_Compass/AP_Compass_HIL.cpp b/libraries/AP_Compass/AP_Compass_HIL.cpp index ba77a74d98..f57d7f5320 100644 --- a/libraries/AP_Compass/AP_Compass_HIL.cpp +++ b/libraries/AP_Compass/AP_Compass_HIL.cpp @@ -16,6 +16,7 @@ bool AP_Compass_HIL::read() { // values set by setHIL function + last_update = millis(); // record time of update return true; } From c7ef72cf28fedc9711d6ffa031ffedb924dcebfd Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 4 Mar 2012 20:35:08 +1100 Subject: [PATCH 063/178] Quaternion: don't update if we have a very long deltat this can be caused by stopping the system in a debugger --- libraries/AP_Quaternion/AP_Quaternion.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/libraries/AP_Quaternion/AP_Quaternion.cpp b/libraries/AP_Quaternion/AP_Quaternion.cpp index cb6cf426c5..a50f9ef86d 100644 --- a/libraries/AP_Quaternion/AP_Quaternion.cpp +++ b/libraries/AP_Quaternion/AP_Quaternion.cpp @@ -257,6 +257,13 @@ void AP_Quaternion::update(void) _imu->update(); deltat = _imu->get_delta_time(); + if (deltat > 1.0) { + // if we stop updating for 1s, we should discard this + // input data. This can happen if you are running the + // code under a debugger, and using this data point + // will just throw off your attitude by a huge amount + return; + } // get current IMU state gyro = _imu->get_gyro(); From 7256652de5bfddf36b4db0797c7c37adb11598a1 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 4 Mar 2012 20:35:40 +1100 Subject: [PATCH 064/178] Quaternion: use GPS to correct for linear acceleration this gives much better pitch estimates. We should do this with the airspeed sensor if available. --- libraries/AP_Quaternion/AP_Quaternion.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/libraries/AP_Quaternion/AP_Quaternion.cpp b/libraries/AP_Quaternion/AP_Quaternion.cpp index a50f9ef86d..1b4346657f 100644 --- a/libraries/AP_Quaternion/AP_Quaternion.cpp +++ b/libraries/AP_Quaternion/AP_Quaternion.cpp @@ -282,6 +282,7 @@ void AP_Quaternion::update(void) // compensate for centripetal acceleration float veloc; veloc = _gps->ground_speed / 100; + accel.x -= _gps->acceleration(); accel.y -= _gyro_smoothed.z * veloc; accel.z += _gyro_smoothed.y * veloc; } From 47ddd4dfddab509a24f6b0bda9f697b2079168d0 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 4 Mar 2012 20:37:10 +1100 Subject: [PATCH 065/178] SITL: disable interrupts during register updates this may prevent bogus mode channel reads --- libraries/Desktop/support/sitl.cpp | 3 +++ libraries/Desktop/support/sitl_adc.cpp | 8 +++++--- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/libraries/Desktop/support/sitl.cpp b/libraries/Desktop/support/sitl.cpp index cb67d441e6..67661d5d29 100644 --- a/libraries/Desktop/support/sitl.cpp +++ b/libraries/Desktop/support/sitl.cpp @@ -26,6 +26,7 @@ #include #include #include +#include #include "sitl_adc.h" #include "sitl_rc.h" #include "desktop.h" @@ -145,6 +146,7 @@ static void sitl_fdm_input(void) case 16: { // a packet giving the receiver PWM inputs uint8_t i; + cli(); for (i=0; i<8; i++) { // setup the ICR4 register for the RC channel // inputs @@ -152,6 +154,7 @@ static void sitl_fdm_input(void) ICR4.set(i, d.pwm_pkt.pwm[i]); } } + sei(); break; } } diff --git a/libraries/Desktop/support/sitl_adc.cpp b/libraries/Desktop/support/sitl_adc.cpp index be857ab88d..0b25f50644 100644 --- a/libraries/Desktop/support/sitl_adc.cpp +++ b/libraries/Desktop/support/sitl_adc.cpp @@ -11,6 +11,7 @@ #include #include #include +#include #include "wiring.h" #include "sitl_adc.h" #include "desktop.h" @@ -88,17 +89,18 @@ void sitl_update_adc(float roll, float pitch, float yaw, // Relative to earth adc[5] = (zAccel / (_accel_scale * _sensor_signs[5])) + accel_offset; /* tell the UDR2 register emulation what values to give to the driver */ + cli(); for (uint8_t i=0; i<6; i++) { UDR2.set(sensor_map[i], adc[i]); } - - runInterrupt(6); - // set the airspeed sensor input UDR2.set(7, airspeed_sensor(airspeed)); /* FIX: rubbish value for temperature for now */ UDR2.set(3, 2000); + sei(); + + runInterrupt(6); } From f70dfe440de69acef57410b1b439772445ae0863 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 5 Mar 2012 11:27:45 +1100 Subject: [PATCH 066/178] Quaternion: fix the gyro bias in centripetal and remove smoothing the centripetal code needs to take account of the current gyro bias. It turned out that the accel and gyro smoothing was causing significant control lag, and we're better off just letting the quaternion code handle it via its own smoothing parameters --- libraries/AP_Quaternion/AP_Quaternion.cpp | 28 ++++++++++++++--------- libraries/AP_Quaternion/AP_Quaternion.h | 21 +++++++++++------ 2 files changed, 31 insertions(+), 18 deletions(-) diff --git a/libraries/AP_Quaternion/AP_Quaternion.cpp b/libraries/AP_Quaternion/AP_Quaternion.cpp index 1b4346657f..6c9455714e 100644 --- a/libraries/AP_Quaternion/AP_Quaternion.cpp +++ b/libraries/AP_Quaternion/AP_Quaternion.cpp @@ -269,27 +269,30 @@ void AP_Quaternion::update(void) gyro = _imu->get_gyro(); accel = _imu->get_accel(); - // keep a smoothed gyro vector for centripetal and reporting - // to mainline code - _gyro_smoothed = (_gyro_smoothed * 0.95) + (gyro * 0.05); - - // Quaternion code uses opposite x and y gyro sense + // Quaternion code uses opposite x and y gyro sense from the + // rest of APM gyro.x = -gyro.x; gyro.y = -gyro.y; + // Quaternion code uses opposite z accel as well + accel.z = -accel.z; if (_centripetal && _gps && _gps->status() == GPS::GPS_OK) { + // compensate for linear acceleration, limited to 1g + float acceleration = _gps->acceleration(); + acceleration = constrain(acceleration, 0, 9.8); + accel.x -= acceleration; + // compensate for centripetal acceleration float veloc; veloc = _gps->ground_speed / 100; - accel.x -= _gps->acceleration(); - accel.y -= _gyro_smoothed.z * veloc; - accel.z += _gyro_smoothed.y * veloc; + // be careful of the signs in this calculation. the + // quaternion system uses different signs than the + // rest of APM + accel.y -= (gyro.z - gyro_bias.z) * veloc; + accel.z += (gyro.y - gyro_bias.y) * veloc; } - // Quaternion code uses opposite z accel - accel.z = -accel.z; - if (_compass == NULL) { update_IMU(deltat, gyro, accel); } else { @@ -298,6 +301,9 @@ void AP_Quaternion::update(void) update_MARG(deltat, gyro, accel, mag); } + // keep the corrected gyro for reporting + _gyro_corrected = gyro; + // compute the Eulers float test = (SEq_1*SEq_3 - SEq_4*SEq_2); const float singularity = 0.499; // 86.3 degrees? diff --git a/libraries/AP_Quaternion/AP_Quaternion.h b/libraries/AP_Quaternion/AP_Quaternion.h index 4550a62dd2..543c37f579 100644 --- a/libraries/AP_Quaternion/AP_Quaternion.h +++ b/libraries/AP_Quaternion/AP_Quaternion.h @@ -59,8 +59,14 @@ public: // compatibility methods with DCM void update_DCM(void) { update(); } void update_DCM_fast(void) { update(); } - Vector3f get_gyro(void) { return _gyro_smoothed; } - Vector3f get_integrator(void) { return gyro_bias; } + Vector3f get_gyro(void) { + // notice the sign reversals here + return Vector3f(-_gyro_corrected.x, -_gyro_corrected.y, _gyro_corrected.z); + } + Vector3f get_integrator(void) { + // notice the sign reversals here + return Vector3f(-gyro_bias.x, -gyro_bias.y, gyro_bias.z); + } float get_accel_weight(void) { return 0; } float get_renorm_val(void) { return 0; } float get_health(void) { return 0; } @@ -91,10 +97,11 @@ private: // true if we are doing centripetal acceleration correction bool _centripetal; - // maximum gyroscope measurement error in rad/s (set to 5 degrees/second) - static const float gyroMeasError = 5.0 * (M_PI/180.0); + // maximum gyroscope measurement error in rad/s (set to 10 degrees/second) + static const float gyroMeasError = 10.0 * (M_PI/180.0); - // maximum gyroscope drift rate in radians/s/s (set to 0.02 degrees/s/s) + // maximum gyroscope drift rate in radians/s/s (set to 0.02 + // degrees/s/s, which is 1.2 degrees/s/minute) static const float gyroMeasDrift = 0.02 * (PI/180.0); float beta; @@ -109,8 +116,8 @@ private: // estimate gyroscope biases error Vector3f gyro_bias; - // smoothed gyro estimate - Vector3f _gyro_smoothed; + // the current corrected gyro vector + Vector3f _gyro_corrected; // estimate of error float _error_rp_sum; From c7d5f06b21fa4f4df53a414909bc477c481c2bad Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 5 Mar 2012 14:31:47 +1100 Subject: [PATCH 067/178] AP_Math: added quaternion helper functions and a test suite --- libraries/AP_Math/AP_Math.cpp | 30 ++++ libraries/AP_Math/AP_Math.h | 7 + libraries/AP_Math/examples/eulers/Makefile | 1 + libraries/AP_Math/examples/eulers/eulers.pde | 159 +++++++++++++++++++ libraries/AP_Math/quaternion.h | 36 +++++ 5 files changed, 233 insertions(+) create mode 100644 libraries/AP_Math/examples/eulers/Makefile create mode 100644 libraries/AP_Math/examples/eulers/eulers.pde create mode 100644 libraries/AP_Math/quaternion.h diff --git a/libraries/AP_Math/AP_Math.cpp b/libraries/AP_Math/AP_Math.cpp index 0541246e53..f4896ef38b 100644 --- a/libraries/AP_Math/AP_Math.cpp +++ b/libraries/AP_Math/AP_Math.cpp @@ -67,3 +67,33 @@ void calculate_euler_angles(Matrix3f &m, float *roll, float *pitch, float *yaw) *yaw = atan2(m.b.x, m.a.x); } } + + +// create a quaternion from Euler angles +void quaternion_from_euler(Quaternion &q, float roll, float pitch, float yaw) +{ + float cr2 = cos(roll/2); + float cp2 = cos(pitch/2); + float cy2 = cos(yaw/2); + // the sign reversal here is due to the different conventions + // in the madgwick quaternion code and the rest of APM + float sr2 = -sin(roll/2); + float sp2 = -sin(pitch/2); + float sy2 = sin(yaw/2); + + q.q1 = cr2*cp2*cy2 + sr2*sp2*sy2; + q.q2 = sr2*cp2*cy2 - cr2*sp2*sy2; + q.q3 = cr2*sp2*cy2 + sr2*cp2*sy2; + q.q4 = cr2*cp2*sy2 - sr2*sp2*cy2; +} + +// create eulers from a quaternion +void euler_from_quaternion(Quaternion &q, float *roll, float *pitch, float *yaw) +{ + *roll = -(atan2(2.0*(q.q1*q.q2 + q.q3*q.q4), + 1 - 2.0*(q.q2*q.q2 + q.q3*q.q3))); + // we let safe_asin() handle the singularities near 90/-90 in pitch + *pitch = -safe_asin(2.0*(q.q1*q.q3 - q.q4*q.q2)); + *yaw = atan2(2.0*(q.q1*q.q4 + q.q2*q.q3), + 1 - 2.0*(q.q3*q.q3 + q.q4*q.q4)); +} diff --git a/libraries/AP_Math/AP_Math.h b/libraries/AP_Math/AP_Math.h index 37cc5bac14..6975ccc28e 100644 --- a/libraries/AP_Math/AP_Math.h +++ b/libraries/AP_Math/AP_Math.h @@ -7,6 +7,7 @@ #include "vector2.h" #include "vector3.h" #include "matrix3.h" +#include "quaternion.h" #include "polygon.h" // define AP_Param types AP_Vector3f and Ap_Matrix3f @@ -24,3 +25,9 @@ void rotation_matrix_from_euler(Matrix3f &m, float roll, float pitch, float yaw) // calculate euler angles from a rotation matrix void calculate_euler_angles(Matrix3f &m, float *roll, float *pitch, float *yaw); + +// create a quaternion from Euler angles +void quaternion_from_euler(Quaternion &q, float roll, float pitch, float yaw); + +// create eulers from a quaternion +void euler_from_quaternion(Quaternion &q, float *roll, float *pitch, float *yaw); diff --git a/libraries/AP_Math/examples/eulers/Makefile b/libraries/AP_Math/examples/eulers/Makefile new file mode 100644 index 0000000000..d1f40fd90f --- /dev/null +++ b/libraries/AP_Math/examples/eulers/Makefile @@ -0,0 +1 @@ +include ../../../AP_Common/Arduino.mk diff --git a/libraries/AP_Math/examples/eulers/eulers.pde b/libraries/AP_Math/examples/eulers/eulers.pde new file mode 100644 index 0000000000..2f27d98b9e --- /dev/null +++ b/libraries/AP_Math/examples/eulers/eulers.pde @@ -0,0 +1,159 @@ +/// -*- tab-width: 4; Mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*- +// +// Unit tests for the AP_Math euler code +// + +#include +#include +#include + +FastSerialPort(Serial, 0); + +static float rad_diff(float rad1, float rad2) +{ + float diff = rad1 - rad2; + if (diff > PI) { + diff -= 2*PI; + } + if (diff < -PI) { + diff += 2*PI; + } + return fabs(diff); +} + +static void test_euler(float roll, float pitch, float yaw) +{ + Matrix3f m; + float roll2, pitch2, yaw2; + + rotation_matrix_from_euler(m, roll, pitch, yaw); + calculate_euler_angles(m, &roll2, &pitch2, &yaw2); + if (m.is_nan()) { + Serial.printf("NAN matrix roll=%f pitch=%f yaw=%f\n", + roll, pitch, yaw); + } + if (isnan(roll2) || + isnan(pitch2) || + isnan(yaw2)) { + Serial.printf("NAN eulers roll=%f pitch=%f yaw=%f\n", + roll, pitch, yaw); + } + if (rad_diff(roll2,roll) > 0.01 || + rad_diff(pitch2, pitch) > 0.01 || + rad_diff(yaw2, yaw) > 0.01) { + Serial.printf("incorrect eulers roll=%f/%f pitch=%f/%f yaw=%f/%f\n", + roll, roll2, pitch, pitch2, yaw, yaw2); + } +} + +#define ARRAY_LENGTH(x) (sizeof((x))/sizeof((x)[0])) + +static const float angles[] = { 0, PI/8, PI/4, PI/2, PI, + -PI/8, -PI/4, -PI/2, -PI}; + +void test_matrix_eulers(void) +{ + uint8_t i, j, k; + uint8_t N = ARRAY_LENGTH(angles); + + Serial.println("rotation matrix unit tests\n"); + + for (i=0; i ToRad(179)) { + // reverse all 3 + roll2 += fmod(roll2+PI, 2*PI); + pitch2 += fmod(pitch2+PI, 2*PI); + yaw2 += fmod(yaw2+PI, 2*PI); + } + + if (rad_diff(roll2,roll) > 0.01 || + rad_diff(pitch2, pitch) > 0.01 || + rad_diff(yaw2, yaw) > 0.01) { + if (ToDeg(rad_diff(pitch, PI/2)) < 1 || + ToDeg(rad_diff(pitch, -PI/2)) < 1) { + // we expect breakdown at these poles + Serial.printf("breakdown eulers roll=%f/%f pitch=%f/%f yaw=%f/%f\n", + ToDeg(roll), ToDeg(roll2), ToDeg(pitch), ToDeg(pitch2), ToDeg(yaw), ToDeg(yaw2)); + } else { + Serial.printf("incorrect eulers roll=%f/%f pitch=%f/%f yaw=%f/%f\n", + ToDeg(roll), ToDeg(roll2), ToDeg(pitch), ToDeg(pitch2), ToDeg(yaw), ToDeg(yaw2)); + } + } else { + Serial.printf("correct eulers roll=%f/%f pitch=%f/%f yaw=%f/%f\n", + ToDeg(roll), ToDeg(roll2), ToDeg(pitch), ToDeg(pitch2), ToDeg(yaw), ToDeg(yaw2)); + } +} + +void test_quaternion_eulers(void) +{ + uint8_t i, j, k; + uint8_t N = ARRAY_LENGTH(angles); + + Serial.println("quaternion unit tests\n"); + + test_quaternion(PI/4, 0, 0); + test_quaternion(0, PI/4, 0); + test_quaternion(0, 0, PI/4); + test_quaternion(-PI/4, 0, 0); + test_quaternion(0, -PI/4, 0); + test_quaternion(0, 0, -PI/4); + test_quaternion(-PI/4, 1, 1); + test_quaternion(1, -PI/4, 1); + test_quaternion(1, 1, -PI/4); + + test_quaternion(ToRad(89), 0, 0.1); + test_quaternion(0, ToRad(89), 0.1); + test_quaternion(0.1, 0, ToRad(89)); + + test_quaternion(ToRad(91), 0, 0.1); + test_quaternion(0, ToRad(91), 0.1); + test_quaternion(0.1, 0, ToRad(91)); + + for (i=0; i + +class Quaternion +{ +public: + float q1, q2, q3, q4; + + // constructor + Quaternion() { q1 = 1; q2 = q3 = q4 = 0; } + + // setting constructor + Quaternion(const float _q1, const float _q2, const float _q3, const float _q4): + q1(_q1), q2(_q2), q3(_q3), q4(_q4) {} + + // function call operator + void operator ()(const float _q1, const float _q2, const float _q3, const float _q4) + { q1 = _q1; q2 = _q2; q3 = _q3; q4 = _q4; } + + // check if any elements are NAN + bool is_nan(void) + { return isnan(q1) || isnan(q2) || isnan(q3) || isnan(q4); } + +}; +#endif // QUATERNION_H From 066a513758d65eefb0d1eb0c21d18e26c6a1ff70 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 5 Mar 2012 15:07:04 +1100 Subject: [PATCH 068/178] Quaternion: added more numerical safety in the quaternion code prevent infinities from creeping in and prevent large drift changes --- libraries/AP_Quaternion/AP_Quaternion.cpp | 94 ++++++++++++++++++----- libraries/AP_Quaternion/AP_Quaternion.h | 14 ++-- 2 files changed, 81 insertions(+), 27 deletions(-) diff --git a/libraries/AP_Quaternion/AP_Quaternion.cpp b/libraries/AP_Quaternion/AP_Quaternion.cpp index 6c9455714e..4a20d4c71a 100644 --- a/libraries/AP_Quaternion/AP_Quaternion.cpp +++ b/libraries/AP_Quaternion/AP_Quaternion.cpp @@ -31,6 +31,13 @@ AP_Quaternion::set_compass(Compass *compass) _compass = compass; } +// to keep the code as close to the original as possible, we use these +// macros for quaternion access +#define SEq_1 q.q1 +#define SEq_2 q.q2 +#define SEq_3 q.q3 +#define SEq_4 q.q4 + // Function to compute one quaternion iteration without magnetometer void AP_Quaternion::update_IMU(float deltat, Vector3f &gyro, Vector3f &accel) { @@ -55,6 +62,11 @@ void AP_Quaternion::update_IMU(float deltat, Vector3f &gyro, Vector3f &accel) // normalise accelerometer vector accel.normalize(); + if (accel.is_inf()) { + // discard this data point + renorm_range_count++; + return; + } // Compute the objective function and Jacobian f_1 = twoSEq_2 * SEq_4 - twoSEq_1 * SEq_3 - accel.x; @@ -75,12 +87,16 @@ void AP_Quaternion::update_IMU(float deltat, Vector3f &gyro, Vector3f &accel) // Normalise the gradient norm = 1.0/sqrt(SEqHatDot_1 * SEqHatDot_1 + SEqHatDot_2 * SEqHatDot_2 + SEqHatDot_3 * SEqHatDot_3 + SEqHatDot_4 * SEqHatDot_4); - if (!isinf(norm)) { - SEqHatDot_1 *= norm; - SEqHatDot_2 *= norm; - SEqHatDot_3 *= norm; - SEqHatDot_4 *= norm; + if (isinf(norm)) { + // we can't do an update - discard this data point and + // hope the next one is better + renorm_range_count++; + return; } + SEqHatDot_1 *= norm; + SEqHatDot_2 *= norm; + SEqHatDot_3 *= norm; + SEqHatDot_4 *= norm; // Compute the quaternion derrivative measured by gyroscopes SEqDot_omega_1 = -halfSEq_2 * gyro.x - halfSEq_3 * gyro.y - halfSEq_4 * gyro.z; @@ -96,12 +112,17 @@ void AP_Quaternion::update_IMU(float deltat, Vector3f &gyro, Vector3f &accel) // Normalise quaternion norm = 1.0/sqrt(SEq_1 * SEq_1 + SEq_2 * SEq_2 + SEq_3 * SEq_3 + SEq_4 * SEq_4); - if (!isinf(norm)) { - SEq_1 *= norm; - SEq_2 *= norm; - SEq_3 *= norm; - SEq_4 *= norm; + if (isinf(norm)) { + // our quaternion is bad! Reset based on roll/pitch/yaw + // and hope for the best ... + renorm_blowup_count++; + quaternion_from_euler(q, roll, pitch, yaw); + return; } + SEq_1 *= norm; + SEq_2 *= norm; + SEq_3 *= norm; + SEq_4 *= norm; } @@ -124,9 +145,19 @@ void AP_Quaternion::update_MARG(float deltat, Vector3f &gyro, Vector3f &accel, V // normalise accelerometer vector accel.normalize(); + if (accel.is_inf()) { + // discard this data point + renorm_range_count++; + return; + } // normalise the magnetometer measurement mag.normalize(); + if (mag.is_inf()) { + // discard this data point + renorm_range_count++; + return; + } // auxiliary variables to avoid repeated calculations float halfSEq_1 = 0.5f * SEq_1; @@ -189,6 +220,11 @@ void AP_Quaternion::update_MARG(float deltat, Vector3f &gyro, Vector3f &accel, V // normalise the gradient to estimate direction of the gyroscope error norm = 1.0 / sqrt(SEqHatDot_1 * SEqHatDot_1 + SEqHatDot_2 * SEqHatDot_2 + SEqHatDot_3 * SEqHatDot_3 + SEqHatDot_4 * SEqHatDot_4); + if (isinf(norm)) { + // discard this data point + renorm_range_count++; + return; + } SEqHatDot_1 *= norm; SEqHatDot_2 *= norm; SEqHatDot_3 *= norm; @@ -205,8 +241,18 @@ void AP_Quaternion::update_MARG(float deltat, Vector3f &gyro, Vector3f &accel, V _error_rp_count++; _error_yaw_count++; - // compute and remove the gyroscope baises - gyro_bias += w_err * (deltat * zeta); + // compute the gyroscope bias delta + Vector3f drift_delta = w_err * (deltat * zeta); + + // don't allow the drift rate to be exceeded. This prevents a + // sudden drift change coming from a outage in the compass + float max_change = gyroMeasDrift * deltat; + drift_delta.x = constrain(drift_delta.x, -max_change, max_change); + drift_delta.y = constrain(drift_delta.y, -max_change, max_change); + drift_delta.z = constrain(drift_delta.z, -max_change, max_change); + gyro_bias += drift_delta; + + // correct the gyro reading for drift gyro -= gyro_bias; // compute the quaternion rate measured by gyroscopes @@ -223,12 +269,17 @@ void AP_Quaternion::update_MARG(float deltat, Vector3f &gyro, Vector3f &accel, V // normalise quaternion norm = 1.0/sqrt(SEq_1 * SEq_1 + SEq_2 * SEq_2 + SEq_3 * SEq_3 + SEq_4 * SEq_4); - if (!isinf(norm)) { - SEq_1 *= norm; - SEq_2 *= norm; - SEq_3 *= norm; - SEq_4 *= norm; + if (isinf(norm)) { + // our quaternion is bad! Reset based on roll/pitch/yaw + // and hope for the best ... + renorm_blowup_count++; + quaternion_from_euler(q, roll, pitch, yaw); + return; } + SEq_1 *= norm; + SEq_2 *= norm; + SEq_3 *= norm; + SEq_4 *= norm; // compute flux in the earth frame // recompute axulirary variables @@ -265,6 +316,13 @@ void AP_Quaternion::update(void) return; } + if (!_have_initial_yaw && _compass && _compass->use_for_yaw()) { + // setup the quaternion with initial compass yaw + quaternion_from_euler(q, 0, 0, _compass->heading); + _have_initial_yaw = true; + gyro_bias.zero(); + } + // get current IMU state gyro = _imu->get_gyro(); accel = _imu->get_accel(); @@ -293,7 +351,7 @@ void AP_Quaternion::update(void) accel.z += (gyro.y - gyro_bias.y) * veloc; } - if (_compass == NULL) { + if (_compass == NULL || !_compass->use_for_yaw()) { update_IMU(deltat, gyro, accel); } else { // mag.z is reversed in quaternion code diff --git a/libraries/AP_Quaternion/AP_Quaternion.h b/libraries/AP_Quaternion/AP_Quaternion.h index 543c37f579..2819cf15be 100644 --- a/libraries/AP_Quaternion/AP_Quaternion.h +++ b/libraries/AP_Quaternion/AP_Quaternion.h @@ -22,12 +22,6 @@ public: _gps(gps), _compass(compass) { - // initial quaternion - SEq_1 = 1; - SEq_2 = 0; - SEq_3 = 0; - SEq_4 = 0; - // reference direction of flux in earth frame b_x = 0; b_z = -1; @@ -97,8 +91,8 @@ private: // true if we are doing centripetal acceleration correction bool _centripetal; - // maximum gyroscope measurement error in rad/s (set to 10 degrees/second) - static const float gyroMeasError = 10.0 * (M_PI/180.0); + // maximum gyroscope measurement error in rad/s (set to 20 degrees/second) + static const float gyroMeasError = 20.0 * (M_PI/180.0); // maximum gyroscope drift rate in radians/s/s (set to 0.02 // degrees/s/s, which is 1.2 degrees/s/minute) @@ -108,8 +102,10 @@ private: float zeta; // quaternion elements - float SEq_1, SEq_2, SEq_3, SEq_4; + Quaternion q; + // magnetic flux estimates. These are used for the automatic + // magnetometer calibration float b_x; float b_z; From f5e6dc0757697487e94dbae8fcf9a326f806f7cc Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 5 Mar 2012 15:07:30 +1100 Subject: [PATCH 069/178] Math: added is_inf() on vector3f --- libraries/AP_Math/vector3.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libraries/AP_Math/vector3.h b/libraries/AP_Math/vector3.h index af999b95be..27dbbcb57e 100644 --- a/libraries/AP_Math/vector3.h +++ b/libraries/AP_Math/vector3.h @@ -181,6 +181,10 @@ public: bool is_nan(void) { return isnan(x) || isnan(y) || isnan(z); } + // check if any elements are infinity + bool is_inf(void) + { return isinf(x) || isinf(y) || isinf(z); } + }; typedef Vector3 Vector3i; From 1ec4c0777c66f33d1148ddad6f7c11724296e33a Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 5 Mar 2012 15:07:45 +1100 Subject: [PATCH 070/178] Math: added comment on quaternion constructor --- libraries/AP_Math/quaternion.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libraries/AP_Math/quaternion.h b/libraries/AP_Math/quaternion.h index 515592ac3c..d5b5913e82 100644 --- a/libraries/AP_Math/quaternion.h +++ b/libraries/AP_Math/quaternion.h @@ -17,7 +17,8 @@ class Quaternion public: float q1, q2, q3, q4; - // constructor + // constructor creates a quaternion equivalent + // to roll=0, pitch=0, yaw=0 Quaternion() { q1 = 1; q2 = q3 = q4 = 0; } // setting constructor From 2596acc8eb66d0004fcf0baba51cceb23a3eed82 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 5 Mar 2012 15:08:01 +1100 Subject: [PATCH 071/178] ACM: removed incorrect mode definition --- ArduCopter/defines.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/ArduCopter/defines.h b/ArduCopter/defines.h index 906f960d52..1cf84ffd0c 100644 --- a/ArduCopter/defines.h +++ b/ArduCopter/defines.h @@ -125,8 +125,6 @@ #define OF_LOITER 10 // Hold a single location using optical flow sensor #define NUM_MODES 11 -#define INITIALISING 9 // in startup routines - #define SIMPLE_1 1 #define SIMPLE_2 2 #define SIMPLE_3 4 From f363f81869efb3be1323eb3417a41f2f8c0efe13 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 5 Mar 2012 18:30:19 +1100 Subject: [PATCH 072/178] Quaternion: added NaN paranoid checking this is for Michael to run --- libraries/AP_Quaternion/AP_Quaternion.cpp | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/libraries/AP_Quaternion/AP_Quaternion.cpp b/libraries/AP_Quaternion/AP_Quaternion.cpp index 4a20d4c71a..d3afcba722 100644 --- a/libraries/AP_Quaternion/AP_Quaternion.cpp +++ b/libraries/AP_Quaternion/AP_Quaternion.cpp @@ -305,6 +305,10 @@ void AP_Quaternion::update(void) Vector3f gyro, accel; float deltat; +#ifdef DESKTOP_BUILD + Quaternion q_saved = q; +#endif + _imu->update(); deltat = _imu->get_delta_time(); @@ -396,6 +400,24 @@ void AP_Quaternion::update(void) if (yaw_sensor < 0) { yaw_sensor += 36000; } + +#ifdef DESKTOP_BUILD + if (q.is_nan() || + isnan(roll) || + isnan(pitch) || + isnan(yaw) || + isnan(b_x) || + isnan(b_z) || + gyro_bias.is_nan()) { + SITL_debug("QUAT NAN: deltat=%f roll=%f pitch=%f yaw=%f q0=[%f %f %f %f] q=[%f %f %f %f] a=[%f %f %f] g=(%f %f %f)\n", + deltat, roll, pitch, yaw, + q_saved.q1, q_saved.q2, q_saved.q3, q_saved.q4, + q.q1, q.q2, q.q3, q.q4, + accel.x, accel.y, accel.z, + gyro.x, gyro.y, gyro.z); + } +#endif + } // average error in roll/pitch since last call From 3b7d78cf022704d519334ac9ff1a61b5a6fa3314 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 5 Mar 2012 18:50:09 +1100 Subject: [PATCH 073/178] Quat: test patch for michael --- libraries/AP_Quaternion/AP_Quaternion.cpp | 41 +++++++++++------------ 1 file changed, 20 insertions(+), 21 deletions(-) diff --git a/libraries/AP_Quaternion/AP_Quaternion.cpp b/libraries/AP_Quaternion/AP_Quaternion.cpp index d3afcba722..dc2080d516 100644 --- a/libraries/AP_Quaternion/AP_Quaternion.cpp +++ b/libraries/AP_Quaternion/AP_Quaternion.cpp @@ -86,7 +86,7 @@ void AP_Quaternion::update_IMU(float deltat, Vector3f &gyro, Vector3f &accel) SEqHatDot_4 = J_14or21 * f_1 + J_11or24 * f_2; // Normalise the gradient - norm = 1.0/sqrt(SEqHatDot_1 * SEqHatDot_1 + SEqHatDot_2 * SEqHatDot_2 + SEqHatDot_3 * SEqHatDot_3 + SEqHatDot_4 * SEqHatDot_4); + norm = 1.0/safe_sqrt(SEqHatDot_1 * SEqHatDot_1 + SEqHatDot_2 * SEqHatDot_2 + SEqHatDot_3 * SEqHatDot_3 + SEqHatDot_4 * SEqHatDot_4); if (isinf(norm)) { // we can't do an update - discard this data point and // hope the next one is better @@ -111,7 +111,7 @@ void AP_Quaternion::update_IMU(float deltat, Vector3f &gyro, Vector3f &accel) SEq_4 += (SEqDot_omega_4 - (beta * SEqHatDot_4)) * deltat; // Normalise quaternion - norm = 1.0/sqrt(SEq_1 * SEq_1 + SEq_2 * SEq_2 + SEq_3 * SEq_3 + SEq_4 * SEq_4); + norm = 1.0/safe_sqrt(SEq_1 * SEq_1 + SEq_2 * SEq_2 + SEq_3 * SEq_3 + SEq_4 * SEq_4); if (isinf(norm)) { // our quaternion is bad! Reset based on roll/pitch/yaw // and hope for the best ... @@ -219,7 +219,7 @@ void AP_Quaternion::update_MARG(float deltat, Vector3f &gyro, Vector3f &accel, V SEqHatDot_4 = J_14or21 * f_1 + J_11or24 * f_2 - J_44 * f_4 - J_54 * f_5 + J_64 * f_6; // normalise the gradient to estimate direction of the gyroscope error - norm = 1.0 / sqrt(SEqHatDot_1 * SEqHatDot_1 + SEqHatDot_2 * SEqHatDot_2 + SEqHatDot_3 * SEqHatDot_3 + SEqHatDot_4 * SEqHatDot_4); + norm = 1.0 / safe_sqrt(SEqHatDot_1 * SEqHatDot_1 + SEqHatDot_2 * SEqHatDot_2 + SEqHatDot_3 * SEqHatDot_3 + SEqHatDot_4 * SEqHatDot_4); if (isinf(norm)) { // discard this data point renorm_range_count++; @@ -268,7 +268,7 @@ void AP_Quaternion::update_MARG(float deltat, Vector3f &gyro, Vector3f &accel, V SEq_4 += (SEqDot_omega_4 - (beta * SEqHatDot_4)) * deltat; // normalise quaternion - norm = 1.0/sqrt(SEq_1 * SEq_1 + SEq_2 * SEq_2 + SEq_3 * SEq_3 + SEq_4 * SEq_4); + norm = 1.0/safe_sqrt(SEq_1 * SEq_1 + SEq_2 * SEq_2 + SEq_3 * SEq_3 + SEq_4 * SEq_4); if (isinf(norm)) { // our quaternion is bad! Reset based on roll/pitch/yaw // and hope for the best ... @@ -307,6 +307,7 @@ void AP_Quaternion::update(void) #ifdef DESKTOP_BUILD Quaternion q_saved = q; + Vector3f bias_saved = gyro_bias; #endif _imu->update(); @@ -363,6 +364,21 @@ void AP_Quaternion::update(void) update_MARG(deltat, gyro, accel, mag); } + +#ifdef DESKTOP_BUILD + if (q.is_nan()) { + SITL_debug("QUAT NAN: deltat=%f roll=%f pitch=%f yaw=%f q0=[%f %f %f %f] q=[%f %f %f %f] a=[%f %f %f] g=(%f %f %f)\n", + deltat, roll, pitch, yaw, + q_saved.q1, q_saved.q2, q_saved.q3, q_saved.q4, + q.q1, q.q2, q.q3, q.q4, + accel.x, accel.y, accel.z, + gyro.x, gyro.y, gyro.z); + q = q_saved; + gyro_bias = bias_saved; + update_IMU(deltat, gyro, accel); + } +#endif + // keep the corrected gyro for reporting _gyro_corrected = gyro; @@ -401,23 +417,6 @@ void AP_Quaternion::update(void) yaw_sensor += 36000; } -#ifdef DESKTOP_BUILD - if (q.is_nan() || - isnan(roll) || - isnan(pitch) || - isnan(yaw) || - isnan(b_x) || - isnan(b_z) || - gyro_bias.is_nan()) { - SITL_debug("QUAT NAN: deltat=%f roll=%f pitch=%f yaw=%f q0=[%f %f %f %f] q=[%f %f %f %f] a=[%f %f %f] g=(%f %f %f)\n", - deltat, roll, pitch, yaw, - q_saved.q1, q_saved.q2, q_saved.q3, q_saved.q4, - q.q1, q.q2, q.q3, q.q4, - accel.x, accel.y, accel.z, - gyro.x, gyro.y, gyro.z); - } -#endif - } // average error in roll/pitch since last call From 3666476bcb92484995e9c36e7f35987ba7d7a37b Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 5 Mar 2012 21:00:22 +1100 Subject: [PATCH 074/178] SITL: prevent nested timer interrupts --- libraries/Desktop/support/sitl.cpp | 7 +++++-- libraries/Desktop/support/sitl_adc.cpp | 2 -- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/libraries/Desktop/support/sitl.cpp b/libraries/Desktop/support/sitl.cpp index 67661d5d29..0671be6caf 100644 --- a/libraries/Desktop/support/sitl.cpp +++ b/libraries/Desktop/support/sitl.cpp @@ -146,7 +146,6 @@ static void sitl_fdm_input(void) case 16: { // a packet giving the receiver PWM inputs uint8_t i; - cli(); for (i=0; i<8; i++) { // setup the ICR4 register for the RC channel // inputs @@ -154,7 +153,6 @@ static void sitl_fdm_input(void) ICR4.set(i, d.pwm_pkt.pwm[i]); } } - sei(); break; } } @@ -221,6 +219,8 @@ static void timer_handler(int signum) { static uint32_t last_update_count; + cli(); + /* make sure we die if our parent dies */ if (kill(parent_pid, 0) != 0) { exit(1); @@ -242,10 +242,12 @@ static void timer_handler(int signum) if (update_count == 0) { sitl_update_gps(0, 0, 0, 0, 0, false); + sei(); return; } if (update_count == last_update_count) { + sei(); return; } last_update_count = update_count; @@ -259,6 +261,7 @@ static void timer_handler(int signum) sim_state.airspeed); sitl_update_barometer(sim_state.altitude); sitl_update_compass(sim_state.heading, sim_state.rollDeg, sim_state.pitchDeg, sim_state.heading); + sei(); } diff --git a/libraries/Desktop/support/sitl_adc.cpp b/libraries/Desktop/support/sitl_adc.cpp index 0b25f50644..b3339d9143 100644 --- a/libraries/Desktop/support/sitl_adc.cpp +++ b/libraries/Desktop/support/sitl_adc.cpp @@ -89,7 +89,6 @@ void sitl_update_adc(float roll, float pitch, float yaw, // Relative to earth adc[5] = (zAccel / (_accel_scale * _sensor_signs[5])) + accel_offset; /* tell the UDR2 register emulation what values to give to the driver */ - cli(); for (uint8_t i=0; i<6; i++) { UDR2.set(sensor_map[i], adc[i]); } @@ -98,7 +97,6 @@ void sitl_update_adc(float roll, float pitch, float yaw, // Relative to earth /* FIX: rubbish value for temperature for now */ UDR2.set(3, 2000); - sei(); runInterrupt(6); } From ccada2e9c25ee9ba78b19a8ed2ab01bb3891737c Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 5 Mar 2012 21:04:26 +1100 Subject: [PATCH 075/178] SITL: avoid parent pid code on cygwin this causes problems on windows --- libraries/Desktop/support/sitl.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/libraries/Desktop/support/sitl.cpp b/libraries/Desktop/support/sitl.cpp index 0671be6caf..4c279d26ef 100644 --- a/libraries/Desktop/support/sitl.cpp +++ b/libraries/Desktop/support/sitl.cpp @@ -55,7 +55,9 @@ struct sitl_fdm { static int sitl_fd; struct sockaddr_in rcout_addr; +#ifndef __CYGWIN__ static pid_t parent_pid; +#endif struct ADC_UDR2 UDR2; struct RC_ICR4 ICR4; extern AP_TimerProcess timer_scheduler; @@ -221,10 +223,12 @@ static void timer_handler(int signum) cli(); +#ifndef __CYGWIN__ /* make sure we die if our parent dies */ if (kill(parent_pid, 0) != 0) { exit(1); } +#endif /* check for packet from flight sim */ sitl_fdm_input(); @@ -292,7 +296,9 @@ static void setup_timer(void) */ void sitl_setup(void) { +#ifndef __CYGWIN__ parent_pid = getppid(); +#endif rcout_addr.sin_family = AF_INET; rcout_addr.sin_port = htons(RCOUT_PORT); From 8abbbe57139bfa335cdeefb86aecdb5a71c5bd90 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 5 Mar 2012 22:40:37 +1100 Subject: [PATCH 076/178] AP_Math: better way of handling safe_sqrt() better to test the result, than predict it --- libraries/AP_Math/AP_Math.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/libraries/AP_Math/AP_Math.cpp b/libraries/AP_Math/AP_Math.cpp index f4896ef38b..e0af504ea3 100644 --- a/libraries/AP_Math/AP_Math.cpp +++ b/libraries/AP_Math/AP_Math.cpp @@ -24,10 +24,11 @@ float safe_asin(float v) // real input should have been zero float safe_sqrt(float v) { - if (isnan(v) || v <= 0.0) { - return 0.0; + float ret = sqrt(v); + if (isnan(ret)) { + return 0; } - return sqrt(v); + return ret; } From 4d65cda0eaec30d3e185f7fa8ecc237e1f41ec17 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 5 Mar 2012 22:41:10 +1100 Subject: [PATCH 077/178] AP_Math: added quaternion->matrix and earth frame routines this will be used for 3d acceleration --- libraries/AP_Math/AP_Math.cpp | 53 +++++++++++++++++++++++++++++------ libraries/AP_Math/AP_Math.h | 11 ++++++-- 2 files changed, 54 insertions(+), 10 deletions(-) diff --git a/libraries/AP_Math/AP_Math.cpp b/libraries/AP_Math/AP_Math.cpp index e0af504ea3..28a49d7aa6 100644 --- a/libraries/AP_Math/AP_Math.cpp +++ b/libraries/AP_Math/AP_Math.cpp @@ -56,7 +56,7 @@ void rotation_matrix_from_euler(Matrix3f &m, float roll, float pitch, float yaw) // calculate euler angles from a rotation matrix // this is based on http://gentlenav.googlecode.com/files/EulerAngles.pdf -void calculate_euler_angles(Matrix3f &m, float *roll, float *pitch, float *yaw) +void calculate_euler_angles(const Matrix3f &m, float *roll, float *pitch, float *yaw) { if (pitch != NULL) { *pitch = -safe_asin(m.c.x); @@ -73,14 +73,14 @@ void calculate_euler_angles(Matrix3f &m, float *roll, float *pitch, float *yaw) // create a quaternion from Euler angles void quaternion_from_euler(Quaternion &q, float roll, float pitch, float yaw) { - float cr2 = cos(roll/2); - float cp2 = cos(pitch/2); - float cy2 = cos(yaw/2); + float cr2 = cos(roll*0.5); + float cp2 = cos(pitch*0.5); + float cy2 = cos(yaw*0.5); // the sign reversal here is due to the different conventions // in the madgwick quaternion code and the rest of APM - float sr2 = -sin(roll/2); - float sp2 = -sin(pitch/2); - float sy2 = sin(yaw/2); + float sr2 = -sin(roll*0.5); + float sp2 = -sin(pitch*0.5); + float sy2 = sin(yaw*0.5); q.q1 = cr2*cp2*cy2 + sr2*sp2*sy2; q.q2 = sr2*cp2*cy2 - cr2*sp2*sy2; @@ -89,7 +89,7 @@ void quaternion_from_euler(Quaternion &q, float roll, float pitch, float yaw) } // create eulers from a quaternion -void euler_from_quaternion(Quaternion &q, float *roll, float *pitch, float *yaw) +void euler_from_quaternion(const Quaternion &q, float *roll, float *pitch, float *yaw) { *roll = -(atan2(2.0*(q.q1*q.q2 + q.q3*q.q4), 1 - 2.0*(q.q2*q.q2 + q.q3*q.q3))); @@ -98,3 +98,40 @@ void euler_from_quaternion(Quaternion &q, float *roll, float *pitch, float *yaw) *yaw = atan2(2.0*(q.q1*q.q4 + q.q2*q.q3), 1 - 2.0*(q.q3*q.q3 + q.q4*q.q4)); } + +// convert a quaternion to a rotation matrix +void quaternion_to_rotation_matrix(const Quaternion &q, Matrix3f &m) +{ + float q3q3 = q.q3 * q.q3; + float q3q4 = q.q3 * q.q4; + float q2q2 = q.q2 * q.q2; + float q2q3 = q.q2 * q.q3; + float q2q4 = q.q2 * q.q4; + float q1q2 = q.q1 * q.q2; + float q1q3 = q.q1 * q.q3; + float q1q4 = q.q1 * q.q4; + float q4q4 = q.q4 * q.q4; + + m.a.x = 1-2*(q3q3 + q4q4); + m.a.y = 2*(q2q3 - q1q4); + m.a.z = - 2*(q2q4 + q1q3); + m.b.x = 2*(q2q3 + q1q4); + m.b.y = 1-2*(q2q2 + q4q4); + m.b.z = -2*(q3q4 - q1q2); + m.c.x = -2*(q2q4 - q1q3); + m.c.y = -2*(q3q4 + q1q2); + m.c.z = 1-2*(q2q2 + q3q3); +} + +// convert a vector in earth frame to a vector in body frame, +// assuming body current rotation is given by a quaternion +void quaternion_earth_to_body(const Quaternion &q, Vector3f &v) +{ + Matrix3f m; + // we reverse z before and afterwards because of the differing + // quaternion conventions from APM conventions. + v.z = -v.z; + quaternion_to_rotation_matrix(q, m); + v = m * v; + v.z = -v.z; +} diff --git a/libraries/AP_Math/AP_Math.h b/libraries/AP_Math/AP_Math.h index 6975ccc28e..c2a1b89af3 100644 --- a/libraries/AP_Math/AP_Math.h +++ b/libraries/AP_Math/AP_Math.h @@ -24,10 +24,17 @@ float safe_sqrt(float v); void rotation_matrix_from_euler(Matrix3f &m, float roll, float pitch, float yaw); // calculate euler angles from a rotation matrix -void calculate_euler_angles(Matrix3f &m, float *roll, float *pitch, float *yaw); +void calculate_euler_angles(const Matrix3f &m, float *roll, float *pitch, float *yaw); // create a quaternion from Euler angles void quaternion_from_euler(Quaternion &q, float roll, float pitch, float yaw); // create eulers from a quaternion -void euler_from_quaternion(Quaternion &q, float *roll, float *pitch, float *yaw); +void euler_from_quaternion(const Quaternion &q, float *roll, float *pitch, float *yaw); + +// convert a quaternion to a rotation matrix +void quaternion_to_rotation_matrix(const Quaternion &q, Matrix3f &m); + +// convert a vector in earth frame to a vector in body frame, +// assuming body current rotation is given by a quaternion +void quaternion_earth_to_body(const Quaternion &q, Vector3f &v); From a92fb67b708f00f297bf7140433545491b86d2a1 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 5 Mar 2012 22:42:29 +1100 Subject: [PATCH 078/178] AP_Math: expanded the math test suite --- libraries/AP_Math/examples/eulers/Makefile | 3 + libraries/AP_Math/examples/eulers/eulers.pde | 172 +++++++++++++------ 2 files changed, 119 insertions(+), 56 deletions(-) diff --git a/libraries/AP_Math/examples/eulers/Makefile b/libraries/AP_Math/examples/eulers/Makefile index d1f40fd90f..fcdc8ff8fe 100644 --- a/libraries/AP_Math/examples/eulers/Makefile +++ b/libraries/AP_Math/examples/eulers/Makefile @@ -1 +1,4 @@ include ../../../AP_Common/Arduino.mk + +sitl: + make -f ../../../../libraries/Desktop/Desktop.mk diff --git a/libraries/AP_Math/examples/eulers/eulers.pde b/libraries/AP_Math/examples/eulers/eulers.pde index 2f27d98b9e..5db00ec80e 100644 --- a/libraries/AP_Math/examples/eulers/eulers.pde +++ b/libraries/AP_Math/examples/eulers/eulers.pde @@ -9,6 +9,22 @@ FastSerialPort(Serial, 0); +#ifdef DESKTOP_BUILD +// all of this is needed to build with SITL +#include +#include +#include +#include +#include +#include +#include +#include +#include +Arduino_Mega_ISR_Registry isr_registry; +AP_Baro_BMP085_HIL barometer; +AP_Compass_HIL compass; +#endif + static float rad_diff(float rad1, float rad2) { float diff = rad1 - rad2; @@ -21,62 +37,9 @@ static float rad_diff(float rad1, float rad2) return fabs(diff); } -static void test_euler(float roll, float pitch, float yaw) +static void check_result(float roll, float pitch, float yaw, + float roll2, float pitch2, float yaw2) { - Matrix3f m; - float roll2, pitch2, yaw2; - - rotation_matrix_from_euler(m, roll, pitch, yaw); - calculate_euler_angles(m, &roll2, &pitch2, &yaw2); - if (m.is_nan()) { - Serial.printf("NAN matrix roll=%f pitch=%f yaw=%f\n", - roll, pitch, yaw); - } - if (isnan(roll2) || - isnan(pitch2) || - isnan(yaw2)) { - Serial.printf("NAN eulers roll=%f pitch=%f yaw=%f\n", - roll, pitch, yaw); - } - if (rad_diff(roll2,roll) > 0.01 || - rad_diff(pitch2, pitch) > 0.01 || - rad_diff(yaw2, yaw) > 0.01) { - Serial.printf("incorrect eulers roll=%f/%f pitch=%f/%f yaw=%f/%f\n", - roll, roll2, pitch, pitch2, yaw, yaw2); - } -} - -#define ARRAY_LENGTH(x) (sizeof((x))/sizeof((x)[0])) - -static const float angles[] = { 0, PI/8, PI/4, PI/2, PI, - -PI/8, -PI/4, -PI/2, -PI}; - -void test_matrix_eulers(void) -{ - uint8_t i, j, k; - uint8_t N = ARRAY_LENGTH(angles); - - Serial.println("rotation matrix unit tests\n"); - - for (i=0; i Date: Tue, 6 Mar 2012 21:52:41 +1100 Subject: [PATCH 079/178] AP_IMU: fixed led flashing in gyro cal thanks Pat! --- libraries/AP_IMU/AP_IMU_INS.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/AP_IMU/AP_IMU_INS.cpp b/libraries/AP_IMU/AP_IMU_INS.cpp index 500f4e0c88..188692e43d 100644 --- a/libraries/AP_IMU/AP_IMU_INS.cpp +++ b/libraries/AP_IMU/AP_IMU_INS.cpp @@ -99,7 +99,7 @@ AP_IMU_INS::_init_gyro(void (*delay_cb)(unsigned long t), void (*flash_leds_cb)( gyro_sum += Vector3f(ins_gyro[0], ins_gyro[1], ins_gyro[2]); if (i % 40 == 20) { FLASH_LEDS(true); - } else if (i % 40 == 20) { + } else if (i % 40 == 0) { FLASH_LEDS(false); } delay_cb(5); From 045b49c4c4448a31704620d5f4c402c0b1274a14 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 7 Mar 2012 15:09:17 +1100 Subject: [PATCH 080/178] DCM: removed update_DCM_fast this combines the functionality of the 'fast' DCM with the normal one, and also speeds up both the yaw drift correction and the matrix update code --- libraries/AP_DCM/AP_DCM.cpp | 411 +++++++++++++++--------------------- libraries/AP_DCM/AP_DCM.h | 56 ++--- 2 files changed, 204 insertions(+), 263 deletions(-) diff --git a/libraries/AP_DCM/AP_DCM.cpp b/libraries/AP_DCM/AP_DCM.cpp index e87a6d0110..5b4d4f625e 100644 --- a/libraries/AP_DCM/AP_DCM.cpp +++ b/libraries/AP_DCM/AP_DCM.cpp @@ -1,8 +1,5 @@ - -#define RADX100 0.000174532925 -#define DEGX100 5729.57795 /* - APM_DCM_FW.cpp - DCM AHRS Library, fixed wing version, for Ardupilot Mega + APM_DCM.cpp - DCM AHRS Library, fixed wing version, for Ardupilot Mega Code by Doug Weibel, Jordi Muñoz and Jose Julio. DIYDrones.com This library works with the ArduPilot Mega and "Oilpan" @@ -21,17 +18,6 @@ */ #include -#define OUTPUTMODE 1 // This is just used for debugging, remove later -#define ToRad(x) (x*0.01745329252) // *pi/180 -#define ToDeg(x) (x*57.2957795131) // *180/pi - -//#define Kp_ROLLPITCH 0.05967 // .0014 * 418/9.81 Pitch&Roll Drift Correction Proportional Gain -//#define Ki_ROLLPITCH 0.00001278 // 0.0000003 * 418/9.81 Pitch&Roll Drift Correction Integrator Gain -//#define Ki_ROLLPITCH 0.0 // 0.0000003 * 418/9.81 Pitch&Roll Drift Correction Integrator Gain - -//#define Kp_YAW 0.8 // Yaw Drift Correction Porportional Gain -//#define Ki_YAW 0.00004 // Yaw Drift CorrectionIntegrator Gain - // this is the speed in cm/s above which we first get a yaw lock with // the GPS #define GPS_SPEED_MIN 300 @@ -46,154 +32,117 @@ AP_DCM::set_compass(Compass *compass) _compass = compass; } -/**************************************************/ + +// run a full DCM update round +// the drift_correction_frequency is how many steps of the algorithm +// to run before doing an accelerometer drift correction step void -AP_DCM::update_DCM_fast(void) +AP_DCM::update_DCM(uint8_t drift_correction_frequency) { float delta_t; Vector3f accel; + // tell the IMU to grab some data _imu->update(); - _gyro_vector = _imu->get_gyro(); // Get current values for IMU sensors - // add the current accel vector into our averaging filter + // ask the IMU how much time this sensor reading represents + delta_t = _imu->get_delta_time(); + + // Get current values for gyros + _gyro_vector = _imu->get_gyro(); + + // accumulate some more accelerometer data accel = _imu->get_accel(); _accel_sum += accel; - _accel_sum_count++; + _drift_correction_time += delta_t; - - delta_t = _imu->get_delta_time(); - - matrix_update(delta_t); // Integrate the DCM matrix - - switch(_toggle++){ - case 0: - normalize(); // Normalize the DCM matrix - break; - - case 1: - euler_rp(); // Calculate pitch, roll, yaw for stabilization and navigation - break; - - case 2: - _accel_vector = _accel_sum / _accel_sum_count; - _accel_sum_count = 0; - _accel_sum.zero(); - drift_correction(); // Normalize the DCM matrix - break; - - case 3: - euler_rp(); // Calculate pitch, roll, yaw for stabilization and navigation - break; - - case 4: - euler_yaw(); - break; - - default: - euler_rp(); // Calculate pitch, roll, yaw for stabilization and navigation - _toggle = 0; - break; + // Integrate the DCM matrix using gyro inputs + matrix_update(delta_t); + if (_dcm_matrix.is_nan()) { + SITL_debug("NaN matrix\n"); } + + // add up the omega vector so we pass a value to the drift + // correction averaged over the same time period as the + // accelerometers + _omega_sum += _omega_integ_corr; + + // Normalize the DCM matrix + normalize(); + + // see if we will perform drift correction on this call + _drift_correction_count++; + + if (_drift_correction_count == drift_correction_frequency) { + // calculate the average accelerometer vector over + // this time + float scale = 1.0 / _drift_correction_count; + _accel_vector = _accel_sum * scale; + _accel_sum.zero(); + + // calculate the average omega value over this time + _omega_smoothed = _omega_sum * scale; + _omega_sum.zero(); + + // Perform drift correction + drift_correction(_drift_correction_time); + + _drift_correction_time = 0; + _drift_correction_count = 0; + } + + // paranoid check for bad values in the DCM matrix + check_matrix(); + + // Calculate pitch, roll, yaw for stabilization and navigation + euler_angles(); } -/**************************************************/ -void -AP_DCM::update_DCM(void) -{ - float delta_t; - Vector3f accel; - - _imu->update(); - _gyro_vector = _imu->get_gyro(); // Get current values for IMU sensors - - // update_DCM() doesn't do averaging over the accel vectors, - // just a mild lowpass filter - accel = _imu->get_accel(); - _accel_vector = (accel * 0.5) + (_accel_vector * 0.5); - - delta_t = _imu->get_delta_time(); - - matrix_update(delta_t); // Integrate the DCM matrix - normalize(); // Normalize the DCM matrix - drift_correction(); // Perform drift correction - euler_angles(); // Calculate pitch, roll, yaw for stabilization and navigation -} - -/**************************************************/ - - //For Debugging -/* -void -printm(const char *l, Matrix3f &m) -{ Serial.println(" "); Serial.println(l); - Serial.print(m.a.x, 12); Serial.print(" "); Serial.print(m.a.y, 12); Serial.print(" "); Serial.println(m.a.z, 12); - Serial.print(m.b.x, 12); Serial.print(" "); Serial.print(m.b.y, 12); Serial.print(" "); Serial.println(m.b.z, 12); - Serial.print(m.c.x, 12); Serial.print(" "); Serial.print(m.c.y, 12); Serial.print(" "); Serial.println(m.c.z, 12); - Serial.print(*(uint32_t *)&(m.a.x), HEX); Serial.print(" "); Serial.print(*(uint32_t *)&(m.a.y), HEX); Serial.print(" "); Serial.println(*(uint32_t *)&(m.a.z), HEX); - Serial.print(*(uint32_t *)&(m.b.x), HEX); Serial.print(" "); Serial.print(*(uint32_t *)&(m.b.y), HEX); Serial.print(" "); Serial.println(*(uint32_t *)&(m.b.z), HEX); - Serial.print(*(uint32_t *)&(m.c.x), HEX); Serial.print(" "); Serial.print(*(uint32_t *)&(m.c.y), HEX); Serial.print(" "); Serial.println(*(uint32_t *)&(m.c.z), HEX); -} -*/ - -/**************************************************/ +// update the DCM matrix using only the gyros void AP_DCM::matrix_update(float _G_Dt) { - Matrix3f update_matrix; - Matrix3f temp_matrix; + // Used for _centripetal correction (theoretically better than _omega) + _omega_integ_corr = _gyro_vector + _omega_I; + // Equation 16, adding proportional and integral correction terms + _omega = _omega_integ_corr + _omega_P; - _omega_integ_corr = _gyro_vector + _omega_I; // Used for _centripetal correction (theoretically better than _omega) - _omega = _omega_integ_corr + _omega_P; // Equation 16, adding proportional and integral correction terms - _omega_smoothed = (_omega_smoothed * 0.5) + (_omega_integ_corr * 0.5); + float tmpx = _G_Dt * _omega.x; + float tmpy = _G_Dt * _omega.y; + float tmpz = _G_Dt * _omega.z; - #if OUTPUTMODE == 1 - float tmp = _G_Dt * _omega.x; - update_matrix.b.z = -tmp; // -delta Theta x - update_matrix.c.y = tmp; // delta Theta x - - tmp = _G_Dt * _omega.y; - update_matrix.c.x = -tmp; // -delta Theta y - update_matrix.a.z = tmp; // delta Theta y - - tmp = _G_Dt * _omega.z; - update_matrix.b.x = tmp; // delta Theta z - update_matrix.a.y = -tmp; // -delta Theta z - - update_matrix.a.x = 0; - update_matrix.b.y = 0; - update_matrix.c.z = 0; - #else // Uncorrected data (no drift correction) - update_matrix.a.x = 0; - update_matrix.a.y = -_G_Dt * _gyro_vector.z; - update_matrix.a.z = _G_Dt * _gyro_vector.y; - update_matrix.b.x = _G_Dt * _gyro_vector.z; - update_matrix.b.y = 0; - update_matrix.b.z = -_G_Dt * _gyro_vector.x; - update_matrix.c.x = -_G_Dt * _gyro_vector.y; - update_matrix.c.y = _G_Dt * _gyro_vector.x; - update_matrix.c.z = 0; - #endif - - temp_matrix = _dcm_matrix * update_matrix; - _dcm_matrix = _dcm_matrix + temp_matrix; // Equation 17 + // this is an expansion of the DCM matrix multiply, with known + // zero elements removed + _dcm_matrix.a.x += _dcm_matrix.a.y * tmpz - _dcm_matrix.a.z * tmpy; + _dcm_matrix.a.y += _dcm_matrix.a.z * tmpx - _dcm_matrix.a.x * tmpz; + _dcm_matrix.a.z += _dcm_matrix.a.x * tmpy - _dcm_matrix.a.y * tmpx; + _dcm_matrix.b.x += _dcm_matrix.b.y * tmpz - _dcm_matrix.b.z * tmpy; + _dcm_matrix.b.y += _dcm_matrix.b.z * tmpx - _dcm_matrix.b.x * tmpz; + _dcm_matrix.b.z += _dcm_matrix.b.x * tmpy - _dcm_matrix.b.y * tmpx; + _dcm_matrix.c.x += _dcm_matrix.c.y * tmpz - _dcm_matrix.c.z * tmpy; + _dcm_matrix.c.y += _dcm_matrix.c.z * tmpx - _dcm_matrix.c.x * tmpz; + _dcm_matrix.c.z += _dcm_matrix.c.x * tmpy - _dcm_matrix.c.y * tmpx; } -// adjust an accelerometer vector for centripetal force +// adjust an accelerometer vector for known acceleration forces void AP_DCM::accel_adjust(Vector3f &accel) { float veloc; + // compensate for linear acceleration, limited to 1g + float acceleration = _gps->acceleration(); + acceleration = constrain(acceleration, 0, 9.8); + accel.x -= acceleration; - veloc = _gps->ground_speed / 100; // We are working with acceleration in m/s^2 units + // compensate for centripetal acceleration + veloc = _gps->ground_speed / 100; // We are working with a modified version of equation 26 as // our IMU object reports acceleration in the positive axis // direction as positive // Equation 26 broken up into separate pieces - accel.y -= _omega_smoothed.z * veloc; accel.z += _omega_smoothed.y * veloc; } @@ -272,45 +221,9 @@ AP_DCM::check_matrix(void) } } -/************************************************* -Direction Cosine Matrix IMU: Theory -William Premerlani and Paul Bizard - -Numerical errors will gradually reduce the orthogonality conditions expressed by equation 5 -to approximations rather than identities. In effect, the axes in the two frames of reference no -longer describe a rigid body. Fortunately, numerical error accumulates very slowly, so it is a -simple matter to stay ahead of it. -We call the process of enforcing the orthogonality conditions ÒrenormalizationÓ. -*/ -void -AP_DCM::normalize(void) -{ - float error = 0; - Vector3f temporary[3]; - - int problem = 0; - - error = _dcm_matrix.a * _dcm_matrix.b; // eq.18 - - temporary[0] = _dcm_matrix.b; - temporary[1] = _dcm_matrix.a; - temporary[0] = _dcm_matrix.a - (temporary[0] * (0.5f * error)); // eq.19 - temporary[1] = _dcm_matrix.b - (temporary[1] * (0.5f * error)); // eq.19 - - temporary[2] = temporary[0] % temporary[1]; // c= a x b // eq.20 - - _dcm_matrix.a = renorm(temporary[0], problem); - _dcm_matrix.b = renorm(temporary[1], problem); - _dcm_matrix.c = renorm(temporary[2], problem); - - if (problem == 1) { // Our solution is blowing up and we will force back to initial condition. Hope we are not upside down! - matrix_reset(true); - } -} - /**************************************************/ -Vector3f -AP_DCM::renorm(Vector3f const &a, int &problem) +bool +AP_DCM::renorm(Vector3f const &a, Vector3f &result) { float renorm_val; @@ -332,7 +245,7 @@ AP_DCM::renorm(Vector3f const &a, int &problem) // we don't want to compound the error by making DCM less // accurate. - renorm_val = 1.0 / sqrt(a * a); + renorm_val = 1.0 / a.length(); // keep the average for reporting _renorm_val_sum += renorm_val; @@ -346,29 +259,61 @@ AP_DCM::renorm(Vector3f const &a, int &problem) // range, we will reset the matrix and hope we // can recover our attitude using drift // correction before we hit the ground! - problem = 1; //Serial.printf("ERROR: DCM renormalisation error. renorm_val=%f\n", // renorm_val); SITL_debug("ERROR: DCM renormalisation error. renorm_val=%f\n", renorm_val); renorm_blowup_count++; + return false; } } - return (a * renorm_val); + result = a * renorm_val; + return true; } +/************************************************* +Direction Cosine Matrix IMU: Theory +William Premerlani and Paul Bizard + +Numerical errors will gradually reduce the orthogonality conditions expressed by equation 5 +to approximations rather than identities. In effect, the axes in the two frames of reference no +longer describe a rigid body. Fortunately, numerical error accumulates very slowly, so it is a +simple matter to stay ahead of it. +We call the process of enforcing the orthogonality conditions ÒrenormalizationÓ. +*/ +void +AP_DCM::normalize(void) +{ + float error; + Vector3f t0, t1, t2; + + error = _dcm_matrix.a * _dcm_matrix.b; // eq.18 + + t0 = _dcm_matrix.a - (_dcm_matrix.b * (0.5f * error)); // eq.19 + t1 = _dcm_matrix.b - (_dcm_matrix.a * (0.5f * error)); // eq.19 + t2 = t0 % t1; // c= a x b // eq.20 + + if (!renorm(t0, _dcm_matrix.a) || + !renorm(t1, _dcm_matrix.b) || + !renorm(t2, _dcm_matrix.c)) { + // Our solution is blowing up and we will force back + // to last euler angles + matrix_reset(true); + } +} + + /**************************************************/ void -AP_DCM::drift_correction(void) +AP_DCM::drift_correction(float deltat) { float error_course = 0; - float accel_weight; - float integrator_magnitude; Vector3f accel; Vector3f error; float error_norm = 0; const float gravity_squared = (9.80665*9.80665); + float yaw_deltat = 0; accel = _accel_vector; @@ -386,13 +331,12 @@ AP_DCM::drift_correction(void) // calculate the z component of the accel vector assuming it // has a length of 9.8. This discards the z accelerometer // sensor reading completely. Logs show that the z accel is - // the noisest, and it seems that using just the x and y accel - // values gives a better attitude estimate than including the - // z accel - + // the noisest, plus it has a disproportionate impact on the + // drift correction result because of the geometry when we are + // mostly flat float zsquared = gravity_squared - ((accel.x * accel.x) + (accel.y * accel.y)); if (zsquared < 0) { - accel_weight = 0; + _omega_P.zero(); } else { if (accel.z > 0) { accel.z = sqrt(zsquared); @@ -400,40 +344,48 @@ AP_DCM::drift_correction(void) accel.z = -sqrt(zsquared); } - // this is arbitrary, and can be removed once we get - // ki and kp right - accel_weight = 0.6; - - _health = constrain(_health+(0.02 * (accel_weight - .5)), 0, 1); - error = _dcm_matrix.c % accel; - // error_roll_pitch are in Accel m/s^2 units - // Limit max error_roll_pitch to limit max omega_P and omega_I + // error is in m/s^2 units + // Limit max error to limit max omega_P and omega_I error_norm = error.length(); if (error_norm > 2) { error *= (2 / error_norm); } - _omega_P = error * (_kp_roll_pitch * accel_weight); - _omega_I += error * (_ki_roll_pitch * accel_weight); + // scale the error for the time over which we are + // applying it + error *= deltat; + + // calculate the new proportional offset + _omega_P = error * _kp_roll_pitch; + + // we limit the change in the integrator to the + // maximum gyro drift rate on each axis + float drift_limit = ToRad(_gyro_drift_rate) * deltat / _ki_roll_pitch; + error.x = constrain(error.x, -drift_limit, drift_limit); + error.y = constrain(error.y, -drift_limit, drift_limit); + error.z = constrain(error.z, -drift_limit, drift_limit); + + // update gyro drift estimate + _omega_I += error * _ki_roll_pitch; } // these sums support the reporting of the DCM state via MAVLink - _accel_weight_sum += accel_weight; - _accel_weight_count++; _error_rp_sum += error_norm; _error_rp_count++; + // yaw drift correction - //*****YAW*************** - - if (_compass && _compass->use_for_yaw()) { + if (_compass && _compass->use_for_yaw() && + _compass->last_update != _compass_last_update) { if (_have_initial_yaw) { // Equation 23, Calculating YAW error // We make the gyro YAW drift correction based // on compass magnetic heading error_course = (_dcm_matrix.a.x * _compass->heading_y) - (_dcm_matrix.b.x * _compass->heading_x); + yaw_deltat = 1.0e-6*(_compass->last_update - _compass_last_update); + _compass_last_update = _compass->last_update; } else { // this is our first estimate of the yaw, // construct a DCM matrix based on the current @@ -448,9 +400,10 @@ AP_DCM::drift_correction(void) rotation_matrix_from_euler(_dcm_matrix, roll, pitch, _compass->heading); _compass->null_offsets_enable(); _have_initial_yaw = true; + _compass_last_update = _compass->last_update; } - } else if (_gps && _gps->status() == GPS::GPS_OK) { - + } else if (_gps && _gps->status() == GPS::GPS_OK && + _gps->last_fix_time != _gps_last_update) { // Use GPS Ground course to correct yaw gyro drift if (_gps->ground_speed >= GPS_SPEED_MIN) { if (_have_initial_yaw) { @@ -458,6 +411,8 @@ AP_DCM::drift_correction(void) float course_over_ground_y = sin(ToRad(_gps->ground_course/100.0)); // Equation 23, Calculating YAW error error_course = (_dcm_matrix.a.x * course_over_ground_y) - (_dcm_matrix.b.x * course_over_ground_x); + yaw_deltat = 1.0e-3*(_gps->last_fix_time - _gps_last_update); + _gps_last_update = _gps->last_fix_time; } else { // when we first start moving, set the // DCM matrix to the current @@ -472,6 +427,7 @@ AP_DCM::drift_correction(void) } _have_initial_yaw = true; error_course = 0; + _gps_last_update = _gps->last_fix_time; } } else if (_gps->ground_speed >= GPS_SPEED_RESET) { // we are not going fast enough to use GPS for @@ -489,20 +445,30 @@ AP_DCM::drift_correction(void) } } - error = _dcm_matrix.c * error_course; // Equation 24, Applys the yaw correction to the XYZ rotation of the aircraft, depeding the position. - - _omega_P += error * _kp_yaw; // Adding yaw correction to proportional correction vector. - _omega_I += error * _ki_yaw; // adding yaw correction to integrator correction vector. - - // Here we will place a limit on the integrator so that the integrator cannot ever exceed ~30 degrees/second - integrator_magnitude = _omega_I.length(); - if (integrator_magnitude > radians(30)) { - _omega_I *= (radians(30) / integrator_magnitude); + if (yaw_deltat == 0 || error_course == 0) { + // nothing to do + return; } + // Equation 24, Applys the yaw correction to the XYZ rotation of the aircraft + error = _dcm_matrix.c * error_course; + + // Adding yaw correction to proportional correction vector. + _omega_P += error * _kp_yaw; + + // limit maximum gyro drift + float drift_limit = ToRad(_gyro_drift_rate) * yaw_deltat / _ki_yaw; + error.z = constrain(error.z, -drift_limit, drift_limit); + + // add yaw correction to integrator correction vector, but + // only for the z gyro. We rely on the accelerometers for x + // and y gyro drift correction. Using the compass for x/y drift + // correction is too inaccurate, and can lead to incorrect builups in + // the x/y drift + _omega_I.z += error.z * _ki_yaw; + _error_yaw_sum += error_course; _error_yaw_count++; - //Serial.print("*"); } @@ -511,8 +477,6 @@ AP_DCM::drift_correction(void) void AP_DCM::euler_angles(void) { - check_matrix(); - calculate_euler_angles(_dcm_matrix, &roll, &pitch, &yaw); roll_sensor = degrees(roll) * 100; @@ -523,39 +487,12 @@ AP_DCM::euler_angles(void) yaw_sensor += 36000; } -void -AP_DCM::euler_rp(void) -{ - check_matrix(); - calculate_euler_angles(_dcm_matrix, &roll, &pitch, NULL); - roll_sensor = roll * DEGX100; //degrees(roll) * 100; - pitch_sensor = pitch * DEGX100; //degrees(pitch) * 100; -} - -void -AP_DCM::euler_yaw(void) -{ - calculate_euler_angles(_dcm_matrix, NULL, NULL, &yaw); - yaw_sensor = yaw * DEGX100; //degrees(yaw) * 100; - - if (yaw_sensor < 0) - yaw_sensor += 36000; -} - - /* reporting of DCM state for MAVLink */ // average accel_weight since last call float AP_DCM::get_accel_weight(void) { - float ret; - if (_accel_weight_count == 0) { - return 0; - } - ret = _accel_weight_sum / _accel_weight_count; - _accel_weight_sum = 0; - _accel_weight_count = 0; - return ret; + return 1.0; } // average renorm_val since last call diff --git a/libraries/AP_DCM/AP_DCM.h b/libraries/AP_DCM/AP_DCM.h index 6d9f091703..1a65c23836 100644 --- a/libraries/AP_DCM/AP_DCM.h +++ b/libraries/AP_DCM/AP_DCM.h @@ -24,27 +24,29 @@ class AP_DCM { public: // Constructors - AP_DCM(IMU *imu, GPS *&gps, Compass *withCompass = NULL) : - _clamp(3), - _kp_roll_pitch(0.05967), - _ki_roll_pitch(0.00001278), - _kp_yaw(0.8), // .8 - _ki_yaw(0.00004), // 0.00004 - _compass(withCompass), + AP_DCM(IMU *imu, GPS *&gps) : + _kp_roll_pitch(12.0), + _ki_roll_pitch(0.0006), + _kp_yaw(3.0), + _ki_yaw(0.003), _gps(gps), _imu(imu), _dcm_matrix(1, 0, 0, - 0, 1, 0, - 0, 0, 1), + 0, 1, 0, + 0, 0, 1), _health(1.), _toggle(0) {} // Accessors - Vector3f get_gyro(void) {return _omega_integ_corr; } // We return the raw gyro vector corrected for bias + + // return the smoothed gyro vector corrected for drift + Vector3f get_gyro(void) {return _omega_smoothed; } Matrix3f get_dcm_matrix(void) {return _dcm_matrix; } Matrix3f get_dcm_transposed(void) {Matrix3f temp = _dcm_matrix; return temp.transpose();} - Vector3f get_integrator(void) {return _omega_I; } // We return the current drift correction integrator values + + // return the current drift correction integrator value + Vector3f get_integrator(void) {return _omega_I; } float get_health(void) {return _health;} void set_centripetal(bool b) {_centripetal = b;} @@ -52,13 +54,13 @@ public: void set_compass(Compass *compass); // Methods - void update_DCM(void); + void update_DCM(uint8_t drift_correction_frequency=1); void update_DCM_fast(void); void matrix_reset(bool recover_eulers = false); long roll_sensor; // Degrees * 100 long pitch_sensor; // Degrees * 100 - long yaw_sensor; // Degrees * 100 + long yaw_sensor; // Degrees * 100 float roll; // Radians float pitch; // Radians @@ -80,11 +82,6 @@ public: float ki_yaw() { return _ki_yaw; } void ki_yaw(float v) { _ki_yaw = v; } - static const float kDCM_kp_rp_high = 0.15; - static const float kDCM_kp_rp_medium = 0.05967; - static const float kDCM_kp_rp_low = 0.01; - int8_t _clamp; - // status reporting float get_accel_weight(void); float get_renorm_val(void); @@ -105,13 +102,12 @@ private: void matrix_update(float _G_Dt); void normalize(void); void check_matrix(void); - Vector3f renorm(Vector3f const &a, int &problem); - void drift_correction(void); + bool renorm(Vector3f const &a, Vector3f &result); + void drift_correction(float deltat); void euler_angles(void); - void euler_rp(void); - void euler_yaw(void); - + // max rate of gyro drift in degrees/s/s + static const float _gyro_drift_rate = 0.04; // members Compass * _compass; @@ -129,21 +125,19 @@ private: // to the main DCM update code Vector3f _accel_vector; Vector3f _accel_sum; - uint8_t _accel_sum_count; Vector3f _gyro_vector; // Store the gyros turn rate in a vector Vector3f _omega_P; // Omega Proportional correction Vector3f _omega_I; // Omega Integrator correction Vector3f _omega_integ_corr; // Partially corrected Gyro_Vector data - used for centrepetal correction Vector3f _omega; // Corrected Gyro_Vector data + Vector3f _omega_sum; Vector3f _omega_smoothed; float _health; bool _centripetal; uint8_t _toggle; // state to support status reporting - float _accel_weight_sum; - uint16_t _accel_weight_count; float _renorm_val_sum; uint16_t _renorm_val_count; float _error_rp_sum; @@ -151,6 +145,16 @@ private: float _error_yaw_sum; uint16_t _error_yaw_count; + // time in micros when we last got a compass fix + uint32_t _compass_last_update; + + // time in millis when we last got a GPS heading + uint32_t _gps_last_update; + + // counter of calls to update_DCM() without drift correction + uint8_t _drift_correction_count; + float _drift_correction_time; + }; #endif From 69c29d35ce5093a0c03158837575e8dddca0c98d Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 7 Mar 2012 15:10:08 +1100 Subject: [PATCH 081/178] ACM: change DCM loop to 100Hz On my APM2 quad this seems to give better results --- ArduCopter/ArduCopter.pde | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ArduCopter/ArduCopter.pde b/ArduCopter/ArduCopter.pde index 15a5e6682d..098434fbd1 100644 --- a/ArduCopter/ArduCopter.pde +++ b/ArduCopter/ArduCopter.pde @@ -856,7 +856,7 @@ void loop() // We want this to execute fast // ---------------------------- - if ((timer - fast_loopTimer) >= 4000 && imu.new_data_available()) { + if ((timer - fast_loopTimer) >= 10000 && imu.new_data_available()) { //Log_Write_Data(13, (int32_t)(timer - fast_loopTimer)); //PORTK |= B00010000; From ef771fecdc6c6ad9ac081c4dca31e9d937849123 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 7 Mar 2012 15:11:19 +1100 Subject: [PATCH 082/178] ACM: removed a lot of the special case code for quaternions --- ArduCopter/ArduCopter.pde | 29 ++++------------------------- 1 file changed, 4 insertions(+), 25 deletions(-) diff --git a/ArduCopter/ArduCopter.pde b/ArduCopter/ArduCopter.pde index 098434fbd1..210e0379be 100644 --- a/ArduCopter/ArduCopter.pde +++ b/ArduCopter/ArduCopter.pde @@ -973,12 +973,9 @@ static void medium_loop() if(g.compass_enabled){ if (compass.read()) { // Calculate heading -#if QUATERNION_ENABLE == ENABLED - compass.calculate(dcm.roll, dcm.pitch); -#else - compass.calculate(dcm.get_dcm_matrix()); - compass.null_offsets(dcm.get_dcm_matrix()); -#endif + Matrix3f m = dcm.get_dcm_matrix(); + compass.calculate(m); + compass.null_offsets(m); } } #endif @@ -1856,12 +1853,11 @@ static void read_AHRS(void) gcs_update(); #endif - dcm.update_DCM_fast(); + dcm.update_DCM(); omega = imu.get_gyro(); } static void update_trig(void){ -#if QUATERNION_ENABLE == DISABLED Vector2f yawvector; Matrix3f temp = dcm.get_dcm_matrix(); @@ -1880,23 +1876,6 @@ static void update_trig(void){ sin_yaw_y = yawvector.x; // 1y = north cos_yaw_x = yawvector.y; // 0x = north -#else - // we need a cheaper way to calculate this .... - Vector2f yawvector; - float cp = cos(dcm.pitch); - float cr = cos(dcm.roll); - float sy = sin(dcm.yaw); - float cy = cos(dcm.yaw); - - yawvector.x = cp * cy; - yawvector.y = cp * sy; - yawvector.normalize(); - - cos_pitch_x = cp; - cos_roll_x = cr; - sin_yaw_y = yawvector.x; - cos_yaw_x = yawvector.y; -#endif //flat: // 0 ° = cos_yaw: 0.00, sin_yaw: 1.00, // 90° = cos_yaw: 1.00, sin_yaw: 0.00, From d6cfc51ae41cad03adec5fe82afb47803f84efed Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 7 Mar 2012 15:11:44 +1100 Subject: [PATCH 083/178] ACM: no need to fetch offsets at startup AP_Param handles this --- ArduCopter/sensors.pde | 1 - 1 file changed, 1 deletion(-) diff --git a/ArduCopter/sensors.pde b/ArduCopter/sensors.pde index cb0da8bb03..5745b7208c 100644 --- a/ArduCopter/sensors.pde +++ b/ArduCopter/sensors.pde @@ -94,7 +94,6 @@ static void init_compass() return; } dcm.set_compass(&compass); - compass.get_offsets(); // load offsets to account for airframe magnetic interference compass.null_offsets_enable(); } From 7291dfc25a87bdaba0975dfd4f029f5ce9f9982d Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 7 Mar 2012 15:11:58 +1100 Subject: [PATCH 084/178] ACM: removed the special case for quaternions in GCS code --- ArduCopter/GCS_Mavlink.pde | 2 -- 1 file changed, 2 deletions(-) diff --git a/ArduCopter/GCS_Mavlink.pde b/ArduCopter/GCS_Mavlink.pde index 78fc8f2530..9ac2fd7e07 100644 --- a/ArduCopter/GCS_Mavlink.pde +++ b/ArduCopter/GCS_Mavlink.pde @@ -99,7 +99,6 @@ static void NOINLINE send_meminfo(mavlink_channel_t chan) static void NOINLINE send_location(mavlink_channel_t chan) { -#if QUATERNION_ENABLE == DISABLED Matrix3f rot = dcm.get_dcm_matrix(); // neglecting angle of attack for now mavlink_msg_global_position_int_send( chan, @@ -109,7 +108,6 @@ static void NOINLINE send_location(mavlink_channel_t chan) g_gps->ground_speed * rot.a.x, g_gps->ground_speed * rot.b.x, g_gps->ground_speed * rot.c.x); -#endif } static void NOINLINE send_nav_controller_output(mavlink_channel_t chan) From 8393c0299bb8c7db1d73a2f7ad0fb72a7c20e0ff Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 7 Mar 2012 15:12:31 +1100 Subject: [PATCH 085/178] ACM: removed the DCM tuning overrides not needed now that DCM scales with deltat --- ArduCopter/system.pde | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/ArduCopter/system.pde b/ArduCopter/system.pde index 1391643a85..b22f1f7a90 100644 --- a/ArduCopter/system.pde +++ b/ArduCopter/system.pde @@ -308,16 +308,6 @@ static void init_ardupilot() // --------------------------- reset_control_switch(); - #if HIL_MODE != HIL_MODE_ATTITUDE -#if QUATERNION_ENABLE == DISABLED - dcm.kp_roll_pitch(0.130000); - dcm.ki_roll_pitch(0.00001278), // 50 hz I term - dcm.kp_yaw(0.12); - dcm.ki_yaw(0.00002); - dcm._clamp = 5; -#endif - #endif - // init the Z damopener // -------------------- #if ACCEL_ALT_HOLD != 0 From 1016d3c95d110650e188b7667137f4466ff4856c Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 7 Mar 2012 15:12:50 +1100 Subject: [PATCH 086/178] ACM: removed quaternion special cases in CLI code --- ArduCopter/test.pde | 22 ++++++---------------- 1 file changed, 6 insertions(+), 16 deletions(-) diff --git a/ArduCopter/test.pde b/ArduCopter/test.pde index 00a3dcb89d..f828dabf3c 100644 --- a/ArduCopter/test.pde +++ b/ArduCopter/test.pde @@ -329,13 +329,10 @@ test_radio(uint8_t argc, const Menu::arg *argv) if(g.compass_enabled){ medium_loopCounter++; if(medium_loopCounter == 5){ + Matrix3f m = dcm.get_dcm_matrix(); compass.read(); // Read magnetometer -#if QUATERNION_ENABLE == ENABLED - compass.calculate(dcm.roll, dcm.pitch); -#else - compass.calculate(dcm.get_dcm_matrix()); - compass.null_offsets(dcm.get_dcm_matrix()); -#endif + compass.calculate(m); + compass.null_offsets(m); medium_loopCounter = 0; } } @@ -552,12 +549,9 @@ test_imu(uint8_t argc, const Menu::arg *argv) if(g.compass_enabled){ compass.read(); // Read magnetometer -#if QUATERNION_ENABLE == ENABLED - compass.calculate(dcm.roll, dcm.pitch); -#else - compass.calculate(dcm.get_dcm_matrix()); - compass.null_offsets(dcm.get_dcm_matrix()); -#endif + Matrix3f m = dcm.get_dcm_matrix(); + compass.calculate(m); + compass.null_offsets(m); } } fast_loopTimer = millis(); @@ -941,11 +935,7 @@ test_mag(uint8_t argc, const Menu::arg *argv) while(1){ delay(100); if (compass.read()) { -#if QUATERNION_ENABLE == ENABLED - compass.calculate(dcm.roll, dcm.pitch); -#else compass.calculate(dcm.get_dcm_matrix()); -#endif Vector3f maggy = compass.get_offsets(); Serial.printf_P(PSTR("Heading: %ld, XYZ: %d, %d, %d\n"), (wrap_360(ToDeg(compass.heading) * 100)) /100, From 371677610de162e295423887e5bb7095f77fb147 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 7 Mar 2012 15:13:13 +1100 Subject: [PATCH 087/178] APM: avoid fetching the DCM matrix twice also no special case for quaternions --- ArduPlane/ArduPlane.pde | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/ArduPlane/ArduPlane.pde b/ArduPlane/ArduPlane.pde index b7ff74cb80..d343e9ee6b 100644 --- a/ArduPlane/ArduPlane.pde +++ b/ArduPlane/ArduPlane.pde @@ -781,12 +781,9 @@ static void medium_loop() if (g.compass_enabled && compass.read()) { dcm.set_compass(&compass); // Calculate heading -#if QUATERNION_ENABLE == ENABLED - compass.calculate(dcm.roll, dcm.pitch); -#else - compass.calculate(dcm.get_dcm_matrix()); - compass.null_offsets(dcm.get_dcm_matrix()); -#endif + Matrix3f m = dcm.get_dcm_matrix(); + compass.calculate(m); + compass.null_offsets(m); } else { dcm.set_compass(NULL); } From 13d5839778ef3f90152d600feab0c228f3abaa37 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 7 Mar 2012 15:13:29 +1100 Subject: [PATCH 088/178] APM: removed quaternion special cases --- ArduPlane/GCS_Mavlink.pde | 2 -- ArduPlane/test.pde | 13 +++---------- 2 files changed, 3 insertions(+), 12 deletions(-) diff --git a/ArduPlane/GCS_Mavlink.pde b/ArduPlane/GCS_Mavlink.pde index 183a049c45..a2e8a40cb4 100644 --- a/ArduPlane/GCS_Mavlink.pde +++ b/ArduPlane/GCS_Mavlink.pde @@ -306,7 +306,6 @@ static void NOINLINE send_meminfo(mavlink_channel_t chan) static void NOINLINE send_location(mavlink_channel_t chan) { -#if QUATERNION_ENABLE == DISABLED Matrix3f rot = dcm.get_dcm_matrix(); // neglecting angle of attack for now mavlink_msg_global_position_int_send( chan, @@ -319,7 +318,6 @@ static void NOINLINE send_location(mavlink_channel_t chan) g_gps->ground_speed * rot.b.x, // Y speed cm/s g_gps->ground_speed * rot.c.x, g_gps->ground_course); // course in 1/100 degree -#endif } static void NOINLINE send_nav_controller_output(mavlink_channel_t chan) diff --git a/ArduPlane/test.pde b/ArduPlane/test.pde index fedb2fdb50..85c8e4ae3f 100644 --- a/ArduPlane/test.pde +++ b/ArduPlane/test.pde @@ -535,11 +535,7 @@ test_imu(uint8_t argc, const Menu::arg *argv) if(medium_loopCounter == 5){ if (compass.read()) { // Calculate heading -#if QUATERNION_ENABLE == ENABLED - compass.calculate(dcm.roll, dcm.pitch); -#else compass.calculate(dcm.get_dcm_matrix()); -#endif } medium_loopCounter = 0; } @@ -605,12 +601,9 @@ test_mag(uint8_t argc, const Menu::arg *argv) if(medium_loopCounter == 5){ if (compass.read()) { // Calculate heading -#if QUATERNION_ENABLE == ENABLED - compass.calculate(dcm.roll, dcm.pitch); -#else - compass.calculate(dcm.get_dcm_matrix()); - compass.null_offsets(dcm.get_dcm_matrix()); -#endif + Matrix3f m = dcm.get_dcm_matrix(); + compass.calculate(m); + compass.null_offsets(m); } medium_loopCounter = 0; } From a0a360f9550e75fb725c02b3c1541498e4af4754 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 7 Mar 2012 15:14:29 +1100 Subject: [PATCH 089/178] ADC: use floats for ADC averaging this costs almost nothing and improved accel/gyro calibration --- libraries/AP_ADC/AP_ADC.h | 2 +- libraries/AP_ADC/AP_ADC_ADS7844.cpp | 4 ++-- libraries/AP_ADC/AP_ADC_ADS7844.h | 2 +- libraries/AP_ADC/AP_ADC_HIL.cpp | 2 +- libraries/AP_ADC/AP_ADC_HIL.h | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/libraries/AP_ADC/AP_ADC.h b/libraries/AP_ADC/AP_ADC.h index 5e6b2d0909..e1b24e4c24 100644 --- a/libraries/AP_ADC/AP_ADC.h +++ b/libraries/AP_ADC/AP_ADC.h @@ -38,7 +38,7 @@ class AP_ADC The function returns the amount of time (in microseconds) since the last call to Ch6(). */ - virtual uint32_t Ch6(const uint8_t *channel_numbers, uint16_t *result) = 0; + virtual uint32_t Ch6(const uint8_t *channel_numbers, float *result) = 0; // check if Ch6() can return new data virtual bool new_data_available(const uint8_t *channel_numbers) = 0; diff --git a/libraries/AP_ADC/AP_ADC_ADS7844.cpp b/libraries/AP_ADC/AP_ADC_ADS7844.cpp index f216f5a895..761d237516 100644 --- a/libraries/AP_ADC/AP_ADC_ADS7844.cpp +++ b/libraries/AP_ADC/AP_ADC_ADS7844.cpp @@ -204,7 +204,7 @@ bool AP_ADC_ADS7844::new_data_available(const uint8_t *channel_numbers) // equal. This will only be true if we always consistently access a // sensor by either Ch6() or Ch() and never mix them. If you mix them // then you will get very strange results -uint32_t AP_ADC_ADS7844::Ch6(const uint8_t *channel_numbers, uint16_t *result) +uint32_t AP_ADC_ADS7844::Ch6(const uint8_t *channel_numbers, float *result) { uint16_t count[6]; uint32_t sum[6]; @@ -230,7 +230,7 @@ uint32_t AP_ADC_ADS7844::Ch6(const uint8_t *channel_numbers, uint16_t *result) // division. That costs us 36 bytes of stack, but I think its // worth it. for (i = 0; i < 6; i++) { - result[i] = (sum[i] + (count[i]/2)) / count[i]; + result[i] = (sum[i] + count[i]) / (float)count[i]; } diff --git a/libraries/AP_ADC/AP_ADC_ADS7844.h b/libraries/AP_ADC/AP_ADC_ADS7844.h index 73be670b3b..36f76f5770 100644 --- a/libraries/AP_ADC/AP_ADC_ADS7844.h +++ b/libraries/AP_ADC/AP_ADC_ADS7844.h @@ -28,7 +28,7 @@ class AP_ADC_ADS7844 : public AP_ADC float Ch(unsigned char ch_num); // Read 6 sensors at once - uint32_t Ch6(const uint8_t *channel_numbers, uint16_t *result); + uint32_t Ch6(const uint8_t *channel_numbers, float *result); // check if Ch6 would block bool new_data_available(const uint8_t *channel_numbers); diff --git a/libraries/AP_ADC/AP_ADC_HIL.cpp b/libraries/AP_ADC/AP_ADC_HIL.cpp index e443941642..24587de2f4 100644 --- a/libraries/AP_ADC/AP_ADC_HIL.cpp +++ b/libraries/AP_ADC/AP_ADC_HIL.cpp @@ -54,7 +54,7 @@ float AP_ADC_HIL::Ch(unsigned char ch_num) } // Read 6 channel values -uint32_t AP_ADC_HIL::Ch6(const uint8_t *channel_numbers, uint16_t *result) +uint32_t AP_ADC_HIL::Ch6(const uint8_t *channel_numbers, float *result) { for (uint8_t i=0; i<6; i++) { result[i] = Ch(channel_numbers[i]); diff --git a/libraries/AP_ADC/AP_ADC_HIL.h b/libraries/AP_ADC/AP_ADC_HIL.h index d9c53f6fdb..1f129f3378 100644 --- a/libraries/AP_ADC/AP_ADC_HIL.h +++ b/libraries/AP_ADC/AP_ADC_HIL.h @@ -36,7 +36,7 @@ class AP_ADC_HIL : public AP_ADC /// // Read 6 sensors at once - uint32_t Ch6(const uint8_t *channel_numbers, uint16_t *result); + uint32_t Ch6(const uint8_t *channel_numbers, float *result); // see if Ch6 would block bool new_data_available(const uint8_t *channel_numbers); From 6eff9107ea3a2d8183c604fe129fff273105f4c3 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 7 Mar 2012 15:14:59 +1100 Subject: [PATCH 090/178] Compass: change last_update to be in microseconds --- libraries/AP_Compass/AP_Compass_HIL.cpp | 2 +- libraries/AP_Compass/AP_Compass_HMC5843.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/AP_Compass/AP_Compass_HIL.cpp b/libraries/AP_Compass/AP_Compass_HIL.cpp index f57d7f5320..1e3187a343 100644 --- a/libraries/AP_Compass/AP_Compass_HIL.cpp +++ b/libraries/AP_Compass/AP_Compass_HIL.cpp @@ -16,7 +16,7 @@ bool AP_Compass_HIL::read() { // values set by setHIL function - last_update = millis(); // record time of update + last_update = micros(); // record time of update return true; } diff --git a/libraries/AP_Compass/AP_Compass_HMC5843.cpp b/libraries/AP_Compass/AP_Compass_HMC5843.cpp index dc452baad7..a34bf8c424 100644 --- a/libraries/AP_Compass/AP_Compass_HMC5843.cpp +++ b/libraries/AP_Compass/AP_Compass_HMC5843.cpp @@ -279,7 +279,7 @@ bool AP_Compass_HMC5843::read() mag_y *= calibration[1]; mag_z *= calibration[2]; - last_update = millis(); // record time of update + last_update = micros(); // record time of update // rotate and offset the magnetometer values // XXX this could well be done in common code... From 4dff78b9c0201eceb14bfc568f08a8e9c1d61f94 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 7 Mar 2012 15:15:13 +1100 Subject: [PATCH 091/178] GPS: expose last_fix_time --- libraries/AP_GPS/GPS.cpp | 4 ++-- libraries/AP_GPS/GPS.h | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/libraries/AP_GPS/GPS.cpp b/libraries/AP_GPS/GPS.cpp index 6fcde0429a..e917cf4458 100644 --- a/libraries/AP_GPS/GPS.cpp +++ b/libraries/AP_GPS/GPS.cpp @@ -36,9 +36,9 @@ GPS::update(void) if (_status == GPS_OK) { // update our acceleration - float deltat = 1.0e-3 * (_idleTimer - _last_fix_time); + float deltat = 1.0e-3 * (_idleTimer - last_fix_time); float deltav = 1.0e-2 * ((float)ground_speed - (float)_last_ground_speed); - _last_fix_time = _idleTimer; + last_fix_time = _idleTimer; _last_ground_speed = ground_speed; if (deltat > 2.0 || deltat == 0) { diff --git a/libraries/AP_GPS/GPS.h b/libraries/AP_GPS/GPS.h index 9889f96a02..1638d76a8c 100644 --- a/libraries/AP_GPS/GPS.h +++ b/libraries/AP_GPS/GPS.h @@ -113,6 +113,9 @@ public: // our approximate linear acceleration in m/s/s float acceleration(void) { return _acceleration; } + // the time we got our last fix in system milliseconds + uint32_t last_fix_time; + protected: Stream *_port; ///< port the GPS is attached to @@ -173,9 +176,6 @@ private: /// Our current status GPS_Status _status; - // the time we got our last fix in system milliseconds - uint32_t _last_fix_time; - // previous ground speed in cm/s uint32_t _last_ground_speed; From 919874f2a08d2a693b8503ecc1c9d9e340b43af6 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 7 Mar 2012 15:15:23 +1100 Subject: [PATCH 092/178] IMU: fixed a warning --- libraries/AP_IMU/AP_IMU_INS.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/AP_IMU/AP_IMU_INS.cpp b/libraries/AP_IMU/AP_IMU_INS.cpp index 188692e43d..f2e44d6d40 100644 --- a/libraries/AP_IMU/AP_IMU_INS.cpp +++ b/libraries/AP_IMU/AP_IMU_INS.cpp @@ -58,7 +58,7 @@ AP_IMU_INS::_init_gyro(void (*delay_cb)(unsigned long t), void (*flash_leds_cb)( { Vector3f last_average, best_avg; float ins_gyro[3]; - float best_diff; + float best_diff = 0; // cold start delay_cb(100); From 3e960f8ef90bde934d8e15830a4ae85fad3efb58 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 7 Mar 2012 15:15:45 +1100 Subject: [PATCH 093/178] InertionSensor: update for new Ch6() interface --- libraries/AP_InertialSensor/AP_InertialSensor_Oilpan.cpp | 6 +++--- libraries/AP_InertialSensor/AP_InertialSensor_Oilpan.h | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/libraries/AP_InertialSensor/AP_InertialSensor_Oilpan.cpp b/libraries/AP_InertialSensor/AP_InertialSensor_Oilpan.cpp index cbdf80fb30..4d13729722 100644 --- a/libraries/AP_InertialSensor/AP_InertialSensor_Oilpan.cpp +++ b/libraries/AP_InertialSensor/AP_InertialSensor_Oilpan.cpp @@ -55,7 +55,7 @@ void AP_InertialSensor_Oilpan::init( AP_PeriodicProcess * scheduler) bool AP_InertialSensor_Oilpan::update() { - uint16_t adc_values[6]; + float adc_values[6]; _sample_time = _adc->Ch6(_sensors, adc_values); _temp = _adc->Ch(_gyro_temp_ch); @@ -115,13 +115,13 @@ void AP_InertialSensor_Oilpan::reset_sample_time() { } /* ------ Private functions -------------------------------------------*/ -float AP_InertialSensor_Oilpan::_gyro_apply_std_offset( uint16_t adc_value ) +float AP_InertialSensor_Oilpan::_gyro_apply_std_offset( float adc_value ) { /* Magic number from AP_ADC_Oilpan.h */ return ((float) adc_value ) - 1658.0f; } -float AP_InertialSensor_Oilpan::_accel_apply_std_offset( uint16_t adc_value ) +float AP_InertialSensor_Oilpan::_accel_apply_std_offset( float adc_value ) { /* Magic number from AP_ADC_Oilpan.h */ return ((float) adc_value ) - 2041.0f; diff --git a/libraries/AP_InertialSensor/AP_InertialSensor_Oilpan.h b/libraries/AP_InertialSensor/AP_InertialSensor_Oilpan.h index 48f43b1694..099cde265e 100644 --- a/libraries/AP_InertialSensor/AP_InertialSensor_Oilpan.h +++ b/libraries/AP_InertialSensor/AP_InertialSensor_Oilpan.h @@ -55,8 +55,8 @@ class AP_InertialSensor_Oilpan : public AP_InertialSensor static const float _adc_constraint; - float _gyro_apply_std_offset( uint16_t adc_value ); - float _accel_apply_std_offset( uint16_t adc_value ); + float _gyro_apply_std_offset( float adc_value ); + float _accel_apply_std_offset( float adc_value ); }; #endif // __AP_INERTIAL_SENSOR_OILPAN_H__ From 8b40c44522de605986190b819b551e6456f5f479 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 7 Mar 2012 15:16:21 +1100 Subject: [PATCH 094/178] Quaternion: separate out drift correction from main updates --- libraries/AP_Quaternion/AP_Quaternion.cpp | 202 +++++++++++++++++++++- libraries/AP_Quaternion/AP_Quaternion.h | 28 ++- 2 files changed, 214 insertions(+), 16 deletions(-) diff --git a/libraries/AP_Quaternion/AP_Quaternion.cpp b/libraries/AP_Quaternion/AP_Quaternion.cpp index dc2080d516..d86c7268b3 100644 --- a/libraries/AP_Quaternion/AP_Quaternion.cpp +++ b/libraries/AP_Quaternion/AP_Quaternion.cpp @@ -116,7 +116,13 @@ void AP_Quaternion::update_IMU(float deltat, Vector3f &gyro, Vector3f &accel) // our quaternion is bad! Reset based on roll/pitch/yaw // and hope for the best ... renorm_blowup_count++; + if (_compass) { + _compass->null_offsets_disable(); + } quaternion_from_euler(q, roll, pitch, yaw); + if (_compass) { + _compass->null_offsets_enable(); + } return; } SEq_1 *= norm; @@ -213,10 +219,10 @@ void AP_Quaternion::update_MARG(float deltat, Vector3f &gyro, Vector3f &accel, V J_64 = twob_xSEq_2; // compute the gradient (matrix multiplication) - SEqHatDot_1 = J_14or21 * f_2 - J_11or24 * f_1 - J_41 * f_4 - J_51 * f_5 + J_61 * f_6; + SEqHatDot_1 = J_14or21 * f_2 - J_11or24 * f_1 - J_41 * f_4 - J_51 * f_5 + J_61 * f_6; SEqHatDot_2 = J_12or23 * f_1 + J_13or22 * f_2 - J_32 * f_3 + J_42 * f_4 + J_52 * f_5 + J_62 * f_6; SEqHatDot_3 = J_12or23 * f_2 - J_33 * f_3 - J_13or22 * f_1 - J_43 * f_4 + J_53 * f_5 + J_63 * f_6; - SEqHatDot_4 = J_14or21 * f_1 + J_11or24 * f_2 - J_44 * f_4 - J_54 * f_5 + J_64 * f_6; + SEqHatDot_4 = J_14or21 * f_1 + J_11or24 * f_2 - J_44 * f_4 - J_54 * f_5 + J_64 * f_6; // normalise the gradient to estimate direction of the gyroscope error norm = 1.0 / safe_sqrt(SEqHatDot_1 * SEqHatDot_1 + SEqHatDot_2 * SEqHatDot_2 + SEqHatDot_3 * SEqHatDot_3 + SEqHatDot_4 * SEqHatDot_4); @@ -273,7 +279,9 @@ void AP_Quaternion::update_MARG(float deltat, Vector3f &gyro, Vector3f &accel, V // our quaternion is bad! Reset based on roll/pitch/yaw // and hope for the best ... renorm_blowup_count++; + _compass->null_offsets_disable(); quaternion_from_euler(q, roll, pitch, yaw); + _compass->null_offsets_disable(); return; } SEq_1 *= norm; @@ -299,6 +307,151 @@ void AP_Quaternion::update_MARG(float deltat, Vector3f &gyro, Vector3f &accel, V } +// Function to compute one quaternion iteration including magnetometer +void AP_Quaternion::update_drift(float deltat, Vector3f &gyro, Vector3f &accel, Vector3f &mag) +{ + // local system variables + float norm; // vector norm + float SEqDot_omega_1, SEqDot_omega_2, SEqDot_omega_3, SEqDot_omega_4; // quaternion rate from gyroscopes elements + float f_1, f_2, f_3, f_4, f_5, f_6; // objective function elements + float J_11or24, J_12or23, J_13or22, J_14or21, J_32, J_33, // objective function Jacobian elements + J_41, J_42, J_43, J_44, J_51, J_52, J_53, J_54, J_61, J_62, J_63, J_64; // + float SEqHatDot_1, SEqHatDot_2, SEqHatDot_3, SEqHatDot_4; // estimated direction of the gyroscope error + + // computed flux in the earth frame + Vector3f flux; + + // estimated direction of the gyroscope error (radians) + Vector3f w_err; + + // normalise accelerometer vector + accel.normalize(); + if (accel.is_inf()) { + // discard this data point + renorm_range_count++; + return; + } + + // normalise the magnetometer measurement + mag.normalize(); + if (mag.is_inf()) { + // discard this data point + renorm_range_count++; + return; + } + + // auxiliary variables to avoid repeated calculations + float halfSEq_1 = 0.5f * SEq_1; + float halfSEq_2 = 0.5f * SEq_2; + float halfSEq_3 = 0.5f * SEq_3; + float halfSEq_4 = 0.5f * SEq_4; + float twoSEq_1 = 2.0f * SEq_1; + float twoSEq_2 = 2.0f * SEq_2; + float twoSEq_3 = 2.0f * SEq_3; + float twoSEq_4 = 2.0f * SEq_4; + float twob_x = 2.0f * b_x; + float twob_z = 2.0f * b_z; + float twob_xSEq_1 = 2.0f * b_x * SEq_1; + float twob_xSEq_2 = 2.0f * b_x * SEq_2; + float twob_xSEq_3 = 2.0f * b_x * SEq_3; + float twob_xSEq_4 = 2.0f * b_x * SEq_4; + float twob_zSEq_1 = 2.0f * b_z * SEq_1; + float twob_zSEq_2 = 2.0f * b_z * SEq_2; + float twob_zSEq_3 = 2.0f * b_z * SEq_3; + float twob_zSEq_4 = 2.0f * b_z * SEq_4; + float SEq_1SEq_2; + float SEq_1SEq_3 = SEq_1 * SEq_3; + float SEq_1SEq_4; + float SEq_2SEq_3; + float SEq_2SEq_4 = SEq_2 * SEq_4; + float SEq_3SEq_4; + Vector3f twom = mag * 2.0; + + // compute the objective function and Jacobian + f_1 = twoSEq_2 * SEq_4 - twoSEq_1 * SEq_3 - accel.x; + f_2 = twoSEq_1 * SEq_2 + twoSEq_3 * SEq_4 - accel.y; + f_3 = 1.0f - twoSEq_2 * SEq_2 - twoSEq_3 * SEq_3 - accel.z; + f_4 = twob_x * (0.5f - SEq_3 * SEq_3 - SEq_4 * SEq_4) + twob_z * (SEq_2SEq_4 - SEq_1SEq_3) - mag.x; + f_5 = twob_x * (SEq_2 * SEq_3 - SEq_1 * SEq_4) + twob_z * (SEq_1 * SEq_2 + SEq_3 * SEq_4) - mag.y; + f_6 = twob_x * (SEq_1SEq_3 + SEq_2SEq_4) + twob_z * (0.5f - SEq_2 * SEq_2 - SEq_3 * SEq_3) - mag.z; + J_11or24 = twoSEq_3; // J_11 negated in matrix multiplication + J_12or23 = 2.0f * SEq_4; + J_13or22 = twoSEq_1; // J_12 negated in matrix multiplication + J_14or21 = twoSEq_2; + J_32 = 2.0f * J_14or21; // negated in matrix multiplication + J_33 = 2.0f * J_11or24; // negated in matrix multiplication + J_41 = twob_zSEq_3; // negated in matrix multiplication + J_42 = twob_zSEq_4; + J_43 = 2.0f * twob_xSEq_3 + twob_zSEq_1; // negated in matrix multiplication + J_44 = 2.0f * twob_xSEq_4 - twob_zSEq_2; // negated in matrix multiplication + J_51 = twob_xSEq_4 - twob_zSEq_2; // negated in matrix multiplication + J_52 = twob_xSEq_3 + twob_zSEq_1; + J_53 = twob_xSEq_2 + twob_zSEq_4; + J_54 = twob_xSEq_1 - twob_zSEq_3; // negated in matrix multiplication + J_61 = twob_xSEq_3; + J_62 = twob_xSEq_4 - 2.0f * twob_zSEq_2; + J_63 = twob_xSEq_1 - 2.0f * twob_zSEq_3; + J_64 = twob_xSEq_2; + + // compute the gradient (matrix multiplication) + SEqHatDot_1 = J_14or21 * f_2 - J_11or24 * f_1 - J_41 * f_4 - J_51 * f_5 + J_61 * f_6; + SEqHatDot_2 = J_12or23 * f_1 + J_13or22 * f_2 - J_32 * f_3 + J_42 * f_4 + J_52 * f_5 + J_62 * f_6; + SEqHatDot_3 = J_12or23 * f_2 - J_33 * f_3 - J_13or22 * f_1 - J_43 * f_4 + J_53 * f_5 + J_63 * f_6; + SEqHatDot_4 = J_14or21 * f_1 + J_11or24 * f_2 - J_44 * f_4 - J_54 * f_5 + J_64 * f_6; + + // normalise the gradient to estimate direction of the gyroscope error + norm = 1.0 / safe_sqrt(SEqHatDot_1 * SEqHatDot_1 + SEqHatDot_2 * SEqHatDot_2 + SEqHatDot_3 * SEqHatDot_3 + SEqHatDot_4 * SEqHatDot_4); + if (isinf(norm)) { + // discard this data point + renorm_range_count++; + return; + } + SEqHatDot_1 *= norm; + SEqHatDot_2 *= norm; + SEqHatDot_3 *= norm; + SEqHatDot_4 *= norm; + + // compute angular estimated direction of the gyroscope error + w_err.x = twoSEq_1 * SEqHatDot_2 - twoSEq_2 * SEqHatDot_1 - twoSEq_3 * SEqHatDot_4 + twoSEq_4 * SEqHatDot_3; + w_err.y = twoSEq_1 * SEqHatDot_3 + twoSEq_2 * SEqHatDot_4 - twoSEq_3 * SEqHatDot_1 - twoSEq_4 * SEqHatDot_2; + w_err.z = twoSEq_1 * SEqHatDot_4 - twoSEq_2 * SEqHatDot_3 + twoSEq_3 * SEqHatDot_2 - twoSEq_4 * SEqHatDot_1; + + // keep track of the error rates + _error_rp_sum += 0.5*(fabs(w_err.x) + fabs(w_err.y)); + _error_yaw_sum += fabs(w_err.z); + _error_rp_count++; + _error_yaw_count++; + + // compute the gyroscope bias delta + Vector3f drift_delta = w_err * (deltat * zeta); + + // don't allow the drift rate to be exceeded. This prevents a + // sudden drift change coming from a outage in the compass + float max_change = gyroMeasDrift * deltat; + drift_delta.x = constrain(drift_delta.x, -max_change, max_change); + drift_delta.y = constrain(drift_delta.y, -max_change, max_change); + drift_delta.z = constrain(drift_delta.z, -max_change, max_change); + gyro_bias += drift_delta; + + // compute flux in the earth frame + // recompute axulirary variables + SEq_1SEq_2 = SEq_1 * SEq_2; + SEq_1SEq_3 = SEq_1 * SEq_3; + SEq_1SEq_4 = SEq_1 * SEq_4; + SEq_3SEq_4 = SEq_3 * SEq_4; + SEq_2SEq_3 = SEq_2 * SEq_3; + SEq_2SEq_4 = SEq_2 * SEq_4; + flux.x = twom.x * (0.5f - SEq_3 * SEq_3 - SEq_4 * SEq_4) + twom.y * (SEq_2SEq_3 - SEq_1SEq_4) + twom.z * (SEq_2SEq_4 + SEq_1SEq_3); + flux.y = twom.x * (SEq_2SEq_3 + SEq_1SEq_4) + twom.y * (0.5f - SEq_2 * SEq_2 - SEq_4 * SEq_4) + twom.z * (SEq_3SEq_4 - SEq_1SEq_2); + flux.z = twom.x * (SEq_2SEq_4 - SEq_1SEq_3) + twom.y * (SEq_3SEq_4 + SEq_1SEq_2) + twom.z * (0.5f - SEq_2 * SEq_2 - SEq_3 * SEq_3); + + // normalise the flux vector to have only components in the x and z + b_x = sqrt((flux.x * flux.x) + (flux.y * flux.y)); + b_z = flux.z; +} + + + // Function to compute one quaternion iteration void AP_Quaternion::update(void) { @@ -321,11 +474,15 @@ void AP_Quaternion::update(void) return; } - if (!_have_initial_yaw && _compass && _compass->use_for_yaw()) { + if (!_have_initial_yaw && _compass && + _compass->use_for_yaw()) { // setup the quaternion with initial compass yaw + _compass->null_offsets_disable(); quaternion_from_euler(q, 0, 0, _compass->heading); _have_initial_yaw = true; + _compass_last_update = _compass->last_update; gyro_bias.zero(); + _compass->null_offsets_enable(); } // get current IMU state @@ -356,14 +513,43 @@ void AP_Quaternion::update(void) accel.z += (gyro.y - gyro_bias.y) * veloc; } - if (_compass == NULL || !_compass->use_for_yaw()) { - update_IMU(deltat, gyro, accel); - } else { - // mag.z is reversed in quaternion code +#if 1 + _gyro_sum += gyro; + _accel_sum += accel; + _sum_count++; + + if (_compass != NULL && _compass->use_for_yaw() && + _compass->last_update != _compass_last_update && + _sum_count != 0) { + // use new compass sample for drift correction + float mag_deltat = 1.0e-6*(_compass->last_update - _compass_last_update); Vector3f mag = Vector3f(_compass->mag_x, _compass->mag_y, - _compass->mag_z); - update_MARG(deltat, gyro, accel, mag); + Vector3f drift_accel = _accel_sum / _sum_count; + Vector3f drift_gyro = _gyro_sum / _sum_count; + _accel_sum.zero(); + _gyro_sum.zero(); + _sum_count = 0; + update_drift(mag_deltat, drift_gyro, drift_accel, mag); + _compass_last_update = _compass->last_update; } + // step the quaternion solution + gyro -= gyro_bias; + update_IMU(deltat, gyro, accel); +#else + if (_compass != NULL && _compass->use_for_yaw()) { + // use new compass sample for drift correction + Vector3f mag = Vector3f(_compass->mag_x, _compass->mag_y, - _compass->mag_z); + update_MARG(deltat, gyro, accel, mag); + } else { + // step the quaternion without drift correction + gyro -= gyro_bias; + _gyro_sum += gyro; + _accel_sum += accel; + _sum_count++; + update_IMU(deltat, gyro, accel); + } +#endif #ifdef DESKTOP_BUILD if (q.is_nan()) { diff --git a/libraries/AP_Quaternion/AP_Quaternion.h b/libraries/AP_Quaternion/AP_Quaternion.h index 2819cf15be..4f069c9510 100644 --- a/libraries/AP_Quaternion/AP_Quaternion.h +++ b/libraries/AP_Quaternion/AP_Quaternion.h @@ -17,10 +17,9 @@ class AP_Quaternion { public: // Constructor - AP_Quaternion(IMU *imu, GPS *&gps, Compass *compass = NULL) : + AP_Quaternion(IMU *imu, GPS *&gps) : _imu(imu), - _gps(gps), - _compass(compass) + _gps(gps) { // reference direction of flux in earth frame b_x = 0; @@ -70,10 +69,16 @@ public: uint8_t renorm_blowup_count; float get_error_rp(void); float get_error_yaw(void); + Matrix3f get_dcm_matrix(void) { + Matrix3f ret; + quaternion_to_rotation_matrix(q, ret); + return ret; + } private: void update_IMU(float deltat, Vector3f &gyro, Vector3f &accel); void update_MARG(float deltat, Vector3f &gyro, Vector3f &accel, Vector3f &mag); + void update_drift(float deltat, Vector3f &gyro, Vector3f &accel, Vector3f &mag); bool _have_initial_yaw; @@ -82,6 +87,8 @@ private: // members Compass * _compass; + // time in microseconds of last compass update + uint32_t _compass_last_update; // note: we use ref-to-pointer here so that our caller can change the GPS without our noticing // IMU under us without our noticing. @@ -91,12 +98,12 @@ private: // true if we are doing centripetal acceleration correction bool _centripetal; - // maximum gyroscope measurement error in rad/s (set to 20 degrees/second) - static const float gyroMeasError = 20.0 * (M_PI/180.0); + // maximum gyroscope measurement error in rad/s (set to 40 degrees/second) + static const float gyroMeasError = 10.0 * (M_PI/180.0); - // maximum gyroscope drift rate in radians/s/s (set to 0.02 - // degrees/s/s, which is 1.2 degrees/s/minute) - static const float gyroMeasDrift = 0.02 * (PI/180.0); + // maximum gyroscope drift rate in radians/s/s (set to 0.005 + // degrees/s/s, which is 0.3 degrees/s/minute) + static const float gyroMeasDrift = 0.005 * (PI/180.0); float beta; float zeta; @@ -115,6 +122,11 @@ private: // the current corrected gyro vector Vector3f _gyro_corrected; + // accel and gyro accumulators for drift correction + Vector3f _gyro_sum; + Vector3f _accel_sum; + uint32_t _sum_count; + // estimate of error float _error_rp_sum; uint16_t _error_rp_count; From f9394f8068cb33a4d92396c1b43bfc6d921bbcee Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 5 Mar 2012 11:26:12 +1100 Subject: [PATCH 095/178] ADC: removed the ADC level accel smoothing the quaternion code does a better job of handling this noise than this filter does --- libraries/AP_ADC/AP_ADC_ADS7844.cpp | 36 +---------------------------- libraries/AP_ADC/AP_ADC_ADS7844.h | 6 ----- 2 files changed, 1 insertion(+), 41 deletions(-) diff --git a/libraries/AP_ADC/AP_ADC_ADS7844.cpp b/libraries/AP_ADC/AP_ADC_ADS7844.cpp index 761d237516..29a694ae08 100644 --- a/libraries/AP_ADC/AP_ADC_ADS7844.cpp +++ b/libraries/AP_ADC/AP_ADC_ADS7844.cpp @@ -126,9 +126,7 @@ void AP_ADC_ADS7844::read(uint32_t tnow) // Constructors //////////////////////////////////////////////////////////////// -AP_ADC_ADS7844::AP_ADC_ADS7844() : - filter_result(false), - _filter_index_accel(0) +AP_ADC_ADS7844::AP_ADC_ADS7844() { } @@ -233,38 +231,6 @@ uint32_t AP_ADC_ADS7844::Ch6(const uint8_t *channel_numbers, float *result) result[i] = (sum[i] + count[i]) / (float)count[i]; } - - if(filter_result){ - uint32_t _sum_accel; - - // Accel filter - for (i = 0; i < 3; i++) { - // move most recent result into filter - _filter_accel[i][_filter_index_accel] = result[i+3]; - - // clear the sum - _sum_accel = 0; - - // sum the filter - for (uint8_t n = 0; n < ADC_ACCEL_FILTER_SIZE; n++) { - _sum_accel += _filter_accel[i][n]; - } - - // filter does a moving average on last 8 reads, sums half with half of last filtered value - // save old result - _prev_accel[i] = result[i+3] = (_sum_accel >> 4) + (_prev_accel[i] >> 1); // divide by 16, divide by 2 - - } - - // increment filter index - _filter_index_accel++; - - // loop our filter - if(_filter_index_accel == ADC_ACCEL_FILTER_SIZE) - _filter_index_accel = 0; - } - - // return number of microseconds since last call uint32_t us = micros(); uint32_t ret = us - last_ch6_micros; diff --git a/libraries/AP_ADC/AP_ADC_ADS7844.h b/libraries/AP_ADC/AP_ADC_ADS7844.h index 36f76f5770..c62004bee4 100644 --- a/libraries/AP_ADC/AP_ADC_ADS7844.h +++ b/libraries/AP_ADC/AP_ADC_ADS7844.h @@ -33,13 +33,7 @@ class AP_ADC_ADS7844 : public AP_ADC // check if Ch6 would block bool new_data_available(const uint8_t *channel_numbers); - bool filter_result; - private: - uint16_t _filter_accel[3][ADC_ACCEL_FILTER_SIZE]; - uint16_t _prev_gyro[3]; - uint16_t _prev_accel[3]; - uint8_t _filter_index_accel; static void read(uint32_t); }; From 828ad7625bd8661475168dd74749bf0e9310a431 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 5 Mar 2012 11:28:04 +1100 Subject: [PATCH 096/178] ACM: removed the ADC filtering code --- ArduCopter/control_modes.pde | 7 ------- ArduCopter/system.pde | 1 - 2 files changed, 8 deletions(-) diff --git a/ArduCopter/control_modes.pde b/ArduCopter/control_modes.pde index cbfc5615bd..ebca424d6c 100644 --- a/ArduCopter/control_modes.pde +++ b/ArduCopter/control_modes.pde @@ -72,13 +72,6 @@ static void read_trim_switch() } } - #elif CH7_OPTION == CH7_ADC_FILTER - if (g.rc_7.radio_in > CH_7_PWM_TRIGGER){ - adc.filter_result = true; - }else{ - adc.filter_result = false; - } - #elif CH7_OPTION == CH7_AUTO_TRIM if (g.rc_7.radio_in > CH_7_PWM_TRIGGER){ auto_level_counter = 10; diff --git a/ArduCopter/system.pde b/ArduCopter/system.pde index b22f1f7a90..ea32cdc2d1 100644 --- a/ArduCopter/system.pde +++ b/ArduCopter/system.pde @@ -218,7 +218,6 @@ static void init_ardupilot() #if HIL_MODE != HIL_MODE_ATTITUDE #if CONFIG_ADC == ENABLED // begin filtering the ADC Gyros - adc.filter_result = true; adc.Init(&timer_scheduler); // APM ADC library initialization #endif // CONFIG_ADC From 9dc08b30cd116706aca1cc64096b062a25297a88 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 7 Mar 2012 16:43:04 +1100 Subject: [PATCH 097/178] Quaternion: bumb up gyro drift limit to match DCM --- libraries/AP_Quaternion/AP_Quaternion.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/AP_Quaternion/AP_Quaternion.h b/libraries/AP_Quaternion/AP_Quaternion.h index 4f069c9510..9f115eeafe 100644 --- a/libraries/AP_Quaternion/AP_Quaternion.h +++ b/libraries/AP_Quaternion/AP_Quaternion.h @@ -103,7 +103,7 @@ private: // maximum gyroscope drift rate in radians/s/s (set to 0.005 // degrees/s/s, which is 0.3 degrees/s/minute) - static const float gyroMeasDrift = 0.005 * (PI/180.0); + static const float gyroMeasDrift = 0.04 * (PI/180.0); float beta; float zeta; From f40547787500a575bbca1b0a0b7d0cc3bca8d0eb Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 7 Mar 2012 17:12:42 +1100 Subject: [PATCH 098/178] DCM: code cleanup and added more comments --- libraries/AP_DCM/AP_DCM.cpp | 63 ++++++++++++++++++++++++++----------- 1 file changed, 44 insertions(+), 19 deletions(-) diff --git a/libraries/AP_DCM/AP_DCM.cpp b/libraries/AP_DCM/AP_DCM.cpp index 5b4d4f625e..9e5e66de64 100644 --- a/libraries/AP_DCM/AP_DCM.cpp +++ b/libraries/AP_DCM/AP_DCM.cpp @@ -35,7 +35,7 @@ AP_DCM::set_compass(Compass *compass) // run a full DCM update round // the drift_correction_frequency is how many steps of the algorithm -// to run before doing an accelerometer drift correction step +// to run before doing an accelerometer and yaw drift correction step void AP_DCM::update_DCM(uint8_t drift_correction_frequency) { @@ -58,9 +58,6 @@ AP_DCM::update_DCM(uint8_t drift_correction_frequency) // Integrate the DCM matrix using gyro inputs matrix_update(delta_t); - if (_dcm_matrix.is_nan()) { - SITL_debug("NaN matrix\n"); - } // add up the omega vector so we pass a value to the drift // correction averaged over the same time period as the @@ -73,9 +70,9 @@ AP_DCM::update_DCM(uint8_t drift_correction_frequency) // see if we will perform drift correction on this call _drift_correction_count++; - if (_drift_correction_count == drift_correction_frequency) { + if (_drift_correction_count >= drift_correction_frequency) { // calculate the average accelerometer vector over - // this time + // since the last drift correction call float scale = 1.0 / _drift_correction_count; _accel_vector = _accel_sum * scale; _accel_sum.zero(); @@ -102,17 +99,25 @@ AP_DCM::update_DCM(uint8_t drift_correction_frequency) void AP_DCM::matrix_update(float _G_Dt) { - // Used for _centripetal correction (theoretically better than _omega) + // _omega_integ_corr is used for _centripetal correction + // (theoretically better than _omega) _omega_integ_corr = _gyro_vector + _omega_I; + // Equation 16, adding proportional and integral correction terms _omega = _omega_integ_corr + _omega_P; + // this is an expansion of the DCM matrix multiply (equation + // 17), with known zero elements removed and the matrix + // operations inlined. This runs much faster than the original + // version of this code, as the compiler was doing a terrible + // job of realising that so many of the factors were in common + // or zero. It also uses much less stack, as we no longer need + // additional local matrices + float tmpx = _G_Dt * _omega.x; float tmpy = _G_Dt * _omega.y; float tmpz = _G_Dt * _omega.z; - // this is an expansion of the DCM matrix multiply, with known - // zero elements removed _dcm_matrix.a.x += _dcm_matrix.a.y * tmpz - _dcm_matrix.a.z * tmpy; _dcm_matrix.a.y += _dcm_matrix.a.z * tmpx - _dcm_matrix.a.x * tmpz; _dcm_matrix.a.z += _dcm_matrix.a.x * tmpy - _dcm_matrix.a.y * tmpx; @@ -221,7 +226,8 @@ AP_DCM::check_matrix(void) } } -/**************************************************/ +// renormalise one vector component of the DCM matrix +// this will return false if renormalization fails bool AP_DCM::renorm(Vector3f const &a, Vector3f &result) { @@ -304,7 +310,11 @@ AP_DCM::normalize(void) } -/**************************************************/ +// perform drift correction. This function aims to update _omega_P and +// _omega_I with our best estimate of the short term and long term +// gyro error. The _omega_P value is what pulls our attitude solution +// back towards the reference vector quickly. The _omega_I term is an +// attempt to learn the long term drift rate of the gyros. void AP_DCM::drift_correction(float deltat) { @@ -333,7 +343,9 @@ AP_DCM::drift_correction(float deltat) // sensor reading completely. Logs show that the z accel is // the noisest, plus it has a disproportionate impact on the // drift correction result because of the geometry when we are - // mostly flat + // mostly flat. Dropping it completely seems to make the DCM + // algorithm much more resilient to large amounts of + // accelerometer noise. float zsquared = gravity_squared - ((accel.x * accel.x) + (accel.y * accel.y)); if (zsquared < 0) { _omega_P.zero(); @@ -377,6 +389,10 @@ AP_DCM::drift_correction(float deltat) // yaw drift correction + // we only do yaw drift correction when we get a new yaw + // reference vector. In between times we rely on the gyros for + // yaw. Avoiding this calculation on every call to + // update_DCM() saves a lot of time if (_compass && _compass->use_for_yaw() && _compass->last_update != _compass_last_update) { if (_have_initial_yaw) { @@ -445,6 +461,10 @@ AP_DCM::drift_correction(float deltat) } } + // see if there is any error in our heading relative to the + // yaw reference. This will be zero most of the time, as we + // only calculate it when we get new data from the yaw + // reference source if (yaw_deltat == 0 || error_course == 0) { // nothing to do return; @@ -453,27 +473,32 @@ AP_DCM::drift_correction(float deltat) // Equation 24, Applys the yaw correction to the XYZ rotation of the aircraft error = _dcm_matrix.c * error_course; - // Adding yaw correction to proportional correction vector. + // Adding yaw correction to proportional correction vector. We + // allow the yaw reference source to affect all 3 components + // of _omega_P as we need to be able to correctly hold a + // heading when roll and pitch are non-zero _omega_P += error * _kp_yaw; - // limit maximum gyro drift + // limit maximum gyro drift from yaw reference float drift_limit = ToRad(_gyro_drift_rate) * yaw_deltat / _ki_yaw; error.z = constrain(error.z, -drift_limit, drift_limit); // add yaw correction to integrator correction vector, but // only for the z gyro. We rely on the accelerometers for x - // and y gyro drift correction. Using the compass for x/y drift - // correction is too inaccurate, and can lead to incorrect builups in - // the x/y drift + // and y gyro drift correction. Using the compass or GPS for + // x/y drift correction is too inaccurate, and can lead to + // incorrect builups in the x/y drift. We rely on the + // accelerometers to get the x/y components right _omega_I.z += error.z * _ki_yaw; + // we keep the sum of yaw error for reporting via MAVLink. _error_yaw_sum += error_course; _error_yaw_count++; - //Serial.print("*"); } -/**************************************************/ +// calculate the euler angles which will be used for high level +// navigation control void AP_DCM::euler_angles(void) { From 982712d58f3ccdd809f871daf871e6653a3fe8e3 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 7 Mar 2012 17:19:51 +1100 Subject: [PATCH 099/178] Quaternion: code cleanups and added comments --- libraries/AP_Quaternion/AP_Quaternion.cpp | 69 +++++++---------------- 1 file changed, 20 insertions(+), 49 deletions(-) diff --git a/libraries/AP_Quaternion/AP_Quaternion.cpp b/libraries/AP_Quaternion/AP_Quaternion.cpp index d86c7268b3..3a297d5798 100644 --- a/libraries/AP_Quaternion/AP_Quaternion.cpp +++ b/libraries/AP_Quaternion/AP_Quaternion.cpp @@ -307,7 +307,9 @@ void AP_Quaternion::update_MARG(float deltat, Vector3f &gyro, Vector3f &accel, V } -// Function to compute one quaternion iteration including magnetometer +// Function to update our gyro_bias drift estimate using the accelerometer +// and magnetometer. This is a cut-down version of update_MARG(), but +// without the quaternion update. void AP_Quaternion::update_drift(float deltat, Vector3f &gyro, Vector3f &accel, Vector3f &mag) { // local system variables @@ -458,11 +460,6 @@ void AP_Quaternion::update(void) Vector3f gyro, accel; float deltat; -#ifdef DESKTOP_BUILD - Quaternion q_saved = q; - Vector3f bias_saved = gyro_bias; -#endif - _imu->update(); deltat = _imu->get_delta_time(); @@ -513,11 +510,21 @@ void AP_Quaternion::update(void) accel.z += (gyro.y - gyro_bias.y) * veloc; } -#if 1 _gyro_sum += gyro; _accel_sum += accel; _sum_count++; + /* + The full Madgwick quaternion 'MARG' system assumes you get + gyro, accel and magnetometer updates at the same rate. On + APM we get them at very different rates, and re-calculating + our drift due to the magnetometer in the fast loop is very + wasteful of CPU. + + Instead, we only update the gyro_bias vector when we get a + new magnetometer point, and use the much simpler + update_IMU() as the main quaternion update function. + */ if (_compass != NULL && _compass->use_for_yaw() && _compass->last_update != _compass_last_update && _sum_count != 0) { @@ -533,64 +540,28 @@ void AP_Quaternion::update(void) _compass_last_update = _compass->last_update; } - // step the quaternion solution + // step the quaternion solution using just gyros and accels gyro -= gyro_bias; update_IMU(deltat, gyro, accel); -#else - if (_compass != NULL && _compass->use_for_yaw()) { - // use new compass sample for drift correction - Vector3f mag = Vector3f(_compass->mag_x, _compass->mag_y, - _compass->mag_z); - update_MARG(deltat, gyro, accel, mag); - } else { - // step the quaternion without drift correction - gyro -= gyro_bias; - _gyro_sum += gyro; - _accel_sum += accel; - _sum_count++; - update_IMU(deltat, gyro, accel); - } -#endif #ifdef DESKTOP_BUILD if (q.is_nan()) { - SITL_debug("QUAT NAN: deltat=%f roll=%f pitch=%f yaw=%f q0=[%f %f %f %f] q=[%f %f %f %f] a=[%f %f %f] g=(%f %f %f)\n", + SITL_debug("QUAT NAN: deltat=%f roll=%f pitch=%f yaw=%f q=[%f %f %f %f] a=[%f %f %f] g=(%f %f %f)\n", deltat, roll, pitch, yaw, - q_saved.q1, q_saved.q2, q_saved.q3, q_saved.q4, q.q1, q.q2, q.q3, q.q4, accel.x, accel.y, accel.z, gyro.x, gyro.y, gyro.z); - q = q_saved; - gyro_bias = bias_saved; - update_IMU(deltat, gyro, accel); } #endif // keep the corrected gyro for reporting _gyro_corrected = gyro; - // compute the Eulers - float test = (SEq_1*SEq_3 - SEq_4*SEq_2); - const float singularity = 0.499; // 86.3 degrees? - if (test > singularity) { - // singularity at south pole - // this one is ok.. - yaw = 2.0 * atan2(SEq_4, SEq_1); - pitch = ToRad(-90.0); - roll = 0.0; - } else if (test < -singularity) { - // singularity at north pole - // this one is invalid :( .. fix it. - yaw = -2.0 * atan2(SEq_4, SEq_1); - pitch = ToRad(90.0); - roll = 0.0; - } else { - roll = -(atan2(2.0*(SEq_1*SEq_2 + SEq_3*SEq_4), - 1 - 2.0*(SEq_2*SEq_2 + SEq_3*SEq_3))); - pitch = -safe_asin(2.0*test); - yaw = atan2(2.0*(SEq_1*SEq_4 + SEq_2*SEq_3), - 1 - 2.0*(SEq_3*SEq_3 + SEq_4*SEq_4)); - } + // calculate our euler angles for high level control and navigation + euler_from_quaternion(q, &roll, &pitch, &yaw); + // the code above assumes zero magnetic declination, so offset + // the yaw here if (_compass != NULL) { yaw += _compass->get_declination(); } From 2673614f6d6a2cf08f1901eed41658936fb707ea Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 7 Mar 2012 17:20:29 +1100 Subject: [PATCH 100/178] SITL: fixed the pwm output on startup --- libraries/Desktop/support/sitl.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/libraries/Desktop/support/sitl.cpp b/libraries/Desktop/support/sitl.cpp index 4c279d26ef..7002f9bbaf 100644 --- a/libraries/Desktop/support/sitl.cpp +++ b/libraries/Desktop/support/sitl.cpp @@ -197,8 +197,11 @@ static void sitl_simulator_output(void) last_update = millis(); for (i=0; i<11; i++) { - // the registers are 2x the PWM value - pwm[i] = (*reg[i])/2; + if (*reg[i] == 0xFFFF) { + pwm[i] = 0; + } else { + pwm[i] = (*reg[i])/2; + } } if (!desktop_state.quadcopter) { From dffb435aac13e1d52a08bf41430ac510e52b5407 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 7 Mar 2012 17:20:47 +1100 Subject: [PATCH 101/178] SITL: make the yaw match the APM conventions --- libraries/Desktop/support/sitl.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/libraries/Desktop/support/sitl.cpp b/libraries/Desktop/support/sitl.cpp index 7002f9bbaf..bea1f18fd2 100644 --- a/libraries/Desktop/support/sitl.cpp +++ b/libraries/Desktop/support/sitl.cpp @@ -324,6 +324,7 @@ void sitl_setup(void) void sitl_simstate_send(uint8_t chan) { double p, q, r; + float yaw; // we want the gyro values to be directly comparable to the // raw_imu message, which is in body frame @@ -331,10 +332,16 @@ void sitl_simstate_send(uint8_t chan) sim_state.rollRate, sim_state.pitchRate, sim_state.yawRate, &p, &q, &r); + // convert to same conventions as DCM + yaw = sim_state.yawDeg; + if (yaw > 180) { + yaw -= 360; + } + mavlink_msg_simstate_send((mavlink_channel_t)chan, ToRad(sim_state.rollDeg), ToRad(sim_state.pitchDeg), - ToRad(sim_state.yawDeg), + ToRad(yaw), sim_state.xAccel, sim_state.yAccel, sim_state.zAccel, From 3344869285a155458f6762df94d7002d12afbcec Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 7 Mar 2012 18:31:02 +1100 Subject: [PATCH 102/178] DCM: minor tuning based on testing my quad --- libraries/AP_DCM/AP_DCM.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/AP_DCM/AP_DCM.h b/libraries/AP_DCM/AP_DCM.h index 1a65c23836..d1a0890653 100644 --- a/libraries/AP_DCM/AP_DCM.h +++ b/libraries/AP_DCM/AP_DCM.h @@ -25,9 +25,9 @@ class AP_DCM public: // Constructors AP_DCM(IMU *imu, GPS *&gps) : - _kp_roll_pitch(12.0), + _kp_roll_pitch(18.0), _ki_roll_pitch(0.0006), - _kp_yaw(3.0), + _kp_yaw(9.0), _ki_yaw(0.003), _gps(gps), _imu(imu), From 801a442ffb9ea8b91a2c2f1f9758c603d5072bc5 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 7 Mar 2012 18:31:35 +1100 Subject: [PATCH 103/178] Quaternion: minor tuning --- libraries/AP_Quaternion/AP_Quaternion.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/AP_Quaternion/AP_Quaternion.h b/libraries/AP_Quaternion/AP_Quaternion.h index 9f115eeafe..861e3164b7 100644 --- a/libraries/AP_Quaternion/AP_Quaternion.h +++ b/libraries/AP_Quaternion/AP_Quaternion.h @@ -98,8 +98,8 @@ private: // true if we are doing centripetal acceleration correction bool _centripetal; - // maximum gyroscope measurement error in rad/s (set to 40 degrees/second) - static const float gyroMeasError = 10.0 * (M_PI/180.0); + // maximum gyroscope measurement error in rad/s (set to 7 degrees/second) + static const float gyroMeasError = 7.0 * (M_PI/180.0); // maximum gyroscope drift rate in radians/s/s (set to 0.005 // degrees/s/s, which is 0.3 degrees/s/minute) From 9a06d357728aa33b15902212a2df053f93d5211f Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 7 Mar 2012 18:40:04 +1100 Subject: [PATCH 104/178] make 'ENABLE' and 'ENABLED' mean the same things users get this wrong far too often! --- ArduCopter/defines.h | 3 +++ ArduPlane/config.h | 4 ++++ 2 files changed, 7 insertions(+) diff --git a/ArduCopter/defines.h b/ArduCopter/defines.h index 1cf84ffd0c..9b48c98789 100644 --- a/ArduCopter/defines.h +++ b/ArduCopter/defines.h @@ -7,6 +7,9 @@ #define ENABLED 1 #define DISABLED 0 +// this avoids a very common config error +#define ENABLE ENABLED +#define DISABLE DISABLED // Flight modes // ------------ diff --git a/ArduPlane/config.h b/ArduPlane/config.h index 435676d94c..43141cdce6 100644 --- a/ArduPlane/config.h +++ b/ArduPlane/config.h @@ -36,6 +36,10 @@ #define ENABLED 1 #define DISABLED 0 +// this avoids a very common config error +#define ENABLE ENABLED +#define DISABLE DISABLED + ////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////// // HARDWARE CONFIGURATION AND CONNECTIONS From 882fa1818b453d6a1064ca4ea4426f4c183443cc Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 8 Mar 2012 00:00:26 +1100 Subject: [PATCH 105/178] DCM: removed the limit on linear acceleration we get linear accelerations of more than 1g when turning corners --- libraries/AP_DCM/AP_DCM.cpp | 7 ++++--- libraries/AP_Quaternion/AP_Quaternion.cpp | 7 ++++--- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/libraries/AP_DCM/AP_DCM.cpp b/libraries/AP_DCM/AP_DCM.cpp index 9e5e66de64..0e0aaac080 100644 --- a/libraries/AP_DCM/AP_DCM.cpp +++ b/libraries/AP_DCM/AP_DCM.cpp @@ -135,13 +135,14 @@ void AP_DCM::accel_adjust(Vector3f &accel) { float veloc; - // compensate for linear acceleration, limited to 1g + // compensate for linear acceleration. This makes a + // surprisingly large difference in the pitch estimate when + // turning, plus on takeoff and landing float acceleration = _gps->acceleration(); - acceleration = constrain(acceleration, 0, 9.8); accel.x -= acceleration; // compensate for centripetal acceleration - veloc = _gps->ground_speed / 100; + veloc = _gps->ground_speed * 0.01; // We are working with a modified version of equation 26 as // our IMU object reports acceleration in the positive axis diff --git a/libraries/AP_Quaternion/AP_Quaternion.cpp b/libraries/AP_Quaternion/AP_Quaternion.cpp index 3a297d5798..7fe75022b5 100644 --- a/libraries/AP_Quaternion/AP_Quaternion.cpp +++ b/libraries/AP_Quaternion/AP_Quaternion.cpp @@ -495,14 +495,15 @@ void AP_Quaternion::update(void) accel.z = -accel.z; if (_centripetal && _gps && _gps->status() == GPS::GPS_OK) { - // compensate for linear acceleration, limited to 1g + // compensate for linear acceleration. This makes a + // surprisingly large difference in the pitch estimate when + // turning, plus on takeoff and landing float acceleration = _gps->acceleration(); - acceleration = constrain(acceleration, 0, 9.8); accel.x -= acceleration; // compensate for centripetal acceleration float veloc; - veloc = _gps->ground_speed / 100; + veloc = _gps->ground_speed * 0.01; // be careful of the signs in this calculation. the // quaternion system uses different signs than the // rest of APM From 9296ac494d1da2c8813cfb69ffea686bd6a16a54 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 8 Mar 2012 18:10:27 +1100 Subject: [PATCH 106/178] AP_InertialSensor: added a get_gyro_drift_rate() interface this returns the expected max drift rate for the particular type of gyro being used --- libraries/AP_InertialSensor/AP_InertialSensor.h | 5 +++++ libraries/AP_InertialSensor/AP_InertialSensor_MPU6000.cpp | 8 ++++++++ libraries/AP_InertialSensor/AP_InertialSensor_MPU6000.h | 1 + libraries/AP_InertialSensor/AP_InertialSensor_Oilpan.cpp | 7 +++++++ libraries/AP_InertialSensor/AP_InertialSensor_Oilpan.h | 1 + 5 files changed, 22 insertions(+) diff --git a/libraries/AP_InertialSensor/AP_InertialSensor.h b/libraries/AP_InertialSensor/AP_InertialSensor.h index 08067b8e1d..44907652c1 100644 --- a/libraries/AP_InertialSensor/AP_InertialSensor.h +++ b/libraries/AP_InertialSensor/AP_InertialSensor.h @@ -57,6 +57,11 @@ class AP_InertialSensor */ virtual uint32_t sample_time() = 0; virtual void reset_sample_time() = 0; + + // return the maximum gyro drift rate in radians/s/s. This + // depends on what gyro chips are being used + virtual float get_gyro_drift_rate(void) = 0; + }; #include "AP_InertialSensor_Oilpan.h" diff --git a/libraries/AP_InertialSensor/AP_InertialSensor_MPU6000.cpp b/libraries/AP_InertialSensor/AP_InertialSensor_MPU6000.cpp index 500bfe464d..fd272c72b0 100644 --- a/libraries/AP_InertialSensor/AP_InertialSensor_MPU6000.cpp +++ b/libraries/AP_InertialSensor/AP_InertialSensor_MPU6000.cpp @@ -326,3 +326,11 @@ float AP_InertialSensor_MPU6000::_temp_to_celsius ( uint16_t regval ) /* TODO */ return 20.0; } + +// return the MPU6k gyro drift rate in radian/s/s +// note that this is much better than the oilpan gyros +float AP_InertialSensor_MPU6000::get_gyro_drift_rate(void) +{ + // 0.5 degrees/second/minute + return ToRad(0.5/60); +} diff --git a/libraries/AP_InertialSensor/AP_InertialSensor_MPU6000.h b/libraries/AP_InertialSensor/AP_InertialSensor_MPU6000.h index fe48070ca8..35f28ac871 100644 --- a/libraries/AP_InertialSensor/AP_InertialSensor_MPU6000.h +++ b/libraries/AP_InertialSensor/AP_InertialSensor_MPU6000.h @@ -33,6 +33,7 @@ class AP_InertialSensor_MPU6000 : public AP_InertialSensor float temperature(); uint32_t sample_time(); void reset_sample_time(); + float get_gyro_drift_rate(); private: diff --git a/libraries/AP_InertialSensor/AP_InertialSensor_Oilpan.cpp b/libraries/AP_InertialSensor/AP_InertialSensor_Oilpan.cpp index 4d13729722..4d2fcb03f4 100644 --- a/libraries/AP_InertialSensor/AP_InertialSensor_Oilpan.cpp +++ b/libraries/AP_InertialSensor/AP_InertialSensor_Oilpan.cpp @@ -126,3 +126,10 @@ float AP_InertialSensor_Oilpan::_accel_apply_std_offset( float adc_value ) /* Magic number from AP_ADC_Oilpan.h */ return ((float) adc_value ) - 2041.0f; } + +// return the oilpan gyro drift rate in radian/s/s +float AP_InertialSensor_Oilpan::get_gyro_drift_rate(void) +{ + // 3.0 degrees/second/minute + return ToRad(3.0/60); +} diff --git a/libraries/AP_InertialSensor/AP_InertialSensor_Oilpan.h b/libraries/AP_InertialSensor/AP_InertialSensor_Oilpan.h index 099cde265e..383bdea7f2 100644 --- a/libraries/AP_InertialSensor/AP_InertialSensor_Oilpan.h +++ b/libraries/AP_InertialSensor/AP_InertialSensor_Oilpan.h @@ -32,6 +32,7 @@ class AP_InertialSensor_Oilpan : public AP_InertialSensor float temperature(); uint32_t sample_time(); void reset_sample_time(); + float get_gyro_drift_rate(); private: From bcb7196680acdf673f83cbe99315c7065c413534 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 8 Mar 2012 18:10:57 +1100 Subject: [PATCH 107/178] IMU: added get_gyro_drift_rate() interface this just calls down to the InertialSensor layer --- libraries/AP_IMU/AP_IMU_INS.cpp | 7 +++++++ libraries/AP_IMU/AP_IMU_INS.h | 1 + libraries/AP_IMU/AP_IMU_Shim.h | 2 ++ libraries/AP_IMU/IMU.cpp | 1 + libraries/AP_IMU/IMU.h | 4 ++++ 5 files changed, 15 insertions(+) diff --git a/libraries/AP_IMU/AP_IMU_INS.cpp b/libraries/AP_IMU/AP_IMU_INS.cpp index f2e44d6d40..ad6b701367 100644 --- a/libraries/AP_IMU/AP_IMU_INS.cpp +++ b/libraries/AP_IMU/AP_IMU_INS.cpp @@ -250,3 +250,10 @@ AP_IMU_INS::update(void) bool AP_IMU_INS::new_data_available(void) { return _ins->new_data_available(); } + +/// return the maximum gyro drift rate in radians/s/s. This +/// depends on what gyro chips are being used +float AP_IMU_INS::get_gyro_drift_rate(void) +{ + return _ins->get_gyro_drift_rate(); +} diff --git a/libraries/AP_IMU/AP_IMU_INS.h b/libraries/AP_IMU/AP_IMU_INS.h index c9f461f04a..4fb82af069 100644 --- a/libraries/AP_IMU/AP_IMU_INS.h +++ b/libraries/AP_IMU/AP_IMU_INS.h @@ -64,6 +64,7 @@ public: virtual void ax(const float v) { _sensor_cal[3] = v; } virtual void ay(const float v) { _sensor_cal[4] = v; } virtual void az(const float v) { _sensor_cal[5] = v; } + virtual float get_gyro_drift_rate(void); private: AP_InertialSensor *_ins; ///< INS provides an axis and unit correct sensor source. diff --git a/libraries/AP_IMU/AP_IMU_Shim.h b/libraries/AP_IMU/AP_IMU_Shim.h index c9c1ce22b8..ffdaffbb77 100644 --- a/libraries/AP_IMU/AP_IMU_Shim.h +++ b/libraries/AP_IMU/AP_IMU_Shim.h @@ -67,6 +67,8 @@ public: // dummy save method void save(void) { } + float get_gyro_drift_rate(void) { return 0; } + private: /// set true when new data is delivered bool _updated; diff --git a/libraries/AP_IMU/IMU.cpp b/libraries/AP_IMU/IMU.cpp index 2fabe704b8..222664c5f7 100644 --- a/libraries/AP_IMU/IMU.cpp +++ b/libraries/AP_IMU/IMU.cpp @@ -41,3 +41,4 @@ float IMU::az(void) { return 0.0; } void IMU::ax(const float v) { } void IMU::ay(const float v) { } void IMU::az(const float v) { } +float IMU::get_gyro_drift_rate(void) { return 0; } diff --git a/libraries/AP_IMU/IMU.h b/libraries/AP_IMU/IMU.h index da259e5370..485f2a4e78 100644 --- a/libraries/AP_IMU/IMU.h +++ b/libraries/AP_IMU/IMU.h @@ -84,6 +84,10 @@ public: /// float get_delta_time(void) { return _sample_time * 1.0e-6; } + /// return the maximum gyro drift rate in radians/s/s. This + /// depends on what gyro chips are being used + virtual float get_gyro_drift_rate(void); + /// A count of bad sensor readings /// /// @todo This should be renamed, as there's no guarantee that sensors From 3b2609c441158a55dfceb24639149e3bf9a78f75 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 8 Mar 2012 18:12:46 +1100 Subject: [PATCH 108/178] DCM: separate out the omega_yaw_P from omega_P this cleans up the separation of drift rates and proportional correction from yaw source and accelerometers, allow the yaw to run at a different rate to the accel correction --- libraries/AP_DCM/AP_DCM.cpp | 213 ++++++++++++++++++++---------------- libraries/AP_DCM/AP_DCM.h | 48 ++++---- 2 files changed, 142 insertions(+), 119 deletions(-) diff --git a/libraries/AP_DCM/AP_DCM.cpp b/libraries/AP_DCM/AP_DCM.cpp index 0e0aaac080..954f79767f 100644 --- a/libraries/AP_DCM/AP_DCM.cpp +++ b/libraries/AP_DCM/AP_DCM.cpp @@ -104,7 +104,7 @@ AP_DCM::matrix_update(float _G_Dt) _omega_integ_corr = _gyro_vector + _omega_I; // Equation 16, adding proportional and integral correction terms - _omega = _omega_integ_corr + _omega_P; + _omega = _omega_integ_corr + _omega_P + _omega_yaw_P; // this is an expansion of the DCM matrix multiply (equation // 17), with known zero elements removed and the matrix @@ -165,13 +165,12 @@ AP_DCM::matrix_reset(bool recover_eulers) } // reset the integration terms - _omega_I.x = 0.0f; - _omega_I.y = 0.0f; - _omega_I.z = 0.0f; - _omega_P = _omega_I; - _omega_integ_corr = _omega_I; - _omega_smoothed = _omega_I; - _omega = _omega_I; + _omega_I.zero(); + _omega_P.zero(); + _omega_yaw_P.zero(); + _omega_integ_corr.zero(); + _omega_smoothed.zero(); + _omega.zero(); // if the caller wants us to try to recover to the current // attitude then calculate the dcm matrix from the current @@ -316,6 +315,9 @@ AP_DCM::normalize(void) // gyro error. The _omega_P value is what pulls our attitude solution // back towards the reference vector quickly. The _omega_I term is an // attempt to learn the long term drift rate of the gyros. +// +// This function also updates _omega_yaw_P with a yaw correction term +// from our yaw reference vector void AP_DCM::drift_correction(float deltat) { @@ -357,31 +359,39 @@ AP_DCM::drift_correction(float deltat) accel.z = -sqrt(zsquared); } + // calculate the error, in m/2^2, between the attitude + // implied by the accelerometers and the attitude + // in the current DCM matrix error = _dcm_matrix.c % accel; - // error is in m/s^2 units - // Limit max error to limit max omega_P and omega_I + // error from the above is in m/s^2 units. + + // Limit max error to limit the effect of noisy values + // on the algorithm. This limits the error to about 11 + // degrees error_norm = error.length(); if (error_norm > 2) { error *= (2 / error_norm); } - // scale the error for the time over which we are - // applying it - error *= deltat; - - // calculate the new proportional offset + // we now want to calculate _omega_P and _omega_I. The + // _omega_P value is what drags us quickly to the + // accelerometer reading. _omega_P = error * _kp_roll_pitch; - // we limit the change in the integrator to the - // maximum gyro drift rate on each axis - float drift_limit = ToRad(_gyro_drift_rate) * deltat / _ki_roll_pitch; - error.x = constrain(error.x, -drift_limit, drift_limit); - error.y = constrain(error.y, -drift_limit, drift_limit); - error.z = constrain(error.z, -drift_limit, drift_limit); + // the _omega_I is the long term accumulated gyro + // error. This determines how much gyro drift we can + // handle. + Vector3f omega_I_delta = error * (_ki_roll_pitch * deltat); - // update gyro drift estimate - _omega_I += error * _ki_roll_pitch; + // limit the slope of omega_I on each axis to + // the maximum drift rate + float drift_limit = _gyro_drift_limit * deltat; + omega_I_delta.x = constrain(omega_I_delta.x, -drift_limit, drift_limit); + omega_I_delta.y = constrain(omega_I_delta.y, -drift_limit, drift_limit); + omega_I_delta.z = constrain(omega_I_delta.z, -drift_limit, drift_limit); + + _omega_I += omega_I_delta; } // these sums support the reporting of the DCM state via MAVLink @@ -394,71 +404,76 @@ AP_DCM::drift_correction(float deltat) // reference vector. In between times we rely on the gyros for // yaw. Avoiding this calculation on every call to // update_DCM() saves a lot of time - if (_compass && _compass->use_for_yaw() && - _compass->last_update != _compass_last_update) { - if (_have_initial_yaw) { - // Equation 23, Calculating YAW error - // We make the gyro YAW drift correction based - // on compass magnetic heading - error_course = (_dcm_matrix.a.x * _compass->heading_y) - (_dcm_matrix.b.x * _compass->heading_x); + if (_compass && _compass->use_for_yaw()) { + if (_compass->last_update != _compass_last_update) { yaw_deltat = 1.0e-6*(_compass->last_update - _compass_last_update); - _compass_last_update = _compass->last_update; - } else { - // this is our first estimate of the yaw, - // construct a DCM matrix based on the current - // roll/pitch and the compass heading, but - - // first ensure the compass heading has been - // calculated - _compass->calculate(_dcm_matrix); - - // now construct a new DCM matrix - _compass->null_offsets_disable(); - rotation_matrix_from_euler(_dcm_matrix, roll, pitch, _compass->heading); - _compass->null_offsets_enable(); - _have_initial_yaw = true; - _compass_last_update = _compass->last_update; - } - } else if (_gps && _gps->status() == GPS::GPS_OK && - _gps->last_fix_time != _gps_last_update) { - // Use GPS Ground course to correct yaw gyro drift - if (_gps->ground_speed >= GPS_SPEED_MIN) { - if (_have_initial_yaw) { - float course_over_ground_x = cos(ToRad(_gps->ground_course/100.0)); - float course_over_ground_y = sin(ToRad(_gps->ground_course/100.0)); + if (_have_initial_yaw && yaw_deltat < 2.0) { // Equation 23, Calculating YAW error - error_course = (_dcm_matrix.a.x * course_over_ground_y) - (_dcm_matrix.b.x * course_over_ground_x); - yaw_deltat = 1.0e-3*(_gps->last_fix_time - _gps_last_update); - _gps_last_update = _gps->last_fix_time; - } else { - // when we first start moving, set the - // DCM matrix to the current - // roll/pitch values, but with yaw - // from the GPS - if (_compass) { - _compass->null_offsets_disable(); - } - rotation_matrix_from_euler(_dcm_matrix, roll, pitch, ToRad(_gps->ground_course)); - if (_compass) { - _compass->null_offsets_enable(); - } - _have_initial_yaw = true; + // We make the gyro YAW drift correction based + // on compass magnetic heading + error_course = (_dcm_matrix.a.x * _compass->heading_y) - (_dcm_matrix.b.x * _compass->heading_x); + _compass_last_update = _compass->last_update; + } else { + // this is our first estimate of the yaw, + // or the compass has come back online after + // no readings for 2 seconds. + // + // construct a DCM matrix based on the current + // roll/pitch and the compass heading. + // First ensure the compass heading has been + // calculated + _compass->calculate(_dcm_matrix); + + // now construct a new DCM matrix + _compass->null_offsets_disable(); + rotation_matrix_from_euler(_dcm_matrix, roll, pitch, _compass->heading); + _compass->null_offsets_enable(); + _have_initial_yaw = true; + _compass_last_update = _compass->last_update; error_course = 0; - _gps_last_update = _gps->last_fix_time; } - } else if (_gps->ground_speed >= GPS_SPEED_RESET) { - // we are not going fast enough to use GPS for - // course correction, but we won't reset - // _have_initial_yaw yet, instead we just let - // the gyro handle yaw - error_course = 0; - } else { - // we are moving very slowly. Reset - // _have_initial_yaw and adjust our heading - // rapidly next time we get a good GPS ground - // speed - error_course = 0; - _have_initial_yaw = false; + } + } else if (_gps && _gps->status() == GPS::GPS_OK) { + if (_gps->last_fix_time != _gps_last_update) { + // Use GPS Ground course to correct yaw gyro drift + if (_gps->ground_speed >= GPS_SPEED_MIN) { + yaw_deltat = 1.0e-3*(_gps->last_fix_time - _gps_last_update); + if (_have_initial_yaw && yaw_deltat < 2.0) { + float course_over_ground_x = cos(ToRad(_gps->ground_course/100.0)); + float course_over_ground_y = sin(ToRad(_gps->ground_course/100.0)); + // Equation 23, Calculating YAW error + error_course = (_dcm_matrix.a.x * course_over_ground_y) - (_dcm_matrix.b.x * course_over_ground_x); + _gps_last_update = _gps->last_fix_time; + } else { + // when we first start moving, set the + // DCM matrix to the current + // roll/pitch values, but with yaw + // from the GPS + if (_compass) { + _compass->null_offsets_disable(); + } + rotation_matrix_from_euler(_dcm_matrix, roll, pitch, ToRad(_gps->ground_course)); + if (_compass) { + _compass->null_offsets_enable(); + } + _have_initial_yaw = true; + error_course = 0; + _gps_last_update = _gps->last_fix_time; + } + } else if (_gps->ground_speed >= GPS_SPEED_RESET) { + // we are not going fast enough to use GPS for + // course correction, but we won't reset + // _have_initial_yaw yet, instead we just let + // the gyro handle yaw + error_course = 0; + } else { + // we are moving very slowly. Reset + // _have_initial_yaw and adjust our heading + // rapidly next time we get a good GPS ground + // speed + error_course = 0; + _have_initial_yaw = false; + } } } @@ -467,22 +482,30 @@ AP_DCM::drift_correction(float deltat) // only calculate it when we get new data from the yaw // reference source if (yaw_deltat == 0 || error_course == 0) { - // nothing to do + // we don't have a new reference heading. Slowly + // decay the _omega_yaw_P to ensure that if we have + // lost the yaw reference sensor completely we don't + // keep using a stale offset + _omega_yaw_P *= 0.97; return; } + // ensure the course error is scaled from -PI to PI + if (error_course > PI) { + error_course -= 2*PI; + } else if (error_course < -PI) { + error_course += 2*PI; + } + // Equation 24, Applys the yaw correction to the XYZ rotation of the aircraft + // this gives us an error in radians error = _dcm_matrix.c * error_course; // Adding yaw correction to proportional correction vector. We // allow the yaw reference source to affect all 3 components - // of _omega_P as we need to be able to correctly hold a + // of _omega_yaw_P as we need to be able to correctly hold a // heading when roll and pitch are non-zero - _omega_P += error * _kp_yaw; - - // limit maximum gyro drift from yaw reference - float drift_limit = ToRad(_gyro_drift_rate) * yaw_deltat / _ki_yaw; - error.z = constrain(error.z, -drift_limit, drift_limit); + _omega_yaw_P = error * _kp_yaw; // add yaw correction to integrator correction vector, but // only for the z gyro. We rely on the accelerometers for x @@ -490,7 +513,13 @@ AP_DCM::drift_correction(float deltat) // x/y drift correction is too inaccurate, and can lead to // incorrect builups in the x/y drift. We rely on the // accelerometers to get the x/y components right - _omega_I.z += error.z * _ki_yaw; + float omega_Iz_delta = error.z * (_ki_yaw * yaw_deltat); + + // limit the slope of omega_I.z to the maximum gyro drift rate + float drift_limit = _gyro_drift_limit * yaw_deltat; + omega_Iz_delta = constrain(omega_Iz_delta, -drift_limit, drift_limit); + + _omega_I.z += omega_Iz_delta; // we keep the sum of yaw error for reporting via MAVLink. _error_yaw_sum += error_course; diff --git a/libraries/AP_DCM/AP_DCM.h b/libraries/AP_DCM/AP_DCM.h index d1a0890653..d8a2d1f268 100644 --- a/libraries/AP_DCM/AP_DCM.h +++ b/libraries/AP_DCM/AP_DCM.h @@ -25,10 +25,8 @@ class AP_DCM public: // Constructors AP_DCM(IMU *imu, GPS *&gps) : - _kp_roll_pitch(18.0), - _ki_roll_pitch(0.0006), - _kp_yaw(9.0), - _ki_yaw(0.003), + _kp_roll_pitch(0.13), + _kp_yaw(0.8), _gps(gps), _imu(imu), _dcm_matrix(1, 0, 0, @@ -36,7 +34,16 @@ public: 0, 0, 1), _health(1.), _toggle(0) - {} + { + // base the ki values by the sensors maximum drift + // rate. The APM2 has gyros which are much less drift + // prone than the APM1, so we should have a lower ki, + // which will make us less prone to increasing omegaI + // incorrectly due to sensor noise + _gyro_drift_limit = imu->get_gyro_drift_rate(); + _ki_roll_pitch = _gyro_drift_limit * 3; + _ki_yaw = _gyro_drift_limit * 4; + } // Accessors @@ -46,7 +53,7 @@ public: Matrix3f get_dcm_transposed(void) {Matrix3f temp = _dcm_matrix; return temp.transpose();} // return the current drift correction integrator value - Vector3f get_integrator(void) {return _omega_I; } + Vector3f get_gyro_drift(void) {return _omega_I; } float get_health(void) {return _health;} void set_centripetal(bool b) {_centripetal = b;} @@ -55,7 +62,7 @@ public: // Methods void update_DCM(uint8_t drift_correction_frequency=1); - void update_DCM_fast(void); + void update(void) { update_DCM(); } void matrix_reset(bool recover_eulers = false); long roll_sensor; // Degrees * 100 @@ -70,18 +77,6 @@ public: uint8_t renorm_range_count; uint8_t renorm_blowup_count; - float kp_roll_pitch() { return _kp_roll_pitch; } - void kp_roll_pitch(float v) { _kp_roll_pitch = v; } - - float ki_roll_pitch() { return _ki_roll_pitch; } - void ki_roll_pitch(float v) { _ki_roll_pitch = v; } - - float kp_yaw() { return _kp_yaw; } - void kp_yaw(float v) { _kp_yaw = v; } - - float ki_yaw() { return _ki_yaw; } - void ki_yaw(float v) { _ki_yaw = v; } - // status reporting float get_accel_weight(void); float get_renorm_val(void); @@ -93,6 +88,7 @@ private: float _ki_roll_pitch; float _kp_yaw; float _ki_yaw; + float _gyro_drift_limit; // radians/s/s bool _have_initial_yaw; // Methods @@ -106,9 +102,6 @@ private: void drift_correction(float deltat); void euler_angles(void); - // max rate of gyro drift in degrees/s/s - static const float _gyro_drift_rate = 0.04; - // members Compass * _compass; @@ -126,11 +119,12 @@ private: Vector3f _accel_vector; Vector3f _accel_sum; - Vector3f _gyro_vector; // Store the gyros turn rate in a vector - Vector3f _omega_P; // Omega Proportional correction - Vector3f _omega_I; // Omega Integrator correction - Vector3f _omega_integ_corr; // Partially corrected Gyro_Vector data - used for centrepetal correction - Vector3f _omega; // Corrected Gyro_Vector data + Vector3f _gyro_vector; // Store the gyros turn rate in a vector + Vector3f _omega_P; // accel Omega Proportional correction + Vector3f _omega_yaw_P; // yaw Omega Proportional correction + Vector3f _omega_I; // Omega Integrator correction + Vector3f _omega_integ_corr; // Partially corrected Gyro_Vector data - used for centrepetal correction + Vector3f _omega; // Corrected Gyro_Vector data Vector3f _omega_sum; Vector3f _omega_smoothed; float _health; From d75e883fe8128541658f6e0182461a8a680cee65 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 8 Mar 2012 18:13:19 +1100 Subject: [PATCH 109/178] GCS: get_integrator() is now get_gyro_drift() in DCM --- ArduCopter/GCS_Mavlink.pde | 2 +- ArduPlane/GCS_Mavlink.pde | 2 +- ArduPlane/Log.pde | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/ArduCopter/GCS_Mavlink.pde b/ArduCopter/GCS_Mavlink.pde index 9ac2fd7e07..aac172ba6a 100644 --- a/ArduCopter/GCS_Mavlink.pde +++ b/ArduCopter/GCS_Mavlink.pde @@ -127,7 +127,7 @@ static void NOINLINE send_nav_controller_output(mavlink_channel_t chan) #if HIL_MODE != HIL_MODE_ATTITUDE static void NOINLINE send_dcm(mavlink_channel_t chan) { - Vector3f omega_I = dcm.get_integrator(); + Vector3f omega_I = dcm.get_gyro_drift(); mavlink_msg_dcm_send( chan, omega_I.x, diff --git a/ArduPlane/GCS_Mavlink.pde b/ArduPlane/GCS_Mavlink.pde index a2e8a40cb4..f1d4cda07d 100644 --- a/ArduPlane/GCS_Mavlink.pde +++ b/ArduPlane/GCS_Mavlink.pde @@ -488,7 +488,7 @@ static void NOINLINE send_raw_imu3(mavlink_channel_t chan) static void NOINLINE send_dcm(mavlink_channel_t chan) { - Vector3f omega_I = dcm.get_integrator(); + Vector3f omega_I = dcm.get_gyro_drift(); mavlink_msg_dcm_send( chan, omega_I.x, diff --git a/ArduPlane/Log.pde b/ArduPlane/Log.pde index 5c7883a83e..ece99ea6c2 100644 --- a/ArduPlane/Log.pde +++ b/ArduPlane/Log.pde @@ -245,9 +245,9 @@ static void Log_Write_Performance() DataFlash.WriteByte(dcm.renorm_blowup_count); DataFlash.WriteByte(gps_fix_count); DataFlash.WriteInt((int)(dcm.get_health() * 1000)); - DataFlash.WriteInt((int)(dcm.get_integrator().x * 1000)); - DataFlash.WriteInt((int)(dcm.get_integrator().y * 1000)); - DataFlash.WriteInt((int)(dcm.get_integrator().z * 1000)); + DataFlash.WriteInt((int)(dcm.get_gyro_drift().x * 1000)); + DataFlash.WriteInt((int)(dcm.get_gyro_drift().y * 1000)); + DataFlash.WriteInt((int)(dcm.get_gyro_drift().z * 1000)); DataFlash.WriteInt(pmTest1); DataFlash.WriteByte(END_BYTE); } From bf16b2926c3eed528b7a310be7910510a858f8d3 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 8 Mar 2012 18:13:32 +1100 Subject: [PATCH 110/178] Quaternion: removed some unused variables --- libraries/AP_Quaternion/AP_Quaternion.cpp | 5 ----- 1 file changed, 5 deletions(-) diff --git a/libraries/AP_Quaternion/AP_Quaternion.cpp b/libraries/AP_Quaternion/AP_Quaternion.cpp index 7fe75022b5..2507e65e88 100644 --- a/libraries/AP_Quaternion/AP_Quaternion.cpp +++ b/libraries/AP_Quaternion/AP_Quaternion.cpp @@ -314,7 +314,6 @@ void AP_Quaternion::update_drift(float deltat, Vector3f &gyro, Vector3f &accel, { // local system variables float norm; // vector norm - float SEqDot_omega_1, SEqDot_omega_2, SEqDot_omega_3, SEqDot_omega_4; // quaternion rate from gyroscopes elements float f_1, f_2, f_3, f_4, f_5, f_6; // objective function elements float J_11or24, J_12or23, J_13or22, J_14or21, J_32, J_33, // objective function Jacobian elements J_41, J_42, J_43, J_44, J_51, J_52, J_53, J_54, J_61, J_62, J_63, J_64; // @@ -343,10 +342,6 @@ void AP_Quaternion::update_drift(float deltat, Vector3f &gyro, Vector3f &accel, } // auxiliary variables to avoid repeated calculations - float halfSEq_1 = 0.5f * SEq_1; - float halfSEq_2 = 0.5f * SEq_2; - float halfSEq_3 = 0.5f * SEq_3; - float halfSEq_4 = 0.5f * SEq_4; float twoSEq_1 = 2.0f * SEq_1; float twoSEq_2 = 2.0f * SEq_2; float twoSEq_3 = 2.0f * SEq_3; From 2f9af05cfadc77928b249ea24262312bcd4b8a57 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 8 Mar 2012 18:14:40 +1100 Subject: [PATCH 111/178] Quaternion: update to get_gyro_drift() interface --- libraries/AP_Quaternion/AP_Quaternion.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/AP_Quaternion/AP_Quaternion.h b/libraries/AP_Quaternion/AP_Quaternion.h index 861e3164b7..f6fef48424 100644 --- a/libraries/AP_Quaternion/AP_Quaternion.h +++ b/libraries/AP_Quaternion/AP_Quaternion.h @@ -56,7 +56,7 @@ public: // notice the sign reversals here return Vector3f(-_gyro_corrected.x, -_gyro_corrected.y, _gyro_corrected.z); } - Vector3f get_integrator(void) { + Vector3f get_gyro_drift(void) { // notice the sign reversals here return Vector3f(-gyro_bias.x, -gyro_bias.y, gyro_bias.z); } From b833190abb2cb0e8f99a6ab1196432ba57d764e7 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 8 Mar 2012 18:15:15 +1100 Subject: [PATCH 112/178] Quaternion: make the quaternion test more generic works with DCM too --- .../examples/Quaternion/Quaternion.pde | 35 +++++++++---------- 1 file changed, 17 insertions(+), 18 deletions(-) diff --git a/libraries/AP_Quaternion/examples/Quaternion/Quaternion.pde b/libraries/AP_Quaternion/examples/Quaternion/Quaternion.pde index 1296a7fbd3..b24cfd8c5b 100644 --- a/libraries/AP_Quaternion/examples/Quaternion/Quaternion.pde +++ b/libraries/AP_Quaternion/examples/Quaternion/Quaternion.pde @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -46,7 +47,8 @@ AP_Compass_HMC5843 compass; static GPS *g_gps; AP_IMU_INS imu(&ins); -AP_Quaternion quaternion(&imu, g_gps); +AP_Quaternion ahrs(&imu, g_gps); +//AP_DCM ahrs(&imu, g_gps); AP_Baro_BMP085_HIL barometer; @@ -102,7 +104,7 @@ void setup(void) if (compass.init()) { Serial.printf("Enabling compass\n"); compass.null_offsets_enable(); - quaternion.set_compass(&compass); + ahrs.set_compass(&compass); } } @@ -111,8 +113,6 @@ void loop(void) static uint16_t counter; static uint32_t last_t, last_print, last_compass; uint32_t now = micros(); - static uint32_t compass_reads; - static uint32_t compass_time; if (last_t == 0) { last_t = now; @@ -120,28 +120,27 @@ void loop(void) } last_t = now; - if (now - last_compass > 100*1000UL) { + if (now - last_compass > 100*1000UL && + compass.read()) { // read compass at 10Hz - compass.read(); last_compass = now; } - quaternion.update(); + ahrs.update(); counter++; if (now - last_print >= 0.5e6) { - Vector3f accel = imu.get_accel(); - Vector3f gyro = imu.get_gyro(); - Serial.printf_P(PSTR("r:%4.1f p:%4.1f y:%4.1f g=(%5.1f %5.1f %5.1f) a=(%5.1f %5.1f %5.1f) rate=%.1f\n"), - ToDeg(quaternion.roll), - ToDeg(quaternion.pitch), - ToDeg(quaternion.yaw), - gyro.x, gyro.y, gyro.z, - accel.x, accel.y, accel.z, - (1.0e6*counter)/(now-last_print)); + Vector3f drift = ahrs.get_gyro_drift(); + Serial.printf_P(PSTR("r:%4.1f p:%4.1f y:%4.1f drift=(%5.1f %5.1f %5.1f) hdg=%.1f rate=%.1f\n"), + ToDeg(ahrs.roll), + ToDeg(ahrs.pitch), + ToDeg(ahrs.yaw), + ToDeg(drift.x), + ToDeg(drift.y), + ToDeg(drift.z), + compass.use_for_yaw()?ToDeg(compass.heading):0.0, + (1.0e6*counter)/(now-last_print)); last_print = now; counter = 0; - compass_reads=0; - compass_time = 0; } } From c8189c80d433d85646c0e8941d744f9b47b72594 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 8 Mar 2012 18:16:11 +1100 Subject: [PATCH 113/178] SITL: cleanup the gyro drift calculations use units that are more easily understood --- libraries/Desktop/support/sitl_adc.h | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/libraries/Desktop/support/sitl_adc.h b/libraries/Desktop/support/sitl_adc.h index 9bf6876a55..100967733a 100644 --- a/libraries/Desktop/support/sitl_adc.h +++ b/libraries/Desktop/support/sitl_adc.h @@ -9,13 +9,13 @@ #include #include -static const float vibration_level = 2.0; -static const float drift_speed = 1.0; -static const float drift_level = 1.0; +static const float vibration_level = 0.5; +static const float drift_speed = 0.5; // degrees/second/minute +static const float drift_time = 5; // time to reverse drift direction (minutes) // order zgyro, xgyro, ygyro, temp, xacc, yacc, zacc, aspd static const float noise_scale[8] = { 150, 150, 150, 0, 400, 400, 400, 0 }; static const float noise_offset[8]= { 0, 0, 0, 0, 0, 0, 0, 0 }; -static const float drift_rate[8] = { 0.7, 1.0, 0.5, 0, 0, 0, 0, 0 }; +static const float drift_rate[8] = { 1.0, 1.0, 1.0, 0, 0, 0, 0, 0 }; static const float base_noise = 2; // generate a random float between -1 and 1 @@ -27,16 +27,16 @@ static double rand_float(void) static inline float gyro_drift(uint8_t chan) { - if (drift_rate[chan] * drift_level == 0.0) { + if (drift_rate[chan] * drift_speed == 0.0) { return 0; } extern long unsigned int micros(void); - double period = 10*drift_rate[chan] * drift_speed; + double period = drift_rate[chan] * drift_time * 2; double minutes = fmod(micros() / 60.0e6, period); if (minutes < period/2) { - return minutes * drift_level; + return minutes * drift_speed / 0.4; } - return (period - minutes) * drift_level; + return (period - minutes) * drift_speed / 0.4; } @@ -59,7 +59,7 @@ static inline float noise_generator(uint8_t chan) } } if (noise_count == 0) { - return rand_float() * base_noise * vibration_level; + return gyro_drift(chan) + rand_float() * base_noise * vibration_level; } return gyro_drift(chan) + noise/noise_count; } From 3989fe2c2cb6592f6084b278bd3dbb691922592c Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 9 Mar 2012 09:02:04 +1100 Subject: [PATCH 114/178] Quaternion: go back to the full update_MARG() the separate drift controller is too erratic on yaw hold to be usable at the moment --- libraries/AP_Quaternion/AP_Quaternion.cpp | 65 ++++++++++++++--------- libraries/AP_Quaternion/AP_Quaternion.h | 8 ++- 2 files changed, 42 insertions(+), 31 deletions(-) diff --git a/libraries/AP_Quaternion/AP_Quaternion.cpp b/libraries/AP_Quaternion/AP_Quaternion.cpp index 2507e65e88..4dd2f438f2 100644 --- a/libraries/AP_Quaternion/AP_Quaternion.cpp +++ b/libraries/AP_Quaternion/AP_Quaternion.cpp @@ -310,11 +310,11 @@ void AP_Quaternion::update_MARG(float deltat, Vector3f &gyro, Vector3f &accel, V // Function to update our gyro_bias drift estimate using the accelerometer // and magnetometer. This is a cut-down version of update_MARG(), but // without the quaternion update. -void AP_Quaternion::update_drift(float deltat, Vector3f &gyro, Vector3f &accel, Vector3f &mag) +void AP_Quaternion::update_drift(float deltat, Vector3f &mag) { // local system variables float norm; // vector norm - float f_1, f_2, f_3, f_4, f_5, f_6; // objective function elements + float f_4, f_5, f_6; // objective function elements float J_11or24, J_12or23, J_13or22, J_14or21, J_32, J_33, // objective function Jacobian elements J_41, J_42, J_43, J_44, J_51, J_52, J_53, J_54, J_61, J_62, J_63, J_64; // float SEqHatDot_1, SEqHatDot_2, SEqHatDot_3, SEqHatDot_4; // estimated direction of the gyroscope error @@ -325,14 +325,6 @@ void AP_Quaternion::update_drift(float deltat, Vector3f &gyro, Vector3f &accel, // estimated direction of the gyroscope error (radians) Vector3f w_err; - // normalise accelerometer vector - accel.normalize(); - if (accel.is_inf()) { - // discard this data point - renorm_range_count++; - return; - } - // normalise the magnetometer measurement mag.normalize(); if (mag.is_inf()) { @@ -365,9 +357,6 @@ void AP_Quaternion::update_drift(float deltat, Vector3f &gyro, Vector3f &accel, Vector3f twom = mag * 2.0; // compute the objective function and Jacobian - f_1 = twoSEq_2 * SEq_4 - twoSEq_1 * SEq_3 - accel.x; - f_2 = twoSEq_1 * SEq_2 + twoSEq_3 * SEq_4 - accel.y; - f_3 = 1.0f - twoSEq_2 * SEq_2 - twoSEq_3 * SEq_3 - accel.z; f_4 = twob_x * (0.5f - SEq_3 * SEq_3 - SEq_4 * SEq_4) + twob_z * (SEq_2SEq_4 - SEq_1SEq_3) - mag.x; f_5 = twob_x * (SEq_2 * SEq_3 - SEq_1 * SEq_4) + twob_z * (SEq_1 * SEq_2 + SEq_3 * SEq_4) - mag.y; f_6 = twob_x * (SEq_1SEq_3 + SEq_2SEq_4) + twob_z * (0.5f - SEq_2 * SEq_2 - SEq_3 * SEq_3) - mag.z; @@ -391,10 +380,10 @@ void AP_Quaternion::update_drift(float deltat, Vector3f &gyro, Vector3f &accel, J_64 = twob_xSEq_2; // compute the gradient (matrix multiplication) - SEqHatDot_1 = J_14or21 * f_2 - J_11or24 * f_1 - J_41 * f_4 - J_51 * f_5 + J_61 * f_6; - SEqHatDot_2 = J_12or23 * f_1 + J_13or22 * f_2 - J_32 * f_3 + J_42 * f_4 + J_52 * f_5 + J_62 * f_6; - SEqHatDot_3 = J_12or23 * f_2 - J_33 * f_3 - J_13or22 * f_1 - J_43 * f_4 + J_53 * f_5 + J_63 * f_6; - SEqHatDot_4 = J_14or21 * f_1 + J_11or24 * f_2 - J_44 * f_4 - J_54 * f_5 + J_64 * f_6; + SEqHatDot_1 = - J_41 * f_4 - J_51 * f_5 + J_61 * f_6; + SEqHatDot_2 = + J_42 * f_4 + J_52 * f_5 + J_62 * f_6; + SEqHatDot_3 = - J_43 * f_4 + J_53 * f_5 + J_63 * f_6; + SEqHatDot_4 = - J_44 * f_4 - J_54 * f_5 + J_64 * f_6; // normalise the gradient to estimate direction of the gyroscope error norm = 1.0 / safe_sqrt(SEqHatDot_1 * SEqHatDot_1 + SEqHatDot_2 * SEqHatDot_2 + SEqHatDot_3 * SEqHatDot_3 + SEqHatDot_4 * SEqHatDot_4); @@ -430,6 +419,28 @@ void AP_Quaternion::update_drift(float deltat, Vector3f &gyro, Vector3f &accel, drift_delta.z = constrain(drift_delta.z, -max_change, max_change); gyro_bias += drift_delta; + // compute then integrate the estimated quaternion rate + SEq_1 -= (beta * SEqHatDot_1) * deltat; + SEq_2 -= (beta * SEqHatDot_2) * deltat; + SEq_3 -= (beta * SEqHatDot_3) * deltat; + SEq_4 -= (beta * SEqHatDot_4) * deltat; + + // normalise quaternion + norm = 1.0/safe_sqrt(SEq_1 * SEq_1 + SEq_2 * SEq_2 + SEq_3 * SEq_3 + SEq_4 * SEq_4); + if (isinf(norm)) { + // our quaternion is bad! Reset based on roll/pitch/yaw + // and hope for the best ... + renorm_blowup_count++; + _compass->null_offsets_disable(); + quaternion_from_euler(q, roll, pitch, yaw); + _compass->null_offsets_disable(); + return; + } + SEq_1 *= norm; + SEq_2 *= norm; + SEq_3 *= norm; + SEq_4 *= norm; + // compute flux in the earth frame // recompute axulirary variables SEq_1SEq_2 = SEq_1 * SEq_2; @@ -506,10 +517,8 @@ void AP_Quaternion::update(void) accel.z += (gyro.y - gyro_bias.y) * veloc; } - _gyro_sum += gyro; - _accel_sum += accel; - _sum_count++; - +#define SEPARATE_DRIFT 0 +#if SEPARATE_DRIFT /* The full Madgwick quaternion 'MARG' system assumes you get gyro, accel and magnetometer updates at the same rate. On @@ -521,24 +530,28 @@ void AP_Quaternion::update(void) new magnetometer point, and use the much simpler update_IMU() as the main quaternion update function. */ + _gyro_sum += gyro; + _accel_sum += accel; + _sum_count++; + if (_compass != NULL && _compass->use_for_yaw() && _compass->last_update != _compass_last_update && _sum_count != 0) { // use new compass sample for drift correction float mag_deltat = 1.0e-6*(_compass->last_update - _compass_last_update); Vector3f mag = Vector3f(_compass->mag_x, _compass->mag_y, - _compass->mag_z); - Vector3f drift_accel = _accel_sum / _sum_count; - Vector3f drift_gyro = _gyro_sum / _sum_count; - _accel_sum.zero(); - _gyro_sum.zero(); _sum_count = 0; - update_drift(mag_deltat, drift_gyro, drift_accel, mag); + update_drift(mag_deltat, mag); _compass_last_update = _compass->last_update; } // step the quaternion solution using just gyros and accels gyro -= gyro_bias; update_IMU(deltat, gyro, accel); +#else + Vector3f mag = Vector3f(_compass->mag_x, _compass->mag_y, - _compass->mag_z); + update_MARG(deltat, gyro, accel, mag); +#endif #ifdef DESKTOP_BUILD if (q.is_nan()) { diff --git a/libraries/AP_Quaternion/AP_Quaternion.h b/libraries/AP_Quaternion/AP_Quaternion.h index f6fef48424..c1e2894a76 100644 --- a/libraries/AP_Quaternion/AP_Quaternion.h +++ b/libraries/AP_Quaternion/AP_Quaternion.h @@ -78,7 +78,7 @@ public: private: void update_IMU(float deltat, Vector3f &gyro, Vector3f &accel); void update_MARG(float deltat, Vector3f &gyro, Vector3f &accel, Vector3f &mag); - void update_drift(float deltat, Vector3f &gyro, Vector3f &accel, Vector3f &mag); + void update_drift(float deltat, Vector3f &mag); bool _have_initial_yaw; @@ -99,11 +99,9 @@ private: bool _centripetal; // maximum gyroscope measurement error in rad/s (set to 7 degrees/second) - static const float gyroMeasError = 7.0 * (M_PI/180.0); + static const float gyroMeasError = 20.0 * (M_PI/180.0); - // maximum gyroscope drift rate in radians/s/s (set to 0.005 - // degrees/s/s, which is 0.3 degrees/s/minute) - static const float gyroMeasDrift = 0.04 * (PI/180.0); + float gyroMeasDrift; float beta; float zeta; From eff6778515c3ba3fa29f1eca1f7a8ee8fc556015 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 9 Mar 2012 09:02:46 +1100 Subject: [PATCH 115/178] Quaternion: use gyro drift value from sensor driver --- libraries/AP_Quaternion/AP_Quaternion.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libraries/AP_Quaternion/AP_Quaternion.h b/libraries/AP_Quaternion/AP_Quaternion.h index c1e2894a76..20028f1efe 100644 --- a/libraries/AP_Quaternion/AP_Quaternion.h +++ b/libraries/AP_Quaternion/AP_Quaternion.h @@ -25,6 +25,10 @@ public: b_x = 0; b_z = -1; + // limit the drift to the drift rate reported by the + // sensor driver + gyroMeasDrift = imu->get_gyro_drift_rate(); + // scaled gyro drift limits beta = sqrt(3.0f / 4.0f) * gyroMeasError; zeta = sqrt(3.0f / 4.0f) * gyroMeasDrift; From 87c463bcc75137ce8dc2a518ced89705475a1f83 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 9 Mar 2012 09:03:47 +1100 Subject: [PATCH 116/178] DCM: after some experimentation, raise the ki values a bit this tracks the max gyro drift more accurately --- libraries/AP_DCM/AP_DCM.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/AP_DCM/AP_DCM.h b/libraries/AP_DCM/AP_DCM.h index d8a2d1f268..5ebe7f554f 100644 --- a/libraries/AP_DCM/AP_DCM.h +++ b/libraries/AP_DCM/AP_DCM.h @@ -41,8 +41,8 @@ public: // which will make us less prone to increasing omegaI // incorrectly due to sensor noise _gyro_drift_limit = imu->get_gyro_drift_rate(); - _ki_roll_pitch = _gyro_drift_limit * 3; - _ki_yaw = _gyro_drift_limit * 4; + _ki_roll_pitch = _gyro_drift_limit * 5; + _ki_yaw = _gyro_drift_limit * 8; } // Accessors From 44ebb203290f1023fe68c9d3843393201e995b59 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 10 Mar 2012 09:39:26 +1100 Subject: [PATCH 117/178] MAVLink: bring the v1.0 MAVLink in sync with 0.9 --- .../include/ardupilotmega/version.h | 2 +- .../GCS_MAVLink/include/common/version.h | 2 +- .../ardupilotmega/ardupilotmega.h | 7 +- .../ardupilotmega/mavlink_msg_hwstatus.h | 166 ++++++++++++++++++ .../include_v1.0/ardupilotmega/testsuite.h | 46 +++++ .../include_v1.0/ardupilotmega/version.h | 2 +- .../GCS_MAVLink/include_v1.0/common/version.h | 2 +- .../ardupilotmega.xml | 8 +- 8 files changed, 227 insertions(+), 8 deletions(-) create mode 100644 libraries/GCS_MAVLink/include_v1.0/ardupilotmega/mavlink_msg_hwstatus.h diff --git a/libraries/GCS_MAVLink/include/ardupilotmega/version.h b/libraries/GCS_MAVLink/include/ardupilotmega/version.h index 21df074daa..21ba95a5b6 100644 --- a/libraries/GCS_MAVLink/include/ardupilotmega/version.h +++ b/libraries/GCS_MAVLink/include/ardupilotmega/version.h @@ -5,7 +5,7 @@ #ifndef MAVLINK_VERSION_H #define MAVLINK_VERSION_H -#define MAVLINK_BUILD_DATE "Thu Mar 1 13:22:36 2012" +#define MAVLINK_BUILD_DATE "Sat Mar 10 09:38:12 2012" #define MAVLINK_WIRE_PROTOCOL_VERSION "0.9" #define MAVLINK_MAX_DIALECT_PAYLOAD_SIZE 101 diff --git a/libraries/GCS_MAVLink/include/common/version.h b/libraries/GCS_MAVLink/include/common/version.h index 68c051a15e..827cc5a715 100644 --- a/libraries/GCS_MAVLink/include/common/version.h +++ b/libraries/GCS_MAVLink/include/common/version.h @@ -5,7 +5,7 @@ #ifndef MAVLINK_VERSION_H #define MAVLINK_VERSION_H -#define MAVLINK_BUILD_DATE "Thu Mar 1 13:22:36 2012" +#define MAVLINK_BUILD_DATE "Sat Mar 10 09:38:12 2012" #define MAVLINK_WIRE_PROTOCOL_VERSION "0.9" #define MAVLINK_MAX_DIALECT_PAYLOAD_SIZE 101 diff --git a/libraries/GCS_MAVLink/include_v1.0/ardupilotmega/ardupilotmega.h b/libraries/GCS_MAVLink/include_v1.0/ardupilotmega/ardupilotmega.h index f3465738f4..b071f8ba8f 100644 --- a/libraries/GCS_MAVLink/include_v1.0/ardupilotmega/ardupilotmega.h +++ b/libraries/GCS_MAVLink/include_v1.0/ardupilotmega/ardupilotmega.h @@ -12,15 +12,15 @@ extern "C" { // MESSAGE LENGTHS AND CRCS #ifndef MAVLINK_MESSAGE_LENGTHS -#define MAVLINK_MESSAGE_LENGTHS {9, 31, 12, 0, 14, 28, 3, 32, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 20, 2, 25, 23, 30, 101, 22, 26, 16, 14, 28, 32, 28, 28, 22, 22, 21, 6, 6, 37, 4, 4, 2, 2, 4, 2, 2, 3, 13, 12, 19, 17, 15, 15, 27, 25, 18, 18, 20, 20, 0, 0, 26, 0, 36, 0, 6, 4, 0, 21, 18, 0, 0, 0, 20, 0, 33, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56, 42, 33, 0, 0, 0, 0, 0, 0, 0, 18, 32, 32, 20, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 42, 8, 4, 12, 15, 13, 6, 15, 14, 0, 12, 3, 8, 28, 36, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 36, 30, 18, 18, 51, 9, 3} +#define MAVLINK_MESSAGE_LENGTHS {9, 31, 12, 0, 14, 28, 3, 32, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 20, 2, 25, 23, 30, 101, 22, 26, 16, 14, 28, 32, 28, 28, 22, 22, 21, 6, 6, 37, 4, 4, 2, 2, 4, 2, 2, 3, 13, 12, 19, 17, 15, 15, 27, 25, 18, 18, 20, 20, 0, 0, 26, 0, 36, 0, 6, 4, 0, 21, 18, 0, 0, 0, 20, 0, 33, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56, 42, 33, 0, 0, 0, 0, 0, 0, 0, 18, 32, 32, 20, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 42, 8, 4, 12, 15, 13, 6, 15, 14, 0, 12, 3, 8, 28, 36, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 36, 30, 18, 18, 51, 9, 3} #endif #ifndef MAVLINK_MESSAGE_CRCS -#define MAVLINK_MESSAGE_CRCS {50, 124, 137, 0, 237, 217, 104, 119, 0, 0, 0, 89, 0, 0, 0, 0, 0, 0, 0, 0, 214, 159, 220, 168, 24, 23, 170, 144, 67, 115, 39, 246, 185, 104, 237, 244, 222, 212, 9, 254, 230, 28, 28, 132, 221, 232, 11, 153, 41, 39, 214, 223, 141, 33, 15, 3, 100, 24, 239, 238, 0, 0, 183, 0, 130, 0, 148, 21, 0, 52, 124, 0, 0, 0, 20, 0, 152, 143, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 183, 63, 54, 0, 0, 0, 0, 0, 0, 0, 19, 102, 158, 208, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 134, 219, 208, 188, 84, 22, 19, 21, 134, 0, 78, 68, 189, 205, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 204, 49, 170, 44, 83, 46, 247} +#define MAVLINK_MESSAGE_CRCS {50, 124, 137, 0, 237, 217, 104, 119, 0, 0, 0, 89, 0, 0, 0, 0, 0, 0, 0, 0, 214, 159, 220, 168, 24, 23, 170, 144, 67, 115, 39, 246, 185, 104, 237, 244, 222, 212, 9, 254, 230, 28, 28, 132, 221, 232, 11, 153, 41, 39, 214, 223, 141, 33, 15, 3, 100, 24, 239, 238, 0, 0, 183, 0, 130, 0, 148, 21, 0, 52, 124, 0, 0, 0, 20, 0, 152, 143, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 183, 63, 54, 0, 0, 0, 0, 0, 0, 0, 19, 102, 158, 208, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 134, 219, 208, 188, 84, 22, 19, 21, 134, 0, 78, 68, 189, 205, 42, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 204, 49, 170, 44, 83, 46, 247} #endif #ifndef MAVLINK_MESSAGE_INFO -#define MAVLINK_MESSAGE_INFO {MAVLINK_MESSAGE_INFO_HEARTBEAT, MAVLINK_MESSAGE_INFO_SYS_STATUS, MAVLINK_MESSAGE_INFO_SYSTEM_TIME, {NULL}, MAVLINK_MESSAGE_INFO_PING, MAVLINK_MESSAGE_INFO_CHANGE_OPERATOR_CONTROL, MAVLINK_MESSAGE_INFO_CHANGE_OPERATOR_CONTROL_ACK, MAVLINK_MESSAGE_INFO_AUTH_KEY, {NULL}, {NULL}, {NULL}, MAVLINK_MESSAGE_INFO_SET_MODE, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, MAVLINK_MESSAGE_INFO_PARAM_REQUEST_READ, MAVLINK_MESSAGE_INFO_PARAM_REQUEST_LIST, MAVLINK_MESSAGE_INFO_PARAM_VALUE, MAVLINK_MESSAGE_INFO_PARAM_SET, MAVLINK_MESSAGE_INFO_GPS_RAW_INT, MAVLINK_MESSAGE_INFO_GPS_STATUS, MAVLINK_MESSAGE_INFO_SCALED_IMU, MAVLINK_MESSAGE_INFO_RAW_IMU, MAVLINK_MESSAGE_INFO_RAW_PRESSURE, MAVLINK_MESSAGE_INFO_SCALED_PRESSURE, MAVLINK_MESSAGE_INFO_ATTITUDE, MAVLINK_MESSAGE_INFO_ATTITUDE_QUATERNION, MAVLINK_MESSAGE_INFO_LOCAL_POSITION_NED, MAVLINK_MESSAGE_INFO_GLOBAL_POSITION_INT, MAVLINK_MESSAGE_INFO_RC_CHANNELS_SCALED, MAVLINK_MESSAGE_INFO_RC_CHANNELS_RAW, MAVLINK_MESSAGE_INFO_SERVO_OUTPUT_RAW, MAVLINK_MESSAGE_INFO_MISSION_REQUEST_PARTIAL_LIST, MAVLINK_MESSAGE_INFO_MISSION_WRITE_PARTIAL_LIST, MAVLINK_MESSAGE_INFO_MISSION_ITEM, MAVLINK_MESSAGE_INFO_MISSION_REQUEST, MAVLINK_MESSAGE_INFO_MISSION_SET_CURRENT, MAVLINK_MESSAGE_INFO_MISSION_CURRENT, MAVLINK_MESSAGE_INFO_MISSION_REQUEST_LIST, MAVLINK_MESSAGE_INFO_MISSION_COUNT, MAVLINK_MESSAGE_INFO_MISSION_CLEAR_ALL, MAVLINK_MESSAGE_INFO_MISSION_ITEM_REACHED, MAVLINK_MESSAGE_INFO_MISSION_ACK, MAVLINK_MESSAGE_INFO_SET_GPS_GLOBAL_ORIGIN, MAVLINK_MESSAGE_INFO_GPS_GLOBAL_ORIGIN, MAVLINK_MESSAGE_INFO_SET_LOCAL_POSITION_SETPOINT, MAVLINK_MESSAGE_INFO_LOCAL_POSITION_SETPOINT, MAVLINK_MESSAGE_INFO_GLOBAL_POSITION_SETPOINT_INT, MAVLINK_MESSAGE_INFO_SET_GLOBAL_POSITION_SETPOINT_INT, MAVLINK_MESSAGE_INFO_SAFETY_SET_ALLOWED_AREA, MAVLINK_MESSAGE_INFO_SAFETY_ALLOWED_AREA, MAVLINK_MESSAGE_INFO_SET_ROLL_PITCH_YAW_THRUST, MAVLINK_MESSAGE_INFO_SET_ROLL_PITCH_YAW_SPEED_THRUST, MAVLINK_MESSAGE_INFO_ROLL_PITCH_YAW_THRUST_SETPOINT, MAVLINK_MESSAGE_INFO_ROLL_PITCH_YAW_SPEED_THRUST_SETPOINT, {NULL}, {NULL}, MAVLINK_MESSAGE_INFO_NAV_CONTROLLER_OUTPUT, {NULL}, MAVLINK_MESSAGE_INFO_STATE_CORRECTION, {NULL}, MAVLINK_MESSAGE_INFO_REQUEST_DATA_STREAM, MAVLINK_MESSAGE_INFO_DATA_STREAM, {NULL}, MAVLINK_MESSAGE_INFO_MANUAL_CONTROL, MAVLINK_MESSAGE_INFO_RC_CHANNELS_OVERRIDE, {NULL}, {NULL}, {NULL}, MAVLINK_MESSAGE_INFO_VFR_HUD, {NULL}, MAVLINK_MESSAGE_INFO_COMMAND_LONG, MAVLINK_MESSAGE_INFO_COMMAND_ACK, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, MAVLINK_MESSAGE_INFO_HIL_STATE, MAVLINK_MESSAGE_INFO_HIL_CONTROLS, MAVLINK_MESSAGE_INFO_HIL_RC_INPUTS_RAW, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, MAVLINK_MESSAGE_INFO_OPTICAL_FLOW, MAVLINK_MESSAGE_INFO_GLOBAL_VISION_POSITION_ESTIMATE, MAVLINK_MESSAGE_INFO_VISION_POSITION_ESTIMATE, MAVLINK_MESSAGE_INFO_VISION_SPEED_ESTIMATE, MAVLINK_MESSAGE_INFO_VICON_POSITION_ESTIMATE, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, MAVLINK_MESSAGE_INFO_SENSOR_OFFSETS, MAVLINK_MESSAGE_INFO_SET_MAG_OFFSETS, MAVLINK_MESSAGE_INFO_MEMINFO, MAVLINK_MESSAGE_INFO_AP_ADC, MAVLINK_MESSAGE_INFO_DIGICAM_CONFIGURE, MAVLINK_MESSAGE_INFO_DIGICAM_CONTROL, MAVLINK_MESSAGE_INFO_MOUNT_CONFIGURE, MAVLINK_MESSAGE_INFO_MOUNT_CONTROL, MAVLINK_MESSAGE_INFO_MOUNT_STATUS, {NULL}, MAVLINK_MESSAGE_INFO_FENCE_POINT, MAVLINK_MESSAGE_INFO_FENCE_FETCH_POINT, MAVLINK_MESSAGE_INFO_FENCE_STATUS, MAVLINK_MESSAGE_INFO_DCM, MAVLINK_MESSAGE_INFO_SIMSTATE, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, MAVLINK_MESSAGE_INFO_MEMORY_VECT, MAVLINK_MESSAGE_INFO_DEBUG_VECT, MAVLINK_MESSAGE_INFO_NAMED_VALUE_FLOAT, MAVLINK_MESSAGE_INFO_NAMED_VALUE_INT, MAVLINK_MESSAGE_INFO_STATUSTEXT, MAVLINK_MESSAGE_INFO_DEBUG, MAVLINK_MESSAGE_INFO_EXTENDED_MESSAGE} +#define MAVLINK_MESSAGE_INFO {MAVLINK_MESSAGE_INFO_HEARTBEAT, MAVLINK_MESSAGE_INFO_SYS_STATUS, MAVLINK_MESSAGE_INFO_SYSTEM_TIME, {NULL}, MAVLINK_MESSAGE_INFO_PING, MAVLINK_MESSAGE_INFO_CHANGE_OPERATOR_CONTROL, MAVLINK_MESSAGE_INFO_CHANGE_OPERATOR_CONTROL_ACK, MAVLINK_MESSAGE_INFO_AUTH_KEY, {NULL}, {NULL}, {NULL}, MAVLINK_MESSAGE_INFO_SET_MODE, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, MAVLINK_MESSAGE_INFO_PARAM_REQUEST_READ, MAVLINK_MESSAGE_INFO_PARAM_REQUEST_LIST, MAVLINK_MESSAGE_INFO_PARAM_VALUE, MAVLINK_MESSAGE_INFO_PARAM_SET, MAVLINK_MESSAGE_INFO_GPS_RAW_INT, MAVLINK_MESSAGE_INFO_GPS_STATUS, MAVLINK_MESSAGE_INFO_SCALED_IMU, MAVLINK_MESSAGE_INFO_RAW_IMU, MAVLINK_MESSAGE_INFO_RAW_PRESSURE, MAVLINK_MESSAGE_INFO_SCALED_PRESSURE, MAVLINK_MESSAGE_INFO_ATTITUDE, MAVLINK_MESSAGE_INFO_ATTITUDE_QUATERNION, MAVLINK_MESSAGE_INFO_LOCAL_POSITION_NED, MAVLINK_MESSAGE_INFO_GLOBAL_POSITION_INT, MAVLINK_MESSAGE_INFO_RC_CHANNELS_SCALED, MAVLINK_MESSAGE_INFO_RC_CHANNELS_RAW, MAVLINK_MESSAGE_INFO_SERVO_OUTPUT_RAW, MAVLINK_MESSAGE_INFO_MISSION_REQUEST_PARTIAL_LIST, MAVLINK_MESSAGE_INFO_MISSION_WRITE_PARTIAL_LIST, MAVLINK_MESSAGE_INFO_MISSION_ITEM, MAVLINK_MESSAGE_INFO_MISSION_REQUEST, MAVLINK_MESSAGE_INFO_MISSION_SET_CURRENT, MAVLINK_MESSAGE_INFO_MISSION_CURRENT, MAVLINK_MESSAGE_INFO_MISSION_REQUEST_LIST, MAVLINK_MESSAGE_INFO_MISSION_COUNT, MAVLINK_MESSAGE_INFO_MISSION_CLEAR_ALL, MAVLINK_MESSAGE_INFO_MISSION_ITEM_REACHED, MAVLINK_MESSAGE_INFO_MISSION_ACK, MAVLINK_MESSAGE_INFO_SET_GPS_GLOBAL_ORIGIN, MAVLINK_MESSAGE_INFO_GPS_GLOBAL_ORIGIN, MAVLINK_MESSAGE_INFO_SET_LOCAL_POSITION_SETPOINT, MAVLINK_MESSAGE_INFO_LOCAL_POSITION_SETPOINT, MAVLINK_MESSAGE_INFO_GLOBAL_POSITION_SETPOINT_INT, MAVLINK_MESSAGE_INFO_SET_GLOBAL_POSITION_SETPOINT_INT, MAVLINK_MESSAGE_INFO_SAFETY_SET_ALLOWED_AREA, MAVLINK_MESSAGE_INFO_SAFETY_ALLOWED_AREA, MAVLINK_MESSAGE_INFO_SET_ROLL_PITCH_YAW_THRUST, MAVLINK_MESSAGE_INFO_SET_ROLL_PITCH_YAW_SPEED_THRUST, MAVLINK_MESSAGE_INFO_ROLL_PITCH_YAW_THRUST_SETPOINT, MAVLINK_MESSAGE_INFO_ROLL_PITCH_YAW_SPEED_THRUST_SETPOINT, {NULL}, {NULL}, MAVLINK_MESSAGE_INFO_NAV_CONTROLLER_OUTPUT, {NULL}, MAVLINK_MESSAGE_INFO_STATE_CORRECTION, {NULL}, MAVLINK_MESSAGE_INFO_REQUEST_DATA_STREAM, MAVLINK_MESSAGE_INFO_DATA_STREAM, {NULL}, MAVLINK_MESSAGE_INFO_MANUAL_CONTROL, MAVLINK_MESSAGE_INFO_RC_CHANNELS_OVERRIDE, {NULL}, {NULL}, {NULL}, MAVLINK_MESSAGE_INFO_VFR_HUD, {NULL}, MAVLINK_MESSAGE_INFO_COMMAND_LONG, MAVLINK_MESSAGE_INFO_COMMAND_ACK, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, MAVLINK_MESSAGE_INFO_HIL_STATE, MAVLINK_MESSAGE_INFO_HIL_CONTROLS, MAVLINK_MESSAGE_INFO_HIL_RC_INPUTS_RAW, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, MAVLINK_MESSAGE_INFO_OPTICAL_FLOW, MAVLINK_MESSAGE_INFO_GLOBAL_VISION_POSITION_ESTIMATE, MAVLINK_MESSAGE_INFO_VISION_POSITION_ESTIMATE, MAVLINK_MESSAGE_INFO_VISION_SPEED_ESTIMATE, MAVLINK_MESSAGE_INFO_VICON_POSITION_ESTIMATE, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, MAVLINK_MESSAGE_INFO_SENSOR_OFFSETS, MAVLINK_MESSAGE_INFO_SET_MAG_OFFSETS, MAVLINK_MESSAGE_INFO_MEMINFO, MAVLINK_MESSAGE_INFO_AP_ADC, MAVLINK_MESSAGE_INFO_DIGICAM_CONFIGURE, MAVLINK_MESSAGE_INFO_DIGICAM_CONTROL, MAVLINK_MESSAGE_INFO_MOUNT_CONFIGURE, MAVLINK_MESSAGE_INFO_MOUNT_CONTROL, MAVLINK_MESSAGE_INFO_MOUNT_STATUS, {NULL}, MAVLINK_MESSAGE_INFO_FENCE_POINT, MAVLINK_MESSAGE_INFO_FENCE_FETCH_POINT, MAVLINK_MESSAGE_INFO_FENCE_STATUS, MAVLINK_MESSAGE_INFO_DCM, MAVLINK_MESSAGE_INFO_SIMSTATE, MAVLINK_MESSAGE_INFO_HWSTATUS, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, MAVLINK_MESSAGE_INFO_MEMORY_VECT, MAVLINK_MESSAGE_INFO_DEBUG_VECT, MAVLINK_MESSAGE_INFO_NAMED_VALUE_FLOAT, MAVLINK_MESSAGE_INFO_NAMED_VALUE_INT, MAVLINK_MESSAGE_INFO_STATUSTEXT, MAVLINK_MESSAGE_INFO_DEBUG, MAVLINK_MESSAGE_INFO_EXTENDED_MESSAGE} #endif #include "../protocol.h" @@ -144,6 +144,7 @@ enum FENCE_BREACH #include "./mavlink_msg_fence_status.h" #include "./mavlink_msg_dcm.h" #include "./mavlink_msg_simstate.h" +#include "./mavlink_msg_hwstatus.h" #ifdef __cplusplus } diff --git a/libraries/GCS_MAVLink/include_v1.0/ardupilotmega/mavlink_msg_hwstatus.h b/libraries/GCS_MAVLink/include_v1.0/ardupilotmega/mavlink_msg_hwstatus.h new file mode 100644 index 0000000000..a439560fb5 --- /dev/null +++ b/libraries/GCS_MAVLink/include_v1.0/ardupilotmega/mavlink_msg_hwstatus.h @@ -0,0 +1,166 @@ +// MESSAGE HWSTATUS PACKING + +#define MAVLINK_MSG_ID_HWSTATUS 165 + +typedef struct __mavlink_hwstatus_t +{ + uint16_t Vcc; ///< board voltage (mV) + uint8_t I2Cerr; ///< I2C error count +} mavlink_hwstatus_t; + +#define MAVLINK_MSG_ID_HWSTATUS_LEN 3 +#define MAVLINK_MSG_ID_165_LEN 3 + + + +#define MAVLINK_MESSAGE_INFO_HWSTATUS { \ + "HWSTATUS", \ + 2, \ + { { "Vcc", NULL, MAVLINK_TYPE_UINT16_T, 0, 0, offsetof(mavlink_hwstatus_t, Vcc) }, \ + { "I2Cerr", NULL, MAVLINK_TYPE_UINT8_T, 0, 2, offsetof(mavlink_hwstatus_t, I2Cerr) }, \ + } \ +} + + +/** + * @brief Pack a hwstatus message + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * + * @param Vcc board voltage (mV) + * @param I2Cerr I2C error count + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_hwstatus_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, + uint16_t Vcc, uint8_t I2Cerr) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[3]; + _mav_put_uint16_t(buf, 0, Vcc); + _mav_put_uint8_t(buf, 2, I2Cerr); + + memcpy(_MAV_PAYLOAD(msg), buf, 3); +#else + mavlink_hwstatus_t packet; + packet.Vcc = Vcc; + packet.I2Cerr = I2Cerr; + + memcpy(_MAV_PAYLOAD(msg), &packet, 3); +#endif + + msg->msgid = MAVLINK_MSG_ID_HWSTATUS; + return mavlink_finalize_message(msg, system_id, component_id, 3, 21); +} + +/** + * @brief Pack a hwstatus message on a channel + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param chan The MAVLink channel this message was sent over + * @param msg The MAVLink message to compress the data into + * @param Vcc board voltage (mV) + * @param I2Cerr I2C error count + * @return length of the message in bytes (excluding serial stream start sign) + */ +static inline uint16_t mavlink_msg_hwstatus_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, + mavlink_message_t* msg, + uint16_t Vcc,uint8_t I2Cerr) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[3]; + _mav_put_uint16_t(buf, 0, Vcc); + _mav_put_uint8_t(buf, 2, I2Cerr); + + memcpy(_MAV_PAYLOAD(msg), buf, 3); +#else + mavlink_hwstatus_t packet; + packet.Vcc = Vcc; + packet.I2Cerr = I2Cerr; + + memcpy(_MAV_PAYLOAD(msg), &packet, 3); +#endif + + msg->msgid = MAVLINK_MSG_ID_HWSTATUS; + return mavlink_finalize_message_chan(msg, system_id, component_id, chan, 3, 21); +} + +/** + * @brief Encode a hwstatus struct into a message + * + * @param system_id ID of this system + * @param component_id ID of this component (e.g. 200 for IMU) + * @param msg The MAVLink message to compress the data into + * @param hwstatus C-struct to read the message contents from + */ +static inline uint16_t mavlink_msg_hwstatus_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const mavlink_hwstatus_t* hwstatus) +{ + return mavlink_msg_hwstatus_pack(system_id, component_id, msg, hwstatus->Vcc, hwstatus->I2Cerr); +} + +/** + * @brief Send a hwstatus message + * @param chan MAVLink channel to send the message + * + * @param Vcc board voltage (mV) + * @param I2Cerr I2C error count + */ +#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS + +static inline void mavlink_msg_hwstatus_send(mavlink_channel_t chan, uint16_t Vcc, uint8_t I2Cerr) +{ +#if MAVLINK_NEED_BYTE_SWAP || !MAVLINK_ALIGNED_FIELDS + char buf[3]; + _mav_put_uint16_t(buf, 0, Vcc); + _mav_put_uint8_t(buf, 2, I2Cerr); + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_HWSTATUS, buf, 3, 21); +#else + mavlink_hwstatus_t packet; + packet.Vcc = Vcc; + packet.I2Cerr = I2Cerr; + + _mav_finalize_message_chan_send(chan, MAVLINK_MSG_ID_HWSTATUS, (const char *)&packet, 3, 21); +#endif +} + +#endif + +// MESSAGE HWSTATUS UNPACKING + + +/** + * @brief Get field Vcc from hwstatus message + * + * @return board voltage (mV) + */ +static inline uint16_t mavlink_msg_hwstatus_get_Vcc(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint16_t(msg, 0); +} + +/** + * @brief Get field I2Cerr from hwstatus message + * + * @return I2C error count + */ +static inline uint8_t mavlink_msg_hwstatus_get_I2Cerr(const mavlink_message_t* msg) +{ + return _MAV_RETURN_uint8_t(msg, 2); +} + +/** + * @brief Decode a hwstatus message into a struct + * + * @param msg The message to decode + * @param hwstatus C-struct to decode the message contents into + */ +static inline void mavlink_msg_hwstatus_decode(const mavlink_message_t* msg, mavlink_hwstatus_t* hwstatus) +{ +#if MAVLINK_NEED_BYTE_SWAP + hwstatus->Vcc = mavlink_msg_hwstatus_get_Vcc(msg); + hwstatus->I2Cerr = mavlink_msg_hwstatus_get_I2Cerr(msg); +#else + memcpy(hwstatus, _MAV_PAYLOAD(msg), 3); +#endif +} diff --git a/libraries/GCS_MAVLink/include_v1.0/ardupilotmega/testsuite.h b/libraries/GCS_MAVLink/include_v1.0/ardupilotmega/testsuite.h index d7ce12505c..5cda49612f 100644 --- a/libraries/GCS_MAVLink/include_v1.0/ardupilotmega/testsuite.h +++ b/libraries/GCS_MAVLink/include_v1.0/ardupilotmega/testsuite.h @@ -782,6 +782,51 @@ static void mavlink_test_simstate(uint8_t system_id, uint8_t component_id, mavli MAVLINK_ASSERT(memcmp(&packet1, &packet2, sizeof(packet1)) == 0); } +static void mavlink_test_hwstatus(uint8_t system_id, uint8_t component_id, mavlink_message_t *last_msg) +{ + mavlink_message_t msg; + uint8_t buffer[MAVLINK_MAX_PACKET_LEN]; + uint16_t i; + mavlink_hwstatus_t packet_in = { + 17235, + 139, + }; + mavlink_hwstatus_t packet1, packet2; + memset(&packet1, 0, sizeof(packet1)); + packet1.Vcc = packet_in.Vcc; + packet1.I2Cerr = packet_in.I2Cerr; + + + + memset(&packet2, 0, sizeof(packet2)); + mavlink_msg_hwstatus_encode(system_id, component_id, &msg, &packet1); + mavlink_msg_hwstatus_decode(&msg, &packet2); + MAVLINK_ASSERT(memcmp(&packet1, &packet2, sizeof(packet1)) == 0); + + memset(&packet2, 0, sizeof(packet2)); + mavlink_msg_hwstatus_pack(system_id, component_id, &msg , packet1.Vcc , packet1.I2Cerr ); + mavlink_msg_hwstatus_decode(&msg, &packet2); + MAVLINK_ASSERT(memcmp(&packet1, &packet2, sizeof(packet1)) == 0); + + memset(&packet2, 0, sizeof(packet2)); + mavlink_msg_hwstatus_pack_chan(system_id, component_id, MAVLINK_COMM_0, &msg , packet1.Vcc , packet1.I2Cerr ); + mavlink_msg_hwstatus_decode(&msg, &packet2); + MAVLINK_ASSERT(memcmp(&packet1, &packet2, sizeof(packet1)) == 0); + + memset(&packet2, 0, sizeof(packet2)); + mavlink_msg_to_send_buffer(buffer, &msg); + for (i=0; i0: unlock focus or keep unlocked, 1: lock focus or keep locked, 3: re-lock focus 0: ignore, 1: shot or start filming Command Identity (incremental loop: 0 to 255)//A command sent multiple times will be executed or pooled just once - Extra parameters enumeration (0 means ignore) + Extra parameters enumeration (0 means ignore) Correspondent value to given extra_param @@ -249,5 +249,11 @@ Angular speed around Y axis rad/s Angular speed around Z axis rad/s + + + Status of key hardware + board voltage (mV) + I2C error count + From b02ca58901a3c67376d838075d661755d282c67b Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 10 Mar 2012 09:43:21 +1100 Subject: [PATCH 118/178] InertialSensor: fixed HIL build --- libraries/AP_InertialSensor/AP_InertialSensor_Stub.cpp | 1 + libraries/AP_InertialSensor/AP_InertialSensor_Stub.h | 1 + 2 files changed, 2 insertions(+) diff --git a/libraries/AP_InertialSensor/AP_InertialSensor_Stub.cpp b/libraries/AP_InertialSensor/AP_InertialSensor_Stub.cpp index e88785e1c6..98bbf38c04 100644 --- a/libraries/AP_InertialSensor/AP_InertialSensor_Stub.cpp +++ b/libraries/AP_InertialSensor/AP_InertialSensor_Stub.cpp @@ -26,3 +26,4 @@ void AP_InertialSensor_Stub::get_sensors( float * sensors ) {} float AP_InertialSensor_Stub::temperature() { return 0.0; } uint32_t AP_InertialSensor_Stub::sample_time() { return 0; } void AP_InertialSensor_Stub::reset_sample_time() {} +float AP_InertialSensor_Stub::get_gyro_drift_rate(void) { return 0.0; } diff --git a/libraries/AP_InertialSensor/AP_InertialSensor_Stub.h b/libraries/AP_InertialSensor/AP_InertialSensor_Stub.h index aae2bd1393..2ddcce038e 100644 --- a/libraries/AP_InertialSensor/AP_InertialSensor_Stub.h +++ b/libraries/AP_InertialSensor/AP_InertialSensor_Stub.h @@ -32,6 +32,7 @@ class AP_InertialSensor_Stub : public AP_InertialSensor float temperature(); uint32_t sample_time(); void reset_sample_time(); + float get_gyro_drift_rate(); }; #endif // __AP_INERTIAL_SENSOR_STUB_H__ From ba8e7643497d446c99f653483a3e44277f1320dd Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 10 Mar 2012 10:33:19 +1100 Subject: [PATCH 119/178] SITL: lower the noise and drift levels for general autotest usage --- libraries/Desktop/support/sitl_adc.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/Desktop/support/sitl_adc.h b/libraries/Desktop/support/sitl_adc.h index 100967733a..6a21d6f0f9 100644 --- a/libraries/Desktop/support/sitl_adc.h +++ b/libraries/Desktop/support/sitl_adc.h @@ -9,8 +9,8 @@ #include #include -static const float vibration_level = 0.5; -static const float drift_speed = 0.5; // degrees/second/minute +static const float vibration_level = 0.2; +static const float drift_speed = 0.2; // degrees/second/minute static const float drift_time = 5; // time to reverse drift direction (minutes) // order zgyro, xgyro, ygyro, temp, xacc, yacc, zacc, aspd static const float noise_scale[8] = { 150, 150, 150, 0, 400, 400, 400, 0 }; From c7480f2281762381bf4069378ae5c4f605789fe2 Mon Sep 17 00:00:00 2001 From: rmackay9 Date: Sun, 11 Mar 2012 01:27:29 +0900 Subject: [PATCH 120/178] ArduCopter - fix to dataflash logging of Mag heading --- ArduCopter/Log.pde | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/ArduCopter/Log.pde b/ArduCopter/Log.pde index c05be04cac..dff9e1f477 100644 --- a/ArduCopter/Log.pde +++ b/ArduCopter/Log.pde @@ -701,7 +701,7 @@ static void Log_Write_Attitude() DataFlash.WriteInt((int)dcm.pitch_sensor); // 4 DataFlash.WriteInt(g.rc_4.control_in); // 5 DataFlash.WriteInt((uint16_t)dcm.yaw_sensor); // 6 - DataFlash.WriteInt((uint16_t)compass.heading); // 6 + DataFlash.WriteInt((uint16_t)(ToDeg(compass.heading)*100)); // 7 DataFlash.WriteByte(END_BYTE); } @@ -720,13 +720,13 @@ static void Log_Read_Attitude() // 1 2 3 4 5 6 7 Serial.printf_P(PSTR("ATT, %d, %d, %d, %d, %d, %u, %u\n"), - temp1, - temp2, - temp3, - temp4, - temp5, - temp6, - temp7); + (int)temp1, + (int)temp2, + (int)temp3, + (int)temp4, + (int)temp5, + (unsigned int)temp6, + (unsigned int)temp7); } // Write a mode packet. Total length : 7 bytes From afc4aceb3246a0b818955b1c1607833c493db612 Mon Sep 17 00:00:00 2001 From: rmackay9 Date: Sun, 11 Mar 2012 01:27:58 +0900 Subject: [PATCH 121/178] ArduCopter - fixed small compile warning about unused x_iterm and y_iterm in navigation.pde --- ArduCopter/navigation.pde | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ArduCopter/navigation.pde b/ArduCopter/navigation.pde index 49bc0a29f0..f46baab66a 100644 --- a/ArduCopter/navigation.pde +++ b/ArduCopter/navigation.pde @@ -103,7 +103,7 @@ static void calc_loiter(int x_error, int y_error) { #if LOITER_RATE == 1 int16_t x_target_speed, y_target_speed; - int16_t x_iterm, y_iterm; + //int16_t x_iterm, y_iterm; // East / West x_target_speed = g.pi_loiter_lon.get_p(x_error); // not contstrained yet From 4ba600c0c56ba2b8706fa6159df74568707f3fe5 Mon Sep 17 00:00:00 2001 From: Jason Short Date: Sat, 10 Mar 2012 12:37:28 -0800 Subject: [PATCH 122/178] upped throttle manual boost to 225 --- ArduCopter/ArduCopter.pde | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ArduCopter/ArduCopter.pde b/ArduCopter/ArduCopter.pde index 210e0379be..64b458c31d 100644 --- a/ArduCopter/ArduCopter.pde +++ b/ArduCopter/ArduCopter.pde @@ -1984,7 +1984,7 @@ static void update_altitude_est() //Serial.printf(" %d, %d, %d, %d\n", climb_rate_actual, climb_rate_error, climb_rate, current_loc.alt); } -#define THROTTLE_ADJUST 200 +#define THROTTLE_ADJUST 225 static void adjust_altitude() { From 29d6085babbeda9fd1e4ebadbbf0e5d5733b9998 Mon Sep 17 00:00:00 2001 From: Jason Short Date: Sat, 10 Mar 2012 12:37:54 -0800 Subject: [PATCH 123/178] added Force_new_altitude call for alt hold --- ArduCopter/ArduCopter.pde | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ArduCopter/ArduCopter.pde b/ArduCopter/ArduCopter.pde index 64b458c31d..e71219448e 100644 --- a/ArduCopter/ArduCopter.pde +++ b/ArduCopter/ArduCopter.pde @@ -1658,7 +1658,7 @@ void update_throttle_mode(void) // we are under automatic throttle control // --------------------------------------- if(reset_throttle_flag) { - set_new_altitude(max(current_loc.alt, 100)); + force_new_altitude(max(current_loc.alt, 100)); reset_throttle_flag = false; update_throttle_cruise(); } From bd4835a1b29a2c62f78ca809ed740ec2facef525 Mon Sep 17 00:00:00 2001 From: Jason Short Date: Sat, 10 Mar 2012 12:38:29 -0800 Subject: [PATCH 124/178] ACM: removed the experiment for rate error. --- ArduCopter/Attitude.pde | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ArduCopter/Attitude.pde b/ArduCopter/Attitude.pde index dba7ce508d..277e87561b 100644 --- a/ArduCopter/Attitude.pde +++ b/ArduCopter/Attitude.pde @@ -204,8 +204,8 @@ get_nav_throttle(int32_t z_error) rate_error = rate_error - climb_rate; // hack to see if we can smooth out oscillations - if(rate_error < 0) - rate_error = rate_error >> 1; + //if(rate_error < 0) + // rate_error = rate_error >> 1; // limit the rate output = constrain(g.pid_throttle.get_pid(rate_error, .02), -80, 120); From fc32da0d2ef0c1390c1e995e0f08103818881249 Mon Sep 17 00:00:00 2001 From: Jason Short Date: Sat, 10 Mar 2012 12:39:16 -0800 Subject: [PATCH 125/178] ACM: increased the available rate error constrain, it was too low --- ArduCopter/Attitude.pde | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ArduCopter/Attitude.pde b/ArduCopter/Attitude.pde index 277e87561b..5188a57a32 100644 --- a/ArduCopter/Attitude.pde +++ b/ArduCopter/Attitude.pde @@ -192,7 +192,7 @@ get_nav_throttle(int32_t z_error) // convert to desired Rate: rate_error = g.pi_alt_hold.get_p(z_error); - rate_error = constrain(rate_error, -150, 150); + rate_error = constrain(rate_error, -250, 250); // limit error to prevent I term wind up z_error = constrain(z_error, -400, 400); From 4b703e88429ea9f72b8b51fc1fd9566d9138498f Mon Sep 17 00:00:00 2001 From: Jason Short Date: Sat, 10 Mar 2012 12:40:07 -0800 Subject: [PATCH 126/178] decreased the loiter rate P for overshoot --- ArduCopter/config.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ArduCopter/config.h b/ArduCopter/config.h index a7b3baf794..12e6880a0a 100644 --- a/ArduCopter/config.h +++ b/ArduCopter/config.h @@ -677,7 +677,7 @@ #endif #ifndef LOITER_RATE_P -# define LOITER_RATE_P 3.0 // +# define LOITER_RATE_P 2.6 // #endif #ifndef LOITER_RATE_I # define LOITER_RATE_I 0.25 // Wind control From 220d5a1c6e90acb39d621f5d76a80d8fc18ab596 Mon Sep 17 00:00:00 2001 From: Jason Short Date: Sat, 10 Mar 2012 12:40:44 -0800 Subject: [PATCH 127/178] ACM: Increased the altitude error P for smoother alt hold response --- ArduCopter/config.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ArduCopter/config.h b/ArduCopter/config.h index 12e6880a0a..80a567d097 100644 --- a/ArduCopter/config.h +++ b/ArduCopter/config.h @@ -727,7 +727,7 @@ #endif #ifndef ALT_HOLD_P -# define ALT_HOLD_P 0.2 // +# define ALT_HOLD_P 0.5 // #endif #ifndef ALT_HOLD_I # define ALT_HOLD_I 0.015 From 83729d0f75d2a5d17b8fbd608dc3d960ddbb4f80 Mon Sep 17 00:00:00 2001 From: Jason Short Date: Sat, 10 Mar 2012 12:41:06 -0800 Subject: [PATCH 128/178] ACM: decreased rate P for alt hold to remove bumpy repsonse --- ArduCopter/config.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ArduCopter/config.h b/ArduCopter/config.h index 80a567d097..4813348168 100644 --- a/ArduCopter/config.h +++ b/ArduCopter/config.h @@ -738,7 +738,7 @@ // RATE control #ifndef THROTTLE_P -# define THROTTLE_P 0.45 // +# define THROTTLE_P 0.25 // #endif #ifndef THROTTLE_I # define THROTTLE_I 0.0 // Don't edit From 204f9957b0596b0606b7aef9093f1d197e477ec1 Mon Sep 17 00:00:00 2001 From: Jason Short Date: Sat, 10 Mar 2012 12:42:22 -0800 Subject: [PATCH 129/178] ACM: Added force_new_altitude call to do immediate changes in altitude and no gradual changes. --- ArduCopter/navigation.pde | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/ArduCopter/navigation.pde b/ArduCopter/navigation.pde index f46baab66a..9c4b928d5e 100644 --- a/ArduCopter/navigation.pde +++ b/ArduCopter/navigation.pde @@ -347,16 +347,21 @@ static void clear_new_altitude() alt_change_flag = REACHED_ALT; } +static void force_new_altitude(int32_t _new_alt) +{ + next_WP.alt = _new_alt; + target_altitude = _new_alt; + alt_change_flag = REACHED_ALT; +} + static void set_new_altitude(int32_t _new_alt) { if(_new_alt == current_loc.alt){ - next_WP.alt = _new_alt; - target_altitude = _new_alt; - alt_change_flag = REACHED_ALT; + force_new_altitude(_new_alt); return; } - // just to be clear + // We start at the current location altitude and gradually change alt next_WP.alt = current_loc.alt; // for calculating the delta time From eb532001797d730f1d703b8fc5e97491c188b00c Mon Sep 17 00:00:00 2001 From: Jason Short Date: Sat, 10 Mar 2012 12:43:01 -0800 Subject: [PATCH 130/178] ACM: Altered the scaling speed for altitude changes for faster rises. --- ArduCopter/navigation.pde | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ArduCopter/navigation.pde b/ArduCopter/navigation.pde index 9c4b928d5e..f1ae71081c 100644 --- a/ArduCopter/navigation.pde +++ b/ArduCopter/navigation.pde @@ -429,9 +429,9 @@ static int32_t get_new_altitude() if (next_WP.alt < target_altitude){ // we are below the target alt if(diff < 200){ - _scale = 5; - } else { _scale = 4; + } else { + _scale = 3; } }else { // we are above the target, going down From 450f89ec5d82d57351ed4aaaf796ebf57b8ee4c7 Mon Sep 17 00:00:00 2001 From: Jason Short Date: Sat, 10 Mar 2012 12:43:28 -0800 Subject: [PATCH 131/178] ACM: Added note about scaling rates --- ArduCopter/navigation.pde | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ArduCopter/navigation.pde b/ArduCopter/navigation.pde index f1ae71081c..b69cb24aa8 100644 --- a/ArduCopter/navigation.pde +++ b/ArduCopter/navigation.pde @@ -424,6 +424,8 @@ static int32_t get_new_altitude() } int32_t diff = abs(next_WP.alt - target_altitude); + // scale is how we generate a desired rate from the elapsed time + // a smaller scale means faster rates int8_t _scale = 4; if (next_WP.alt < target_altitude){ From 5ad732050555a7784773bc7c419cd96f4d8548aa Mon Sep 17 00:00:00 2001 From: Jason Short Date: Sat, 10 Mar 2012 12:44:18 -0800 Subject: [PATCH 132/178] ACM: changed alt hold initialization of altitude to be immediate --- ArduCopter/system.pde | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ArduCopter/system.pde b/ArduCopter/system.pde index ea32cdc2d1..5cd24dd1c1 100644 --- a/ArduCopter/system.pde +++ b/ArduCopter/system.pde @@ -447,7 +447,7 @@ static void set_mode(byte mode) roll_pitch_mode = ALT_HOLD_RP; throttle_mode = ALT_HOLD_THR; - set_next_WP(¤t_loc); + force_new_altitude(max(current_loc.alt, 100)); break; case AUTO: From f9d0dc9daa6951648ea5a3e0b1c4f6fcac7d165c Mon Sep 17 00:00:00 2001 From: Jason Short Date: Sat, 10 Mar 2012 12:44:49 -0800 Subject: [PATCH 133/178] ACM: disabled auto_calibration until more testing can be done --- ArduCopter/system.pde | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ArduCopter/system.pde b/ArduCopter/system.pde index 5cd24dd1c1..b0810b0b92 100644 --- a/ArduCopter/system.pde +++ b/ArduCopter/system.pde @@ -579,7 +579,7 @@ static void update_throttle_cruise() } // recalc kp - g.pid_throttle.kP((float)g.throttle_cruise.get() / 981.0); + //g.pid_throttle.kP((float)g.throttle_cruise.get() / 981.0); //Serial.printf("kp:%1.4f\n",kp); } From 0671bb9168a450750e9304afdb5ae1c59c167503 Mon Sep 17 00:00:00 2001 From: Jason Short Date: Sat, 10 Mar 2012 12:45:03 -0800 Subject: [PATCH 134/178] ACM: Firmware rev --- ArduCopter/ArduCopter.pde | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ArduCopter/ArduCopter.pde b/ArduCopter/ArduCopter.pde index e71219448e..f0af3b4959 100644 --- a/ArduCopter/ArduCopter.pde +++ b/ArduCopter/ArduCopter.pde @@ -1,6 +1,6 @@ /// -*- tab-width: 4; Mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*- -#define THISFIRMWARE "ArduCopter V2.4.1" +#define THISFIRMWARE "ArduCopter V2.4.2" /* ArduCopter Version 2.4 Authors: Jason Short From cb8729109ce939e703b13c70c62e542e89bb2ded Mon Sep 17 00:00:00 2001 From: Jason Short Date: Sat, 10 Mar 2012 14:17:16 -0800 Subject: [PATCH 135/178] ACM: Added Loiter_D for tuning as #23 --- ArduCopter/defines.h | 1 + 1 file changed, 1 insertion(+) diff --git a/ArduCopter/defines.h b/ArduCopter/defines.h index 9b48c98789..c0645ead8a 100644 --- a/ArduCopter/defines.h +++ b/ArduCopter/defines.h @@ -170,6 +170,7 @@ #define CH6_NAV_I 20 #define CH6_LOITER_RATE_P 22 +#define CH6_LOITER_RATE_D 23 // nav byte mask From 62c2aa49245f0b3fee4dd0163edad86ba9d4b086 Mon Sep 17 00:00:00 2001 From: Jason Short Date: Sat, 10 Mar 2012 14:17:57 -0800 Subject: [PATCH 136/178] ACM: Added Loiter D tuning --- ArduCopter/ArduCopter.pde | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/ArduCopter/ArduCopter.pde b/ArduCopter/ArduCopter.pde index f0af3b4959..4c48728556 100644 --- a/ArduCopter/ArduCopter.pde +++ b/ArduCopter/ArduCopter.pde @@ -2079,6 +2079,11 @@ static void tuning(){ g.pid_loiter_rate_lat.kP(tuning_value); break; + case CH6_LOITER_RATE_D: + g.pid_loiter_rate_lon.kD(tuning_value); + g.pid_loiter_rate_lat.kD(tuning_value); + break; + case CH6_NAV_I: g.pid_nav_lat.kI(tuning_value); g.pid_nav_lon.kI(tuning_value); From 289c64c0b9173adbf600c2ae8b7121a833d90edf Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 10 Mar 2012 13:44:36 +1100 Subject: [PATCH 137/178] Math: added vector3.rotate() and matrix3.rotation() methods these operate on a "enum Rotation" which defines a set of standard rotations. These are much faster than our previous method, plus use less memory --- libraries/AP_Math/AP_Math.h | 6 ++ libraries/AP_Math/matrix3.cpp | 98 +++++++++++++++++++++++++++++ libraries/AP_Math/matrix3.h | 3 + libraries/AP_Math/rotations.h | 39 ++++++++++++ libraries/AP_Math/vector3.cpp | 114 ++++++++++++++++++++++++++++++++++ libraries/AP_Math/vector3.h | 3 + 6 files changed, 263 insertions(+) create mode 100644 libraries/AP_Math/matrix3.cpp create mode 100644 libraries/AP_Math/rotations.h create mode 100644 libraries/AP_Math/vector3.cpp diff --git a/libraries/AP_Math/AP_Math.h b/libraries/AP_Math/AP_Math.h index c2a1b89af3..22de694877 100644 --- a/libraries/AP_Math/AP_Math.h +++ b/libraries/AP_Math/AP_Math.h @@ -1,9 +1,13 @@ // -*- tab-width: 4; Mode: C++; c-basic-offset: 4; indent-tabs-mode: t -*- +#ifndef AP_MATH_H +#define AP_MATH_H + // Assorted useful math operations for ArduPilot(Mega) #include #include +#include "rotations.h" #include "vector2.h" #include "vector3.h" #include "matrix3.h" @@ -38,3 +42,5 @@ void quaternion_to_rotation_matrix(const Quaternion &q, Matrix3f &m); // convert a vector in earth frame to a vector in body frame, // assuming body current rotation is given by a quaternion void quaternion_earth_to_body(const Quaternion &q, Vector3f &v); + +#endif diff --git a/libraries/AP_Math/matrix3.cpp b/libraries/AP_Math/matrix3.cpp new file mode 100644 index 0000000000..d50419f332 --- /dev/null +++ b/libraries/AP_Math/matrix3.cpp @@ -0,0 +1,98 @@ +/// -*- tab-width: 4; Mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*- +/* + * matrix3.cpp + * Copyright (C) Andrew Tridgell 2012 + * + * This file is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This file is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + */ + +#include "AP_Math.h" + +#define HALF_SQRT_2 0.70710678118654757 + +#define MATRIX_ROTATION_NONE Matrix3f(1, 0, 0, 0, 1, 0, 0 ,0, 1) +#define MATRIX_ROTATION_YAW_45 Matrix3f(HALF_SQRT_2, -HALF_SQRT_2, 0, HALF_SQRT_2, HALF_SQRT_2, 0, 0, 0, 1) +#define MATRIX_ROTATION_YAW_90 Matrix3f(0, -1, 0, 1, 0, 0, 0, 0, 1) +#define MATRIX_ROTATION_YAW_135 Matrix3f(-HALF_SQRT_2, -HALF_SQRT_2, 0, HALF_SQRT_2, -HALF_SQRT_2, 0, 0, 0, 1) +#define MATRIX_ROTATION_YAW_180 Matrix3f(-1, 0, 0, 0, -1, 0, 0, 0, 1) +#define MATRIX_ROTATION_YAW_225 Matrix3f(-HALF_SQRT_2, HALF_SQRT_2, 0, -HALF_SQRT_2, -HALF_SQRT_2, 0, 0, 0, 1) +#define MATRIX_ROTATION_YAW_270 Matrix3f(0, 1, 0, -1, 0, 0, 0, 0, 1) +#define MATRIX_ROTATION_YAW_315 Matrix3f(HALF_SQRT_2, HALF_SQRT_2, 0, -HALF_SQRT_2, HALF_SQRT_2, 0, 0, 0, 1) +#define MATRIX_ROTATION_ROLL_180 Matrix3f(1, 0, 0, 0, -1, 0, 0, 0, -1) +#define MATRIX_ROTATION_ROLL_180_YAW_45 Matrix3f(HALF_SQRT_2, HALF_SQRT_2, 0, HALF_SQRT_2, -HALF_SQRT_2, 0, 0, 0, -1) +#define MATRIX_ROTATION_ROLL_180_YAW_90 Matrix3f(0, 1, 0, 1, 0, 0, 0, 0, -1) +#define MATRIX_ROTATION_ROLL_180_YAW_135 Matrix3f(-HALF_SQRT_2, HALF_SQRT_2, 0, HALF_SQRT_2, HALF_SQRT_2, 0, 0, 0, -1) +#define MATRIX_ROTATION_PITCH_180 Matrix3f(-1, 0, 0, 0, 1, 0, 0, 0, -1) +#define MATRIX_ROTATION_ROLL_180_YAW_225 Matrix3f(-HALF_SQRT_2, -HALF_SQRT_2, 0, -HALF_SQRT_2, HALF_SQRT_2, 0, 0, 0, -1) +#define MATRIX_ROTATION_ROLL_180_YAW_270 Matrix3f(0, -1, 0, -1, 0, 0, 0, 0, -1) +#define MATRIX_ROTATION_ROLL_180_YAW_315 Matrix3f(HALF_SQRT_2, -HALF_SQRT_2, 0, -HALF_SQRT_2, -HALF_SQRT_2, 0, 0, 0, -1) + +// fill in a matrix with a standard rotation +template +void Matrix3::rotation(enum Rotation r) +{ + switch (r) { + case ROTATION_NONE: + *this = MATRIX_ROTATION_NONE; + break; + case ROTATION_YAW_45: + *this = MATRIX_ROTATION_YAW_45; + break; + case ROTATION_YAW_90: + *this = MATRIX_ROTATION_YAW_90; + break; + case ROTATION_YAW_135: + *this = MATRIX_ROTATION_YAW_135; + break; + case ROTATION_YAW_180: + *this = MATRIX_ROTATION_YAW_180; + break; + case ROTATION_YAW_225: + *this = MATRIX_ROTATION_YAW_225; + break; + case ROTATION_YAW_270: + *this = MATRIX_ROTATION_YAW_270; + break; + case ROTATION_YAW_315: + *this = MATRIX_ROTATION_YAW_315; + break; + case ROTATION_ROLL_180: + *this = MATRIX_ROTATION_ROLL_180; + break; + case ROTATION_ROLL_180_YAW_45: + *this = MATRIX_ROTATION_ROLL_180_YAW_45; + break; + case ROTATION_ROLL_180_YAW_90: + *this = MATRIX_ROTATION_ROLL_180_YAW_90; + break; + case ROTATION_ROLL_180_YAW_135: + *this = MATRIX_ROTATION_ROLL_180_YAW_135; + break; + case ROTATION_PITCH_180: + *this = MATRIX_ROTATION_PITCH_180; + break; + case ROTATION_ROLL_180_YAW_225: + *this = MATRIX_ROTATION_ROLL_180_YAW_225; + break; + case ROTATION_ROLL_180_YAW_270: + *this = MATRIX_ROTATION_ROLL_180_YAW_270; + break; + case ROTATION_ROLL_180_YAW_315: + *this = MATRIX_ROTATION_ROLL_180_YAW_315; + break; + } +} + +// only define for float +template void Matrix3::rotation(enum Rotation); diff --git a/libraries/AP_Math/matrix3.h b/libraries/AP_Math/matrix3.h index 0df2ae7bce..561c56a64e 100644 --- a/libraries/AP_Math/matrix3.h +++ b/libraries/AP_Math/matrix3.h @@ -128,6 +128,9 @@ public: bool is_nan(void) { return a.is_nan() || b.is_nan() || c.is_nan(); } + // fill in the matrix with a standard rotation + void rotation(enum Rotation rotation); + }; typedef Matrix3 Matrix3i; diff --git a/libraries/AP_Math/rotations.h b/libraries/AP_Math/rotations.h new file mode 100644 index 0000000000..839119b9e8 --- /dev/null +++ b/libraries/AP_Math/rotations.h @@ -0,0 +1,39 @@ +/// -*- tab-width: 4; Mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*- +/* + * rotations.h + * Copyright (C) Andrew Tridgell 2012 + * + * This file is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This file is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + */ + +// these rotation values are stored to EEPROM, so be careful not to +// change the numbering of any existing entry when adding a new entry. +enum Rotation { + ROTATION_NONE = 0, + ROTATION_YAW_45, + ROTATION_YAW_90, + ROTATION_YAW_135, + ROTATION_YAW_180, + ROTATION_YAW_225, + ROTATION_YAW_270, + ROTATION_YAW_315, + ROTATION_ROLL_180, + ROTATION_ROLL_180_YAW_45, + ROTATION_ROLL_180_YAW_90, + ROTATION_ROLL_180_YAW_135, + ROTATION_PITCH_180, + ROTATION_ROLL_180_YAW_225, + ROTATION_ROLL_180_YAW_270, + ROTATION_ROLL_180_YAW_315 +}; diff --git a/libraries/AP_Math/vector3.cpp b/libraries/AP_Math/vector3.cpp new file mode 100644 index 0000000000..9e0be0630c --- /dev/null +++ b/libraries/AP_Math/vector3.cpp @@ -0,0 +1,114 @@ +/// -*- tab-width: 4; Mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*- +/* + * vector3.cpp + * Copyright (C) Andrew Tridgell 2012 + * + * This file is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This file is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + */ + +#include "AP_Math.h" + +#define HALF_SQRT_2 0.70710678118654757 + +// rotate a vector by a standard rotation, attempting +// to use the minimum number of floating point operations +template +void Vector3::rotate(enum Rotation rotation) +{ + T tmp; + switch (rotation) { + case ROTATION_NONE: + return; + case ROTATION_YAW_45: { + tmp = HALF_SQRT_2*(x - y); + y = HALF_SQRT_2*(x + y); + x = tmp; + return; + } + case ROTATION_YAW_90: { + tmp = x; x = -y; y = tmp; + return; + } + case ROTATION_YAW_135: { + tmp = -HALF_SQRT_2*(x + y); + y = HALF_SQRT_2*(x - y); + x = tmp; + return; + } + case ROTATION_YAW_180: + x = -x; y = -y; + return; + case ROTATION_YAW_225: { + tmp = HALF_SQRT_2*(y - x); + y = -HALF_SQRT_2*(x + y); + x = tmp; + return; + } + case ROTATION_YAW_270: { + tmp = x; x = y; y = -tmp; + return; + } + case ROTATION_YAW_315: { + tmp = HALF_SQRT_2*(x + y); + y = HALF_SQRT_2*(y - x); + x = tmp; + return; + } + case ROTATION_ROLL_180: { + y = -y; z = -z; + return; + } + case ROTATION_ROLL_180_YAW_45: { + tmp = HALF_SQRT_2*(x + y); + y = HALF_SQRT_2*(x - y); + x = tmp; z = -z; + return; + } + case ROTATION_ROLL_180_YAW_90: { + tmp = x; x = y; y = tmp; z = -z; + return; + } + case ROTATION_ROLL_180_YAW_135: { + tmp = HALF_SQRT_2*(y - x); + y = HALF_SQRT_2*(y + x); + x = tmp; z = -z; + return; + } + case ROTATION_PITCH_180: { + x = -x; z = -z; + return; + } + case ROTATION_ROLL_180_YAW_225: { + tmp = -HALF_SQRT_2*(x + y); + y = HALF_SQRT_2*(y - x); + x = tmp; z = -z; + return; + } + case ROTATION_ROLL_180_YAW_270: { + tmp = x; x = -y; y = -tmp; z = -z; + return; + } + case ROTATION_ROLL_180_YAW_315: { + tmp = HALF_SQRT_2*(x - y); + y = -HALF_SQRT_2*(x + y); + x = tmp; z = -z; + return; + } + } +} + +// only define for signed numbers +template void Vector3::rotate(enum Rotation); +template void Vector3::rotate(enum Rotation); +template void Vector3::rotate(enum Rotation); diff --git a/libraries/AP_Math/vector3.h b/libraries/AP_Math/vector3.h index 27dbbcb57e..acabf1776f 100644 --- a/libraries/AP_Math/vector3.h +++ b/libraries/AP_Math/vector3.h @@ -185,6 +185,9 @@ public: bool is_inf(void) { return isinf(x) || isinf(y) || isinf(z); } + // rotate by a standard rotation + void rotate(enum Rotation rotation); + }; typedef Vector3 Vector3i; From 55aa43a70d85ea2b8d1d6ad5b2f69002651d95ff Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 10 Mar 2012 13:45:05 +1100 Subject: [PATCH 138/178] Math: added a test suite for the new rotation methods --- libraries/AP_Math/examples/rotations/Makefile | 4 + .../AP_Math/examples/rotations/rotations.pde | 180 ++++++++++++++++++ 2 files changed, 184 insertions(+) create mode 100644 libraries/AP_Math/examples/rotations/Makefile create mode 100644 libraries/AP_Math/examples/rotations/rotations.pde diff --git a/libraries/AP_Math/examples/rotations/Makefile b/libraries/AP_Math/examples/rotations/Makefile new file mode 100644 index 0000000000..fcdc8ff8fe --- /dev/null +++ b/libraries/AP_Math/examples/rotations/Makefile @@ -0,0 +1,4 @@ +include ../../../AP_Common/Arduino.mk + +sitl: + make -f ../../../../libraries/Desktop/Desktop.mk diff --git a/libraries/AP_Math/examples/rotations/rotations.pde b/libraries/AP_Math/examples/rotations/rotations.pde new file mode 100644 index 0000000000..7095446794 --- /dev/null +++ b/libraries/AP_Math/examples/rotations/rotations.pde @@ -0,0 +1,180 @@ +/// -*- tab-width: 4; Mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*- +// +// Unit tests for the AP_Math rotations code +// + +#include +#include +#include + +FastSerialPort(Serial, 0); + +#ifdef DESKTOP_BUILD +// all of this is needed to build with SITL +#include +#include +#include +#include +#include +#include +#include +#include +#include +Arduino_Mega_ISR_Registry isr_registry; +AP_Baro_BMP085_HIL barometer; +AP_Compass_HIL compass; +#endif + + +// standard rotation matrices (these are the originals from the old code) +#define MATRIX_ROTATION_NONE Matrix3f(1, 0, 0, 0, 1, 0, 0 ,0, 1) +#define MATRIX_ROTATION_YAW_45 Matrix3f(0.70710678, -0.70710678, 0, 0.70710678, 0.70710678, 0, 0, 0, 1) +#define MATRIX_ROTATION_YAW_90 Matrix3f(0, -1, 0, 1, 0, 0, 0, 0, 1) +#define MATRIX_ROTATION_YAW_135 Matrix3f(-0.70710678, -0.70710678, 0, 0.70710678, -0.70710678, 0, 0, 0, 1) +#define MATRIX_ROTATION_YAW_180 Matrix3f(-1, 0, 0, 0, -1, 0, 0, 0, 1) +#define MATRIX_ROTATION_YAW_225 Matrix3f(-0.70710678, 0.70710678, 0, -0.70710678, -0.70710678, 0, 0, 0, 1) +#define MATRIX_ROTATION_YAW_270 Matrix3f(0, 1, 0, -1, 0, 0, 0, 0, 1) +#define MATRIX_ROTATION_YAW_315 Matrix3f(0.70710678, 0.70710678, 0, -0.70710678, 0.70710678, 0, 0, 0, 1) +#define MATRIX_ROTATION_ROLL_180 Matrix3f(1, 0, 0, 0, -1, 0, 0, 0, -1) +#define MATRIX_ROTATION_ROLL_180_YAW_45 Matrix3f(0.70710678, 0.70710678, 0, 0.70710678, -0.70710678, 0, 0, 0, -1) +#define MATRIX_ROTATION_ROLL_180_YAW_90 Matrix3f(0, 1, 0, 1, 0, 0, 0, 0, -1) +#define MATRIX_ROTATION_ROLL_180_YAW_135 Matrix3f(-0.70710678, 0.70710678, 0, 0.70710678, 0.70710678, 0, 0, 0, -1) +#define MATRIX_ROTATION_PITCH_180 Matrix3f(-1, 0, 0, 0, 1, 0, 0, 0, -1) +#define MATRIX_ROTATION_ROLL_180_YAW_225 Matrix3f(-0.70710678, -0.70710678, 0, -0.70710678, 0.70710678, 0, 0, 0, -1) +#define MATRIX_ROTATION_ROLL_180_YAW_270 Matrix3f(0, -1, 0, -1, 0, 0, 0, 0, -1) +#define MATRIX_ROTATION_ROLL_180_YAW_315 Matrix3f(0.70710678, -0.70710678, 0, -0.70710678, -0.70710678, 0, 0, 0, -1) + +static void print_matrix(Matrix3f &m) +{ + Serial.printf("[%.2f %.2f %.2f] [%.2f %.2f %.2f] [%.2f %.2f %.2f]\n", + m.a.x, m.a.y, m.a.z, + m.b.x, m.b.y, m.b.z, + m.c.x, m.c.y, m.c.z); +} + +// test one matrix +static void test_matrix(enum Rotation rotation, Matrix3f m) +{ + Matrix3f m2, diff; + const float accuracy = 1.0e-6; + m2.rotation(rotation); + diff = (m - m2); + if (diff.a.length() > accuracy || + diff.b.length() > accuracy || + diff.c.length() > accuracy) { + Serial.printf("rotation matrix %u incorrect\n", (unsigned)rotation); + print_matrix(m); + print_matrix(m2); + } +} + +// test generation of rotation matrices +static void test_matrices(void) +{ + Serial.println("testing rotation matrices\n"); + test_matrix(ROTATION_NONE, MATRIX_ROTATION_NONE); + test_matrix(ROTATION_YAW_45, MATRIX_ROTATION_YAW_45); + test_matrix(ROTATION_YAW_90, MATRIX_ROTATION_YAW_90); + test_matrix(ROTATION_YAW_135, MATRIX_ROTATION_YAW_135); + test_matrix(ROTATION_YAW_180, MATRIX_ROTATION_YAW_180); + test_matrix(ROTATION_YAW_225, MATRIX_ROTATION_YAW_225); + test_matrix(ROTATION_YAW_270, MATRIX_ROTATION_YAW_270); + test_matrix(ROTATION_YAW_315, MATRIX_ROTATION_YAW_315); + test_matrix(ROTATION_ROLL_180, MATRIX_ROTATION_ROLL_180); + test_matrix(ROTATION_ROLL_180_YAW_45, MATRIX_ROTATION_ROLL_180_YAW_45); + test_matrix(ROTATION_ROLL_180_YAW_90, MATRIX_ROTATION_ROLL_180_YAW_90); + test_matrix(ROTATION_ROLL_180_YAW_135, MATRIX_ROTATION_ROLL_180_YAW_135); + test_matrix(ROTATION_PITCH_180, MATRIX_ROTATION_PITCH_180); + test_matrix(ROTATION_ROLL_180_YAW_225, MATRIX_ROTATION_ROLL_180_YAW_225); + test_matrix(ROTATION_ROLL_180_YAW_270, MATRIX_ROTATION_ROLL_180_YAW_270); + test_matrix(ROTATION_ROLL_180_YAW_315, MATRIX_ROTATION_ROLL_180_YAW_315); +} + +// test rotation of vectors +static void test_vector(enum Rotation rotation, Vector3f v1, bool show=true) +{ + Vector3f v2, diff; + Matrix3f m; + v2 = v1; + m.rotation(rotation); + v1.rotate(rotation); + v2 = m * v2; + diff = v1 - v2; + if (diff.length() > 1.0e-6) { + Serial.printf("rotation vector %u incorrect\n", (unsigned)rotation); + Serial.printf("%u %f %f %f\n", + (unsigned)rotation, + v2.x, v2.y, v2.z); + } + if (show) { + Serial.printf("%u %f %f %f\n", + (unsigned)rotation, + v1.x, v1.y, v1.z); + } +} + +// generate a random float between -1 and 1 +static float rand_num(void) +{ + float ret = ((unsigned)random()) % 2000000; + return (ret - 1.0e6) / 1.0e6; +} + +// test rotation of vectors +static void test_vector(enum Rotation rotation) +{ + uint8_t i; + + Vector3f v1; + v1.x = 1; + v1.y = 2; + v1.z = 3; + test_vector(rotation, v1); + + for (i=0; i<10; i++) { + v1.x = rand_num(); + v1.y = rand_num(); + v1.z = rand_num(); + test_vector(rotation, v1, false); + } +} + +// test rotation of vectors +static void test_vectors(void) +{ + Serial.println("testing rotation of vectors\n"); + test_vector(ROTATION_NONE); + test_vector(ROTATION_YAW_45); + test_vector(ROTATION_YAW_90); + test_vector(ROTATION_YAW_135); + test_vector(ROTATION_YAW_180); + test_vector(ROTATION_YAW_225); + test_vector(ROTATION_YAW_270); + test_vector(ROTATION_YAW_315); + test_vector(ROTATION_ROLL_180); + test_vector(ROTATION_ROLL_180_YAW_45); + test_vector(ROTATION_ROLL_180_YAW_90); + test_vector(ROTATION_ROLL_180_YAW_135); + test_vector(ROTATION_PITCH_180); + test_vector(ROTATION_ROLL_180_YAW_225); + test_vector(ROTATION_ROLL_180_YAW_270); + test_vector(ROTATION_ROLL_180_YAW_315); +} + + +/* + rotation tests + */ +void setup(void) +{ + Serial.begin(115200); + Serial.println("rotation unit tests\n"); + test_matrices(); + test_vectors(); + Serial.println("rotation unit tests done\n"); +} + +void +loop(void) +{ +} From cb96dd975f8098de20095fe4a4296b4379978511 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 10 Mar 2012 13:45:35 +1100 Subject: [PATCH 139/178] Compass: update the compass driver to use the new vector.rotate() method --- libraries/AP_Compass/AP_Compass_HMC5843.cpp | 38 ++++++--------------- libraries/AP_Compass/AP_Compass_HMC5843.h | 2 +- libraries/AP_Compass/Compass.cpp | 11 +++--- libraries/AP_Compass/Compass.h | 22 ++---------- 4 files changed, 18 insertions(+), 55 deletions(-) diff --git a/libraries/AP_Compass/AP_Compass_HMC5843.cpp b/libraries/AP_Compass/AP_Compass_HMC5843.cpp index a34bf8c424..a4fb928ee4 100644 --- a/libraries/AP_Compass/AP_Compass_HMC5843.cpp +++ b/libraries/AP_Compass/AP_Compass_HMC5843.cpp @@ -71,16 +71,6 @@ bool AP_Compass_HMC5843::write_register(uint8_t address, byte value) return true; } -/* - the 5883L has a different orientation to the 5843. This allows us to - use a single MAG_ORIENTATION for both - */ -static void rotate_for_5883L(AP_Matrix3f *_orientation_matrix) -{ - _orientation_matrix->set_and_save(_orientation_matrix->get() * Matrix3f(ROTATION_YAW_90)); -} - - // Read Sensor data bool AP_Compass_HMC5843::read_raw() { @@ -148,20 +138,11 @@ AP_Compass_HMC5843::init() } if ( _base_config == (SampleAveraging_8<<5 | DataOutputRate_75HZ<<2 | NormalOperation)) { // a 5883L supports the sample averaging config - int old_product_id = product_id; - product_id = AP_COMPASS_TYPE_HMC5883L; calibration_gain = 0x60; expected_x = 766; expected_yz = 713; gain_multiple = 660.0 / 1090; // adjustment for runtime vs calibration gain - - if (old_product_id != product_id) { - /* now we know the compass type we need to rotate the - * orientation matrix that we were given - */ - rotate_for_5883L(&_orientation_matrix); - } } else if (_base_config == (NormalOperation | DataOutputRate_75HZ<<2)) { product_id = AP_COMPASS_TYPE_HMC5843; } else { @@ -280,11 +261,15 @@ bool AP_Compass_HMC5843::read() mag_z *= calibration[2]; last_update = micros(); // record time of update - // rotate and offset the magnetometer values - // XXX this could well be done in common code... - Vector3f rot_mag = _orientation_matrix.get() * Vector3f(mag_x,mag_y,mag_z); - rot_mag = rot_mag + _offset.get(); + // rotate to the desired orientation + Vector3f rot_mag = Vector3f(mag_x,mag_y,mag_z); + rot_mag.rotate((enum Rotation)_orientation.get()); + if (product_id == AP_COMPASS_TYPE_HMC5883L) { + rot_mag.rotate(ROTATION_YAW_90); + } + + rot_mag += _offset.get(); mag_x = rot_mag.x; mag_y = rot_mag.y; mag_z = rot_mag.z; @@ -295,10 +280,7 @@ bool AP_Compass_HMC5843::read() // set orientation void -AP_Compass_HMC5843::set_orientation(const Matrix3f &rotation_matrix) +AP_Compass_HMC5843::set_orientation(enum Rotation rotation) { - _orientation_matrix.set_and_save(rotation_matrix); - if (product_id == AP_COMPASS_TYPE_HMC5883L) { - rotate_for_5883L(&_orientation_matrix); - } + _orientation.set_and_save(rotation); } diff --git a/libraries/AP_Compass/AP_Compass_HMC5843.h b/libraries/AP_Compass/AP_Compass_HMC5843.h index d419686f08..b525b2dce5 100644 --- a/libraries/AP_Compass/AP_Compass_HMC5843.h +++ b/libraries/AP_Compass/AP_Compass_HMC5843.h @@ -60,7 +60,7 @@ class AP_Compass_HMC5843 : public Compass AP_Compass_HMC5843() : Compass() {} virtual bool init(void); virtual bool read(void); - virtual void set_orientation(const Matrix3f &rotation_matrix); + virtual void set_orientation(enum Rotation rotation); }; #endif diff --git a/libraries/AP_Compass/Compass.cpp b/libraries/AP_Compass/Compass.cpp index 4e06ac6d12..458d6edc4b 100644 --- a/libraries/AP_Compass/Compass.cpp +++ b/libraries/AP_Compass/Compass.cpp @@ -2,11 +2,12 @@ #include "Compass.h" const AP_Param::GroupInfo Compass::var_info[] PROGMEM = { - AP_GROUPINFO("ORIENT", 0, Compass, _orientation_matrix), + // index 0 was used for the old orientation matrix AP_GROUPINFO("OFS", 1, Compass, _offset), AP_GROUPINFO("DEC", 2, Compass, _declination), AP_GROUPINFO("LEARN", 3, Compass, _learn), // true if learning calibration AP_GROUPINFO("USE", 4, Compass, _use_for_yaw), // true if used for DCM yaw + AP_GROUPINFO("ORIENT", 5, Compass, _orientation), AP_GROUPEND }; @@ -22,9 +23,7 @@ Compass::Compass(void) : _null_enable(false), _null_init_done(false) { - // Default the orientation matrix to none - will be overridden at group load time - // if an orientation has previously been saved. - _orientation_matrix.set(ROTATION_NONE); + _orientation.set(ROTATION_NONE); } // Default init method, just returns success. @@ -36,9 +35,9 @@ Compass::init() } void -Compass::set_orientation(const Matrix3f &rotation_matrix) +Compass::set_orientation(enum Rotation rotation) { - _orientation_matrix.set_and_save(rotation_matrix); + _orientation.set_and_save(rotation); } void diff --git a/libraries/AP_Compass/Compass.h b/libraries/AP_Compass/Compass.h index cc3bc5e704..4ded933688 100644 --- a/libraries/AP_Compass/Compass.h +++ b/libraries/AP_Compass/Compass.h @@ -12,24 +12,6 @@ #define AP_COMPASS_TYPE_HMC5843 0x02 #define AP_COMPASS_TYPE_HMC5883L 0x03 -// standard rotation matrices -#define ROTATION_NONE Matrix3f(1, 0, 0, 0, 1, 0, 0 ,0, 1) -#define ROTATION_YAW_45 Matrix3f(0.70710678, -0.70710678, 0, 0.70710678, 0.70710678, 0, 0, 0, 1) -#define ROTATION_YAW_90 Matrix3f(0, -1, 0, 1, 0, 0, 0, 0, 1) -#define ROTATION_YAW_135 Matrix3f(-0.70710678, -0.70710678, 0, 0.70710678, -0.70710678, 0, 0, 0, 1) -#define ROTATION_YAW_180 Matrix3f(-1, 0, 0, 0, -1, 0, 0, 0, 1) -#define ROTATION_YAW_225 Matrix3f(-0.70710678, 0.70710678, 0, -0.70710678, -0.70710678, 0, 0, 0, 1) -#define ROTATION_YAW_270 Matrix3f(0, 1, 0, -1, 0, 0, 0, 0, 1) -#define ROTATION_YAW_315 Matrix3f(0.70710678, 0.70710678, 0, -0.70710678, 0.70710678, 0, 0, 0, 1) -#define ROTATION_ROLL_180 Matrix3f(1, 0, 0, 0, -1, 0, 0, 0, -1) -#define ROTATION_ROLL_180_YAW_45 Matrix3f(0.70710678, 0.70710678, 0, 0.70710678, -0.70710678, 0, 0, 0, -1) -#define ROTATION_ROLL_180_YAW_90 Matrix3f(0, 1, 0, 1, 0, 0, 0, 0, -1) -#define ROTATION_ROLL_180_YAW_135 Matrix3f(-0.70710678, 0.70710678, 0, 0.70710678, 0.70710678, 0, 0, 0, -1) -#define ROTATION_PITCH_180 Matrix3f(-1, 0, 0, 0, 1, 0, 0, 0, -1) -#define ROTATION_ROLL_180_YAW_225 Matrix3f(-0.70710678, -0.70710678, 0, -0.70710678, 0.70710678, 0, 0, 0, -1) -#define ROTATION_ROLL_180_YAW_270 Matrix3f(0, -1, 0, -1, 0, 0, 0, 0, -1) -#define ROTATION_ROLL_180_YAW_315 Matrix3f(0.70710678, -0.70710678, 0, -0.70710678, -0.70710678, 0, 0, 0, -1) - class Compass { public: @@ -79,7 +61,7 @@ public: /// @param rotation_matrix Rotation matrix to transform magnetometer readings /// to the body frame. /// - virtual void set_orientation(const Matrix3f &rotation_matrix); + virtual void set_orientation(enum Rotation rotation); /// Sets the compass offset x/y/z values. /// @@ -137,7 +119,7 @@ public: static const struct AP_Param::GroupInfo var_info[]; protected: - AP_Matrix3f _orientation_matrix; + AP_Int8 _orientation; AP_Vector3f _offset; AP_Float _declination; AP_Int8 _learn; /// Date: Sat, 10 Mar 2012 13:51:28 +1100 Subject: [PATCH 140/178] OpticalFlow: fixed line endings this library was a mixture of dos and unix line endings, which makes for very messy editing --- libraries/AP_OpticalFlow/AP_OpticalFlow.cpp | 204 ++-- libraries/AP_OpticalFlow/AP_OpticalFlow.h | 142 +-- .../AP_OpticalFlow_ADNS3080.cpp | 942 +++++++++--------- .../AP_OpticalFlow/AP_OpticalFlow_ADNS3080.h | 286 +++--- 4 files changed, 787 insertions(+), 787 deletions(-) diff --git a/libraries/AP_OpticalFlow/AP_OpticalFlow.cpp b/libraries/AP_OpticalFlow/AP_OpticalFlow.cpp index 00fb2eca2c..1aeed584c0 100644 --- a/libraries/AP_OpticalFlow/AP_OpticalFlow.cpp +++ b/libraries/AP_OpticalFlow/AP_OpticalFlow.cpp @@ -1,109 +1,109 @@ -/* - ADC.cpp - Analog Digital Converter Base Class for Ardupilot Mega - Code by James Goppert. DIYDrones.com - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. -*/ - -#include "AP_OpticalFlow.h" - -#define FORTYFIVE_DEGREES 0.78539816 - -AP_OpticalFlow* AP_OpticalFlow::_sensor = NULL; // pointer to the last instantiated optical flow sensor. Will be turned into a table if we ever add support for more than one sensor - -// init - initCommAPI parameter controls whether I2C/SPI interface is initialised (set to false if other devices are on the I2C/SPI bus and have already initialised the interface) -bool -AP_OpticalFlow::init(bool initCommAPI) -{ - _orientation_matrix = Matrix3f(1, 0, 0, 0, 1, 0, 0, 0, 1); - update_conversion_factors(); - return true; // just return true by default -} - -// set_orientation - Rotation vector to transform sensor readings to the body frame. -void -AP_OpticalFlow::set_orientation(const Matrix3f &rotation_matrix) -{ - _orientation_matrix = rotation_matrix; -} - -// read value from the sensor. Should be overridden by derived class -bool -AP_OpticalFlow::update() -{ +/* + ADC.cpp - Analog Digital Converter Base Class for Ardupilot Mega + Code by James Goppert. DIYDrones.com + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. +*/ + +#include "AP_OpticalFlow.h" + +#define FORTYFIVE_DEGREES 0.78539816 + +AP_OpticalFlow* AP_OpticalFlow::_sensor = NULL; // pointer to the last instantiated optical flow sensor. Will be turned into a table if we ever add support for more than one sensor + +// init - initCommAPI parameter controls whether I2C/SPI interface is initialised (set to false if other devices are on the I2C/SPI bus and have already initialised the interface) +bool +AP_OpticalFlow::init(bool initCommAPI) +{ + _orientation_matrix = Matrix3f(1, 0, 0, 0, 1, 0, 0, 0, 1); + update_conversion_factors(); + return true; // just return true by default +} + +// set_orientation - Rotation vector to transform sensor readings to the body frame. +void +AP_OpticalFlow::set_orientation(const Matrix3f &rotation_matrix) +{ + _orientation_matrix = rotation_matrix; +} + +// read value from the sensor. Should be overridden by derived class +bool +AP_OpticalFlow::update() +{ return true; -} - -// reads a value from the sensor (will be sensor specific) -byte -AP_OpticalFlow::read_register(byte address) -{ +} + +// reads a value from the sensor (will be sensor specific) +byte +AP_OpticalFlow::read_register(byte address) +{ return 0; -} - -// writes a value to one of the sensor's register (will be sensor specific) -void -AP_OpticalFlow::write_register(byte address, byte value) -{ -} - -// rotate raw values to arrive at final x,y,dx and dy values -void -AP_OpticalFlow::apply_orientation_matrix() -{ - Vector3f rot_vector; - - // next rotate dx and dy - rot_vector = _orientation_matrix * Vector3f(raw_dx, raw_dy, 0); - dx = rot_vector.x; - dy = rot_vector.y; - - // add rotated values to totals (perhaps this is pointless as we need to take into account yaw, roll, pitch) - x += dx; - y += dy; -} - -// updatse conversion factors that are dependent upon field_of_view -void -AP_OpticalFlow::update_conversion_factors() -{ - conv_factor = (1.0 / (float)(num_pixels * scaler)) * 2.0 * tan(field_of_view / 2.0); // multiply this number by altitude and pixel change to get horizontal move (in same units as altitude) - // 0.00615 - radians_to_pixels = (num_pixels * scaler) / field_of_view; - // 162.99 -} - -// updates internal lon and lat with estimation based on optical flow -void -AP_OpticalFlow::update_position(float roll, float pitch, float cos_yaw_x, float sin_yaw_y, float altitude) -{ - float diff_roll = roll - _last_roll; - float diff_pitch = pitch - _last_pitch; - - // only update position if surface quality is good and angle is not over 45 degrees - if( surface_quality >= 10 && fabs(roll) <= FORTYFIVE_DEGREES && fabs(pitch) <= FORTYFIVE_DEGREES ) { - altitude = max(altitude, 0); - // calculate expected x,y diff due to roll and pitch change - exp_change_x = diff_roll * radians_to_pixels; - exp_change_y = -diff_pitch * radians_to_pixels; - - // real estimated raw change from mouse - change_x = dx - exp_change_x; - change_y = dy - exp_change_y; - +} + +// writes a value to one of the sensor's register (will be sensor specific) +void +AP_OpticalFlow::write_register(byte address, byte value) +{ +} + +// rotate raw values to arrive at final x,y,dx and dy values +void +AP_OpticalFlow::apply_orientation_matrix() +{ + Vector3f rot_vector; + + // next rotate dx and dy + rot_vector = _orientation_matrix * Vector3f(raw_dx, raw_dy, 0); + dx = rot_vector.x; + dy = rot_vector.y; + + // add rotated values to totals (perhaps this is pointless as we need to take into account yaw, roll, pitch) + x += dx; + y += dy; +} + +// updatse conversion factors that are dependent upon field_of_view +void +AP_OpticalFlow::update_conversion_factors() +{ + conv_factor = (1.0 / (float)(num_pixels * scaler)) * 2.0 * tan(field_of_view / 2.0); // multiply this number by altitude and pixel change to get horizontal move (in same units as altitude) + // 0.00615 + radians_to_pixels = (num_pixels * scaler) / field_of_view; + // 162.99 +} + +// updates internal lon and lat with estimation based on optical flow +void +AP_OpticalFlow::update_position(float roll, float pitch, float cos_yaw_x, float sin_yaw_y, float altitude) +{ + float diff_roll = roll - _last_roll; + float diff_pitch = pitch - _last_pitch; + + // only update position if surface quality is good and angle is not over 45 degrees + if( surface_quality >= 10 && fabs(roll) <= FORTYFIVE_DEGREES && fabs(pitch) <= FORTYFIVE_DEGREES ) { + altitude = max(altitude, 0); + // calculate expected x,y diff due to roll and pitch change + exp_change_x = diff_roll * radians_to_pixels; + exp_change_y = -diff_pitch * radians_to_pixels; + + // real estimated raw change from mouse + change_x = dx - exp_change_x; + change_y = dy - exp_change_y; + float avg_altitude = (altitude + _last_altitude)*0.5; - // convert raw change to horizontal movement in cm - x_cm = -change_x * avg_altitude * conv_factor; // perhaps this altitude should actually be the distance to the ground? i.e. if we are very rolled over it should be longer? - y_cm = -change_y * avg_altitude * conv_factor; // for example if you are leaned over at 45 deg the ground will appear farther away and motion from opt flow sensor will be less - - // convert x/y movements into lon/lat movement - vlon = x_cm * sin_yaw_y + y_cm * cos_yaw_x; - vlat = y_cm * sin_yaw_y - x_cm * cos_yaw_x; - } + // convert raw change to horizontal movement in cm + x_cm = -change_x * avg_altitude * conv_factor; // perhaps this altitude should actually be the distance to the ground? i.e. if we are very rolled over it should be longer? + y_cm = -change_y * avg_altitude * conv_factor; // for example if you are leaned over at 45 deg the ground will appear farther away and motion from opt flow sensor will be less + + // convert x/y movements into lon/lat movement + vlon = x_cm * sin_yaw_y + y_cm * cos_yaw_x; + vlat = y_cm * sin_yaw_y - x_cm * cos_yaw_x; + } _last_altitude = altitude; _last_roll = roll; diff --git a/libraries/AP_OpticalFlow/AP_OpticalFlow.h b/libraries/AP_OpticalFlow/AP_OpticalFlow.h index 968de9cd49..5e6657fefe 100644 --- a/libraries/AP_OpticalFlow/AP_OpticalFlow.h +++ b/libraries/AP_OpticalFlow/AP_OpticalFlow.h @@ -1,74 +1,74 @@ -#ifndef AP_OPTICALFLOW_H -#define AP_OPTICALFLOW_H - -/* - AP_OpticalFlow.cpp - OpticalFlow Base Class for Ardupilot Mega - Code by Randy Mackay. DIYDrones.com - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - Methods: - init() : initializate sensor and library. - read : reads latest value from OpticalFlow and stores values in x,y, surface_quality parameter - read_register() : reads a value from the sensor (will be sensor specific) - write_register() : writes a value to one of the sensor's register (will be sensor specific) -*/ - -#include -#include -#include - -// standard rotation matrices -#define AP_OPTICALFLOW_ROTATION_NONE Matrix3f(1, 0, 0, 0, 1, 0, 0 ,0, 1) -#define AP_OPTICALFLOW_ROTATION_YAW_45 Matrix3f(0.70710678, -0.70710678, 0, 0.70710678, 0.70710678, 0, 0, 0, 1) -#define AP_OPTICALFLOW_ROTATION_YAW_90 Matrix3f(0, -1, 0, 1, 0, 0, 0, 0, 1) -#define AP_OPTICALFLOW_ROTATION_YAW_135 Matrix3f(-0.70710678, -0.70710678, 0, 0.70710678, -0.70710678, 0, 0, 0, 1) -#define AP_OPTICALFLOW_ROTATION_YAW_180 Matrix3f(-1, 0, 0, 0, -1, 0, 0, 0, 1) -#define AP_OPTICALFLOW_ROTATION_YAW_225 Matrix3f(-0.70710678, 0.70710678, 0, -0.70710678, -0.70710678, 0, 0, 0, 1) -#define AP_OPTICALFLOW_ROTATION_YAW_270 Matrix3f(0, 1, 0, -1, 0, 0, 0, 0, 1) -#define AP_OPTICALFLOW_ROTATION_YAW_315 Matrix3f(0.70710678, 0.70710678, 0, -0.70710678, 0.70710678, 0, 0, 0, 1) - -class AP_OpticalFlow -{ - public: - int raw_dx, raw_dy; // raw sensor change in x and y position (i.e. unrotated) - int surface_quality; // image quality (below 15 you really can't trust the x,y values returned) - int x,y; // total x,y position - int dx,dy; // rotated change in x and y position - float vlon, vlat; // position as offsets from original position - unsigned long last_update; // millis() time of last update - float field_of_view; // field of view in Radians - float scaler; // number returned from sensor when moved one pixel - int num_pixels; // number of pixels of resolution in the sensor - // temp variables - delete me! - float exp_change_x, exp_change_y; - float change_x, change_y; - float x_cm, y_cm; - - AP_OpticalFlow() { _sensor = this; }; - ~AP_OpticalFlow() { _sensor = NULL; }; - virtual bool init(bool initCommAPI = true); // parameter controls whether I2C/SPI interface is initialised (set to false if other devices are on the I2C/SPI bus and have already initialised the interface) - virtual byte read_register(byte address); - virtual void write_register(byte address, byte value); - virtual void set_orientation(const Matrix3f &rotation_matrix); // Rotation vector to transform sensor readings to the body frame. - virtual void set_field_of_view(const float fov) { field_of_view = fov; update_conversion_factors(); }; // sets field of view of sensor - static void read(uint32_t ) { if( _sensor != NULL ) _sensor->update(); }; // call to update all attached sensors - virtual bool update(); // read latest values from sensor and fill in x,y and totals. returns true on success - virtual void update_position(float roll, float pitch, float cos_yaw_x, float sin_yaw_y, float altitude); // updates internal lon and lat with estimation based on optical flow - -protected: - static AP_OpticalFlow *_sensor; // pointer to the last instantiated optical flow sensor. Will be turned into a table if we ever add support for more than one sensor - Matrix3f _orientation_matrix; - float conv_factor; // multiply this number by altitude and pixel change to get horizontal move (in same units as altitude) - float radians_to_pixels; +#ifndef AP_OPTICALFLOW_H +#define AP_OPTICALFLOW_H + +/* + AP_OpticalFlow.cpp - OpticalFlow Base Class for Ardupilot Mega + Code by Randy Mackay. DIYDrones.com + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + Methods: + init() : initializate sensor and library. + read : reads latest value from OpticalFlow and stores values in x,y, surface_quality parameter + read_register() : reads a value from the sensor (will be sensor specific) + write_register() : writes a value to one of the sensor's register (will be sensor specific) +*/ + +#include +#include +#include + +// standard rotation matrices +#define AP_OPTICALFLOW_ROTATION_NONE Matrix3f(1, 0, 0, 0, 1, 0, 0 ,0, 1) +#define AP_OPTICALFLOW_ROTATION_YAW_45 Matrix3f(0.70710678, -0.70710678, 0, 0.70710678, 0.70710678, 0, 0, 0, 1) +#define AP_OPTICALFLOW_ROTATION_YAW_90 Matrix3f(0, -1, 0, 1, 0, 0, 0, 0, 1) +#define AP_OPTICALFLOW_ROTATION_YAW_135 Matrix3f(-0.70710678, -0.70710678, 0, 0.70710678, -0.70710678, 0, 0, 0, 1) +#define AP_OPTICALFLOW_ROTATION_YAW_180 Matrix3f(-1, 0, 0, 0, -1, 0, 0, 0, 1) +#define AP_OPTICALFLOW_ROTATION_YAW_225 Matrix3f(-0.70710678, 0.70710678, 0, -0.70710678, -0.70710678, 0, 0, 0, 1) +#define AP_OPTICALFLOW_ROTATION_YAW_270 Matrix3f(0, 1, 0, -1, 0, 0, 0, 0, 1) +#define AP_OPTICALFLOW_ROTATION_YAW_315 Matrix3f(0.70710678, 0.70710678, 0, -0.70710678, 0.70710678, 0, 0, 0, 1) + +class AP_OpticalFlow +{ + public: + int raw_dx, raw_dy; // raw sensor change in x and y position (i.e. unrotated) + int surface_quality; // image quality (below 15 you really can't trust the x,y values returned) + int x,y; // total x,y position + int dx,dy; // rotated change in x and y position + float vlon, vlat; // position as offsets from original position + unsigned long last_update; // millis() time of last update + float field_of_view; // field of view in Radians + float scaler; // number returned from sensor when moved one pixel + int num_pixels; // number of pixels of resolution in the sensor + // temp variables - delete me! + float exp_change_x, exp_change_y; + float change_x, change_y; + float x_cm, y_cm; + + AP_OpticalFlow() { _sensor = this; }; + ~AP_OpticalFlow() { _sensor = NULL; }; + virtual bool init(bool initCommAPI = true); // parameter controls whether I2C/SPI interface is initialised (set to false if other devices are on the I2C/SPI bus and have already initialised the interface) + virtual byte read_register(byte address); + virtual void write_register(byte address, byte value); + virtual void set_orientation(const Matrix3f &rotation_matrix); // Rotation vector to transform sensor readings to the body frame. + virtual void set_field_of_view(const float fov) { field_of_view = fov; update_conversion_factors(); }; // sets field of view of sensor + static void read(uint32_t ) { if( _sensor != NULL ) _sensor->update(); }; // call to update all attached sensors + virtual bool update(); // read latest values from sensor and fill in x,y and totals. returns true on success + virtual void update_position(float roll, float pitch, float cos_yaw_x, float sin_yaw_y, float altitude); // updates internal lon and lat with estimation based on optical flow + +protected: + static AP_OpticalFlow *_sensor; // pointer to the last instantiated optical flow sensor. Will be turned into a table if we ever add support for more than one sensor + Matrix3f _orientation_matrix; + float conv_factor; // multiply this number by altitude and pixel change to get horizontal move (in same units as altitude) + float radians_to_pixels; float _last_roll, _last_pitch, _last_altitude; - virtual void apply_orientation_matrix(); // rotate raw values to arrive at final x,y,dx and dy values - virtual void update_conversion_factors(); -}; - + virtual void apply_orientation_matrix(); // rotate raw values to arrive at final x,y,dx and dy values + virtual void update_conversion_factors(); +}; + #include "AP_OpticalFlow_ADNS3080.h" -#endif +#endif diff --git a/libraries/AP_OpticalFlow/AP_OpticalFlow_ADNS3080.cpp b/libraries/AP_OpticalFlow/AP_OpticalFlow_ADNS3080.cpp index dc24db1392..fda2472619 100644 --- a/libraries/AP_OpticalFlow/AP_OpticalFlow_ADNS3080.cpp +++ b/libraries/AP_OpticalFlow/AP_OpticalFlow_ADNS3080.cpp @@ -1,482 +1,482 @@ -/* - AP_OpticalFlow_ADNS3080.cpp - ADNS3080 OpticalFlow Library for Ardupilot Mega - Code by Randy Mackay. DIYDrones.com - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - External ADNS3080 OpticalFlow is connected via Serial port 2 (in SPI mode) - TXD2 = MOSI = pin PH1 - RXD2 = MISO = pin PH0 - XCK2 = SCK = pin PH2 - Chip Select pin is PC4 (33) [PH6 (9)] - We are using the 16 clocks per conversion timming to increase efficiency (fast) - The sampling frequency is 400Hz (Timer2 overflow interrupt) - So if our loop is at 50Hz, our needed sampling freq should be 100Hz, so - we have an 4x oversampling and averaging. - - Methods: - Init() : Initialization of interrupts an Timers (Timer2 overflow interrupt) - Read() : Read latest values from OpticalFlow and store to x,y, surface_quality parameters - -*/ - -#include "AP_OpticalFlow_ADNS3080.h" -#include "SPI.h" -#if defined(ARDUINO) && ARDUINO >= 100 - #include "Arduino.h" -#else - #include "WProgram.h" -#endif - -#define AP_SPI_TIMEOUT 1000 - -union NumericIntType -{ - int intValue; - unsigned int uintValue; - byte byteValue[2]; -}; - - // Constructors //////////////////////////////////////////////////////////////// -AP_OpticalFlow_ADNS3080::AP_OpticalFlow_ADNS3080(int cs_pin, int reset_pin) : _cs_pin(cs_pin), _reset_pin(reset_pin) -{ - num_pixels = ADNS3080_PIXELS_X; - field_of_view = AP_OPTICALFLOW_ADNS3080_08_FOV; - scaler = AP_OPTICALFLOW_ADNS3080_SCALER; -} - - -// Public Methods ////////////////////////////////////////////////////////////// -// init - initialise sensor -// initCommAPI parameter controls whether SPI interface is initialised (set to false if other devices are on the SPI bus and have already initialised the interface) -bool -AP_OpticalFlow_ADNS3080::init(bool initCommAPI) -{ - int retry = 0; - - pinMode(AP_SPI_DATAOUT,OUTPUT); - pinMode(AP_SPI_DATAIN,INPUT); - pinMode(AP_SPI_CLOCK,OUTPUT); - pinMode(_cs_pin,OUTPUT); - if( _reset_pin != 0) - pinMode(ADNS3080_RESET,OUTPUT); - - digitalWrite(_cs_pin,HIGH); // disable device (Chip select is active low) - - // reset the device - reset(); - - // start the SPI library: - if( initCommAPI ) { - SPI.begin(); - } - - // check the sensor is functioning - if( retry < 3 ) { - if( read_register(ADNS3080_PRODUCT_ID) == 0x17 ) - return true; +/* + AP_OpticalFlow_ADNS3080.cpp - ADNS3080 OpticalFlow Library for Ardupilot Mega + Code by Randy Mackay. DIYDrones.com + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + External ADNS3080 OpticalFlow is connected via Serial port 2 (in SPI mode) + TXD2 = MOSI = pin PH1 + RXD2 = MISO = pin PH0 + XCK2 = SCK = pin PH2 + Chip Select pin is PC4 (33) [PH6 (9)] + We are using the 16 clocks per conversion timming to increase efficiency (fast) + The sampling frequency is 400Hz (Timer2 overflow interrupt) + So if our loop is at 50Hz, our needed sampling freq should be 100Hz, so + we have an 4x oversampling and averaging. + + Methods: + Init() : Initialization of interrupts an Timers (Timer2 overflow interrupt) + Read() : Read latest values from OpticalFlow and store to x,y, surface_quality parameters + +*/ + +#include "AP_OpticalFlow_ADNS3080.h" +#include "SPI.h" +#if defined(ARDUINO) && ARDUINO >= 100 + #include "Arduino.h" +#else + #include "WProgram.h" +#endif + +#define AP_SPI_TIMEOUT 1000 + +union NumericIntType +{ + int intValue; + unsigned int uintValue; + byte byteValue[2]; +}; + + // Constructors //////////////////////////////////////////////////////////////// +AP_OpticalFlow_ADNS3080::AP_OpticalFlow_ADNS3080(int cs_pin, int reset_pin) : _cs_pin(cs_pin), _reset_pin(reset_pin) +{ + num_pixels = ADNS3080_PIXELS_X; + field_of_view = AP_OPTICALFLOW_ADNS3080_08_FOV; + scaler = AP_OPTICALFLOW_ADNS3080_SCALER; +} + + +// Public Methods ////////////////////////////////////////////////////////////// +// init - initialise sensor +// initCommAPI parameter controls whether SPI interface is initialised (set to false if other devices are on the SPI bus and have already initialised the interface) +bool +AP_OpticalFlow_ADNS3080::init(bool initCommAPI) +{ + int retry = 0; + + pinMode(AP_SPI_DATAOUT,OUTPUT); + pinMode(AP_SPI_DATAIN,INPUT); + pinMode(AP_SPI_CLOCK,OUTPUT); + pinMode(_cs_pin,OUTPUT); + if( _reset_pin != 0) + pinMode(ADNS3080_RESET,OUTPUT); + + digitalWrite(_cs_pin,HIGH); // disable device (Chip select is active low) + + // reset the device + reset(); + + // start the SPI library: + if( initCommAPI ) { + SPI.begin(); + } + + // check the sensor is functioning + if( retry < 3 ) { + if( read_register(ADNS3080_PRODUCT_ID) == 0x17 ) + return true; retry++; } return false; -} - -// -// backup_spi_settings - checks current SPI settings (clock speed, etc), sets values to what we need -// -byte -AP_OpticalFlow_ADNS3080::backup_spi_settings() -{ - // store current spi values - orig_spi_settings_spcr = SPCR & (DORD | CPOL | CPHA); - orig_spi_settings_spsr = SPSR & SPI2X; - - // set the values that we need - SPI.setBitOrder(MSBFIRST); - SPI.setDataMode(SPI_MODE3); - SPI.setClockDivider(SPI_CLOCK_DIV8); // sensor running at 2Mhz. this is it's maximum speed - - return orig_spi_settings_spcr; -} - -// restore_spi_settings - restores SPI settings (clock speed, etc) to what their values were before the sensor used the bus -byte -AP_OpticalFlow_ADNS3080::restore_spi_settings() -{ - byte temp; - - // restore SPSR - temp = SPSR; - temp &= ~SPI2X; - temp |= orig_spi_settings_spsr; - SPSR = temp; - - // restore SPCR - temp = SPCR; - temp &= ~(DORD | CPOL | CPHA); // zero out the important bits - temp |= orig_spi_settings_spcr; // restore important bits - SPCR = temp; - - return temp; -} - -// Read a register from the sensor -byte -AP_OpticalFlow_ADNS3080::read_register(byte address) -{ - byte result = 0, junk = 0; - - backup_spi_settings(); - - // take the chip select low to select the device - digitalWrite(_cs_pin, LOW); - - // send the device the register you want to read: - junk = SPI.transfer(address); - - // small delay - delayMicroseconds(50); - - // send a value of 0 to read the first byte returned: - result = SPI.transfer(0x00); - - // take the chip select high to de-select: - digitalWrite(_cs_pin, HIGH); - - restore_spi_settings(); - - return result; -} - -// write a value to one of the sensor's registers -void -AP_OpticalFlow_ADNS3080::write_register(byte address, byte value) -{ - byte junk = 0; - - backup_spi_settings(); - - // take the chip select low to select the device - digitalWrite(_cs_pin, LOW); - - // send register address - junk = SPI.transfer(address | 0x80 ); - - // small delay - delayMicroseconds(50); - - // send data - junk = SPI.transfer(value); - - // take the chip select high to de-select: - digitalWrite(_cs_pin, HIGH); - - restore_spi_settings(); -} - -// reset sensor by holding a pin high (or is it low?) for 10us. -void -AP_OpticalFlow_ADNS3080::reset() -{ - // return immediately if the reset pin is not defined - if( _reset_pin == 0) - return; - - digitalWrite(_reset_pin,HIGH); // reset sensor - delayMicroseconds(10); - digitalWrite(_reset_pin,LOW); // return sensor to normal -} - -// read latest values from sensor and fill in x,y and totals -bool -AP_OpticalFlow_ADNS3080::update() -{ - byte motion_reg; - surface_quality = (unsigned int)read_register(ADNS3080_SQUAL); - delayMicroseconds(50); // small delay - - // check for movement, update x,y values - motion_reg = read_register(ADNS3080_MOTION); - _overflow = ((motion_reg & 0x10) != 0); // check if we've had an overflow - if( (motion_reg & 0x80) != 0 ) { - raw_dx = ((char)read_register(ADNS3080_DELTA_X)); - delayMicroseconds(50); // small delay - raw_dy = ((char)read_register(ADNS3080_DELTA_Y)); - _motion = true; - }else{ - raw_dx = 0; - raw_dy = 0; - } - - last_update = millis(); - - apply_orientation_matrix(); - - return true; -} - -void -AP_OpticalFlow_ADNS3080::disable_serial_pullup() -{ - byte regVal = read_register(ADNS3080_EXTENDED_CONFIG); - regVal = (regVal | ADNS3080_SERIALNPU_OFF); - delayMicroseconds(50); // small delay - write_register(ADNS3080_EXTENDED_CONFIG, regVal); -} - -// get_led_always_on - returns true if LED is always on, false if only on when required -bool -AP_OpticalFlow_ADNS3080::get_led_always_on() -{ - return ( (read_register(ADNS3080_CONFIGURATION_BITS) & 0x40) > 0 ); -} - -// set_led_always_on - set parameter to true if you want LED always on, otherwise false for only when required -void -AP_OpticalFlow_ADNS3080::set_led_always_on( bool alwaysOn ) -{ - byte regVal = read_register(ADNS3080_CONFIGURATION_BITS); +} + +// +// backup_spi_settings - checks current SPI settings (clock speed, etc), sets values to what we need +// +byte +AP_OpticalFlow_ADNS3080::backup_spi_settings() +{ + // store current spi values + orig_spi_settings_spcr = SPCR & (DORD | CPOL | CPHA); + orig_spi_settings_spsr = SPSR & SPI2X; + + // set the values that we need + SPI.setBitOrder(MSBFIRST); + SPI.setDataMode(SPI_MODE3); + SPI.setClockDivider(SPI_CLOCK_DIV8); // sensor running at 2Mhz. this is it's maximum speed + + return orig_spi_settings_spcr; +} + +// restore_spi_settings - restores SPI settings (clock speed, etc) to what their values were before the sensor used the bus +byte +AP_OpticalFlow_ADNS3080::restore_spi_settings() +{ + byte temp; + + // restore SPSR + temp = SPSR; + temp &= ~SPI2X; + temp |= orig_spi_settings_spsr; + SPSR = temp; + + // restore SPCR + temp = SPCR; + temp &= ~(DORD | CPOL | CPHA); // zero out the important bits + temp |= orig_spi_settings_spcr; // restore important bits + SPCR = temp; + + return temp; +} + +// Read a register from the sensor +byte +AP_OpticalFlow_ADNS3080::read_register(byte address) +{ + byte result = 0, junk = 0; + + backup_spi_settings(); + + // take the chip select low to select the device + digitalWrite(_cs_pin, LOW); + + // send the device the register you want to read: + junk = SPI.transfer(address); + + // small delay + delayMicroseconds(50); + + // send a value of 0 to read the first byte returned: + result = SPI.transfer(0x00); + + // take the chip select high to de-select: + digitalWrite(_cs_pin, HIGH); + + restore_spi_settings(); + + return result; +} + +// write a value to one of the sensor's registers +void +AP_OpticalFlow_ADNS3080::write_register(byte address, byte value) +{ + byte junk = 0; + + backup_spi_settings(); + + // take the chip select low to select the device + digitalWrite(_cs_pin, LOW); + + // send register address + junk = SPI.transfer(address | 0x80 ); + + // small delay + delayMicroseconds(50); + + // send data + junk = SPI.transfer(value); + + // take the chip select high to de-select: + digitalWrite(_cs_pin, HIGH); + + restore_spi_settings(); +} + +// reset sensor by holding a pin high (or is it low?) for 10us. +void +AP_OpticalFlow_ADNS3080::reset() +{ + // return immediately if the reset pin is not defined + if( _reset_pin == 0) + return; + + digitalWrite(_reset_pin,HIGH); // reset sensor + delayMicroseconds(10); + digitalWrite(_reset_pin,LOW); // return sensor to normal +} + +// read latest values from sensor and fill in x,y and totals +bool +AP_OpticalFlow_ADNS3080::update() +{ + byte motion_reg; + surface_quality = (unsigned int)read_register(ADNS3080_SQUAL); + delayMicroseconds(50); // small delay + + // check for movement, update x,y values + motion_reg = read_register(ADNS3080_MOTION); + _overflow = ((motion_reg & 0x10) != 0); // check if we've had an overflow + if( (motion_reg & 0x80) != 0 ) { + raw_dx = ((char)read_register(ADNS3080_DELTA_X)); + delayMicroseconds(50); // small delay + raw_dy = ((char)read_register(ADNS3080_DELTA_Y)); + _motion = true; + }else{ + raw_dx = 0; + raw_dy = 0; + } + + last_update = millis(); + + apply_orientation_matrix(); + + return true; +} + +void +AP_OpticalFlow_ADNS3080::disable_serial_pullup() +{ + byte regVal = read_register(ADNS3080_EXTENDED_CONFIG); + regVal = (regVal | ADNS3080_SERIALNPU_OFF); + delayMicroseconds(50); // small delay + write_register(ADNS3080_EXTENDED_CONFIG, regVal); +} + +// get_led_always_on - returns true if LED is always on, false if only on when required +bool +AP_OpticalFlow_ADNS3080::get_led_always_on() +{ + return ( (read_register(ADNS3080_CONFIGURATION_BITS) & 0x40) > 0 ); +} + +// set_led_always_on - set parameter to true if you want LED always on, otherwise false for only when required +void +AP_OpticalFlow_ADNS3080::set_led_always_on( bool alwaysOn ) +{ + byte regVal = read_register(ADNS3080_CONFIGURATION_BITS); regVal = (regVal & 0xbf) | (alwaysOn << 6); - delayMicroseconds(50); // small delay - write_register(ADNS3080_CONFIGURATION_BITS, regVal); -} - -// returns resolution (either 400 or 1600 counts per inch) -int -AP_OpticalFlow_ADNS3080::get_resolution() -{ - if( (read_register(ADNS3080_CONFIGURATION_BITS) & 0x10) == 0 ) - return 400; - else - return 1600; -} - -// set parameter to 400 or 1600 counts per inch -void -AP_OpticalFlow_ADNS3080::set_resolution(int resolution) -{ - byte regVal = read_register(ADNS3080_CONFIGURATION_BITS); - - if( resolution == ADNS3080_RESOLUTION_400 ) { - regVal &= ~0x10; - scaler = AP_OPTICALFLOW_ADNS3080_SCALER; - }else if( resolution == ADNS3080_RESOLUTION_1600) { - regVal |= 0x10; - scaler = AP_OPTICALFLOW_ADNS3080_SCALER * 4; - } - - delayMicroseconds(50); // small delay - write_register(ADNS3080_CONFIGURATION_BITS, regVal); - - // this will affect conversion factors so update them - update_conversion_factors(); -} - -// get_frame_rate_auto - return whether frame rate is set to "auto" or manual -bool -AP_OpticalFlow_ADNS3080::get_frame_rate_auto() -{ - byte regVal = read_register(ADNS3080_EXTENDED_CONFIG); + delayMicroseconds(50); // small delay + write_register(ADNS3080_CONFIGURATION_BITS, regVal); +} + +// returns resolution (either 400 or 1600 counts per inch) +int +AP_OpticalFlow_ADNS3080::get_resolution() +{ + if( (read_register(ADNS3080_CONFIGURATION_BITS) & 0x10) == 0 ) + return 400; + else + return 1600; +} + +// set parameter to 400 or 1600 counts per inch +void +AP_OpticalFlow_ADNS3080::set_resolution(int resolution) +{ + byte regVal = read_register(ADNS3080_CONFIGURATION_BITS); + + if( resolution == ADNS3080_RESOLUTION_400 ) { + regVal &= ~0x10; + scaler = AP_OPTICALFLOW_ADNS3080_SCALER; + }else if( resolution == ADNS3080_RESOLUTION_1600) { + regVal |= 0x10; + scaler = AP_OPTICALFLOW_ADNS3080_SCALER * 4; + } + + delayMicroseconds(50); // small delay + write_register(ADNS3080_CONFIGURATION_BITS, regVal); + + // this will affect conversion factors so update them + update_conversion_factors(); +} + +// get_frame_rate_auto - return whether frame rate is set to "auto" or manual +bool +AP_OpticalFlow_ADNS3080::get_frame_rate_auto() +{ + byte regVal = read_register(ADNS3080_EXTENDED_CONFIG); if( (regVal & 0x01) != 0 ) { - return false; - }else{ - return true; - } -} - -// set_frame_rate_auto - set frame rate to auto (true) or manual (false) -void -AP_OpticalFlow_ADNS3080::set_frame_rate_auto(bool auto_frame_rate) -{ - byte regVal = read_register(ADNS3080_EXTENDED_CONFIG); - delayMicroseconds(50); // small delay - if( auto_frame_rate == true ) { - // set specific frame period - write_register(ADNS3080_FRAME_PERIOD_MAX_BOUND_LOWER,0xE0); - delayMicroseconds(50); // small delay - write_register(ADNS3080_FRAME_PERIOD_MAX_BOUND_UPPER,0x1A); - delayMicroseconds(50); // small delay - - // decide what value to update in extended config - regVal = (regVal & ~0x01); - }else{ - // decide what value to update in extended config - regVal = (regVal & ~0x01) | 0x01; - } - write_register(ADNS3080_EXTENDED_CONFIG, regVal); -} - -// get frame period -unsigned int -AP_OpticalFlow_ADNS3080::get_frame_period() -{ - NumericIntType aNum; - aNum.byteValue[1] = read_register(ADNS3080_FRAME_PERIOD_UPPER); - delayMicroseconds(50); // small delay - aNum.byteValue[0] = read_register(ADNS3080_FRAME_PERIOD_LOWER); - return aNum.uintValue; -} - -// set frame period -void -AP_OpticalFlow_ADNS3080::set_frame_period(unsigned int period) -{ - NumericIntType aNum; - aNum.uintValue = period; - - // set frame rate to manual - set_frame_rate_auto(false); - delayMicroseconds(50); // small delay - - // set specific frame period - write_register(ADNS3080_FRAME_PERIOD_MAX_BOUND_LOWER,aNum.byteValue[0]); - delayMicroseconds(50); // small delay - write_register(ADNS3080_FRAME_PERIOD_MAX_BOUND_UPPER,aNum.byteValue[1]); - -} - -unsigned int -AP_OpticalFlow_ADNS3080::get_frame_rate() -{ - unsigned long clockSpeed = ADNS3080_CLOCK_SPEED; - unsigned int rate = clockSpeed / get_frame_period(); - return rate; -} - -void -AP_OpticalFlow_ADNS3080::set_frame_rate(unsigned int rate) -{ - unsigned long clockSpeed = ADNS3080_CLOCK_SPEED; - unsigned int period = (unsigned int)(clockSpeed / (unsigned long)rate); - - set_frame_period(period); -} - -// get_shutter_speed_auto - returns true if shutter speed is adjusted automatically, false if manual -bool -AP_OpticalFlow_ADNS3080::get_shutter_speed_auto() -{ - byte regVal = read_register(ADNS3080_EXTENDED_CONFIG); - if( (regVal & 0x02) > 0 ) { - return false; - }else{ - return true; - } -} - -// set_shutter_speed_auto - set shutter speed to auto (true), or manual (false) -void -AP_OpticalFlow_ADNS3080::set_shutter_speed_auto(bool auto_shutter_speed) -{ - byte regVal = read_register(ADNS3080_EXTENDED_CONFIG); - delayMicroseconds(50); // small delay - if( auto_shutter_speed ) { - // return shutter speed max to default - write_register(ADNS3080_SHUTTER_MAX_BOUND_LOWER,0x8c); - delayMicroseconds(50); // small delay - write_register(ADNS3080_SHUTTER_MAX_BOUND_UPPER,0x20); - delayMicroseconds(50); // small delay - - // determine value to put into extended config + return false; + }else{ + return true; + } +} + +// set_frame_rate_auto - set frame rate to auto (true) or manual (false) +void +AP_OpticalFlow_ADNS3080::set_frame_rate_auto(bool auto_frame_rate) +{ + byte regVal = read_register(ADNS3080_EXTENDED_CONFIG); + delayMicroseconds(50); // small delay + if( auto_frame_rate == true ) { + // set specific frame period + write_register(ADNS3080_FRAME_PERIOD_MAX_BOUND_LOWER,0xE0); + delayMicroseconds(50); // small delay + write_register(ADNS3080_FRAME_PERIOD_MAX_BOUND_UPPER,0x1A); + delayMicroseconds(50); // small delay + + // decide what value to update in extended config + regVal = (regVal & ~0x01); + }else{ + // decide what value to update in extended config + regVal = (regVal & ~0x01) | 0x01; + } + write_register(ADNS3080_EXTENDED_CONFIG, regVal); +} + +// get frame period +unsigned int +AP_OpticalFlow_ADNS3080::get_frame_period() +{ + NumericIntType aNum; + aNum.byteValue[1] = read_register(ADNS3080_FRAME_PERIOD_UPPER); + delayMicroseconds(50); // small delay + aNum.byteValue[0] = read_register(ADNS3080_FRAME_PERIOD_LOWER); + return aNum.uintValue; +} + +// set frame period +void +AP_OpticalFlow_ADNS3080::set_frame_period(unsigned int period) +{ + NumericIntType aNum; + aNum.uintValue = period; + + // set frame rate to manual + set_frame_rate_auto(false); + delayMicroseconds(50); // small delay + + // set specific frame period + write_register(ADNS3080_FRAME_PERIOD_MAX_BOUND_LOWER,aNum.byteValue[0]); + delayMicroseconds(50); // small delay + write_register(ADNS3080_FRAME_PERIOD_MAX_BOUND_UPPER,aNum.byteValue[1]); + +} + +unsigned int +AP_OpticalFlow_ADNS3080::get_frame_rate() +{ + unsigned long clockSpeed = ADNS3080_CLOCK_SPEED; + unsigned int rate = clockSpeed / get_frame_period(); + return rate; +} + +void +AP_OpticalFlow_ADNS3080::set_frame_rate(unsigned int rate) +{ + unsigned long clockSpeed = ADNS3080_CLOCK_SPEED; + unsigned int period = (unsigned int)(clockSpeed / (unsigned long)rate); + + set_frame_period(period); +} + +// get_shutter_speed_auto - returns true if shutter speed is adjusted automatically, false if manual +bool +AP_OpticalFlow_ADNS3080::get_shutter_speed_auto() +{ + byte regVal = read_register(ADNS3080_EXTENDED_CONFIG); + if( (regVal & 0x02) > 0 ) { + return false; + }else{ + return true; + } +} + +// set_shutter_speed_auto - set shutter speed to auto (true), or manual (false) +void +AP_OpticalFlow_ADNS3080::set_shutter_speed_auto(bool auto_shutter_speed) +{ + byte regVal = read_register(ADNS3080_EXTENDED_CONFIG); + delayMicroseconds(50); // small delay + if( auto_shutter_speed ) { + // return shutter speed max to default + write_register(ADNS3080_SHUTTER_MAX_BOUND_LOWER,0x8c); + delayMicroseconds(50); // small delay + write_register(ADNS3080_SHUTTER_MAX_BOUND_UPPER,0x20); + delayMicroseconds(50); // small delay + + // determine value to put into extended config regVal &= ~0x02; - }else{ - // determine value to put into extended config + }else{ + // determine value to put into extended config regVal |= 0x02; - } - write_register(ADNS3080_EXTENDED_CONFIG, regVal); - delayMicroseconds(50); // small delay -} - -// get_shutter_speed_auto - returns true if shutter speed is adjusted automatically, false if manual -unsigned int -AP_OpticalFlow_ADNS3080::get_shutter_speed() -{ - NumericIntType aNum; - aNum.byteValue[1] = read_register(ADNS3080_SHUTTER_UPPER); - delayMicroseconds(50); // small delay - aNum.byteValue[0] = read_register(ADNS3080_SHUTTER_LOWER); - return aNum.uintValue; -} - - -// set_shutter_speed_auto - set shutter speed to auto (true), or manual (false) + } + write_register(ADNS3080_EXTENDED_CONFIG, regVal); + delayMicroseconds(50); // small delay +} + +// get_shutter_speed_auto - returns true if shutter speed is adjusted automatically, false if manual +unsigned int +AP_OpticalFlow_ADNS3080::get_shutter_speed() +{ + NumericIntType aNum; + aNum.byteValue[1] = read_register(ADNS3080_SHUTTER_UPPER); + delayMicroseconds(50); // small delay + aNum.byteValue[0] = read_register(ADNS3080_SHUTTER_LOWER); + return aNum.uintValue; +} + + +// set_shutter_speed_auto - set shutter speed to auto (true), or manual (false) void -AP_OpticalFlow_ADNS3080::set_shutter_speed(unsigned int shutter_speed) -{ - NumericIntType aNum; - aNum.uintValue = shutter_speed; - - // set shutter speed to manual - set_shutter_speed_auto(false); - delayMicroseconds(50); // small delay - - // set specific shutter speed - write_register(ADNS3080_SHUTTER_MAX_BOUND_LOWER,aNum.byteValue[0]); - delayMicroseconds(50); // small delay - write_register(ADNS3080_SHUTTER_MAX_BOUND_UPPER,aNum.byteValue[1]); - delayMicroseconds(50); // small delay - - // larger delay - delay(50); - - // need to update frame period to cause shutter value to take effect - aNum.byteValue[1] = read_register(ADNS3080_FRAME_PERIOD_UPPER); - delayMicroseconds(50); // small delay - aNum.byteValue[0] = read_register(ADNS3080_FRAME_PERIOD_LOWER); - delayMicroseconds(50); // small delay - write_register(ADNS3080_FRAME_PERIOD_MAX_BOUND_LOWER,aNum.byteValue[0]); - delayMicroseconds(50); // small delay - write_register(ADNS3080_FRAME_PERIOD_MAX_BOUND_UPPER,aNum.byteValue[1]); - delayMicroseconds(50); // small delay -} - -// clear_motion - will cause the Delta_X, Delta_Y, and internal motion registers to be cleared -void -AP_OpticalFlow_ADNS3080::clear_motion() -{ - write_register(ADNS3080_MOTION_CLEAR,0xFF); // writing anything to this register will clear the sensor's motion registers - x = 0; - y = 0; - dx = 0; - dy = 0; - _motion = false; -} - -// get_pixel_data - captures an image from the sensor and stores it to the pixe_data array +AP_OpticalFlow_ADNS3080::set_shutter_speed(unsigned int shutter_speed) +{ + NumericIntType aNum; + aNum.uintValue = shutter_speed; + + // set shutter speed to manual + set_shutter_speed_auto(false); + delayMicroseconds(50); // small delay + + // set specific shutter speed + write_register(ADNS3080_SHUTTER_MAX_BOUND_LOWER,aNum.byteValue[0]); + delayMicroseconds(50); // small delay + write_register(ADNS3080_SHUTTER_MAX_BOUND_UPPER,aNum.byteValue[1]); + delayMicroseconds(50); // small delay + + // larger delay + delay(50); + + // need to update frame period to cause shutter value to take effect + aNum.byteValue[1] = read_register(ADNS3080_FRAME_PERIOD_UPPER); + delayMicroseconds(50); // small delay + aNum.byteValue[0] = read_register(ADNS3080_FRAME_PERIOD_LOWER); + delayMicroseconds(50); // small delay + write_register(ADNS3080_FRAME_PERIOD_MAX_BOUND_LOWER,aNum.byteValue[0]); + delayMicroseconds(50); // small delay + write_register(ADNS3080_FRAME_PERIOD_MAX_BOUND_UPPER,aNum.byteValue[1]); + delayMicroseconds(50); // small delay +} + +// clear_motion - will cause the Delta_X, Delta_Y, and internal motion registers to be cleared void -AP_OpticalFlow_ADNS3080::print_pixel_data(Stream *serPort) -{ - int i,j; - bool isFirstPixel = true; - byte regValue; - byte pixelValue; - - // write to frame capture register to force capture of frame - write_register(ADNS3080_FRAME_CAPTURE,0x83); - - // wait 3 frame periods + 10 nanoseconds for frame to be captured - delayMicroseconds(1510); // min frame speed is 2000 frames/second so 1 frame = 500 nano seconds. so 500 x 3 + 10 = 1510 - - // display the pixel data - for( i=0; iprintln("failed to find first pixel"); - } - isFirstPixel = false; - pixelValue = ( regValue << 2); - serPort->print(pixelValue,DEC); - if( j!= ADNS3080_PIXELS_X-1 ) - serPort->print(","); - delayMicroseconds(50); - } - serPort->println(); - } - - // hardware reset to restore sensor to normal operation - reset(); -} + serPort->println("failed to find first pixel"); + } + isFirstPixel = false; + pixelValue = ( regValue << 2); + serPort->print(pixelValue,DEC); + if( j!= ADNS3080_PIXELS_X-1 ) + serPort->print(","); + delayMicroseconds(50); + } + serPort->println(); + } + + // hardware reset to restore sensor to normal operation + reset(); +} diff --git a/libraries/AP_OpticalFlow/AP_OpticalFlow_ADNS3080.h b/libraries/AP_OpticalFlow/AP_OpticalFlow_ADNS3080.h index cb5eb1bb3d..eee31c5eb8 100644 --- a/libraries/AP_OpticalFlow/AP_OpticalFlow_ADNS3080.h +++ b/libraries/AP_OpticalFlow/AP_OpticalFlow_ADNS3080.h @@ -1,145 +1,145 @@ -#ifndef AP_OPTICALFLOW_ADNS3080_H -#define AP_OPTICALFLOW_ADNS3080_H - -#include "AP_OpticalFlow.h" - -// orientations for ADNS3080 sensor -#define AP_OPTICALFLOW_ADNS3080_PINS_FORWARD AP_OPTICALFLOW_ROTATION_YAW_180 -#define AP_OPTICALFLOW_ADNS3080_PINS_FORWARD_RIGHT AP_OPTICALFLOW_ROTATION_YAW_135 -#define AP_OPTICALFLOW_ADNS3080_PINS_RIGHT AP_OPTICALFLOW_ROTATION_YAW_90 -#define AP_OPTICALFLOW_ADNS3080_PINS_BACK_RIGHT AP_OPTICALFLOW_ROTATION_YAW_45 -#define AP_OPTICALFLOW_ADNS3080_PINS_BACK AP_OPTICALFLOW_ROTATION_NONE -#define AP_OPTICALFLOW_ADNS3080_PINS_BACK_LEFT AP_OPTICALFLOW_ROTATION_YAW_315 -#define AP_OPTICALFLOW_ADNS3080_PINS_LEFT AP_OPTICALFLOW_ROTATION_YAW_270 -#define AP_OPTICALFLOW_ADNS3080_PINS_FORWARD_LEFT AP_OPTICALFLOW_ROTATION_YAW_225 - -// field of view of ADNS3080 sensor lenses -#define AP_OPTICALFLOW_ADNS3080_08_FOV 0.202458 // 11.6 degrees - -// scaler - value returned when sensor is moved equivalent of 1 pixel -#define AP_OPTICALFLOW_ADNS3080_SCALER 1.1 - -// We use Serial Port 2 in SPI Mode -#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) - #define AP_SPI_DATAIN 50 // MISO // PB3 - #define AP_SPI_DATAOUT 51 // MOSI // PB2 - #define AP_SPI_CLOCK 52 // SCK // PB1 - #define ADNS3080_CHIP_SELECT 34 // PC3 - #define ADNS3080_RESET 0 // reset pin is unattached by default -#else // normal arduino SPI pins...these need to be checked - #define AP_SPI_DATAIN 12 //MISO - #define AP_SPI_DATAOUT 11 //MOSI - #define AP_SPI_CLOCK 13 //SCK - #define ADNS3080_CHIP_SELECT 10 //SS - #define ADNS3080_RESET 9 //RESET -#endif - -// ADNS3080 hardware config -#define ADNS3080_PIXELS_X 30 -#define ADNS3080_PIXELS_Y 30 -#define ADNS3080_CLOCK_SPEED 24000000 - -// Register Map for the ADNS3080 Optical OpticalFlow Sensor -#define ADNS3080_PRODUCT_ID 0x00 -#define ADNS3080_REVISION_ID 0x01 -#define ADNS3080_MOTION 0x02 -#define ADNS3080_DELTA_X 0x03 -#define ADNS3080_DELTA_Y 0x04 -#define ADNS3080_SQUAL 0x05 -#define ADNS3080_PIXEL_SUM 0x06 -#define ADNS3080_MAXIMUM_PIXEL 0x07 -#define ADNS3080_CONFIGURATION_BITS 0x0a -#define ADNS3080_EXTENDED_CONFIG 0x0b -#define ADNS3080_DATA_OUT_LOWER 0x0c -#define ADNS3080_DATA_OUT_UPPER 0x0d -#define ADNS3080_SHUTTER_LOWER 0x0e -#define ADNS3080_SHUTTER_UPPER 0x0f -#define ADNS3080_FRAME_PERIOD_LOWER 0x10 -#define ADNS3080_FRAME_PERIOD_UPPER 0x11 -#define ADNS3080_MOTION_CLEAR 0x12 -#define ADNS3080_FRAME_CAPTURE 0x13 -#define ADNS3080_SROM_ENABLE 0x14 -#define ADNS3080_FRAME_PERIOD_MAX_BOUND_LOWER 0x19 -#define ADNS3080_FRAME_PERIOD_MAX_BOUND_UPPER 0x1a -#define ADNS3080_FRAME_PERIOD_MIN_BOUND_LOWER 0x1b -#define ADNS3080_FRAME_PERIOD_MIN_BOUND_UPPER 0x1c -#define ADNS3080_SHUTTER_MAX_BOUND_LOWER 0x1e -#define ADNS3080_SHUTTER_MAX_BOUND_UPPER 0x1e -#define ADNS3080_SROM_ID 0x1f -#define ADNS3080_OBSERVATION 0x3d -#define ADNS3080_INVERSE_PRODUCT_ID 0x3f -#define ADNS3080_PIXEL_BURST 0x40 -#define ADNS3080_MOTION_BURST 0x50 -#define ADNS3080_SROM_LOAD 0x60 - -// Configuration Bits -#define ADNS3080_LED_MODE_ALWAYS_ON 0x00 -#define ADNS3080_LED_MODE_WHEN_REQUIRED 0x01 - -#define ADNS3080_RESOLUTION_400 400 -#define ADNS3080_RESOLUTION_1600 1600 - -// Extended Configuration bits -#define ADNS3080_SERIALNPU_OFF 0x02 - -#define ADNS3080_FRAME_RATE_MAX 6469 -#define ADNS3080_FRAME_RATE_MIN 2000 - - -class AP_OpticalFlow_ADNS3080 : public AP_OpticalFlow -{ - private: - // bytes to store SPI settings - byte orig_spi_settings_spcr; - byte orig_spi_settings_spsr; - - // save and restore SPI settings - byte backup_spi_settings(); - byte restore_spi_settings(); - - public: - int _cs_pin; // pin used for chip select - int _reset_pin; // pin used for chip reset - bool _motion; // true if there has been motion - bool _overflow; // true if the x or y data buffers overflowed - - public: - AP_OpticalFlow_ADNS3080(int cs_pin = ADNS3080_CHIP_SELECT, int reset_pin = ADNS3080_RESET); - bool init(bool initCommAPI = true); // parameter controls whether I2C/SPI interface is initialised (set to false if other devices are on the I2C/SPI bus and have already initialised the interface) - byte read_register(byte address); - void write_register(byte address, byte value); - void reset(); // reset sensor by holding a pin high (or is it low?) for 10us. - bool update(); // read latest values from sensor and fill in x,y and totals, return true on successful read - - // ADNS3080 specific features - bool motion() { if( _motion ) { _motion = false; return true; }else{ return false; } } // return true if there has been motion since the last time this was called - - void disable_serial_pullup(); - - bool get_led_always_on(); // returns true if LED is always on, false if only on when required - void set_led_always_on( bool alwaysOn ); // set parameter to true if you want LED always on, otherwise false for only when required - - int get_resolution(); // returns resolution (either 400 or 1600 counts per inch) - void set_resolution(int resolution); // set parameter to 400 or 1600 counts per inch - - bool get_frame_rate_auto(); // get_frame_rate_auto - return true if frame rate is set to "auto", false if manual - void set_frame_rate_auto(bool auto_frame_rate); // set_frame_rate_auto(bool) - set frame rate to auto (true), or manual (false) - - unsigned int get_frame_period(); // get_frame_period - - void set_frame_period(unsigned int period); - - unsigned int get_frame_rate(); - void set_frame_rate(unsigned int rate); - - bool get_shutter_speed_auto(); // get_shutter_speed_auto - returns true if shutter speed is adjusted automatically, false if manual - void set_shutter_speed_auto(bool auto_shutter_speed); // set_shutter_speed_auto - set shutter speed to auto (true), or manual (false) - - unsigned int get_shutter_speed(); +#ifndef AP_OPTICALFLOW_ADNS3080_H +#define AP_OPTICALFLOW_ADNS3080_H + +#include "AP_OpticalFlow.h" + +// orientations for ADNS3080 sensor +#define AP_OPTICALFLOW_ADNS3080_PINS_FORWARD AP_OPTICALFLOW_ROTATION_YAW_180 +#define AP_OPTICALFLOW_ADNS3080_PINS_FORWARD_RIGHT AP_OPTICALFLOW_ROTATION_YAW_135 +#define AP_OPTICALFLOW_ADNS3080_PINS_RIGHT AP_OPTICALFLOW_ROTATION_YAW_90 +#define AP_OPTICALFLOW_ADNS3080_PINS_BACK_RIGHT AP_OPTICALFLOW_ROTATION_YAW_45 +#define AP_OPTICALFLOW_ADNS3080_PINS_BACK AP_OPTICALFLOW_ROTATION_NONE +#define AP_OPTICALFLOW_ADNS3080_PINS_BACK_LEFT AP_OPTICALFLOW_ROTATION_YAW_315 +#define AP_OPTICALFLOW_ADNS3080_PINS_LEFT AP_OPTICALFLOW_ROTATION_YAW_270 +#define AP_OPTICALFLOW_ADNS3080_PINS_FORWARD_LEFT AP_OPTICALFLOW_ROTATION_YAW_225 + +// field of view of ADNS3080 sensor lenses +#define AP_OPTICALFLOW_ADNS3080_08_FOV 0.202458 // 11.6 degrees + +// scaler - value returned when sensor is moved equivalent of 1 pixel +#define AP_OPTICALFLOW_ADNS3080_SCALER 1.1 + +// We use Serial Port 2 in SPI Mode +#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) + #define AP_SPI_DATAIN 50 // MISO // PB3 + #define AP_SPI_DATAOUT 51 // MOSI // PB2 + #define AP_SPI_CLOCK 52 // SCK // PB1 + #define ADNS3080_CHIP_SELECT 34 // PC3 + #define ADNS3080_RESET 0 // reset pin is unattached by default +#else // normal arduino SPI pins...these need to be checked + #define AP_SPI_DATAIN 12 //MISO + #define AP_SPI_DATAOUT 11 //MOSI + #define AP_SPI_CLOCK 13 //SCK + #define ADNS3080_CHIP_SELECT 10 //SS + #define ADNS3080_RESET 9 //RESET +#endif + +// ADNS3080 hardware config +#define ADNS3080_PIXELS_X 30 +#define ADNS3080_PIXELS_Y 30 +#define ADNS3080_CLOCK_SPEED 24000000 + +// Register Map for the ADNS3080 Optical OpticalFlow Sensor +#define ADNS3080_PRODUCT_ID 0x00 +#define ADNS3080_REVISION_ID 0x01 +#define ADNS3080_MOTION 0x02 +#define ADNS3080_DELTA_X 0x03 +#define ADNS3080_DELTA_Y 0x04 +#define ADNS3080_SQUAL 0x05 +#define ADNS3080_PIXEL_SUM 0x06 +#define ADNS3080_MAXIMUM_PIXEL 0x07 +#define ADNS3080_CONFIGURATION_BITS 0x0a +#define ADNS3080_EXTENDED_CONFIG 0x0b +#define ADNS3080_DATA_OUT_LOWER 0x0c +#define ADNS3080_DATA_OUT_UPPER 0x0d +#define ADNS3080_SHUTTER_LOWER 0x0e +#define ADNS3080_SHUTTER_UPPER 0x0f +#define ADNS3080_FRAME_PERIOD_LOWER 0x10 +#define ADNS3080_FRAME_PERIOD_UPPER 0x11 +#define ADNS3080_MOTION_CLEAR 0x12 +#define ADNS3080_FRAME_CAPTURE 0x13 +#define ADNS3080_SROM_ENABLE 0x14 +#define ADNS3080_FRAME_PERIOD_MAX_BOUND_LOWER 0x19 +#define ADNS3080_FRAME_PERIOD_MAX_BOUND_UPPER 0x1a +#define ADNS3080_FRAME_PERIOD_MIN_BOUND_LOWER 0x1b +#define ADNS3080_FRAME_PERIOD_MIN_BOUND_UPPER 0x1c +#define ADNS3080_SHUTTER_MAX_BOUND_LOWER 0x1e +#define ADNS3080_SHUTTER_MAX_BOUND_UPPER 0x1e +#define ADNS3080_SROM_ID 0x1f +#define ADNS3080_OBSERVATION 0x3d +#define ADNS3080_INVERSE_PRODUCT_ID 0x3f +#define ADNS3080_PIXEL_BURST 0x40 +#define ADNS3080_MOTION_BURST 0x50 +#define ADNS3080_SROM_LOAD 0x60 + +// Configuration Bits +#define ADNS3080_LED_MODE_ALWAYS_ON 0x00 +#define ADNS3080_LED_MODE_WHEN_REQUIRED 0x01 + +#define ADNS3080_RESOLUTION_400 400 +#define ADNS3080_RESOLUTION_1600 1600 + +// Extended Configuration bits +#define ADNS3080_SERIALNPU_OFF 0x02 + +#define ADNS3080_FRAME_RATE_MAX 6469 +#define ADNS3080_FRAME_RATE_MIN 2000 + + +class AP_OpticalFlow_ADNS3080 : public AP_OpticalFlow +{ + private: + // bytes to store SPI settings + byte orig_spi_settings_spcr; + byte orig_spi_settings_spsr; + + // save and restore SPI settings + byte backup_spi_settings(); + byte restore_spi_settings(); + + public: + int _cs_pin; // pin used for chip select + int _reset_pin; // pin used for chip reset + bool _motion; // true if there has been motion + bool _overflow; // true if the x or y data buffers overflowed + + public: + AP_OpticalFlow_ADNS3080(int cs_pin = ADNS3080_CHIP_SELECT, int reset_pin = ADNS3080_RESET); + bool init(bool initCommAPI = true); // parameter controls whether I2C/SPI interface is initialised (set to false if other devices are on the I2C/SPI bus and have already initialised the interface) + byte read_register(byte address); + void write_register(byte address, byte value); + void reset(); // reset sensor by holding a pin high (or is it low?) for 10us. + bool update(); // read latest values from sensor and fill in x,y and totals, return true on successful read + + // ADNS3080 specific features + bool motion() { if( _motion ) { _motion = false; return true; }else{ return false; } } // return true if there has been motion since the last time this was called + + void disable_serial_pullup(); + + bool get_led_always_on(); // returns true if LED is always on, false if only on when required + void set_led_always_on( bool alwaysOn ); // set parameter to true if you want LED always on, otherwise false for only when required + + int get_resolution(); // returns resolution (either 400 or 1600 counts per inch) + void set_resolution(int resolution); // set parameter to 400 or 1600 counts per inch + + bool get_frame_rate_auto(); // get_frame_rate_auto - return true if frame rate is set to "auto", false if manual + void set_frame_rate_auto(bool auto_frame_rate); // set_frame_rate_auto(bool) - set frame rate to auto (true), or manual (false) + + unsigned int get_frame_period(); // get_frame_period - + void set_frame_period(unsigned int period); + + unsigned int get_frame_rate(); + void set_frame_rate(unsigned int rate); + + bool get_shutter_speed_auto(); // get_shutter_speed_auto - returns true if shutter speed is adjusted automatically, false if manual + void set_shutter_speed_auto(bool auto_shutter_speed); // set_shutter_speed_auto - set shutter speed to auto (true), or manual (false) + + unsigned int get_shutter_speed(); void set_shutter_speed(unsigned int shutter_speed); - - void clear_motion(); // will cause the x,y, dx, dy, and the sensor's motion registers to be cleared - + + void clear_motion(); // will cause the x,y, dx, dy, and the sensor's motion registers to be cleared + void print_pixel_data(Stream *serPort); // dumps a 30x30 image to the Serial port -}; - -#endif +}; + +#endif From 6021daf4236dcf6d327e89e44417c4a5c62a1e31 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 10 Mar 2012 13:57:06 +1100 Subject: [PATCH 141/178] OpticalFlow: adapt optical flow library to new rotation system --- libraries/AP_OpticalFlow/AP_OpticalFlow.cpp | 18 ++++++++++-------- libraries/AP_OpticalFlow/AP_OpticalFlow.h | 14 ++------------ .../AP_OpticalFlow/AP_OpticalFlow_ADNS3080.h | 16 ++++++++-------- 3 files changed, 20 insertions(+), 28 deletions(-) diff --git a/libraries/AP_OpticalFlow/AP_OpticalFlow.cpp b/libraries/AP_OpticalFlow/AP_OpticalFlow.cpp index 1aeed584c0..06323d6c2f 100644 --- a/libraries/AP_OpticalFlow/AP_OpticalFlow.cpp +++ b/libraries/AP_OpticalFlow/AP_OpticalFlow.cpp @@ -18,16 +18,16 @@ AP_OpticalFlow* AP_OpticalFlow::_sensor = NULL; // pointer to the last instanti bool AP_OpticalFlow::init(bool initCommAPI) { - _orientation_matrix = Matrix3f(1, 0, 0, 0, 1, 0, 0, 0, 1); - update_conversion_factors(); - return true; // just return true by default + _orientation = ROTATION_NONE; + update_conversion_factors(); + return true; // just return true by default } // set_orientation - Rotation vector to transform sensor readings to the body frame. void -AP_OpticalFlow::set_orientation(const Matrix3f &rotation_matrix) +AP_OpticalFlow::set_orientation(enum Rotation rotation) { - _orientation_matrix = rotation_matrix; + _orientation = rotation; } // read value from the sensor. Should be overridden by derived class @@ -54,10 +54,12 @@ AP_OpticalFlow::write_register(byte address, byte value) void AP_OpticalFlow::apply_orientation_matrix() { - Vector3f rot_vector; + Vector3f rot_vector; + rot_vector(raw_dx, raw_dy, 0); // next rotate dx and dy - rot_vector = _orientation_matrix * Vector3f(raw_dx, raw_dy, 0); + rot_vector.rotate(_orientation); + dx = rot_vector.x; dy = rot_vector.y; @@ -108,4 +110,4 @@ AP_OpticalFlow::update_position(float roll, float pitch, float cos_yaw_x, float _last_altitude = altitude; _last_roll = roll; _last_pitch = pitch; -} \ No newline at end of file +} diff --git a/libraries/AP_OpticalFlow/AP_OpticalFlow.h b/libraries/AP_OpticalFlow/AP_OpticalFlow.h index 5e6657fefe..187499b57e 100644 --- a/libraries/AP_OpticalFlow/AP_OpticalFlow.h +++ b/libraries/AP_OpticalFlow/AP_OpticalFlow.h @@ -21,16 +21,6 @@ #include #include -// standard rotation matrices -#define AP_OPTICALFLOW_ROTATION_NONE Matrix3f(1, 0, 0, 0, 1, 0, 0 ,0, 1) -#define AP_OPTICALFLOW_ROTATION_YAW_45 Matrix3f(0.70710678, -0.70710678, 0, 0.70710678, 0.70710678, 0, 0, 0, 1) -#define AP_OPTICALFLOW_ROTATION_YAW_90 Matrix3f(0, -1, 0, 1, 0, 0, 0, 0, 1) -#define AP_OPTICALFLOW_ROTATION_YAW_135 Matrix3f(-0.70710678, -0.70710678, 0, 0.70710678, -0.70710678, 0, 0, 0, 1) -#define AP_OPTICALFLOW_ROTATION_YAW_180 Matrix3f(-1, 0, 0, 0, -1, 0, 0, 0, 1) -#define AP_OPTICALFLOW_ROTATION_YAW_225 Matrix3f(-0.70710678, 0.70710678, 0, -0.70710678, -0.70710678, 0, 0, 0, 1) -#define AP_OPTICALFLOW_ROTATION_YAW_270 Matrix3f(0, 1, 0, -1, 0, 0, 0, 0, 1) -#define AP_OPTICALFLOW_ROTATION_YAW_315 Matrix3f(0.70710678, 0.70710678, 0, -0.70710678, 0.70710678, 0, 0, 0, 1) - class AP_OpticalFlow { public: @@ -53,7 +43,7 @@ class AP_OpticalFlow virtual bool init(bool initCommAPI = true); // parameter controls whether I2C/SPI interface is initialised (set to false if other devices are on the I2C/SPI bus and have already initialised the interface) virtual byte read_register(byte address); virtual void write_register(byte address, byte value); - virtual void set_orientation(const Matrix3f &rotation_matrix); // Rotation vector to transform sensor readings to the body frame. + virtual void set_orientation(enum Rotation rotation); // Rotation vector to transform sensor readings to the body frame. virtual void set_field_of_view(const float fov) { field_of_view = fov; update_conversion_factors(); }; // sets field of view of sensor static void read(uint32_t ) { if( _sensor != NULL ) _sensor->update(); }; // call to update all attached sensors virtual bool update(); // read latest values from sensor and fill in x,y and totals. returns true on success @@ -61,7 +51,7 @@ class AP_OpticalFlow protected: static AP_OpticalFlow *_sensor; // pointer to the last instantiated optical flow sensor. Will be turned into a table if we ever add support for more than one sensor - Matrix3f _orientation_matrix; + enum Rotation _orientation; float conv_factor; // multiply this number by altitude and pixel change to get horizontal move (in same units as altitude) float radians_to_pixels; float _last_roll, _last_pitch, _last_altitude; diff --git a/libraries/AP_OpticalFlow/AP_OpticalFlow_ADNS3080.h b/libraries/AP_OpticalFlow/AP_OpticalFlow_ADNS3080.h index eee31c5eb8..fc998e139f 100644 --- a/libraries/AP_OpticalFlow/AP_OpticalFlow_ADNS3080.h +++ b/libraries/AP_OpticalFlow/AP_OpticalFlow_ADNS3080.h @@ -4,14 +4,14 @@ #include "AP_OpticalFlow.h" // orientations for ADNS3080 sensor -#define AP_OPTICALFLOW_ADNS3080_PINS_FORWARD AP_OPTICALFLOW_ROTATION_YAW_180 -#define AP_OPTICALFLOW_ADNS3080_PINS_FORWARD_RIGHT AP_OPTICALFLOW_ROTATION_YAW_135 -#define AP_OPTICALFLOW_ADNS3080_PINS_RIGHT AP_OPTICALFLOW_ROTATION_YAW_90 -#define AP_OPTICALFLOW_ADNS3080_PINS_BACK_RIGHT AP_OPTICALFLOW_ROTATION_YAW_45 -#define AP_OPTICALFLOW_ADNS3080_PINS_BACK AP_OPTICALFLOW_ROTATION_NONE -#define AP_OPTICALFLOW_ADNS3080_PINS_BACK_LEFT AP_OPTICALFLOW_ROTATION_YAW_315 -#define AP_OPTICALFLOW_ADNS3080_PINS_LEFT AP_OPTICALFLOW_ROTATION_YAW_270 -#define AP_OPTICALFLOW_ADNS3080_PINS_FORWARD_LEFT AP_OPTICALFLOW_ROTATION_YAW_225 +#define AP_OPTICALFLOW_ADNS3080_PINS_FORWARD ROTATION_YAW_180 +#define AP_OPTICALFLOW_ADNS3080_PINS_FORWARD_RIGHT ROTATION_YAW_135 +#define AP_OPTICALFLOW_ADNS3080_PINS_RIGHT ROTATION_YAW_90 +#define AP_OPTICALFLOW_ADNS3080_PINS_BACK_RIGHT ROTATION_YAW_45 +#define AP_OPTICALFLOW_ADNS3080_PINS_BACK ROTATION_NONE +#define AP_OPTICALFLOW_ADNS3080_PINS_BACK_LEFT ROTATION_YAW_315 +#define AP_OPTICALFLOW_ADNS3080_PINS_LEFT ROTATION_YAW_270 +#define AP_OPTICALFLOW_ADNS3080_PINS_FORWARD_LEFT ROTATION_YAW_225 // field of view of ADNS3080 sensor lenses #define AP_OPTICALFLOW_ADNS3080_08_FOV 0.202458 // 11.6 degrees From 9e30b5e4a580af359d203a919c7c507f284d2b61 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 10 Mar 2012 14:27:30 +1100 Subject: [PATCH 142/178] I2C: fixed cr/lf mess --- libraries/I2C/I2C.cpp | 1121 ++++++++++++++++++++--------------------- libraries/I2C/I2C.h | 240 ++++----- 2 files changed, 680 insertions(+), 681 deletions(-) diff --git a/libraries/I2C/I2C.cpp b/libraries/I2C/I2C.cpp index 254670138f..20aaf22f14 100644 --- a/libraries/I2C/I2C.cpp +++ b/libraries/I2C/I2C.cpp @@ -1,567 +1,566 @@ -/* - I2C.cpp - I2C library - Copyright (c) 2011 Wayne Truchsess. All right reserved. - Rev 2.0 - September 19th, 2011 - - Added support for timeout function to prevent - and recover from bus lockup (thanks to PaulS - and CrossRoads on the Arduino forum) - - Changed return type for stop() from void to - uint8_t to handle timeOut function - Rev 1.0 - August 8th, 2011 - - This is a modified version of the Arduino Wire/TWI - library. Functions were rewritten to provide more functionality - and also the use of Repeated Start. Some I2C devices will not - function correctly without the use of a Repeated Start. The - initial version of this library only supports the Master. - - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -*/ - -#include -#include "I2C.h" -#if defined(ARDUINO) && ARDUINO >= 100 - #include "Arduino.h" -#else - #include "WProgram.h" -#endif - - - -uint8_t I2C::bytesAvailable = 0; -uint8_t I2C::bufferIndex = 0; -uint8_t I2C::totalBytes = 0; -uint16_t I2C::timeOutDelay = 0; - -I2C::I2C() -{ -} - - -////////////// Public Methods //////////////////////////////////////// - - - -void I2C::begin() -{ - #if defined(__AVR_ATmega168__) || defined(__AVR_ATmega8__) || defined(__AVR_ATmega328P__) - // activate internal pull-ups for twi - // as per note from atmega8 manual pg167 - sbi(PORTC, 4); - sbi(PORTC, 5); - #else - // activate internal pull-ups for twi - // as per note from atmega128 manual pg204 - sbi(PORTD, 0); - sbi(PORTD, 1); - #endif - // initialize twi prescaler and bit rate - cbi(TWSR, TWPS0); - cbi(TWSR, TWPS1); - TWBR = ((CPU_FREQ / 100000) - 16) / 2; - // enable twi module, acks, and twi interrupt - TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWEA); -} - -void I2C::end() -{ - TWCR = 0; -} - -void I2C::timeOut(uint16_t _timeOut) -{ - timeOutDelay = _timeOut; -} - -void I2C::setSpeed(boolean _fast) -{ - if(!_fast) - { - TWBR = ((CPU_FREQ / 100000) - 16) / 2; - } - else - { - TWBR = ((CPU_FREQ / 400000) - 16) / 2; - } -} - -void I2C::pullup(boolean activate) -{ - if(activate) - { - #if defined(__AVR_ATmega168__) || defined(__AVR_ATmega8__) || defined(__AVR_ATmega328P__) - // activate internal pull-ups for twi - // as per note from atmega8 manual pg167 - sbi(PORTC, 4); - sbi(PORTC, 5); - #else - // activate internal pull-ups for twi - // as per note from atmega128 manual pg204 - sbi(PORTD, 0); - sbi(PORTD, 1); - #endif - } - else - { - #if defined(__AVR_ATmega168__) || defined(__AVR_ATmega8__) || defined(__AVR_ATmega328P__) - // deactivate internal pull-ups for twi - // as per note from atmega8 manual pg167 - cbi(PORTC, 4); - cbi(PORTC, 5); - #else - // deactivate internal pull-ups for twi - // as per note from atmega128 manual pg204 - cbi(PORTD, 0); - cbi(PORTD, 1); - #endif - } -} - -/////////////carry over from Wire library /////////// - -uint8_t I2C::beginTransmission(uint8_t address) -{ - returnStatusWire = 0; - returnStatus = 0; - returnStatus = start(); - returnStatusWire = returnStatus; - if(returnStatus){return(returnStatus);} - returnStatus = sendAddress(SLA_W(address)); - returnStatusWire = returnStatus; - return(returnStatus); -} - -uint8_t I2C::beginTransmission(int address) -{ - return(beginTransmission((uint8_t) address)); -} - -uint8_t I2C::send(uint8_t databyte) -{ - if(returnStatusWire) - { - return(returnStatusWire); - } - returnStatus = 0; - returnStatus = sendByte(databyte); - returnStatusWire = returnStatus; - return(returnStatus); -} - -uint8_t I2C::send(int databyte) -{ - return(send((uint8_t) databyte)); -} - -uint8_t I2C::endTransmission() -{ - stop(); - return(returnStatusWire); -} - -uint8_t I2C::requestFrom(int address, int numberBytes) -{ - return(requestFrom((uint8_t) address, (uint8_t) numberBytes)); -} - -uint8_t I2C::requestFrom(uint8_t address, uint8_t numberBytes) -{ - returnStatus = 0; - returnStatus = read(address,numberBytes); - if(!returnStatus) - { - return(numberBytes); - } - return(0); -} - -uint8_t I2C::available() -{ - return(bytesAvailable); -} - -uint8_t I2C::receive() -{ - bufferIndex = totalBytes - bytesAvailable; - if(!bytesAvailable) - { - bufferIndex = 0; - return(0); - } - bytesAvailable--; - return(data[bufferIndex]); -} - - - - - -///////////////////////////////////////////////////// - -uint8_t I2C::write(uint8_t address, uint8_t registerAddress) -{ - returnStatus = 0; - returnStatus = start(); - if(returnStatus){return(returnStatus);} - returnStatus = sendAddress(SLA_W(address)); - if(returnStatus){return(returnStatus);} - returnStatus = sendByte(registerAddress); - if(returnStatus){return(returnStatus);} - returnStatus = stop(); - return(returnStatus); -} - -uint8_t I2C::write(int address, int registerAddress) -{ - return(write((uint8_t) address, (uint8_t) registerAddress)); -} - -uint8_t I2C::write(uint8_t address, uint8_t registerAddress, uint8_t databyte) -{ - returnStatus = 0; - returnStatus = start(); - if(returnStatus){return(returnStatus);} - returnStatus = sendAddress(SLA_W(address)); - if(returnStatus){return(returnStatus);} - returnStatus = sendByte(registerAddress); - if(returnStatus){return(returnStatus);} - returnStatus = sendByte(databyte); - if(returnStatus){return(returnStatus);} - returnStatus = stop(); - return(returnStatus); -} - -uint8_t I2C::write(int address, int registerAddress, int databyte) -{ - return(write((uint8_t) address, (uint8_t) registerAddress, (uint8_t) databyte)); -} - -uint8_t I2C::write(uint8_t address, uint8_t registerAddress, char *databytes) -{ - uint8_t bufferLength = strlen(databytes); - returnStatus = 0; - returnStatus = write(address, registerAddress, (uint8_t*)databytes, bufferLength); - return(returnStatus); -} - -uint8_t I2C::write(uint8_t address, uint8_t registerAddress, uint8_t *databytes, uint8_t numberBytes) -{ - returnStatus = 0; - returnStatus = start(); - if(returnStatus){return(returnStatus);} - returnStatus = sendAddress(SLA_W(address)); - if(returnStatus){return(returnStatus);} - returnStatus = sendByte(registerAddress); - if(returnStatus){return(returnStatus);} - for (uint8_t i = 0; i < numberBytes; i++) - { - returnStatus = sendByte(databytes[i]); - if(returnStatus){return(returnStatus);} - } - returnStatus = stop(); - return(returnStatus); -} - -uint8_t I2C::read(int address, int numberBytes) -{ - return(read((uint8_t) address, (uint8_t) numberBytes)); -} - -uint8_t I2C::read(uint8_t address, uint8_t numberBytes) -{ - bytesAvailable = 0; - bufferIndex = 0; - if(numberBytes == 0){numberBytes++;} - nack = numberBytes - 1; - returnStatus = 0; - returnStatus = start(); - if(returnStatus){return(returnStatus);} - returnStatus = sendAddress(SLA_R(address)); - if(returnStatus){return(returnStatus);} - for(uint8_t i = 0; i < numberBytes; i++) - { - if( i == nack ) - { - returnStatus = receiveByte(0); - if(returnStatus != MR_DATA_NACK){return(returnStatus);} - } - else - { - returnStatus = receiveByte(1); - if(returnStatus != MR_DATA_ACK){return(returnStatus);} - } - data[i] = TWDR; - bytesAvailable = i+1; - totalBytes = i+1; - } - returnStatus = stop(); - return(returnStatus); -} - -uint8_t I2C::read(int address, int registerAddress, int numberBytes) -{ - return(read((uint8_t) address, (uint8_t) registerAddress, (uint8_t) numberBytes)); -} - -uint8_t I2C::read(uint8_t address, uint8_t registerAddress, uint8_t numberBytes) -{ - bytesAvailable = 0; - bufferIndex = 0; - if(numberBytes == 0){numberBytes++;} - nack = numberBytes - 1; - returnStatus = 0; - returnStatus = start(); - if(returnStatus){return(returnStatus);} - returnStatus = sendAddress(SLA_W(address)); - if(returnStatus){return(returnStatus);} - returnStatus = sendByte(registerAddress); - if(returnStatus){return(returnStatus);} - returnStatus = start(); - if(returnStatus){return(returnStatus);} - returnStatus = sendAddress(SLA_R(address)); - if(returnStatus){return(returnStatus);} - for(uint8_t i = 0; i < numberBytes; i++) - { - if( i == nack ) - { - returnStatus = receiveByte(0); - if(returnStatus != MR_DATA_NACK){return(returnStatus);} - } - else - { - returnStatus = receiveByte(1); - if(returnStatus != MR_DATA_ACK){return(returnStatus);} - } - data[i] = TWDR; - bytesAvailable = i+1; - totalBytes = i+1; - } - returnStatus = stop(); - return(returnStatus); -} - -uint8_t I2C::read(uint8_t address, uint8_t numberBytes, uint8_t *dataBuffer) -{ - bytesAvailable = 0; - bufferIndex = 0; - if(numberBytes == 0){numberBytes++;} - nack = numberBytes - 1; - returnStatus = 0; - returnStatus = start(); - if(returnStatus){return(returnStatus);} - returnStatus = sendAddress(SLA_R(address)); - if(returnStatus){return(returnStatus);} - for(uint8_t i = 0; i < numberBytes; i++) - { - if( i == nack ) - { - returnStatus = receiveByte(0); - if(returnStatus != MR_DATA_NACK){return(returnStatus);} - } - else - { - returnStatus = receiveByte(1); - if(returnStatus != MR_DATA_ACK){return(returnStatus);} - } - dataBuffer[i] = TWDR; - bytesAvailable = i+1; - totalBytes = i+1; - } - returnStatus = stop(); - return(returnStatus); -} - -uint8_t I2C::read(uint8_t address, uint8_t registerAddress, uint8_t numberBytes, uint8_t *dataBuffer) -{ - bytesAvailable = 0; - bufferIndex = 0; - if(numberBytes == 0){numberBytes++;} - nack = numberBytes - 1; - returnStatus = 0; - returnStatus = start(); - if(returnStatus){return(returnStatus);} - returnStatus = sendAddress(SLA_W(address)); - if(returnStatus){return(returnStatus);} - returnStatus = sendByte(registerAddress); - if(returnStatus){return(returnStatus);} - returnStatus = start(); - if(returnStatus){return(returnStatus);} - returnStatus = sendAddress(SLA_R(address)); - if(returnStatus){return(returnStatus);} - for(uint8_t i = 0; i < numberBytes; i++) - { - if( i == nack ) - { - returnStatus = receiveByte(0); - if(returnStatus != MR_DATA_NACK){return(returnStatus);} - } - else - { - returnStatus = receiveByte(1); - if(returnStatus != MR_DATA_ACK){return(returnStatus);} - } - dataBuffer[i] = TWDR; - bytesAvailable = i+1; - totalBytes = i+1; - } - returnStatus = stop(); - return(returnStatus); -} - - -/////////////// Private Methods //////////////////////////////////////// - - -uint8_t I2C::start() -{ - unsigned long startingTime = millis(); - TWCR = (1<= timeOutDelay) - { - lockUp(); - return(1); - } - - } - if ((TWI_STATUS == START) || (TWI_STATUS == REPEATED_START)) - { - return(0); - } - return(TWI_STATUS); -} - -uint8_t I2C::sendAddress(uint8_t i2cAddress) -{ - TWDR = i2cAddress; - unsigned long startingTime = millis(); - TWCR = (1<= timeOutDelay) - { - lockUp(); - return(1); - } - - } - if ((TWI_STATUS == MT_SLA_ACK) || (TWI_STATUS == MR_SLA_ACK)) - { - return(0); - } - return(TWI_STATUS); -} - -uint8_t I2C::sendByte(uint8_t i2cData) -{ - TWDR = i2cData; - unsigned long startingTime = millis(); - TWCR = (1<= timeOutDelay) - { - lockUp(); - return(1); - } - - } - if (TWI_STATUS == MT_DATA_ACK) - { - return(0); - } - return(TWI_STATUS); -} - -uint8_t I2C::receiveByte(boolean ack) -{ - unsigned long startingTime = millis(); - if(ack) - { - TWCR = (1<= timeOutDelay) - { - lockUp(); - return(1); - } - - } - return(TWI_STATUS); -} - -uint8_t I2C::stop() -{ - unsigned long startingTime = millis(); - TWCR = (1<= timeOutDelay) - { - lockUp(); - return(1); - } - - } - return(0); -} - -void I2C::lockUp() -{ - TWCR = 0; //releases SDA and SCL lines to high impedance - TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWEA); //reinitialize TWI +/* + I2C.cpp - I2C library + Copyright (c) 2011 Wayne Truchsess. All right reserved. + Rev 2.0 - September 19th, 2011 + - Added support for timeout function to prevent + and recover from bus lockup (thanks to PaulS + and CrossRoads on the Arduino forum) + - Changed return type for stop() from void to + uint8_t to handle timeOut function + Rev 1.0 - August 8th, 2011 + + This is a modified version of the Arduino Wire/TWI + library. Functions were rewritten to provide more functionality + and also the use of Repeated Start. Some I2C devices will not + function correctly without the use of a Repeated Start. The + initial version of this library only supports the Master. + + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include +#include "I2C.h" +#if defined(ARDUINO) && ARDUINO >= 100 + #include "Arduino.h" +#else + #include "WProgram.h" +#endif + + + +uint8_t I2C::bytesAvailable = 0; +uint8_t I2C::bufferIndex = 0; +uint8_t I2C::totalBytes = 0; +uint16_t I2C::timeOutDelay = 0; + +I2C::I2C() +{ +} + + +////////////// Public Methods //////////////////////////////////////// + + + +void I2C::begin() +{ + #if defined(__AVR_ATmega168__) || defined(__AVR_ATmega8__) || defined(__AVR_ATmega328P__) + // activate internal pull-ups for twi + // as per note from atmega8 manual pg167 + sbi(PORTC, 4); + sbi(PORTC, 5); + #else + // activate internal pull-ups for twi + // as per note from atmega128 manual pg204 + sbi(PORTD, 0); + sbi(PORTD, 1); + #endif + // initialize twi prescaler and bit rate + cbi(TWSR, TWPS0); + cbi(TWSR, TWPS1); + TWBR = ((CPU_FREQ / 100000) - 16) / 2; + // enable twi module, acks, and twi interrupt + TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWEA); +} + +void I2C::end() +{ + TWCR = 0; +} + +void I2C::timeOut(uint16_t _timeOut) +{ + timeOutDelay = _timeOut; +} + +void I2C::setSpeed(boolean _fast) +{ + if(!_fast) + { + TWBR = ((CPU_FREQ / 100000) - 16) / 2; + } + else + { + TWBR = ((CPU_FREQ / 400000) - 16) / 2; + } +} + +void I2C::pullup(boolean activate) +{ + if(activate) + { + #if defined(__AVR_ATmega168__) || defined(__AVR_ATmega8__) || defined(__AVR_ATmega328P__) + // activate internal pull-ups for twi + // as per note from atmega8 manual pg167 + sbi(PORTC, 4); + sbi(PORTC, 5); + #else + // activate internal pull-ups for twi + // as per note from atmega128 manual pg204 + sbi(PORTD, 0); + sbi(PORTD, 1); + #endif + } + else + { + #if defined(__AVR_ATmega168__) || defined(__AVR_ATmega8__) || defined(__AVR_ATmega328P__) + // deactivate internal pull-ups for twi + // as per note from atmega8 manual pg167 + cbi(PORTC, 4); + cbi(PORTC, 5); + #else + // deactivate internal pull-ups for twi + // as per note from atmega128 manual pg204 + cbi(PORTD, 0); + cbi(PORTD, 1); + #endif + } +} + +/////////////carry over from Wire library /////////// + +uint8_t I2C::beginTransmission(uint8_t address) +{ + returnStatusWire = 0; + returnStatus = 0; + returnStatus = start(); + returnStatusWire = returnStatus; + if(returnStatus){return(returnStatus);} + returnStatus = sendAddress(SLA_W(address)); + returnStatusWire = returnStatus; + return(returnStatus); +} + +uint8_t I2C::beginTransmission(int address) +{ + return(beginTransmission((uint8_t) address)); +} + +uint8_t I2C::send(uint8_t databyte) +{ + if(returnStatusWire) + { + return(returnStatusWire); + } + returnStatus = 0; + returnStatus = sendByte(databyte); + returnStatusWire = returnStatus; + return(returnStatus); +} + +uint8_t I2C::send(int databyte) +{ + return(send((uint8_t) databyte)); +} + +uint8_t I2C::endTransmission() +{ + stop(); + return(returnStatusWire); +} + +uint8_t I2C::requestFrom(int address, int numberBytes) +{ + return(requestFrom((uint8_t) address, (uint8_t) numberBytes)); +} + +uint8_t I2C::requestFrom(uint8_t address, uint8_t numberBytes) +{ + returnStatus = 0; + returnStatus = read(address,numberBytes); + if(!returnStatus) + { + return(numberBytes); + } + return(0); +} + +uint8_t I2C::available() +{ + return(bytesAvailable); +} + +uint8_t I2C::receive() +{ + bufferIndex = totalBytes - bytesAvailable; + if(!bytesAvailable) + { + bufferIndex = 0; + return(0); + } + bytesAvailable--; + return(data[bufferIndex]); +} + + + + + +///////////////////////////////////////////////////// + +uint8_t I2C::write(uint8_t address, uint8_t registerAddress) +{ + returnStatus = 0; + returnStatus = start(); + if(returnStatus){return(returnStatus);} + returnStatus = sendAddress(SLA_W(address)); + if(returnStatus){return(returnStatus);} + returnStatus = sendByte(registerAddress); + if(returnStatus){return(returnStatus);} + returnStatus = stop(); + return(returnStatus); +} + +uint8_t I2C::write(int address, int registerAddress) +{ + return(write((uint8_t) address, (uint8_t) registerAddress)); +} + +uint8_t I2C::write(uint8_t address, uint8_t registerAddress, uint8_t databyte) +{ + returnStatus = 0; + returnStatus = start(); + if(returnStatus){return(returnStatus);} + returnStatus = sendAddress(SLA_W(address)); + if(returnStatus){return(returnStatus);} + returnStatus = sendByte(registerAddress); + if(returnStatus){return(returnStatus);} + returnStatus = sendByte(databyte); + if(returnStatus){return(returnStatus);} + returnStatus = stop(); + return(returnStatus); +} + +uint8_t I2C::write(int address, int registerAddress, int databyte) +{ + return(write((uint8_t) address, (uint8_t) registerAddress, (uint8_t) databyte)); +} + +uint8_t I2C::write(uint8_t address, uint8_t registerAddress, char *databytes) +{ + uint8_t bufferLength = strlen(databytes); + returnStatus = 0; + returnStatus = write(address, registerAddress, (uint8_t*)databytes, bufferLength); + return(returnStatus); +} + +uint8_t I2C::write(uint8_t address, uint8_t registerAddress, uint8_t *databytes, uint8_t numberBytes) +{ + returnStatus = 0; + returnStatus = start(); + if(returnStatus){return(returnStatus);} + returnStatus = sendAddress(SLA_W(address)); + if(returnStatus){return(returnStatus);} + returnStatus = sendByte(registerAddress); + if(returnStatus){return(returnStatus);} + for (uint8_t i = 0; i < numberBytes; i++) + { + returnStatus = sendByte(databytes[i]); + if(returnStatus){return(returnStatus);} + } + returnStatus = stop(); + return(returnStatus); +} + +uint8_t I2C::read(int address, int numberBytes) +{ + return(read((uint8_t) address, (uint8_t) numberBytes)); +} + +uint8_t I2C::read(uint8_t address, uint8_t numberBytes) +{ + bytesAvailable = 0; + bufferIndex = 0; + if(numberBytes == 0){numberBytes++;} + nack = numberBytes - 1; + returnStatus = 0; + returnStatus = start(); + if(returnStatus){return(returnStatus);} + returnStatus = sendAddress(SLA_R(address)); + if(returnStatus){return(returnStatus);} + for(uint8_t i = 0; i < numberBytes; i++) + { + if( i == nack ) + { + returnStatus = receiveByte(0); + if(returnStatus != MR_DATA_NACK){return(returnStatus);} + } + else + { + returnStatus = receiveByte(1); + if(returnStatus != MR_DATA_ACK){return(returnStatus);} + } + data[i] = TWDR; + bytesAvailable = i+1; + totalBytes = i+1; + } + returnStatus = stop(); + return(returnStatus); +} + +uint8_t I2C::read(int address, int registerAddress, int numberBytes) +{ + return(read((uint8_t) address, (uint8_t) registerAddress, (uint8_t) numberBytes)); +} + +uint8_t I2C::read(uint8_t address, uint8_t registerAddress, uint8_t numberBytes) +{ + bytesAvailable = 0; + bufferIndex = 0; + if(numberBytes == 0){numberBytes++;} + nack = numberBytes - 1; + returnStatus = 0; + returnStatus = start(); + if(returnStatus){return(returnStatus);} + returnStatus = sendAddress(SLA_W(address)); + if(returnStatus){return(returnStatus);} + returnStatus = sendByte(registerAddress); + if(returnStatus){return(returnStatus);} + returnStatus = start(); + if(returnStatus){return(returnStatus);} + returnStatus = sendAddress(SLA_R(address)); + if(returnStatus){return(returnStatus);} + for(uint8_t i = 0; i < numberBytes; i++) + { + if( i == nack ) + { + returnStatus = receiveByte(0); + if(returnStatus != MR_DATA_NACK){return(returnStatus);} + } + else + { + returnStatus = receiveByte(1); + if(returnStatus != MR_DATA_ACK){return(returnStatus);} + } + data[i] = TWDR; + bytesAvailable = i+1; + totalBytes = i+1; + } + returnStatus = stop(); + return(returnStatus); +} + +uint8_t I2C::read(uint8_t address, uint8_t numberBytes, uint8_t *dataBuffer) +{ + bytesAvailable = 0; + bufferIndex = 0; + if(numberBytes == 0){numberBytes++;} + nack = numberBytes - 1; + returnStatus = 0; + returnStatus = start(); + if(returnStatus){return(returnStatus);} + returnStatus = sendAddress(SLA_R(address)); + if(returnStatus){return(returnStatus);} + for(uint8_t i = 0; i < numberBytes; i++) + { + if( i == nack ) + { + returnStatus = receiveByte(0); + if(returnStatus != MR_DATA_NACK){return(returnStatus);} + } + else + { + returnStatus = receiveByte(1); + if(returnStatus != MR_DATA_ACK){return(returnStatus);} + } + dataBuffer[i] = TWDR; + bytesAvailable = i+1; + totalBytes = i+1; + } + returnStatus = stop(); + return(returnStatus); +} + +uint8_t I2C::read(uint8_t address, uint8_t registerAddress, uint8_t numberBytes, uint8_t *dataBuffer) +{ + bytesAvailable = 0; + bufferIndex = 0; + if(numberBytes == 0){numberBytes++;} + nack = numberBytes - 1; + returnStatus = 0; + returnStatus = start(); + if(returnStatus){return(returnStatus);} + returnStatus = sendAddress(SLA_W(address)); + if(returnStatus){return(returnStatus);} + returnStatus = sendByte(registerAddress); + if(returnStatus){return(returnStatus);} + returnStatus = start(); + if(returnStatus){return(returnStatus);} + returnStatus = sendAddress(SLA_R(address)); + if(returnStatus){return(returnStatus);} + for(uint8_t i = 0; i < numberBytes; i++) + { + if( i == nack ) + { + returnStatus = receiveByte(0); + if(returnStatus != MR_DATA_NACK){return(returnStatus);} + } + else + { + returnStatus = receiveByte(1); + if(returnStatus != MR_DATA_ACK){return(returnStatus);} + } + dataBuffer[i] = TWDR; + bytesAvailable = i+1; + totalBytes = i+1; + } + returnStatus = stop(); + return(returnStatus); +} + + +/////////////// Private Methods //////////////////////////////////////// + + +uint8_t I2C::start() +{ + unsigned long startingTime = millis(); + TWCR = (1<= timeOutDelay) + { + lockUp(); + return(1); + } + + } + if ((TWI_STATUS == START) || (TWI_STATUS == REPEATED_START)) + { + return(0); + } + return(TWI_STATUS); +} + +uint8_t I2C::sendAddress(uint8_t i2cAddress) +{ + TWDR = i2cAddress; + unsigned long startingTime = millis(); + TWCR = (1<= timeOutDelay) + { + lockUp(); + return(1); + } + + } + if ((TWI_STATUS == MT_SLA_ACK) || (TWI_STATUS == MR_SLA_ACK)) + { + return(0); + } + return(TWI_STATUS); +} + +uint8_t I2C::sendByte(uint8_t i2cData) +{ + TWDR = i2cData; + unsigned long startingTime = millis(); + TWCR = (1<= timeOutDelay) + { + lockUp(); + return(1); + } + + } + if (TWI_STATUS == MT_DATA_ACK) + { + return(0); + } + return(TWI_STATUS); +} + +uint8_t I2C::receiveByte(boolean ack) +{ + unsigned long startingTime = millis(); + if(ack) + { + TWCR = (1<= timeOutDelay) + { + lockUp(); + return(1); + } + + } + return(TWI_STATUS); +} + +uint8_t I2C::stop() +{ + unsigned long startingTime = millis(); + TWCR = (1<= timeOutDelay) + { + lockUp(); + return(1); + } + + } + return(0); +} + +void I2C::lockUp() +{ + TWCR = 0; //releases SDA and SCL lines to high impedance + TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWEA); //reinitialize TWI _lockup_count++; } uint8_t I2C::lockup_count(void) { return _lockup_count; -} - -SIGNAL(TWI_vect) -{ - switch(TWI_STATUS){ - case 0x20: - case 0x30: - case 0x48: - TWCR = (1< -#if defined(ARDUINO) && ARDUINO >= 100 - #include "Arduino.h" -#else - #include "WProgram.h" -#endif - -#ifndef I2C_h -#define I2C_h - - -#define START 0x08 -#define REPEATED_START 0x10 -#define MT_SLA_ACK 0x18 -#define MT_DATA_ACK 0x28 -#define MR_SLA_ACK 0x40 -#define MR_DATA_ACK 0x50 -#define MR_DATA_NACK 0x58 -#define TWI_STATUS (TWSR & 0xF8) -#define SLA_W(address) (address << 1) -#define SLA_R(address) ((address << 1) + 0x01) -#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit)) -#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit)) - -#define MAX_BUFFER_SIZE 32 - - -#ifndef CPU_FREQ -#define CPU_FREQ 16000000L -#endif - - - -class I2C -{ - public: - I2C(); - void begin(); - void end(); - void timeOut(uint16_t); - void setSpeed(boolean); - void pullup(boolean); - ///////carry over from Wire library//////// - uint8_t returnStatusWire; - uint8_t beginTransmission(uint8_t); - uint8_t beginTransmission(int); - uint8_t send(uint8_t); - uint8_t send(int); - uint8_t endTransmission(); - uint8_t requestFrom(uint8_t, uint8_t); - uint8_t requestFrom(int, int); - uint8_t available(); - /////////////////////////////////////////// - uint8_t write(uint8_t, uint8_t); - uint8_t write(int, int); - uint8_t write(uint8_t, uint8_t, uint8_t); - uint8_t write(int, int, int); - uint8_t write(uint8_t, uint8_t, char*); - uint8_t write(uint8_t, uint8_t, uint8_t*, uint8_t); - uint8_t read(uint8_t, uint8_t); - uint8_t read(int, int); - uint8_t read(uint8_t, uint8_t, uint8_t); - uint8_t read(int, int, int); - uint8_t read(uint8_t, uint8_t, uint8_t*); - uint8_t read(uint8_t, uint8_t, uint8_t, uint8_t*); - uint8_t receive(); +/* + I2C.h - I2C library + Copyright (c) 2011 Wayne Truchsess. All right reserved. + Rev 2.0 - September 19th, 2011 + - Added support for timeout function to prevent + and recover from bus lockup (thanks to PaulS + and CrossRoads on the Arduino forum) + - Changed return type for stop() from void to + uint8_t to handle timeOut function + Rev 1.0 - August 8th, 2011 + + This is a modified version of the Arduino Wire/TWI + library. Functions were rewritten to provide more functionality + and also the use of Repeated Start. Some I2C devices will not + function correctly without the use of a Repeated Start. The + initial version of this library only supports the Master. + + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include +#if defined(ARDUINO) && ARDUINO >= 100 + #include "Arduino.h" +#else + #include "WProgram.h" +#endif + +#ifndef I2C_h +#define I2C_h + + +#define START 0x08 +#define REPEATED_START 0x10 +#define MT_SLA_ACK 0x18 +#define MT_DATA_ACK 0x28 +#define MR_SLA_ACK 0x40 +#define MR_DATA_ACK 0x50 +#define MR_DATA_NACK 0x58 +#define TWI_STATUS (TWSR & 0xF8) +#define SLA_W(address) (address << 1) +#define SLA_R(address) ((address << 1) + 0x01) +#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit)) +#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit)) + +#define MAX_BUFFER_SIZE 32 + + +#ifndef CPU_FREQ +#define CPU_FREQ 16000000L +#endif + + + +class I2C +{ + public: + I2C(); + void begin(); + void end(); + void timeOut(uint16_t); + void setSpeed(boolean); + void pullup(boolean); + ///////carry over from Wire library//////// + uint8_t returnStatusWire; + uint8_t beginTransmission(uint8_t); + uint8_t beginTransmission(int); + uint8_t send(uint8_t); + uint8_t send(int); + uint8_t endTransmission(); + uint8_t requestFrom(uint8_t, uint8_t); + uint8_t requestFrom(int, int); + uint8_t available(); + /////////////////////////////////////////// + uint8_t write(uint8_t, uint8_t); + uint8_t write(int, int); + uint8_t write(uint8_t, uint8_t, uint8_t); + uint8_t write(int, int, int); + uint8_t write(uint8_t, uint8_t, char*); + uint8_t write(uint8_t, uint8_t, uint8_t*, uint8_t); + uint8_t read(uint8_t, uint8_t); + uint8_t read(int, int); + uint8_t read(uint8_t, uint8_t, uint8_t); + uint8_t read(int, int, int); + uint8_t read(uint8_t, uint8_t, uint8_t*); + uint8_t read(uint8_t, uint8_t, uint8_t, uint8_t*); + uint8_t receive(); uint8_t lockup_count(); - - private: - uint8_t start(); - uint8_t sendAddress(uint8_t); - uint8_t sendByte(uint8_t); - uint8_t receiveByte(boolean); - uint8_t stop(); - void lockUp(); - uint8_t returnStatus; - uint8_t nack; - uint8_t data[MAX_BUFFER_SIZE]; + + private: + uint8_t start(); + uint8_t sendAddress(uint8_t); + uint8_t sendByte(uint8_t); + uint8_t receiveByte(boolean); + uint8_t stop(); + void lockUp(); + uint8_t returnStatus; + uint8_t nack; + uint8_t data[MAX_BUFFER_SIZE]; uint8_t _lockup_count; - static uint8_t bytesAvailable; - static uint8_t bufferIndex; - static uint8_t totalBytes; - static uint16_t timeOutDelay; - -}; - -extern I2C I2c; - -#endif + static uint8_t bytesAvailable; + static uint8_t bufferIndex; + static uint8_t totalBytes; + static uint16_t timeOutDelay; + +}; + +extern I2C I2c; + +#endif From 9f0cb78f08ae1c93cd753583531901396ac6fb28 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 10 Mar 2012 16:44:22 +1100 Subject: [PATCH 143/178] AP_Math: re-work quaternion functions to be more C++ like thanks to Adam for the suggestion! --- libraries/AP_Math/AP_Math.cpp | 66 ------------------------- libraries/AP_Math/AP_Math.h | 13 ----- libraries/AP_Math/quaternion.cpp | 85 ++++++++++++++++++++++++++++++++ libraries/AP_Math/quaternion.h | 11 +++++ 4 files changed, 96 insertions(+), 79 deletions(-) create mode 100644 libraries/AP_Math/quaternion.cpp diff --git a/libraries/AP_Math/AP_Math.cpp b/libraries/AP_Math/AP_Math.cpp index 28a49d7aa6..e97763a2b5 100644 --- a/libraries/AP_Math/AP_Math.cpp +++ b/libraries/AP_Math/AP_Math.cpp @@ -69,69 +69,3 @@ void calculate_euler_angles(const Matrix3f &m, float *roll, float *pitch, float } } - -// create a quaternion from Euler angles -void quaternion_from_euler(Quaternion &q, float roll, float pitch, float yaw) -{ - float cr2 = cos(roll*0.5); - float cp2 = cos(pitch*0.5); - float cy2 = cos(yaw*0.5); - // the sign reversal here is due to the different conventions - // in the madgwick quaternion code and the rest of APM - float sr2 = -sin(roll*0.5); - float sp2 = -sin(pitch*0.5); - float sy2 = sin(yaw*0.5); - - q.q1 = cr2*cp2*cy2 + sr2*sp2*sy2; - q.q2 = sr2*cp2*cy2 - cr2*sp2*sy2; - q.q3 = cr2*sp2*cy2 + sr2*cp2*sy2; - q.q4 = cr2*cp2*sy2 - sr2*sp2*cy2; -} - -// create eulers from a quaternion -void euler_from_quaternion(const Quaternion &q, float *roll, float *pitch, float *yaw) -{ - *roll = -(atan2(2.0*(q.q1*q.q2 + q.q3*q.q4), - 1 - 2.0*(q.q2*q.q2 + q.q3*q.q3))); - // we let safe_asin() handle the singularities near 90/-90 in pitch - *pitch = -safe_asin(2.0*(q.q1*q.q3 - q.q4*q.q2)); - *yaw = atan2(2.0*(q.q1*q.q4 + q.q2*q.q3), - 1 - 2.0*(q.q3*q.q3 + q.q4*q.q4)); -} - -// convert a quaternion to a rotation matrix -void quaternion_to_rotation_matrix(const Quaternion &q, Matrix3f &m) -{ - float q3q3 = q.q3 * q.q3; - float q3q4 = q.q3 * q.q4; - float q2q2 = q.q2 * q.q2; - float q2q3 = q.q2 * q.q3; - float q2q4 = q.q2 * q.q4; - float q1q2 = q.q1 * q.q2; - float q1q3 = q.q1 * q.q3; - float q1q4 = q.q1 * q.q4; - float q4q4 = q.q4 * q.q4; - - m.a.x = 1-2*(q3q3 + q4q4); - m.a.y = 2*(q2q3 - q1q4); - m.a.z = - 2*(q2q4 + q1q3); - m.b.x = 2*(q2q3 + q1q4); - m.b.y = 1-2*(q2q2 + q4q4); - m.b.z = -2*(q3q4 - q1q2); - m.c.x = -2*(q2q4 - q1q3); - m.c.y = -2*(q3q4 + q1q2); - m.c.z = 1-2*(q2q2 + q3q3); -} - -// convert a vector in earth frame to a vector in body frame, -// assuming body current rotation is given by a quaternion -void quaternion_earth_to_body(const Quaternion &q, Vector3f &v) -{ - Matrix3f m; - // we reverse z before and afterwards because of the differing - // quaternion conventions from APM conventions. - v.z = -v.z; - quaternion_to_rotation_matrix(q, m); - v = m * v; - v.z = -v.z; -} diff --git a/libraries/AP_Math/AP_Math.h b/libraries/AP_Math/AP_Math.h index 22de694877..035142f355 100644 --- a/libraries/AP_Math/AP_Math.h +++ b/libraries/AP_Math/AP_Math.h @@ -30,17 +30,4 @@ void rotation_matrix_from_euler(Matrix3f &m, float roll, float pitch, float yaw) // calculate euler angles from a rotation matrix void calculate_euler_angles(const Matrix3f &m, float *roll, float *pitch, float *yaw); -// create a quaternion from Euler angles -void quaternion_from_euler(Quaternion &q, float roll, float pitch, float yaw); - -// create eulers from a quaternion -void euler_from_quaternion(const Quaternion &q, float *roll, float *pitch, float *yaw); - -// convert a quaternion to a rotation matrix -void quaternion_to_rotation_matrix(const Quaternion &q, Matrix3f &m); - -// convert a vector in earth frame to a vector in body frame, -// assuming body current rotation is given by a quaternion -void quaternion_earth_to_body(const Quaternion &q, Vector3f &v); - #endif diff --git a/libraries/AP_Math/quaternion.cpp b/libraries/AP_Math/quaternion.cpp new file mode 100644 index 0000000000..f587bf1d31 --- /dev/null +++ b/libraries/AP_Math/quaternion.cpp @@ -0,0 +1,85 @@ +/// -*- tab-width: 4; Mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*- +/* + * quaternion.cpp + * Copyright (C) Andrew Tridgell 2012 + * + * This file is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This file is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + */ + +#include "AP_Math.h" + +// return the rotation matrix equivalent for this quaternion +void Quaternion::rotation_matrix(Matrix3f &m) +{ + float q3q3 = q3 * q3; + float q3q4 = q3 * q4; + float q2q2 = q2 * q2; + float q2q3 = q2 * q3; + float q2q4 = q2 * q4; + float q1q2 = q1 * q2; + float q1q3 = q1 * q3; + float q1q4 = q1 * q4; + float q4q4 = q4 * q4; + + m.a.x = 1-2*(q3q3 + q4q4); + m.a.y = 2*(q2q3 - q1q4); + m.a.z = - 2*(q2q4 + q1q3); + m.b.x = 2*(q2q3 + q1q4); + m.b.y = 1-2*(q2q2 + q4q4); + m.b.z = -2*(q3q4 - q1q2); + m.c.x = -2*(q2q4 - q1q3); + m.c.y = -2*(q3q4 + q1q2); + m.c.z = 1-2*(q2q2 + q3q3); +} + +// convert a vector from earth to body frame +void Quaternion::earth_to_body(Vector3f &v) +{ + Matrix3f m; + // we reverse z before and afterwards because of the differing + // quaternion conventions from APM conventions. + v.z = -v.z; + rotation_matrix(m); + v = m * v; + v.z = -v.z; +} + +// create a quaternion from Euler angles +void Quaternion::from_euler(float roll, float pitch, float yaw) +{ + float cr2 = cos(roll*0.5); + float cp2 = cos(pitch*0.5); + float cy2 = cos(yaw*0.5); + // the sign reversal here is due to the different conventions + // in the madgwick quaternion code and the rest of APM + float sr2 = -sin(roll*0.5); + float sp2 = -sin(pitch*0.5); + float sy2 = sin(yaw*0.5); + + q1 = cr2*cp2*cy2 + sr2*sp2*sy2; + q2 = sr2*cp2*cy2 - cr2*sp2*sy2; + q3 = cr2*sp2*cy2 + sr2*cp2*sy2; + q4 = cr2*cp2*sy2 - sr2*sp2*cy2; +} + +// create eulers from a quaternion +void Quaternion::to_euler(float *roll, float *pitch, float *yaw) +{ + *roll = -(atan2(2.0*(q1*q2 + q3*q4), + 1 - 2.0*(q2*q2 + q3*q3))); + // we let safe_asin() handle the singularities near 90/-90 in pitch + *pitch = -safe_asin(2.0*(q1*q3 - q4*q2)); + *yaw = atan2(2.0*(q1*q4 + q2*q3), + 1 - 2.0*(q3*q3 + q4*q4)); +} diff --git a/libraries/AP_Math/quaternion.h b/libraries/AP_Math/quaternion.h index d5b5913e82..f1932dbc29 100644 --- a/libraries/AP_Math/quaternion.h +++ b/libraries/AP_Math/quaternion.h @@ -33,5 +33,16 @@ public: bool is_nan(void) { return isnan(q1) || isnan(q2) || isnan(q3) || isnan(q4); } + // return the rotation matrix equivalent for this quaternion + void rotation_matrix(Matrix3f &m); + + // convert a vector from earth to body frame + void earth_to_body(Vector3f &v); + + // create a quaternion from Euler angles + void from_euler(float roll, float pitch, float yaw); + + // create eulers from a quaternion + void to_euler(float *roll, float *pitch, float *yaw); }; #endif // QUATERNION_H From 16c95236c08dfde07d8156c8a6a7fe695630dd76 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 10 Mar 2012 16:44:37 +1100 Subject: [PATCH 144/178] Quaternion: use the new quaternion API --- libraries/AP_Quaternion/AP_Quaternion.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/libraries/AP_Quaternion/AP_Quaternion.cpp b/libraries/AP_Quaternion/AP_Quaternion.cpp index 4dd2f438f2..bab1a06ef5 100644 --- a/libraries/AP_Quaternion/AP_Quaternion.cpp +++ b/libraries/AP_Quaternion/AP_Quaternion.cpp @@ -119,7 +119,7 @@ void AP_Quaternion::update_IMU(float deltat, Vector3f &gyro, Vector3f &accel) if (_compass) { _compass->null_offsets_disable(); } - quaternion_from_euler(q, roll, pitch, yaw); + q.from_euler(roll, pitch, yaw); if (_compass) { _compass->null_offsets_enable(); } @@ -280,7 +280,7 @@ void AP_Quaternion::update_MARG(float deltat, Vector3f &gyro, Vector3f &accel, V // and hope for the best ... renorm_blowup_count++; _compass->null_offsets_disable(); - quaternion_from_euler(q, roll, pitch, yaw); + q.from_euler(roll, pitch, yaw); _compass->null_offsets_disable(); return; } @@ -432,7 +432,7 @@ void AP_Quaternion::update_drift(float deltat, Vector3f &mag) // and hope for the best ... renorm_blowup_count++; _compass->null_offsets_disable(); - quaternion_from_euler(q, roll, pitch, yaw); + q.from_euler(roll, pitch, yaw); _compass->null_offsets_disable(); return; } @@ -481,7 +481,7 @@ void AP_Quaternion::update(void) _compass->use_for_yaw()) { // setup the quaternion with initial compass yaw _compass->null_offsets_disable(); - quaternion_from_euler(q, 0, 0, _compass->heading); + q.from_euler(0, 0, _compass->heading); _have_initial_yaw = true; _compass_last_update = _compass->last_update; gyro_bias.zero(); @@ -567,7 +567,7 @@ void AP_Quaternion::update(void) _gyro_corrected = gyro; // calculate our euler angles for high level control and navigation - euler_from_quaternion(q, &roll, &pitch, &yaw); + q.to_euler(&roll, &pitch, &yaw); // the code above assumes zero magnetic declination, so offset // the yaw here From 5c6368bad3778943e553e16e70d362a1b9e76804 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 10 Mar 2012 17:05:54 +1100 Subject: [PATCH 145/178] AP_Math: allow null pointers in Quaternion::to_euler() this matches the Matrix3f method --- libraries/AP_Math/quaternion.cpp | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/libraries/AP_Math/quaternion.cpp b/libraries/AP_Math/quaternion.cpp index f587bf1d31..aae3cada05 100644 --- a/libraries/AP_Math/quaternion.cpp +++ b/libraries/AP_Math/quaternion.cpp @@ -76,10 +76,16 @@ void Quaternion::from_euler(float roll, float pitch, float yaw) // create eulers from a quaternion void Quaternion::to_euler(float *roll, float *pitch, float *yaw) { - *roll = -(atan2(2.0*(q1*q2 + q3*q4), - 1 - 2.0*(q2*q2 + q3*q3))); - // we let safe_asin() handle the singularities near 90/-90 in pitch - *pitch = -safe_asin(2.0*(q1*q3 - q4*q2)); - *yaw = atan2(2.0*(q1*q4 + q2*q3), - 1 - 2.0*(q3*q3 + q4*q4)); + if (roll) { + *roll = -(atan2(2.0*(q1*q2 + q3*q4), + 1 - 2.0*(q2*q2 + q3*q3))); + } + if (pitch) { + // we let safe_asin() handle the singularities near 90/-90 in pitch + *pitch = -safe_asin(2.0*(q1*q3 - q4*q2)); + } + if (yaw) { + *yaw = atan2(2.0*(q1*q4 + q2*q3), + 1 - 2.0*(q3*q3 + q4*q4)); + } } From 4422486d44b339ed3ff4c6956387d4685f03644b Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 10 Mar 2012 17:06:35 +1100 Subject: [PATCH 146/178] AP_Math: made rotation matrices more C++ thanks to Adam for the suggestion --- libraries/AP_Math/AP_Math.cpp | 39 --------------------------------- libraries/AP_Math/AP_Math.h | 6 ----- libraries/AP_Math/matrix3.cpp | 41 +++++++++++++++++++++++++++++++++++ libraries/AP_Math/matrix3.h | 5 +++++ 4 files changed, 46 insertions(+), 45 deletions(-) diff --git a/libraries/AP_Math/AP_Math.cpp b/libraries/AP_Math/AP_Math.cpp index e97763a2b5..ab16fbe833 100644 --- a/libraries/AP_Math/AP_Math.cpp +++ b/libraries/AP_Math/AP_Math.cpp @@ -30,42 +30,3 @@ float safe_sqrt(float v) } return ret; } - - -// create a rotation matrix given some euler angles -// this is based on http://gentlenav.googlecode.com/files/EulerAngles.pdf -void rotation_matrix_from_euler(Matrix3f &m, float roll, float pitch, float yaw) -{ - float cp = cos(pitch); - float sp = sin(pitch); - float sr = sin(roll); - float cr = cos(roll); - float sy = sin(yaw); - float cy = cos(yaw); - - m.a.x = cp * cy; - m.a.y = (sr * sp * cy) - (cr * sy); - m.a.z = (cr * sp * cy) + (sr * sy); - m.b.x = cp * sy; - m.b.y = (sr * sp * sy) + (cr * cy); - m.b.z = (cr * sp * sy) - (sr * cy); - m.c.x = -sp; - m.c.y = sr * cp; - m.c.z = cr * cp; -} - -// calculate euler angles from a rotation matrix -// this is based on http://gentlenav.googlecode.com/files/EulerAngles.pdf -void calculate_euler_angles(const Matrix3f &m, float *roll, float *pitch, float *yaw) -{ - if (pitch != NULL) { - *pitch = -safe_asin(m.c.x); - } - if (roll != NULL) { - *roll = atan2(m.c.y, m.c.z); - } - if (yaw != NULL) { - *yaw = atan2(m.b.x, m.a.x); - } -} - diff --git a/libraries/AP_Math/AP_Math.h b/libraries/AP_Math/AP_Math.h index 035142f355..cdc1d957d9 100644 --- a/libraries/AP_Math/AP_Math.h +++ b/libraries/AP_Math/AP_Math.h @@ -24,10 +24,4 @@ float safe_asin(float v); // a varient of sqrt() that always gives a valid answer. float safe_sqrt(float v); -// create a rotation matrix given some euler angles -void rotation_matrix_from_euler(Matrix3f &m, float roll, float pitch, float yaw); - -// calculate euler angles from a rotation matrix -void calculate_euler_angles(const Matrix3f &m, float *roll, float *pitch, float *yaw); - #endif diff --git a/libraries/AP_Math/matrix3.cpp b/libraries/AP_Math/matrix3.cpp index d50419f332..9122be5316 100644 --- a/libraries/AP_Math/matrix3.cpp +++ b/libraries/AP_Math/matrix3.cpp @@ -94,5 +94,46 @@ void Matrix3::rotation(enum Rotation r) } } +// create a rotation matrix given some euler angles +// this is based on http://gentlenav.googlecode.com/files/EulerAngles.pdf +template +void Matrix3::from_euler(float roll, float pitch, float yaw) +{ + float cp = cos(pitch); + float sp = sin(pitch); + float sr = sin(roll); + float cr = cos(roll); + float sy = sin(yaw); + float cy = cos(yaw); + + a.x = cp * cy; + a.y = (sr * sp * cy) - (cr * sy); + a.z = (cr * sp * cy) + (sr * sy); + b.x = cp * sy; + b.y = (sr * sp * sy) + (cr * cy); + b.z = (cr * sp * sy) - (sr * cy); + c.x = -sp; + c.y = sr * cp; + c.z = cr * cp; +} + +// calculate euler angles from a rotation matrix +// this is based on http://gentlenav.googlecode.com/files/EulerAngles.pdf +template +void Matrix3::to_euler(float *roll, float *pitch, float *yaw) +{ + if (pitch != NULL) { + *pitch = -safe_asin(c.x); + } + if (roll != NULL) { + *roll = atan2(c.y, c.z); + } + if (yaw != NULL) { + *yaw = atan2(b.x, a.x); + } +} + // only define for float template void Matrix3::rotation(enum Rotation); +template void Matrix3::from_euler(float roll, float pitch, float yaw); +template void Matrix3::to_euler(float *roll, float *pitch, float *yaw); diff --git a/libraries/AP_Math/matrix3.h b/libraries/AP_Math/matrix3.h index 561c56a64e..85861d6783 100644 --- a/libraries/AP_Math/matrix3.h +++ b/libraries/AP_Math/matrix3.h @@ -131,6 +131,11 @@ public: // fill in the matrix with a standard rotation void rotation(enum Rotation rotation); + // create a rotation matrix from Euler angles + void from_euler(float roll, float pitch, float yaw); + + // create eulers from a rotation matrix + void to_euler(float *roll, float *pitch, float *yaw); }; typedef Matrix3 Matrix3i; From 4d3789d11cda3dc94d29b1e330c6e6b60714ccbb Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 10 Mar 2012 17:06:46 +1100 Subject: [PATCH 147/178] AP_Math: update the test suite --- libraries/AP_Math/examples/eulers/eulers.pde | 27 ++++++++++---------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/libraries/AP_Math/examples/eulers/eulers.pde b/libraries/AP_Math/examples/eulers/eulers.pde index 5db00ec80e..953f71cee8 100644 --- a/libraries/AP_Math/examples/eulers/eulers.pde +++ b/libraries/AP_Math/examples/eulers/eulers.pde @@ -66,9 +66,6 @@ static void check_result(float roll, float pitch, float yaw, Serial.printf("incorrect eulers roll=%f/%f pitch=%f/%f yaw=%f/%f\n", ToDeg(roll), ToDeg(roll2), ToDeg(pitch), ToDeg(pitch2), ToDeg(yaw), ToDeg(yaw2)); } - } else { - Serial.printf("correct eulers roll=%f/%f pitch=%f/%f yaw=%f/%f\n", - ToDeg(roll), ToDeg(roll2), ToDeg(pitch), ToDeg(pitch2), ToDeg(yaw), ToDeg(yaw2)); } } @@ -77,8 +74,8 @@ static void test_euler(float roll, float pitch, float yaw) Matrix3f m; float roll2, pitch2, yaw2; - rotation_matrix_from_euler(m, roll, pitch, yaw); - calculate_euler_angles(m, &roll2, &pitch2, &yaw2); + m.from_euler(roll, pitch, yaw); + m.to_euler(&roll2, &pitch2, &yaw2); check_result(roll, pitch, yaw, roll2, pitch2, yaw2); } @@ -107,8 +104,8 @@ static void test_quaternion(float roll, float pitch, float yaw) Quaternion q; float roll2, pitch2, yaw2; - quaternion_from_euler(q, roll, pitch, yaw); - euler_from_quaternion(q, &roll2, &pitch2, &yaw2); + q.from_euler(roll, pitch, yaw); + q.to_euler(&roll2, &pitch2, &yaw2); check_result(roll, pitch, yaw, roll2, pitch2, yaw2); } @@ -152,17 +149,19 @@ static void test_conversion(float roll, float pitch, float yaw) Matrix3f m, m2; float roll2, pitch2, yaw2; + float roll3, pitch3, yaw3; - quaternion_from_euler(q, roll, pitch, yaw); - quaternion_to_rotation_matrix(q, m); - rotation_matrix_from_euler(m2, roll, pitch, yaw); - - calculate_euler_angles(m, &roll2, &pitch2, &yaw2); + q.from_euler(roll, pitch, yaw); + q.rotation_matrix(m); + m.to_euler(&roll2, &pitch2, &yaw2); + m2.from_euler(roll, pitch, yaw); + m2.to_euler(&roll3, &pitch3, &yaw3); if (m.is_nan()) { Serial.printf("NAN matrix roll=%f pitch=%f yaw=%f\n", roll, pitch, yaw); } check_result(roll, pitch, yaw, roll2, pitch2, yaw2); + check_result(roll, pitch, yaw, roll3, pitch3, yaw3); } void test_conversions(void) @@ -194,9 +193,9 @@ void test_frame_transforms(void) Serial.println("frame transform tests\n"); - quaternion_from_euler(q, ToRad(90), 0, 0); + q.from_euler(ToRad(90), 0, 0); v2 = v = Vector3f(0, 0, 1); - quaternion_earth_to_body(q, v2); + q.earth_to_body(v2); printf("%f %f %f\n", v2.x, v2.y, v2.z); } From e8f1c5742b453c8541c37989975c8492123218bf Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 10 Mar 2012 17:07:07 +1100 Subject: [PATCH 148/178] DCM: update for new Matrix3f interface --- libraries/AP_DCM/AP_DCM.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/libraries/AP_DCM/AP_DCM.cpp b/libraries/AP_DCM/AP_DCM.cpp index 954f79767f..5d08c9b810 100644 --- a/libraries/AP_DCM/AP_DCM.cpp +++ b/libraries/AP_DCM/AP_DCM.cpp @@ -176,10 +176,10 @@ AP_DCM::matrix_reset(bool recover_eulers) // attitude then calculate the dcm matrix from the current // roll/pitch/yaw values if (recover_eulers && !isnan(roll) && !isnan(pitch) && !isnan(yaw)) { - rotation_matrix_from_euler(_dcm_matrix, roll, pitch, yaw); + _dcm_matrix.from_euler(roll, pitch, yaw); } else { // otherwise make it flat - rotation_matrix_from_euler(_dcm_matrix, 0, 0, 0); + _dcm_matrix.from_euler(0, 0, 0); } if (_compass != NULL) { @@ -426,7 +426,7 @@ AP_DCM::drift_correction(float deltat) // now construct a new DCM matrix _compass->null_offsets_disable(); - rotation_matrix_from_euler(_dcm_matrix, roll, pitch, _compass->heading); + _dcm_matrix.from_euler(roll, pitch, _compass->heading); _compass->null_offsets_enable(); _have_initial_yaw = true; _compass_last_update = _compass->last_update; @@ -452,7 +452,7 @@ AP_DCM::drift_correction(float deltat) if (_compass) { _compass->null_offsets_disable(); } - rotation_matrix_from_euler(_dcm_matrix, roll, pitch, ToRad(_gps->ground_course)); + _dcm_matrix.from_euler(roll, pitch, ToRad(_gps->ground_course)); if (_compass) { _compass->null_offsets_enable(); } @@ -532,7 +532,7 @@ AP_DCM::drift_correction(float deltat) void AP_DCM::euler_angles(void) { - calculate_euler_angles(_dcm_matrix, &roll, &pitch, &yaw); + _dcm_matrix.to_euler(&roll, &pitch, &yaw); roll_sensor = degrees(roll) * 100; pitch_sensor = degrees(pitch) * 100; From 4bf28d499ab4fdc18be56ebe801f27aad304ea66 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 10 Mar 2012 17:07:20 +1100 Subject: [PATCH 149/178] Quaternion: update for new Quaternion interface --- libraries/AP_Quaternion/AP_Quaternion.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/AP_Quaternion/AP_Quaternion.h b/libraries/AP_Quaternion/AP_Quaternion.h index 20028f1efe..4d8b061765 100644 --- a/libraries/AP_Quaternion/AP_Quaternion.h +++ b/libraries/AP_Quaternion/AP_Quaternion.h @@ -75,7 +75,7 @@ public: float get_error_yaw(void); Matrix3f get_dcm_matrix(void) { Matrix3f ret; - quaternion_to_rotation_matrix(q, ret); + q.rotation_matrix(ret); return ret; } From 0ec98576897dac224ec08a18a6b899ad406d6388 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 10 Mar 2012 17:29:32 +1100 Subject: [PATCH 150/178] Math: any euler angle with pitch > 90 is invalid both DCM and quaternion always return pitch in the range -90 to 90 --- libraries/AP_Math/examples/eulers/eulers.pde | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/libraries/AP_Math/examples/eulers/eulers.pde b/libraries/AP_Math/examples/eulers/eulers.pde index 953f71cee8..620b6d60f3 100644 --- a/libraries/AP_Math/examples/eulers/eulers.pde +++ b/libraries/AP_Math/examples/eulers/eulers.pde @@ -57,7 +57,9 @@ static void check_result(float roll, float pitch, float yaw, if (rad_diff(roll2,roll) > 0.01 || rad_diff(pitch2, pitch) > 0.01 || rad_diff(yaw2, yaw) > 0.01) { - if (ToDeg(rad_diff(pitch, PI/2)) < 1 || + if (pitch >= PI/2 || + pitch <= -PI/2 || + ToDeg(rad_diff(pitch, PI/2)) < 1 || ToDeg(rad_diff(pitch, -PI/2)) < 1) { // we expect breakdown at these poles Serial.printf("breakdown eulers roll=%f/%f pitch=%f/%f yaw=%f/%f\n", @@ -152,14 +154,19 @@ static void test_conversion(float roll, float pitch, float yaw) float roll3, pitch3, yaw3; q.from_euler(roll, pitch, yaw); + q.to_euler(&roll2, &pitch2, &yaw2); + check_result(roll, pitch, yaw, roll2, pitch2, yaw2); + q.rotation_matrix(m); m.to_euler(&roll2, &pitch2, &yaw2); + m2.from_euler(roll, pitch, yaw); m2.to_euler(&roll3, &pitch3, &yaw3); if (m.is_nan()) { Serial.printf("NAN matrix roll=%f pitch=%f yaw=%f\n", roll, pitch, yaw); } + check_result(roll, pitch, yaw, roll2, pitch2, yaw2); check_result(roll, pitch, yaw, roll3, pitch3, yaw3); } @@ -206,6 +213,9 @@ void setup(void) { Serial.begin(115200); Serial.println("euler unit tests\n"); + + test_conversion(0, PI, 0); + test_frame_transforms(); test_conversions(); test_quaternion_eulers(); From 0da64e98f89418dc0be102e34f1ecb5e42b0f746 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 10 Mar 2012 20:03:48 +1100 Subject: [PATCH 151/178] Compass: don't save the orientation to EEPROM there is no point in saving this, the value is only configurable at compile time for now, and is always set --- libraries/AP_Compass/AP_Compass_HMC5843.cpp | 4 ++-- libraries/AP_Compass/Compass.cpp | 7 +++---- libraries/AP_Compass/Compass.h | 2 +- 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/libraries/AP_Compass/AP_Compass_HMC5843.cpp b/libraries/AP_Compass/AP_Compass_HMC5843.cpp index a4fb928ee4..6ec074d28b 100644 --- a/libraries/AP_Compass/AP_Compass_HMC5843.cpp +++ b/libraries/AP_Compass/AP_Compass_HMC5843.cpp @@ -264,7 +264,7 @@ bool AP_Compass_HMC5843::read() // rotate to the desired orientation Vector3f rot_mag = Vector3f(mag_x,mag_y,mag_z); - rot_mag.rotate((enum Rotation)_orientation.get()); + rot_mag.rotate(_orientation); if (product_id == AP_COMPASS_TYPE_HMC5883L) { rot_mag.rotate(ROTATION_YAW_90); } @@ -282,5 +282,5 @@ bool AP_Compass_HMC5843::read() void AP_Compass_HMC5843::set_orientation(enum Rotation rotation) { - _orientation.set_and_save(rotation); + _orientation = rotation; } diff --git a/libraries/AP_Compass/Compass.cpp b/libraries/AP_Compass/Compass.cpp index 458d6edc4b..7a54c25dc0 100644 --- a/libraries/AP_Compass/Compass.cpp +++ b/libraries/AP_Compass/Compass.cpp @@ -7,7 +7,6 @@ const AP_Param::GroupInfo Compass::var_info[] PROGMEM = { AP_GROUPINFO("DEC", 2, Compass, _declination), AP_GROUPINFO("LEARN", 3, Compass, _learn), // true if learning calibration AP_GROUPINFO("USE", 4, Compass, _use_for_yaw), // true if used for DCM yaw - AP_GROUPINFO("ORIENT", 5, Compass, _orientation), AP_GROUPEND }; @@ -21,9 +20,9 @@ Compass::Compass(void) : _learn(1), _use_for_yaw(1), _null_enable(false), - _null_init_done(false) + _null_init_done(false), + _orientation(ROTATION_NONE) { - _orientation.set(ROTATION_NONE); } // Default init method, just returns success. @@ -37,7 +36,7 @@ Compass::init() void Compass::set_orientation(enum Rotation rotation) { - _orientation.set_and_save(rotation); + _orientation = rotation; } void diff --git a/libraries/AP_Compass/Compass.h b/libraries/AP_Compass/Compass.h index 4ded933688..35135ee03e 100644 --- a/libraries/AP_Compass/Compass.h +++ b/libraries/AP_Compass/Compass.h @@ -119,7 +119,7 @@ public: static const struct AP_Param::GroupInfo var_info[]; protected: - AP_Int8 _orientation; + enum Rotation _orientation; AP_Vector3f _offset; AP_Float _declination; AP_Int8 _learn; /// Date: Sun, 11 Mar 2012 19:00:51 +1100 Subject: [PATCH 152/178] Compass: removed an incorrect comment --- libraries/AP_Compass/Compass.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/libraries/AP_Compass/Compass.h b/libraries/AP_Compass/Compass.h index 35135ee03e..2d423909c0 100644 --- a/libraries/AP_Compass/Compass.h +++ b/libraries/AP_Compass/Compass.h @@ -27,8 +27,6 @@ public: /// Constructor /// - /// @param key Storage key used for configuration data. - /// Compass(); /// Initialize the compass device. From d2a07b16036de21d2b1ad56aed498896b40047d1 Mon Sep 17 00:00:00 2001 From: Adam M Rivera Date: Sat, 10 Mar 2012 13:38:45 -0600 Subject: [PATCH 153/178] Added AP_Declination library. It contains the lookup table (lat/lng -> declination) as well as a method that performs the lookup. Signed-off-by: Andrew Tridgell --- libraries/AP_Declination/AP_Declination.cpp | 48 +++++++++++++++++++++ libraries/AP_Declination/AP_Declination.h | 25 +++++++++++ 2 files changed, 73 insertions(+) create mode 100644 libraries/AP_Declination/AP_Declination.cpp create mode 100644 libraries/AP_Declination/AP_Declination.h diff --git a/libraries/AP_Declination/AP_Declination.cpp b/libraries/AP_Declination/AP_Declination.cpp new file mode 100644 index 0000000000..13f4a26a5e --- /dev/null +++ b/libraries/AP_Declination/AP_Declination.cpp @@ -0,0 +1,48 @@ +/// -*- tab-width: 4; Mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*- +#include "AP_Declination.h" + +/* + * Adam M Rivera + * With direction from: Andrew Tridgell, Jason Short, Justin Beech + * + * Adapted from: http://www.societyofrobots.com/robotforum/index.php?topic=11855.0 + * Scott Ferguson + * scottfromscott@gmail.com + * +*/ + +static const int8_t dec_tbl[25][73] PROGMEM = {46,46,45,44,44,43,42,42,41,41,40,39,38,37,36,35,33,31,28,26,23,20,16,13,10,7,4,1,-1,-3,-5,-7,-9,-12,-14,-16,-19,-22,-26,-29,-33,-36,-40,-44,-48,-51,-55,-58,-61,-64,-66,-68,-71,-72,-74,-74,-75,-74,-72,-68,-61,-48,-25,2,22,33,40,43,45,46,47,46,46,36,36,36,36,36,35,35,35,35,34,34,34,34,33,32,31,30,28,26,23,20,17,14,10,6,3,0,-2,-4,-7,-9,-10,-12,-14,-15,-17,-20,-23,-26,-29,-32,-36,-40,-43,-47,-50,-53,-56,-58,-60,-62,-63,-64,-64,-63,-62,-59,-55,-49,-41,-30,-17,-4,6,15,22,27,31,33,34,35,36,36,30,30,30,30,30,30,30,29,29,29,29,29,29,29,29,28,27,26,24,21,18,15,11,7,3,0,-3,-6,-9,-11,-12,-14,-15,-16,-17,-19,-21,-23,-26,-29,-32,-35,-39,-42,-45,-48,-51,-53,-55,-56,-57,-57,-56,-55,-53,-49,-44,-38,-31,-23,-14,-6,0,7,13,17,21,24,26,27,29,29,30,25,25,26,26,26,25,25,25,25,25,25,25,25,26,25,25,24,23,21,19,16,12,8,4,0,-3,-7,-10,-13,-15,-16,-17,-18,-19,-20,-21,-22,-23,-25,-28,-31,-34,-37,-40,-43,-46,-48,-49,-50,-51,-51,-50,-48,-45,-42,-37,-32,-26,-19,-13,-7,-1,3,7,11,14,17,19,21,23,24,25,25,21,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,21,20,18,16,13,9,5,1,-3,-7,-11,-14,-17,-18,-20,-21,-21,-22,-22,-22,-23,-23,-25,-27,-29,-32,-35,-37,-40,-42,-44,-45,-45,-45,-44,-42,-40,-36,-32,-27,-22,-17,-12,-7,-3,0,3,7,9,12,14,16,18,19,20,21,21,18,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,18,17,16,14,10,7,2,-1,-6,-10,-14,-17,-19,-21,-22,-23,-24,-24,-24,-24,-23,-23,-23,-24,-26,-28,-30,-33,-35,-37,-38,-39,-39,-38,-36,-34,-31,-28,-24,-19,-15,-10,-6,-3,0,1,4,6,8,10,12,14,15,16,17,18,18,16,16,17,17,17,17,17,17,17,17,17,16,16,16,16,16,16,15,13,11,8,4,0,-4,-9,-13,-16,-19,-21,-23,-24,-25,-25,-25,-25,-24,-23,-21,-20,-20,-21,-22,-24,-26,-28,-30,-31,-32,-31,-30,-29,-27,-24,-21,-17,-13,-9,-6,-3,-1,0,2,4,5,7,9,10,12,13,14,15,16,16,14,14,14,15,15,15,15,15,15,15,14,14,14,14,14,14,13,12,11,9,5,2,-2,-6,-11,-15,-18,-21,-23,-24,-25,-25,-25,-25,-24,-22,-21,-18,-16,-15,-15,-15,-17,-19,-21,-22,-24,-24,-24,-23,-22,-20,-18,-15,-12,-9,-5,-3,-1,0,1,2,4,5,6,8,9,10,11,12,13,14,14,12,13,13,13,13,13,13,13,13,13,13,13,12,12,12,12,11,10,9,6,3,0,-4,-8,-12,-16,-19,-21,-23,-24,-24,-24,-24,-23,-22,-20,-17,-15,-12,-10,-9,-9,-10,-12,-13,-15,-17,-17,-18,-17,-16,-15,-13,-11,-8,-5,-3,-1,0,1,1,2,3,4,6,7,8,9,10,11,12,12,12,11,11,11,11,11,12,12,12,12,12,11,11,11,11,11,10,10,9,7,5,2,-1,-5,-9,-13,-17,-20,-22,-23,-23,-23,-23,-22,-20,-18,-16,-14,-11,-9,-6,-5,-4,-5,-6,-8,-9,-11,-12,-12,-12,-12,-11,-9,-8,-6,-3,-1,0,0,1,1,2,3,4,5,6,7,8,9,10,11,11,11,10,10,10,10,10,10,10,10,10,10,10,10,10,10,9,9,9,7,6,3,0,-3,-6,-10,-14,-17,-20,-21,-22,-22,-22,-21,-19,-17,-15,-13,-10,-8,-6,-4,-2,-2,-2,-2,-4,-5,-7,-8,-8,-9,-8,-8,-7,-5,-4,-2,0,0,1,1,1,2,2,3,4,5,6,7,8,9,10,10,10,9,9,9,9,9,9,9,10,10,9,9,9,9,9,9,8,8,6,5,2,0,-4,-7,-11,-15,-17,-19,-21,-21,-21,-20,-18,-16,-14,-12,-10,-8,-6,-4,-2,-1,0,0,0,-1,-2,-4,-5,-5,-6,-6,-5,-5,-4,-3,-1,0,0,1,1,1,1,2,3,3,5,6,7,8,8,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,8,8,8,8,7,5,4,1,-1,-5,-8,-12,-15,-17,-19,-20,-20,-19,-18,-16,-14,-11,-9,-7,-5,-4,-2,-1,0,0,1,1,0,0,-2,-3,-3,-4,-4,-4,-3,-3,-2,-1,0,0,0,0,0,1,1,2,3,4,5,6,7,8,8,9,9,9,9,9,8,8,8,9,9,9,9,9,8,8,8,8,7,6,5,3,0,-2,-5,-9,-12,-15,-17,-18,-19,-19,-18,-16,-14,-12,-9,-7,-5,-4,-2,-1,0,0,1,1,1,1,0,0,-1,-2,-2,-3,-3,-2,-2,-1,-1,0,0,0,0,0,0,0,1,2,3,4,5,6,7,8,8,9,8,8,8,8,8,8,9,9,9,9,9,9,8,8,8,7,6,4,2,0,-3,-6,-9,-12,-15,-17,-18,-18,-17,-16,-14,-12,-10,-8,-6,-4,-2,-1,0,0,1,2,2,2,2,1,0,0,-1,-1,-1,-2,-2,-1,-1,0,0,0,0,0,0,0,0,0,1,2,3,4,5,6,7,8,8,8,8,8,8,9,9,9,9,9,9,9,9,9,8,8,7,5,3,1,-1,-4,-7,-10,-13,-15,-16,-17,-17,-16,-15,-13,-11,-9,-6,-5,-3,-2,0,0,0,1,2,2,2,2,1,1,0,0,0,-1,-1,-1,-1,-1,0,0,0,0,-1,-1,-1,-1,-1,0,0,1,3,4,5,7,7,8,8,8,9,9,9,9,10,10,10,10,10,10,10,9,8,7,5,3,0,-2,-5,-8,-11,-13,-15,-16,-16,-16,-15,-13,-12,-10,-8,-6,-4,-2,-1,0,0,1,2,2,3,3,2,2,1,0,0,0,0,0,0,0,0,0,0,-1,-1,-2,-2,-2,-2,-2,-1,0,0,1,3,4,6,7,8,7,8,9,9,9,10,10,11,11,11,11,11,10,10,9,7,5,3,0,-2,-6,-9,-11,-13,-15,-16,-16,-15,-14,-13,-11,-9,-7,-5,-3,-2,0,0,1,1,2,3,3,3,3,2,2,1,1,0,0,0,0,0,0,0,-1,-1,-2,-3,-3,-4,-4,-4,-3,-2,-1,0,1,3,5,6,7,6,8,9,9,10,11,11,12,12,12,12,12,11,11,9,7,5,2,0,-3,-7,-10,-12,-14,-15,-16,-15,-15,-13,-12,-10,-8,-7,-5,-3,-1,0,0,1,2,2,3,3,4,3,3,3,2,2,1,1,1,0,0,0,0,-1,-2,-3,-4,-4,-5,-5,-5,-5,-4,-2,-1,0,2,3,5,6,6,7,8,10,11,12,12,13,13,14,14,13,13,11,10,8,5,2,0,-4,-8,-11,-13,-15,-16,-16,-16,-15,-13,-12,-10,-8,-6,-5,-3,-1,0,0,1,2,3,3,4,4,4,4,4,3,3,3,2,2,1,1,0,0,-1,-2,-3,-5,-6,-7,-7,-7,-6,-5,-4,-3,-1,0,2,4,6,5,7,8,10,11,12,13,14,15,15,15,14,14,12,11,8,5,2,-1,-5,-9,-12,-14,-16,-17,-17,-16,-15,-14,-12,-11,-9,-7,-5,-3,-1,0,0,1,2,3,4,4,5,5,5,5,5,5,4,4,3,3,2,1,0,-1,-2,-4,-6,-7,-8,-8,-8,-8,-7,-6,-4,-2,0,1,3,5,4,6,8,10,12,13,14,15,16,16,16,16,15,13,11,9,5,2,-2,-6,-10,-13,-16,-17,-18,-18,-17,-16,-15,-13,-11,-9,-7,-5,-4,-2,0,0,1,3,3,4,5,6,6,7,7,7,7,7,6,5,4,3,2,0,-1,-3,-5,-7,-8,-9,-10,-10,-10,-9,-7,-5,-4,-1,0,2,4,4,6,8,10,12,14,15,16,17,18,18,17,16,15,12,9,5,1,-3,-8,-12,-15,-18,-19,-20,-20,-19,-18,-16,-15,-13,-11,-8,-6,-4,-2,-1,0,1,3,4,5,6,7,8,9,9,9,9,9,9,8,7,5,3,1,-1,-3,-6,-8,-10,-11,-12,-12,-11,-10,-9,-7,-5,-2,0,1,4,4,6,8,11,13,15,16,18,19,19,19,19,18,16,13,10,5,0,-5,-10,-15,-18,-21,-22,-23,-22,-22,-20,-18,-17,-14,-12,-10,-8,-5,-3,-1,0,1,3,5,6,8,9,10,11,12,12,13,12,12,11,9,7,5,2,0,-3,-6,-9,-11,-12,-13,-13,-12,-11,-10,-8,-6,-3,-1,1,4,3,6,9,11,14,16,17,19,20,21,21,21,19,17,14,10,4,-1,-8,-14,-19,-22,-25,-26,-26,-26,-25,-23,-21,-19,-17,-14,-12,-9,-7,-4,-2,0,1,3,5,7,9,11,13,14,15,16,16,16,16,15,13,10,7,4,0,-3,-7,-10,-12,-14,-15,-14,-14,-12,-11,-9,-6,-4,-1,1,3,}; + +float +AP_Declination::get_declination(float lat, float lon) +{ + float decSW, decSE, decNW, decNE, decmin, decmax; + float lonmin,latmin; + uint8_t latmin_index,lonmin_index; + /* set base point (latmin, lonmin) of grid */ + + /* no limits test on lon */ + if (lon == 180) lonmin = 175; + else lonmin = floor(lon/5)*5; + + /* supported lat's -60..60, so range check... */ + if (lat >= 60) latmin = 55; + else if (lat < -60) latmin = -60; + else latmin = floor(lat/5)*5; + + /* array index = (degrees+[60|180])/5 */ + latmin_index= (60+latmin)/5; + lonmin_index= (180+lonmin)/5; + + + decSW = (int8_t)pgm_read_byte_far(&dec_tbl[latmin_index][lonmin_index]); + decSE = (int8_t)pgm_read_byte_far(&dec_tbl[latmin_index][lonmin_index+1]); + decNE = (int8_t)pgm_read_byte_far(&dec_tbl[latmin_index+1][lonmin_index+1]); + decNW = (int8_t)pgm_read_byte_far(&dec_tbl[latmin_index+1][lonmin_index]); + + /* approximate declination within the grid using bilinear interpolation */ + + decmin = (lon - lonmin) / 5 * (decSE - decSW) + decSW; + decmax = (lon - lonmin) / 5 * (decNE - decNW) + decNW; + return (lat - latmin) / 5 * (decmax - decmin) + decmin; +} \ No newline at end of file diff --git a/libraries/AP_Declination/AP_Declination.h b/libraries/AP_Declination/AP_Declination.h new file mode 100644 index 0000000000..75ba3f0c4d --- /dev/null +++ b/libraries/AP_Declination/AP_Declination.h @@ -0,0 +1,25 @@ +// -*- tab-width: 4; Mode: C++; c-basic-offset: 4; indent-tabs-mode: t -*- + +#ifndef AP_Declination_h +#define AP_Declination_h + +// Just incase it wasn't included elsewhere +#include +#include + +/* + * Adam M Rivera + * With direction from: Andrew Tridgell, Jason Short, Justin Beech + * + * Adapted from: http://www.societyofrobots.com/robotforum/index.php?topic=11855.0 + * Scott Ferguson + * scottfromscott@gmail.com + * +*/ +class AP_Declination +{ +public: + static float get_declination(float lat, float lon); +}; + +#endif From e22da153ece26f89c3c0f985383444d6068f906f Mon Sep 17 00:00:00 2001 From: Adam M Rivera Date: Sat, 10 Mar 2012 13:51:35 -0600 Subject: [PATCH 154/178] Added AP_Declination test sketch. I will be improving the test sketch soon. Signed-off-by: Andrew Tridgell --- .../AP_Declination_test.pde | 21 +++++++++++++++++++ .../examples/AP_Declination_test/Makefile | 1 + 2 files changed, 22 insertions(+) create mode 100644 libraries/AP_Declination/examples/AP_Declination_test/AP_Declination_test.pde create mode 100644 libraries/AP_Declination/examples/AP_Declination_test/Makefile diff --git a/libraries/AP_Declination/examples/AP_Declination_test/AP_Declination_test.pde b/libraries/AP_Declination/examples/AP_Declination_test/AP_Declination_test.pde new file mode 100644 index 0000000000..baf0b7ee02 --- /dev/null +++ b/libraries/AP_Declination/examples/AP_Declination_test/AP_Declination_test.pde @@ -0,0 +1,21 @@ +/// -*- tab-width: 4; Mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*- + +// AVR runtime +#include +#include +#include +#include +#include +#include + +FastSerialPort(Serial, 0); + +void setup(void) +{ + float declination = AP_Declination::get_declination(43.064191, -87.997498); + Serial.printf("declination: %d", declination); +} + +void loop(void) +{ +} \ No newline at end of file diff --git a/libraries/AP_Declination/examples/AP_Declination_test/Makefile b/libraries/AP_Declination/examples/AP_Declination_test/Makefile new file mode 100644 index 0000000000..d1f40fd90f --- /dev/null +++ b/libraries/AP_Declination/examples/AP_Declination_test/Makefile @@ -0,0 +1 @@ +include ../../../AP_Common/Arduino.mk From e08b50ee91a4bf03d0350cb3511c04d84061c0a1 Mon Sep 17 00:00:00 2001 From: Adam M Rivera Date: Sat, 10 Mar 2012 17:17:17 -0600 Subject: [PATCH 155/178] AP_Declination: Increased range of supported latitude coordinates. Fixed incorrect type usage to save stack space. Signed-off-by: Andrew Tridgell --- libraries/AP_Declination/AP_Declination.cpp | 61 ++++++++++++++++----- libraries/AP_Declination/AP_Declination.h | 1 + 2 files changed, 47 insertions(+), 15 deletions(-) diff --git a/libraries/AP_Declination/AP_Declination.cpp b/libraries/AP_Declination/AP_Declination.cpp index 13f4a26a5e..3da3d0c4e6 100644 --- a/libraries/AP_Declination/AP_Declination.cpp +++ b/libraries/AP_Declination/AP_Declination.cpp @@ -11,37 +11,68 @@ * */ -static const int8_t dec_tbl[25][73] PROGMEM = {46,46,45,44,44,43,42,42,41,41,40,39,38,37,36,35,33,31,28,26,23,20,16,13,10,7,4,1,-1,-3,-5,-7,-9,-12,-14,-16,-19,-22,-26,-29,-33,-36,-40,-44,-48,-51,-55,-58,-61,-64,-66,-68,-71,-72,-74,-74,-75,-74,-72,-68,-61,-48,-25,2,22,33,40,43,45,46,47,46,46,36,36,36,36,36,35,35,35,35,34,34,34,34,33,32,31,30,28,26,23,20,17,14,10,6,3,0,-2,-4,-7,-9,-10,-12,-14,-15,-17,-20,-23,-26,-29,-32,-36,-40,-43,-47,-50,-53,-56,-58,-60,-62,-63,-64,-64,-63,-62,-59,-55,-49,-41,-30,-17,-4,6,15,22,27,31,33,34,35,36,36,30,30,30,30,30,30,30,29,29,29,29,29,29,29,29,28,27,26,24,21,18,15,11,7,3,0,-3,-6,-9,-11,-12,-14,-15,-16,-17,-19,-21,-23,-26,-29,-32,-35,-39,-42,-45,-48,-51,-53,-55,-56,-57,-57,-56,-55,-53,-49,-44,-38,-31,-23,-14,-6,0,7,13,17,21,24,26,27,29,29,30,25,25,26,26,26,25,25,25,25,25,25,25,25,26,25,25,24,23,21,19,16,12,8,4,0,-3,-7,-10,-13,-15,-16,-17,-18,-19,-20,-21,-22,-23,-25,-28,-31,-34,-37,-40,-43,-46,-48,-49,-50,-51,-51,-50,-48,-45,-42,-37,-32,-26,-19,-13,-7,-1,3,7,11,14,17,19,21,23,24,25,25,21,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,21,20,18,16,13,9,5,1,-3,-7,-11,-14,-17,-18,-20,-21,-21,-22,-22,-22,-23,-23,-25,-27,-29,-32,-35,-37,-40,-42,-44,-45,-45,-45,-44,-42,-40,-36,-32,-27,-22,-17,-12,-7,-3,0,3,7,9,12,14,16,18,19,20,21,21,18,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,18,17,16,14,10,7,2,-1,-6,-10,-14,-17,-19,-21,-22,-23,-24,-24,-24,-24,-23,-23,-23,-24,-26,-28,-30,-33,-35,-37,-38,-39,-39,-38,-36,-34,-31,-28,-24,-19,-15,-10,-6,-3,0,1,4,6,8,10,12,14,15,16,17,18,18,16,16,17,17,17,17,17,17,17,17,17,16,16,16,16,16,16,15,13,11,8,4,0,-4,-9,-13,-16,-19,-21,-23,-24,-25,-25,-25,-25,-24,-23,-21,-20,-20,-21,-22,-24,-26,-28,-30,-31,-32,-31,-30,-29,-27,-24,-21,-17,-13,-9,-6,-3,-1,0,2,4,5,7,9,10,12,13,14,15,16,16,14,14,14,15,15,15,15,15,15,15,14,14,14,14,14,14,13,12,11,9,5,2,-2,-6,-11,-15,-18,-21,-23,-24,-25,-25,-25,-25,-24,-22,-21,-18,-16,-15,-15,-15,-17,-19,-21,-22,-24,-24,-24,-23,-22,-20,-18,-15,-12,-9,-5,-3,-1,0,1,2,4,5,6,8,9,10,11,12,13,14,14,12,13,13,13,13,13,13,13,13,13,13,13,12,12,12,12,11,10,9,6,3,0,-4,-8,-12,-16,-19,-21,-23,-24,-24,-24,-24,-23,-22,-20,-17,-15,-12,-10,-9,-9,-10,-12,-13,-15,-17,-17,-18,-17,-16,-15,-13,-11,-8,-5,-3,-1,0,1,1,2,3,4,6,7,8,9,10,11,12,12,12,11,11,11,11,11,12,12,12,12,12,11,11,11,11,11,10,10,9,7,5,2,-1,-5,-9,-13,-17,-20,-22,-23,-23,-23,-23,-22,-20,-18,-16,-14,-11,-9,-6,-5,-4,-5,-6,-8,-9,-11,-12,-12,-12,-12,-11,-9,-8,-6,-3,-1,0,0,1,1,2,3,4,5,6,7,8,9,10,11,11,11,10,10,10,10,10,10,10,10,10,10,10,10,10,10,9,9,9,7,6,3,0,-3,-6,-10,-14,-17,-20,-21,-22,-22,-22,-21,-19,-17,-15,-13,-10,-8,-6,-4,-2,-2,-2,-2,-4,-5,-7,-8,-8,-9,-8,-8,-7,-5,-4,-2,0,0,1,1,1,2,2,3,4,5,6,7,8,9,10,10,10,9,9,9,9,9,9,9,10,10,9,9,9,9,9,9,8,8,6,5,2,0,-4,-7,-11,-15,-17,-19,-21,-21,-21,-20,-18,-16,-14,-12,-10,-8,-6,-4,-2,-1,0,0,0,-1,-2,-4,-5,-5,-6,-6,-5,-5,-4,-3,-1,0,0,1,1,1,1,2,3,3,5,6,7,8,8,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,8,8,8,8,7,5,4,1,-1,-5,-8,-12,-15,-17,-19,-20,-20,-19,-18,-16,-14,-11,-9,-7,-5,-4,-2,-1,0,0,1,1,0,0,-2,-3,-3,-4,-4,-4,-3,-3,-2,-1,0,0,0,0,0,1,1,2,3,4,5,6,7,8,8,9,9,9,9,9,8,8,8,9,9,9,9,9,8,8,8,8,7,6,5,3,0,-2,-5,-9,-12,-15,-17,-18,-19,-19,-18,-16,-14,-12,-9,-7,-5,-4,-2,-1,0,0,1,1,1,1,0,0,-1,-2,-2,-3,-3,-2,-2,-1,-1,0,0,0,0,0,0,0,1,2,3,4,5,6,7,8,8,9,8,8,8,8,8,8,9,9,9,9,9,9,8,8,8,7,6,4,2,0,-3,-6,-9,-12,-15,-17,-18,-18,-17,-16,-14,-12,-10,-8,-6,-4,-2,-1,0,0,1,2,2,2,2,1,0,0,-1,-1,-1,-2,-2,-1,-1,0,0,0,0,0,0,0,0,0,1,2,3,4,5,6,7,8,8,8,8,8,8,9,9,9,9,9,9,9,9,9,8,8,7,5,3,1,-1,-4,-7,-10,-13,-15,-16,-17,-17,-16,-15,-13,-11,-9,-6,-5,-3,-2,0,0,0,1,2,2,2,2,1,1,0,0,0,-1,-1,-1,-1,-1,0,0,0,0,-1,-1,-1,-1,-1,0,0,1,3,4,5,7,7,8,8,8,9,9,9,9,10,10,10,10,10,10,10,9,8,7,5,3,0,-2,-5,-8,-11,-13,-15,-16,-16,-16,-15,-13,-12,-10,-8,-6,-4,-2,-1,0,0,1,2,2,3,3,2,2,1,0,0,0,0,0,0,0,0,0,0,-1,-1,-2,-2,-2,-2,-2,-1,0,0,1,3,4,6,7,8,7,8,9,9,9,10,10,11,11,11,11,11,10,10,9,7,5,3,0,-2,-6,-9,-11,-13,-15,-16,-16,-15,-14,-13,-11,-9,-7,-5,-3,-2,0,0,1,1,2,3,3,3,3,2,2,1,1,0,0,0,0,0,0,0,-1,-1,-2,-3,-3,-4,-4,-4,-3,-2,-1,0,1,3,5,6,7,6,8,9,9,10,11,11,12,12,12,12,12,11,11,9,7,5,2,0,-3,-7,-10,-12,-14,-15,-16,-15,-15,-13,-12,-10,-8,-7,-5,-3,-1,0,0,1,2,2,3,3,4,3,3,3,2,2,1,1,1,0,0,0,0,-1,-2,-3,-4,-4,-5,-5,-5,-5,-4,-2,-1,0,2,3,5,6,6,7,8,10,11,12,12,13,13,14,14,13,13,11,10,8,5,2,0,-4,-8,-11,-13,-15,-16,-16,-16,-15,-13,-12,-10,-8,-6,-5,-3,-1,0,0,1,2,3,3,4,4,4,4,4,3,3,3,2,2,1,1,0,0,-1,-2,-3,-5,-6,-7,-7,-7,-6,-5,-4,-3,-1,0,2,4,6,5,7,8,10,11,12,13,14,15,15,15,14,14,12,11,8,5,2,-1,-5,-9,-12,-14,-16,-17,-17,-16,-15,-14,-12,-11,-9,-7,-5,-3,-1,0,0,1,2,3,4,4,5,5,5,5,5,5,4,4,3,3,2,1,0,-1,-2,-4,-6,-7,-8,-8,-8,-8,-7,-6,-4,-2,0,1,3,5,4,6,8,10,12,13,14,15,16,16,16,16,15,13,11,9,5,2,-2,-6,-10,-13,-16,-17,-18,-18,-17,-16,-15,-13,-11,-9,-7,-5,-4,-2,0,0,1,3,3,4,5,6,6,7,7,7,7,7,6,5,4,3,2,0,-1,-3,-5,-7,-8,-9,-10,-10,-10,-9,-7,-5,-4,-1,0,2,4,4,6,8,10,12,14,15,16,17,18,18,17,16,15,12,9,5,1,-3,-8,-12,-15,-18,-19,-20,-20,-19,-18,-16,-15,-13,-11,-8,-6,-4,-2,-1,0,1,3,4,5,6,7,8,9,9,9,9,9,9,8,7,5,3,1,-1,-3,-6,-8,-10,-11,-12,-12,-11,-10,-9,-7,-5,-2,0,1,4,4,6,8,11,13,15,16,18,19,19,19,19,18,16,13,10,5,0,-5,-10,-15,-18,-21,-22,-23,-22,-22,-20,-18,-17,-14,-12,-10,-8,-5,-3,-1,0,1,3,5,6,8,9,10,11,12,12,13,12,12,11,9,7,5,2,0,-3,-6,-9,-11,-12,-13,-13,-12,-11,-10,-8,-6,-3,-1,1,4,3,6,9,11,14,16,17,19,20,21,21,21,19,17,14,10,4,-1,-8,-14,-19,-22,-25,-26,-26,-26,-25,-23,-21,-19,-17,-14,-12,-9,-7,-4,-2,0,1,3,5,7,9,11,13,14,15,16,16,16,16,15,13,10,7,4,0,-3,-7,-10,-12,-14,-15,-14,-14,-12,-11,-9,-6,-4,-1,1,3,}; +static const int8_t dec_tbl[37][73] PROGMEM = \ +{{150,145,140,135,130,125,120,115,110,105,100,95,90,85,80,75,70,65,60,55,50,45,40,35,30,25,20,15,10,5,0,-4,-9,-14,-19,-24,-29,-34,-39,-44,-49,-54,-59,-64,-69,-74,-79,-84,-89,-94,-99,104,109,114,119,124,129,134,139,144,149,154,159,164,169,174,179,175,170,165,160,155,150}, \ +{143,137,131,126,120,115,110,105,100,95,90,85,80,75,71,66,62,57,53,48,44,39,35,31,27,22,18,14,9,5,1,-3,-7,-11,-16,-20,-25,-29,-34,-38,-43,-47,-52,-57,-61,-66,-71,-76,-81,-86,-91,-96,101,107,112,117,123,128,134,140,146,151,157,163,169,175,178,172,166,160,154,148,143}, \ +{130,124,118,112,107,101,96,92,87,82,78,74,70,65,61,57,54,50,46,42,38,34,31,27,23,19,16,12,8,4,1,-2,-6,-10,-14,-18,-22,-26,-30,-34,-38,-43,-47,-51,-56,-61,-65,-70,-75,-79,-84,-89,-94,100,105,111,116,122,128,135,141,148,155,162,170,177,174,166,159,151,144,137,130}, \ +{111,104,99,94,89,85,81,77,73,70,66,63,60,56,53,50,46,43,40,36,33,30,26,23,20,16,13,10,6,3,0,-3,-6,-9,-13,-16,-20,-24,-28,-32,-36,-40,-44,-48,-52,-57,-61,-65,-70,-74,-79,-84,-88,-93,-98,103,109,115,121,128,135,143,152,162,172,176,165,154,144,134,125,118,111}, \ +{85,81,77,74,71,68,65,63,60,58,56,53,51,49,46,43,41,38,35,32,29,26,23,19,16,13,10,7,4,1,-1,-3,-6,-9,-13,-16,-19,-23,-26,-30,-34,-38,-42,-46,-50,-54,-58,-62,-66,-70,-74,-78,-83,-87,-91,-95,100,105,110,117,124,133,144,159,178,160,141,125,112,103,96,90,85}, \ +{62,60,58,57,55,54,52,51,50,48,47,46,44,42,41,39,36,34,31,28,25,22,19,16,13,10,7,4,2,0,-3,-5,-8,-10,-13,-16,-19,-22,-26,-29,-33,-37,-41,-45,-49,-53,-56,-60,-64,-67,-70,-74,-77,-80,-83,-86,-89,-91,-94,-97,101,105,111,130,109,84,77,74,71,68,66,64,62}, \ +{46,46,45,44,44,43,42,42,41,41,40,39,38,37,36,35,33,31,28,26,23,20,16,13,10,7,4,1,-1,-3,-5,-7,-9,-12,-14,-16,-19,-22,-26,-29,-33,-36,-40,-44,-48,-51,-55,-58,-61,-64,-66,-68,-71,-72,-74,-74,-75,-74,-72,-68,-61,-48,-25,2,22,33,40,43,45,46,47,46,46}, \ +{36,36,36,36,36,35,35,35,35,34,34,34,34,33,32,31,30,28,26,23,20,17,14,10,6,3,0,-2,-4,-7,-9,-10,-12,-14,-15,-17,-20,-23,-26,-29,-32,-36,-40,-43,-47,-50,-53,-56,-58,-60,-62,-63,-64,-64,-63,-62,-59,-55,-49,-41,-30,-17,-4,6,15,22,27,31,33,34,35,36,36}, \ +{30,30,30,30,30,30,30,29,29,29,29,29,29,29,29,28,27,26,24,21,18,15,11,7,3,0,-3,-6,-9,-11,-12,-14,-15,-16,-17,-19,-21,-23,-26,-29,-32,-35,-39,-42,-45,-48,-51,-53,-55,-56,-57,-57,-56,-55,-53,-49,-44,-38,-31,-23,-14,-6,0,7,13,17,21,24,26,27,29,29,30}, \ +{25,25,26,26,26,25,25,25,25,25,25,25,25,26,25,25,24,23,21,19,16,12,8,4,0,-3,-7,-10,-13,-15,-16,-17,-18,-19,-20,-21,-22,-23,-25,-28,-31,-34,-37,-40,-43,-46,-48,-49,-50,-51,-51,-50,-48,-45,-42,-37,-32,-26,-19,-13,-7,-1,3,7,11,14,17,19,21,23,24,25,25}, \ +{21,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,21,20,18,16,13,9,5,1,-3,-7,-11,-14,-17,-18,-20,-21,-21,-22,-22,-22,-23,-23,-25,-27,-29,-32,-35,-37,-40,-42,-44,-45,-45,-45,-44,-42,-40,-36,-32,-27,-22,-17,-12,-7,-3,0,3,7,9,12,14,16,18,19,20,21,21}, \ +{18,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,18,17,16,14,10,7,2,-1,-6,-10,-14,-17,-19,-21,-22,-23,-24,-24,-24,-24,-23,-23,-23,-24,-26,-28,-30,-33,-35,-37,-38,-39,-39,-38,-36,-34,-31,-28,-24,-19,-15,-10,-6,-3,0,1,4,6,8,10,12,14,15,16,17,18,18}, \ +{16,16,17,17,17,17,17,17,17,17,17,16,16,16,16,16,16,15,13,11,8,4,0,-4,-9,-13,-16,-19,-21,-23,-24,-25,-25,-25,-25,-24,-23,-21,-20,-20,-21,-22,-24,-26,-28,-30,-31,-32,-31,-30,-29,-27,-24,-21,-17,-13,-9,-6,-3,-1,0,2,4,5,7,9,10,12,13,14,15,16,16}, \ +{14,14,14,15,15,15,15,15,15,15,14,14,14,14,14,14,13,12,11,9,5,2,-2,-6,-11,-15,-18,-21,-23,-24,-25,-25,-25,-25,-24,-22,-21,-18,-16,-15,-15,-15,-17,-19,-21,-22,-24,-24,-24,-23,-22,-20,-18,-15,-12,-9,-5,-3,-1,0,1,2,4,5,6,8,9,10,11,12,13,14,14}, \ +{12,13,13,13,13,13,13,13,13,13,13,13,12,12,12,12,11,10,9,6,3,0,-4,-8,-12,-16,-19,-21,-23,-24,-24,-24,-24,-23,-22,-20,-17,-15,-12,-10,-9,-9,-10,-12,-13,-15,-17,-17,-18,-17,-16,-15,-13,-11,-8,-5,-3,-1,0,1,1,2,3,4,6,7,8,9,10,11,12,12,12}, \ +{11,11,11,11,11,12,12,12,12,12,11,11,11,11,11,10,10,9,7,5,2,-1,-5,-9,-13,-17,-20,-22,-23,-23,-23,-23,-22,-20,-18,-16,-14,-11,-9,-6,-5,-4,-5,-6,-8,-9,-11,-12,-12,-12,-12,-11,-9,-8,-6,-3,-1,0,0,1,1,2,3,4,5,6,7,8,9,10,11,11,11}, \ +{10,10,10,10,10,10,10,10,10,10,10,10,10,10,9,9,9,7,6,3,0,-3,-6,-10,-14,-17,-20,-21,-22,-22,-22,-21,-19,-17,-15,-13,-10,-8,-6,-4,-2,-2,-2,-2,-4,-5,-7,-8,-8,-9,-8,-8,-7,-5,-4,-2,0,0,1,1,1,2,2,3,4,5,6,7,8,9,10,10,10}, +{9,9,9,9,9,9,9,10,10,9,9,9,9,9,9,8,8,6,5,2,0,-4,-7,-11,-15,-17,-19,-21,-21,-21,-20,-18,-16,-14,-12,-10,-8,-6,-4,-2,-1,0,0,0,-1,-2,-4,-5,-5,-6,-6,-5,-5,-4,-3,-1,0,0,1,1,1,1,2,3,3,5,6,7,8,8,9,9,9}, \ +{9,9,9,9,9,9,9,9,9,9,9,9,8,8,8,8,7,5,4,1,-1,-5,-8,-12,-15,-17,-19,-20,-20,-19,-18,-16,-14,-11,-9,-7,-5,-4,-2,-1,0,0,1,1,0,0,-2,-3,-3,-4,-4,-4,-3,-3,-2,-1,0,0,0,0,0,1,1,2,3,4,5,6,7,8,8,9,9}, \ +{9,9,9,8,8,8,9,9,9,9,9,8,8,8,8,7,6,5,3,0,-2,-5,-9,-12,-15,-17,-18,-19,-19,-18,-16,-14,-12,-9,-7,-5,-4,-2,-1,0,0,1,1,1,1,0,0,-1,-2,-2,-3,-3,-2,-2,-1,-1,0,0,0,0,0,0,0,1,2,3,4,5,6,7,8,8,9}, \ +{8,8,8,8,8,8,9,9,9,9,9,9,8,8,8,7,6,4,2,0,-3,-6,-9,-12,-15,-17,-18,-18,-17,-16,-14,-12,-10,-8,-6,-4,-2,-1,0,0,1,2,2,2,2,1,0,0,-1,-1,-1,-2,-2,-1,-1,0,0,0,0,0,0,0,0,0,1,2,3,4,5,6,7,8,8}, \ +{8,8,8,8,9,9,9,9,9,9,9,9,9,8,8,7,5,3,1,-1,-4,-7,-10,-13,-15,-16,-17,-17,-16,-15,-13,-11,-9,-6,-5,-3,-2,0,0,0,1,2,2,2,2,1,1,0,0,0,-1,-1,-1,-1,-1,0,0,0,0,-1,-1,-1,-1,-1,0,0,1,3,4,5,7,7,8}, \ +{8,8,9,9,9,9,10,10,10,10,10,10,10,9,8,7,5,3,0,-2,-5,-8,-11,-13,-15,-16,-16,-16,-15,-13,-12,-10,-8,-6,-4,-2,-1,0,0,1,2,2,3,3,2,2,1,0,0,0,0,0,0,0,0,0,0,-1,-1,-2,-2,-2,-2,-2,-1,0,0,1,3,4,6,7,8}, \ +{7,8,9,9,9,10,10,11,11,11,11,11,10,10,9,7,5,3,0,-2,-6,-9,-11,-13,-15,-16,-16,-15,-14,-13,-11,-9,-7,-5,-3,-2,0,0,1,1,2,3,3,3,3,2,2,1,1,0,0,0,0,0,0,0,-1,-1,-2,-3,-3,-4,-4,-4,-3,-2,-1,0,1,3,5,6,7}, \ +{6,8,9,9,10,11,11,12,12,12,12,12,11,11,9,7,5,2,0,-3,-7,-10,-12,-14,-15,-16,-15,-15,-13,-12,-10,-8,-7,-5,-3,-1,0,0,1,2,2,3,3,4,3,3,3,2,2,1,1,1,0,0,0,0,-1,-2,-3,-4,-4,-5,-5,-5,-5,-4,-2,-1,0,2,3,5,6}, \ +{6,7,8,10,11,12,12,13,13,14,14,13,13,11,10,8,5,2,0,-4,-8,-11,-13,-15,-16,-16,-16,-15,-13,-12,-10,-8,-6,-5,-3,-1,0,0,1,2,3,3,4,4,4,4,4,3,3,3,2,2,1,1,0,0,-1,-2,-3,-5,-6,-7,-7,-7,-6,-5,-4,-3,-1,0,2,4,6}, \ +{5,7,8,10,11,12,13,14,15,15,15,14,14,12,11,8,5,2,-1,-5,-9,-12,-14,-16,-17,-17,-16,-15,-14,-12,-11,-9,-7,-5,-3,-1,0,0,1,2,3,4,4,5,5,5,5,5,5,4,4,3,3,2,1,0,-1,-2,-4,-6,-7,-8,-8,-8,-8,-7,-6,-4,-2,0,1,3,5}, \ +{4,6,8,10,12,13,14,15,16,16,16,16,15,13,11,9,5,2,-2,-6,-10,-13,-16,-17,-18,-18,-17,-16,-15,-13,-11,-9,-7,-5,-4,-2,0,0,1,3,3,4,5,6,6,7,7,7,7,7,6,5,4,3,2,0,-1,-3,-5,-7,-8,-9,-10,-10,-10,-9,-7,-5,-4,-1,0,2,4}, \ +{4,6,8,10,12,14,15,16,17,18,18,17,16,15,12,9,5,1,-3,-8,-12,-15,-18,-19,-20,-20,-19,-18,-16,-15,-13,-11,-8,-6,-4,-2,-1,0,1,3,4,5,6,7,8,9,9,9,9,9,9,8,7,5,3,1,-1,-3,-6,-8,-10,-11,-12,-12,-11,-10,-9,-7,-5,-2,0,1,4}, \ +{4,6,8,11,13,15,16,18,19,19,19,19,18,16,13,10,5,0,-5,-10,-15,-18,-21,-22,-23,-22,-22,-20,-18,-17,-14,-12,-10,-8,-5,-3,-1,0,1,3,5,6,8,9,10,11,12,12,13,12,12,11,9,7,5,2,0,-3,-6,-9,-11,-12,-13,-13,-12,-11,-10,-8,-6,-3,-1,1,4}, \ +{3,6,9,11,14,16,17,19,20,21,21,21,19,17,14,10,4,-1,-8,-14,-19,-22,-25,-26,-26,-26,-25,-23,-21,-19,-17,-14,-12,-9,-7,-4,-2,0,1,3,5,7,9,11,13,14,15,16,16,16,16,15,13,10,7,4,0,-3,-7,-10,-12,-14,-15,-14,-14,-12,-11,-9,-6,-4,-1,1,3}, \ +{4,6,9,12,14,17,19,21,22,23,23,23,21,19,15,9,2,-5,-13,-20,-25,-28,-30,-31,-31,-30,-29,-27,-25,-22,-20,-17,-14,-11,-9,-6,-3,0,1,4,6,9,11,13,15,17,19,20,21,21,21,20,18,15,11,6,2,-2,-7,-11,-13,-15,-16,-16,-15,-13,-11,-9,-7,-4,-1,1,4}, \ +{4,7,10,13,15,18,20,22,24,25,25,25,23,20,15,7,-2,-12,-22,-29,-34,-37,-38,-38,-37,-36,-34,-31,-29,-26,-23,-20,-17,-13,-10,-7,-4,-1,2,5,8,11,13,16,18,21,23,24,26,26,26,26,24,21,17,12,5,0,-6,-10,-14,-16,-16,-16,-15,-14,-12,-10,-7,-4,-1,1,4}, \ +{4,7,10,13,16,19,22,24,26,27,27,26,24,19,11,-1,-15,-28,-37,-43,-46,-47,-47,-45,-44,-41,-39,-36,-32,-29,-26,-22,-19,-15,-11,-8,-4,-1,2,5,9,12,15,19,22,24,27,29,31,33,33,33,32,30,26,21,14,6,0,-6,-11,-14,-15,-16,-15,-14,-12,-9,-7,-4,-1,1,4}, \ +{6,9,12,15,18,21,23,25,27,28,27,24,17,4,-14,-34,-49,-56,-60,-60,-60,-58,-56,-53,-50,-47,-43,-40,-36,-32,-28,-25,-21,-17,-13,-9,-5,-1,2,6,10,14,17,21,24,28,31,34,37,39,41,42,43,43,41,38,33,25,17,8,0,-4,-8,-10,-10,-10,-8,-7,-4,-2,0,3,6}, \ +{22,24,26,28,30,32,33,31,23,-18,-81,-96,-99,-98,-95,-93,-89,-86,-82,-78,-74,-70,-66,-62,-57,-53,-49,-44,-40,-36,-32,-27,-23,-19,-14,-10,-6,-1,2,6,10,15,19,23,27,31,35,38,42,45,49,52,55,57,60,61,63,63,62,61,57,53,47,40,33,28,23,21,19,19,19,20,22}, +{168,173,178,176,171,166,161,156,151,146,141,136,131,126,121,116,111,106,101,-96,-91,-86,-81,-76,-71,-66,-61,-56,-51,-46,-41,-36,-31,-26,-21,-16,-11,-6,-1,3,8,13,18,23,28,33,38,43,48,53,58,63,68,73,78,83,88,93,98,103,108,113,118,123,128,133,138,143,148,153,158,163,168}}; float AP_Declination::get_declination(float lat, float lon) { - float decSW, decSE, decNW, decNE, decmin, decmax; - float lonmin,latmin; + int8_t decSW, decSE, decNW, decNE, lonmin, latmin; uint8_t latmin_index,lonmin_index; - /* set base point (latmin, lonmin) of grid */ + float decmin, decmax; - /* no limits test on lon */ - if (lon == 180) lonmin = 175; - else lonmin = floor(lon/5)*5; + // Validate input values + lat = constrain(lat, -90, 90); + lon = constrain(lon, -180, 180); - /* supported lat's -60..60, so range check... */ - if (lat >= 60) latmin = 55; - else if (lat < -60) latmin = -60; - else latmin = floor(lat/5)*5; + latmin = floor(lat/5)*5; + lonmin = floor(lon/5)*5; - /* array index = (degrees+[60|180])/5 */ - latmin_index= (60+latmin)/5; + latmin_index= (90+latmin)/5; lonmin_index= (180+lonmin)/5; - decSW = (int8_t)pgm_read_byte_far(&dec_tbl[latmin_index][lonmin_index]); decSE = (int8_t)pgm_read_byte_far(&dec_tbl[latmin_index][lonmin_index+1]); decNE = (int8_t)pgm_read_byte_far(&dec_tbl[latmin_index+1][lonmin_index+1]); decNW = (int8_t)pgm_read_byte_far(&dec_tbl[latmin_index+1][lonmin_index]); /* approximate declination within the grid using bilinear interpolation */ - decmin = (lon - lonmin) / 5 * (decSE - decSW) + decSW; decmax = (lon - lonmin) / 5 * (decNE - decNW) + decNW; return (lat - latmin) / 5 * (decmax - decmin) + decmin; diff --git a/libraries/AP_Declination/AP_Declination.h b/libraries/AP_Declination/AP_Declination.h index 75ba3f0c4d..5d10caec11 100644 --- a/libraries/AP_Declination/AP_Declination.h +++ b/libraries/AP_Declination/AP_Declination.h @@ -6,6 +6,7 @@ // Just incase it wasn't included elsewhere #include #include +#include "../AP_Common/AP_Common.h" /* * Adam M Rivera From fe8c896d692a270b7adb3cf6909d8d644d7d7395 Mon Sep 17 00:00:00 2001 From: Adam M Rivera Date: Sat, 10 Mar 2012 17:19:04 -0600 Subject: [PATCH 156/178] AP_Declination: Added method set_initial_location This will set the declination based on lat/lon if the user has not yet saved one to the EEPROM, OR if they have specified via the config parameter that they want it to overwrite the declination every 3D fix. Signed-off-by: Andrew Tridgell --- libraries/AP_Compass/Compass.cpp | 19 +++++++++++++++++++ libraries/AP_Compass/Compass.h | 9 +++++++++ 2 files changed, 28 insertions(+) diff --git a/libraries/AP_Compass/Compass.cpp b/libraries/AP_Compass/Compass.cpp index 7a54c25dc0..ad84d9d03a 100644 --- a/libraries/AP_Compass/Compass.cpp +++ b/libraries/AP_Compass/Compass.cpp @@ -57,6 +57,25 @@ Compass::get_offsets() return _offset; } +bool +Compass::set_initial_location(long latitude, long longitude, bool force) +{ + // If the user has choosen to use auto-declination regardless of the planner value + // OR + // If the declination failed to load from the EEPROM (ie. not set by user) + if(force || !_declination.load()) + { + // Set the declination based on the lat/lng from GPS + _declination.set(radians(AP_Declination::get_declination((float)latitude / 10000000, (float)longitude / 10000000))); + + // Reset null offsets + null_offsets_disable(); + null_offsets_enable(); + return true; + } + return false; +} + void Compass::set_declination(float radians) { diff --git a/libraries/AP_Compass/Compass.h b/libraries/AP_Compass/Compass.h index 2d423909c0..770a520d60 100644 --- a/libraries/AP_Compass/Compass.h +++ b/libraries/AP_Compass/Compass.h @@ -5,6 +5,7 @@ #include #include "../AP_Common/AP_Common.h" #include "../AP_Math/AP_Math.h" +#include "../AP_Declination/AP_Declination.h" // ArduPilot Mega Declination Helper Library // compass product id #define AP_COMPASS_TYPE_UNKNOWN 0x00 @@ -80,6 +81,14 @@ public: /// virtual Vector3f &get_offsets(); + /// Sets the initial location used to get declination - Returns true if declination set + /// + /// @param latitude GPS Latitude. + /// @param longitude GPS Longitude. + /// @param force Force the compass declination update. + /// + bool set_initial_location(long latitude, long longitude, bool force); + /// Program new offset values. /// /// @param x Offset to the raw mag_x value. From 2524f9c8df291f86e07c8d1fbf06d7211ee54b98 Mon Sep 17 00:00:00 2001 From: Adam M Rivera Date: Sat, 10 Mar 2012 17:20:09 -0600 Subject: [PATCH 157/178] AP_Declination: Added new config value to allow the user to have the declination overwritten on every 3D fix. Signed-off-by: Andrew Tridgell --- ArduCopter/APM_Config.h | 2 ++ ArduCopter/config.h | 4 ++++ ArduPlane/APM_Config.h | 3 +++ ArduPlane/config.h | 3 +++ 4 files changed, 12 insertions(+) diff --git a/ArduCopter/APM_Config.h b/ArduCopter/APM_Config.h index 1c766e182f..ee4f024ed2 100644 --- a/ArduCopter/APM_Config.h +++ b/ArduCopter/APM_Config.h @@ -90,3 +90,5 @@ // #define MOT_7 CH_7 // #define MOT_8 CH_8 +// Enabling this will use the GPS lat/long coordinate to get the compass declination +//#define AUTOMATIC_DECLINATION ENABLED \ No newline at end of file diff --git a/ArduCopter/config.h b/ArduCopter/config.h index 4813348168..31b7463b60 100644 --- a/ArduCopter/config.h +++ b/ArduCopter/config.h @@ -425,6 +425,10 @@ # define GROUND_START_DELAY 3 #endif +#ifndef AUTOMATIC_DECLINATION + #define AUTOMATIC_DECLINATION DISABLED +#endif + ////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////// diff --git a/ArduPlane/APM_Config.h b/ArduPlane/APM_Config.h index 0b40f0e887..146dead877 100644 --- a/ArduPlane/APM_Config.h +++ b/ArduPlane/APM_Config.h @@ -39,3 +39,6 @@ #define AIRSPEED_CRUISE 25 #define THROTTLE_FAILSAFE ENABLED */ + +// Enabling this will use the GPS lat/long coordinate to get the compass declination +//#define AUTOMATIC_DECLINATION ENABLED diff --git a/ArduPlane/config.h b/ArduPlane/config.h index 43141cdce6..490fdb0631 100644 --- a/ArduPlane/config.h +++ b/ArduPlane/config.h @@ -418,6 +418,9 @@ # define GROUND_START_DELAY 0 #endif +#ifndef AUTOMATIC_DECLINATION + #define AUTOMATIC_DECLINATION DISABLED +#endif ////////////////////////////////////////////////////////////////////////////// // ENABLE_AIR_START From d3667faef4764b603f7f78edf9b19f8309f65c20 Mon Sep 17 00:00:00 2001 From: Adam M Rivera Date: Sat, 10 Mar 2012 17:20:54 -0600 Subject: [PATCH 158/178] AP_Declination: Added call to compass.set_initial_location if the compass is enabled when the 3D fix is obtained. Signed-off-by: Andrew Tridgell --- ArduCopter/ArduCopter.pde | 15 +++++++++++++-- ArduPlane/ArduPlane.pde | 12 ++++++++++++ 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/ArduCopter/ArduCopter.pde b/ArduCopter/ArduCopter.pde index 4c48728556..3b17f105e3 100644 --- a/ArduCopter/ArduCopter.pde +++ b/ArduCopter/ArduCopter.pde @@ -35,6 +35,7 @@ Jean-Louis Naudin :Auto Landing Sandro Benigno :Camera support Olivier Adler :PPM Encoder John Arne Birkeland :PPM Encoder +Adam M Rivera :Auto Compass Declination And much more so PLEASE PM me on DIYDRONES to add your contribution to the List @@ -65,6 +66,7 @@ http://code.google.com/p/ardupilot-mega/downloads/list #include // ArduPilot Mega Analog to Digital Converter Library #include #include +#include // ArduPilot Mega Declination Helper Library #include // ArduPilot Mega Magnetometer Library #include // ArduPilot Mega Vector/Matrix math Library #include // ArduPilot Mega Inertial Sensor (accel & gyro) Library @@ -238,7 +240,6 @@ static GPS *g_gps_null; #endif AP_TimerProcess timer_scheduler; - #elif HIL_MODE == HIL_MODE_SENSORS // sensor emulators AP_ADC_HIL adc; @@ -1374,6 +1375,17 @@ static void update_GPS(void) ground_start_count = 5; }else{ + // If we have a compass installed + if(g.compass_enabled) + { + // Set compass declination automatically + if(compass.set_initial_location(g_gps->latitude, g_gps->longitude, AUTOMATIC_DECLINATION == ENABLED)) + { + // Report if an update was made + report_compass(); + } + } + // save home to eeprom (we must have a good fix to have reached this point) init_home(); ground_start_count = 0; @@ -1391,7 +1403,6 @@ static void update_GPS(void) //update_altitude(); alt_sensor_flag = true; #endif - } } diff --git a/ArduPlane/ArduPlane.pde b/ArduPlane/ArduPlane.pde index d343e9ee6b..f6ddbc73e4 100644 --- a/ArduPlane/ArduPlane.pde +++ b/ArduPlane/ArduPlane.pde @@ -36,6 +36,7 @@ version 2.1 of the License, or (at your option) any later version. #include // ArduPilot Mega polymorphic analog getter #include // ArduPilot Mega TimerProcess #include // ArduPilot barometer library +#include // ArduPilot Mega Declination Helper Library #include // ArduPilot Mega Magnetometer Library #include // ArduPilot Mega Vector/Matrix math Library #include // Inertial Sensor (uncalibated IMU) Library @@ -974,6 +975,17 @@ static void update_GPS(void) init_home(); } + // If we have a compass installed + if(g.compass_enabled) + { + // Set compass declination automatically + if(compass.set_initial_location(g_gps->latitude, g_gps->longitude, AUTOMATIC_DECLINATION == ENABLED)) + { + // Report if an update was made + report_compass(); + } + } + ground_start_count = 0; } } From b9be6ed290791ba412b530fd8249d79d32298c32 Mon Sep 17 00:00:00 2001 From: Adam M Rivera Date: Sat, 10 Mar 2012 21:13:46 -0600 Subject: [PATCH 159/178] AP_Declination: Updated comment. Signed-off-by: Andrew Tridgell --- libraries/AP_Declination/AP_Declination.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/AP_Declination/AP_Declination.cpp b/libraries/AP_Declination/AP_Declination.cpp index 3da3d0c4e6..1464cedcba 100644 --- a/libraries/AP_Declination/AP_Declination.cpp +++ b/libraries/AP_Declination/AP_Declination.cpp @@ -57,7 +57,7 @@ AP_Declination::get_declination(float lat, float lon) uint8_t latmin_index,lonmin_index; float decmin, decmax; - // Validate input values + // Constrain to valid inputs lat = constrain(lat, -90, 90); lon = constrain(lon, -180, 180); From c1b945018bbfd279c3d99294bfb5cf2346a4e908 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 11 Mar 2012 20:53:22 +1100 Subject: [PATCH 160/178] AP_Declination: fixed usage of headers --- libraries/AP_Declination/AP_Declination.cpp | 15 ++++++++++++--- libraries/AP_Declination/AP_Declination.h | 7 +------ 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/libraries/AP_Declination/AP_Declination.cpp b/libraries/AP_Declination/AP_Declination.cpp index 1464cedcba..8cdf830297 100644 --- a/libraries/AP_Declination/AP_Declination.cpp +++ b/libraries/AP_Declination/AP_Declination.cpp @@ -1,6 +1,4 @@ /// -*- tab-width: 4; Mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*- -#include "AP_Declination.h" - /* * Adam M Rivera * With direction from: Andrew Tridgell, Jason Short, Justin Beech @@ -9,8 +7,19 @@ * Scott Ferguson * scottfromscott@gmail.com * + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License + as published by the Free Software Foundation; either version 2.1 + of the License, or (at your option) any later version. */ +#include +#include +#include +#include +#include + static const int8_t dec_tbl[37][73] PROGMEM = \ {{150,145,140,135,130,125,120,115,110,105,100,95,90,85,80,75,70,65,60,55,50,45,40,35,30,25,20,15,10,5,0,-4,-9,-14,-19,-24,-29,-34,-39,-44,-49,-54,-59,-64,-69,-74,-79,-84,-89,-94,-99,104,109,114,119,124,129,134,139,144,149,154,159,164,169,174,179,175,170,165,160,155,150}, \ {143,137,131,126,120,115,110,105,100,95,90,85,80,75,71,66,62,57,53,48,44,39,35,31,27,22,18,14,9,5,1,-3,-7,-11,-16,-20,-25,-29,-34,-38,-43,-47,-52,-57,-61,-66,-71,-76,-81,-86,-91,-96,101,107,112,117,123,128,134,140,146,151,157,163,169,175,178,172,166,160,154,148,143}, \ @@ -76,4 +85,4 @@ AP_Declination::get_declination(float lat, float lon) decmin = (lon - lonmin) / 5 * (decSE - decSW) + decSW; decmax = (lon - lonmin) / 5 * (decNE - decNW) + decNW; return (lat - latmin) / 5 * (decmax - decmin) + decmin; -} \ No newline at end of file +} diff --git a/libraries/AP_Declination/AP_Declination.h b/libraries/AP_Declination/AP_Declination.h index 5d10caec11..26e9abb283 100644 --- a/libraries/AP_Declination/AP_Declination.h +++ b/libraries/AP_Declination/AP_Declination.h @@ -3,11 +3,6 @@ #ifndef AP_Declination_h #define AP_Declination_h -// Just incase it wasn't included elsewhere -#include -#include -#include "../AP_Common/AP_Common.h" - /* * Adam M Rivera * With direction from: Andrew Tridgell, Jason Short, Justin Beech @@ -23,4 +18,4 @@ public: static float get_declination(float lat, float lon); }; -#endif +#endif // AP_Declination_h From b337441ec51913b92a0a8eb36b10aa8a12508e5b Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 11 Mar 2012 20:58:39 +1100 Subject: [PATCH 161/178] SITL: added pgm_read_byte_far() --- libraries/Desktop/include/avr/pgmspace.h | 1 + 1 file changed, 1 insertion(+) diff --git a/libraries/Desktop/include/avr/pgmspace.h b/libraries/Desktop/include/avr/pgmspace.h index dd13ee03a0..55bc8a5a16 100644 --- a/libraries/Desktop/include/avr/pgmspace.h +++ b/libraries/Desktop/include/avr/pgmspace.h @@ -36,6 +36,7 @@ extern char *strncpy_P(char *dest, PGM_P src, size_t n); extern void *memcpy_P(void *dest, PGM_P src, size_t n); static inline uint8_t pgm_read_byte(PGM_P s) { return (uint8_t)*s; } + static inline uint8_t pgm_read_byte_far(const void *s) { return *(const uint8_t *)s; } static inline uint16_t pgm_read_word(const void *s) { return *(const uint16_t *)s; } #define GETBYTE(flag, mask, pnt) ({ \ From 2a03a0584fcabb529548f03d20da9d7027fe0fe3 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 11 Mar 2012 21:46:41 +1100 Subject: [PATCH 162/178] AP_Declination: disable library when AUTOMATIC_DECLINATION is not ENABLED unfortunately this library was causing avrdude to fail to load the hex to my APM2. Until we work out why, it's disabled. --- ArduCopter/ArduCopter.pde | 19 +++++++++---------- ArduPlane/ArduPlane.pde | 19 +++++++++---------- 2 files changed, 18 insertions(+), 20 deletions(-) diff --git a/ArduCopter/ArduCopter.pde b/ArduCopter/ArduCopter.pde index 3b17f105e3..7db27efdc6 100644 --- a/ArduCopter/ArduCopter.pde +++ b/ArduCopter/ArduCopter.pde @@ -66,7 +66,6 @@ http://code.google.com/p/ardupilot-mega/downloads/list #include // ArduPilot Mega Analog to Digital Converter Library #include #include -#include // ArduPilot Mega Declination Helper Library #include // ArduPilot Mega Magnetometer Library #include // ArduPilot Mega Vector/Matrix math Library #include // ArduPilot Mega Inertial Sensor (accel & gyro) Library @@ -97,6 +96,11 @@ http://code.google.com/p/ardupilot-mega/downloads/list #include "Parameters.h" #include "GCS.h" +#if AUTOMATIC_DECLINATION == ENABLED +// this is in an #if to avoid the static data +#include // ArduPilot Mega Declination Helper Library +#endif + //////////////////////////////////////////////////////////////////////////////// // Serial ports //////////////////////////////////////////////////////////////////////////////// @@ -1375,17 +1379,12 @@ static void update_GPS(void) ground_start_count = 5; }else{ - // If we have a compass installed - if(g.compass_enabled) - { +#if AUTOMATIC_DECLINATION == ENABLED + if(g.compass_enabled) { // Set compass declination automatically - if(compass.set_initial_location(g_gps->latitude, g_gps->longitude, AUTOMATIC_DECLINATION == ENABLED)) - { - // Report if an update was made - report_compass(); - } + compass.set_initial_location(g_gps->latitude, g_gps->longitude, false); } - +#endif // save home to eeprom (we must have a good fix to have reached this point) init_home(); ground_start_count = 0; diff --git a/ArduPlane/ArduPlane.pde b/ArduPlane/ArduPlane.pde index f6ddbc73e4..177a11b37e 100644 --- a/ArduPlane/ArduPlane.pde +++ b/ArduPlane/ArduPlane.pde @@ -36,7 +36,6 @@ version 2.1 of the License, or (at your option) any later version. #include // ArduPilot Mega polymorphic analog getter #include // ArduPilot Mega TimerProcess #include // ArduPilot barometer library -#include // ArduPilot Mega Declination Helper Library #include // ArduPilot Mega Magnetometer Library #include // ArduPilot Mega Vector/Matrix math Library #include // Inertial Sensor (uncalibated IMU) Library @@ -61,6 +60,11 @@ version 2.1 of the License, or (at your option) any later version. #include "Parameters.h" #include "GCS.h" +#if AUTOMATIC_DECLINATION == ENABLED +// this is in an #if to avoid the static data +#include // ArduPilot Mega Declination Helper Library +#endif + //////////////////////////////////////////////////////////////////////////////// // Serial ports //////////////////////////////////////////////////////////////////////////////// @@ -975,17 +979,12 @@ static void update_GPS(void) init_home(); } - // If we have a compass installed - if(g.compass_enabled) - { +#if AUTOMATIC_DECLINATION == ENABLED + if (g.compass_enabled) { // Set compass declination automatically - if(compass.set_initial_location(g_gps->latitude, g_gps->longitude, AUTOMATIC_DECLINATION == ENABLED)) - { - // Report if an update was made - report_compass(); - } + compass.set_initial_location(g_gps->latitude, g_gps->longitude, false); } - +#endif ground_start_count = 0; } } From 6e9ffb4249524722c40eabc74b41e1d97e60a5c1 Mon Sep 17 00:00:00 2001 From: Amilcar Lucas Date: Sun, 11 Mar 2012 21:30:09 +0100 Subject: [PATCH 163/178] correct small typos in comments --- ArduPlane/config.h | 2 +- libraries/AP_Common/AP_Param.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ArduPlane/config.h b/ArduPlane/config.h index 490fdb0631..90515198a2 100644 --- a/ArduPlane/config.h +++ b/ArduPlane/config.h @@ -519,7 +519,7 @@ -/* The following parmaeters have no corresponding control implementation +/* The following parameters have no corresponding control implementation #ifndef THROTTLE_ALT_P # define THROTTLE_ALT_P 0.32 #endif diff --git a/libraries/AP_Common/AP_Param.h b/libraries/AP_Common/AP_Param.h index 596b07c29e..68564fa8a4 100644 --- a/libraries/AP_Common/AP_Param.h +++ b/libraries/AP_Common/AP_Param.h @@ -22,7 +22,7 @@ #define AP_MAX_NAME_SIZE 15 #define AP_NESTED_GROUPS_ENABLED -// a varient of offsetof() to work around C++ restrictions. +// a variant of offsetof() to work around C++ restrictions. // this can only be used when the offset of a variable in a object // is constant and known at compile time #define AP_VAROFFSET(type, element) (((uintptr_t)(&((const type *)1)->element))-1) From a869a012949decbc5b51cdf761c3a521856cdd33 Mon Sep 17 00:00:00 2001 From: rmackay9 Date: Mon, 12 Mar 2012 12:09:04 +0900 Subject: [PATCH 164/178] ArduCopter - Log.pde - added wrap_360 to compass heading field of ATT message to resolve overflow problem that caused heading to appear as being off by 70 degrees --- ArduCopter/Log.pde | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ArduCopter/Log.pde b/ArduCopter/Log.pde index dff9e1f477..cdfbbe8126 100644 --- a/ArduCopter/Log.pde +++ b/ArduCopter/Log.pde @@ -701,7 +701,7 @@ static void Log_Write_Attitude() DataFlash.WriteInt((int)dcm.pitch_sensor); // 4 DataFlash.WriteInt(g.rc_4.control_in); // 5 DataFlash.WriteInt((uint16_t)dcm.yaw_sensor); // 6 - DataFlash.WriteInt((uint16_t)(ToDeg(compass.heading)*100)); // 7 + DataFlash.WriteInt((uint16_t)(wrap_360(ToDeg(compass.heading)*100))); // 7 DataFlash.WriteByte(END_BYTE); } From 77fe7de55d4802fa5ce67e51574c349be6d1fe41 Mon Sep 17 00:00:00 2001 From: Jason Short Date: Sun, 11 Mar 2012 22:43:25 -0700 Subject: [PATCH 165/178] ACM: The I term in update_nav_wp with the no_nav condition was pulling from the wrong PID loop and was essentially 0 all the time. --- ArduCopter/ArduCopter.pde | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ArduCopter/ArduCopter.pde b/ArduCopter/ArduCopter.pde index 7db27efdc6..c9f21fd94f 100644 --- a/ArduCopter/ArduCopter.pde +++ b/ArduCopter/ArduCopter.pde @@ -2202,8 +2202,8 @@ static void update_nav_wp() // or change Loiter position // We bring copy over our Iterms for wind control, but we don't navigate - nav_lon = g.pi_loiter_lon.get_integrator(); - nav_lat = g.pi_loiter_lat.get_integrator(); + nav_lon = g.pid_loiter_rate_lon.get_integrator(); + nav_lat = g.pid_loiter_rate_lon.get_integrator(); // rotate pitch and roll to the copter frame of reference calc_loiter_pitch_roll(); From 0ab6b6e5921410398123166043d46a0d92292e82 Mon Sep 17 00:00:00 2001 From: Jason Short Date: Sun, 11 Mar 2012 23:17:41 -0700 Subject: [PATCH 166/178] ACM: Rate_d filter for PID loop of Loiter. --- ArduCopter/ArduCopter.pde | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/ArduCopter/ArduCopter.pde b/ArduCopter/ArduCopter.pde index c9f21fd94f..d7e67518ce 100644 --- a/ArduCopter/ArduCopter.pde +++ b/ArduCopter/ArduCopter.pde @@ -341,6 +341,9 @@ static const char* flight_mode_strings[] = { static int16_t x_actual_speed; static int16_t y_actual_speed; +static int16_t x_rate_d; +static int16_t y_rate_d; + // The difference between the desired rate of travel and the actual rate of travel // updated after GPS read - 5-10hz static int16_t x_rate_error; @@ -523,6 +526,9 @@ int32_t pitch_axis; AverageFilterInt32_Size3 roll_rate_d_filter; // filtered acceleration AverageFilterInt32_Size3 pitch_rate_d_filter; // filtered pitch acceleration +AverageFilterInt16_Size3 lat_rate_d_filter; // for filtering D term +AverageFilterInt16_Size3 lon_rate_d_filter; // for filtering D term + // Barometer filter AverageFilterInt32_Size5 baro_filter; // filtered pitch acceleration From 0d434ca92c986a18fffb5ff5e12a717721ca45db Mon Sep 17 00:00:00 2001 From: Jason Short Date: Sun, 11 Mar 2012 23:18:07 -0700 Subject: [PATCH 167/178] ACM: Tuning based on flights today --- ArduCopter/config.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ArduCopter/config.h b/ArduCopter/config.h index 31b7463b60..438408c05a 100644 --- a/ArduCopter/config.h +++ b/ArduCopter/config.h @@ -681,13 +681,13 @@ #endif #ifndef LOITER_RATE_P -# define LOITER_RATE_P 2.6 // +# define LOITER_RATE_P 2.0 // #endif #ifndef LOITER_RATE_I -# define LOITER_RATE_I 0.25 // Wind control +# define LOITER_RATE_I 0.10 // Wind control #endif #ifndef LOITER_RATE_D -# define LOITER_RATE_D 0.0 // try 2 or 3 for LOITER_RATE 1 +# define LOITER_RATE_D 1.0 // try 2 or 3 for LOITER_RATE 1 #endif #ifndef LOITER_RATE_IMAX # define LOITER_RATE_IMAX 30 // degrees From a989b88680f01160b44f0868e2eb562452e783a8 Mon Sep 17 00:00:00 2001 From: Jason Short Date: Sun, 11 Mar 2012 23:18:43 -0700 Subject: [PATCH 168/178] ACM: made same as Loiter I --- ArduCopter/config.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ArduCopter/config.h b/ArduCopter/config.h index 438408c05a..46c2221725 100644 --- a/ArduCopter/config.h +++ b/ArduCopter/config.h @@ -107,7 +107,7 @@ // default RC speed in Hz if INSTANT_PWM is not used #ifndef RC_FAST_SPEED -# define RC_FAST_SPEED 400 +# define RC_FAST_SPEED 490 #endif // LED and IO Pins @@ -700,7 +700,7 @@ # define NAV_P 3.0 // #endif #ifndef NAV_I -# define NAV_I 0.25 // Wind control +# define NAV_I 0.20 // Wind control #endif #ifndef NAV_D # define NAV_D 0.00 // From b3795f1c004cc0a829dc82af3e93270324686559 Mon Sep 17 00:00:00 2001 From: Jason Short Date: Sun, 11 Mar 2012 23:19:07 -0700 Subject: [PATCH 169/178] ACM: removed Filtering code for motors in Quad for testing --- ArduCopter/motors_quad.pde | 37 ------------------------------------- 1 file changed, 37 deletions(-) diff --git a/ArduCopter/motors_quad.pde b/ArduCopter/motors_quad.pde index 8066a382d7..41cb7760e0 100644 --- a/ArduCopter/motors_quad.pde +++ b/ArduCopter/motors_quad.pde @@ -100,43 +100,6 @@ static void output_motors_armed() } #endif - // this filter slows the acceleration of motors vs the deceleration - // Idea by Denny Rowland to help with his Yaw issue - /*for(int8_t i = MOT_1; i <= MOT_4; i++){ - if(motor_filtered[i] < motor_out[i]){ - motor_filtered[i] = (motor_out[i] + motor_filtered[i]) / 2; - }else{ - // don't filter - motor_filtered[i] = motor_out[i]; - } - } - APM_RC.OutputCh(MOT_1, motor_filtered[MOT_1]); - APM_RC.OutputCh(MOT_2, motor_filtered[MOT_2]); - APM_RC.OutputCh(MOT_3, motor_filtered[MOT_3]); - APM_RC.OutputCh(MOT_4, motor_filtered[MOT_4]); - */ - - - /* - if(g.rc_7.radio_in > 1700){ - for(int8_t i = MOT_1; i <= MOT_4; i++){ - motor_out[i] = (motor_previous[i] * 3 + motor_out[i]) / 4; - motor_previous[i] = motor_out[i]; - } - - APM_RC.OutputCh(MOT_1, motor_out[MOT_1]); - APM_RC.OutputCh(MOT_2, motor_out[MOT_2]); - APM_RC.OutputCh(MOT_3, motor_out[MOT_3]); - APM_RC.OutputCh(MOT_4, motor_out[MOT_4]); - }else{ - APM_RC.OutputCh(MOT_1, motor_out[MOT_1]); - APM_RC.OutputCh(MOT_2, motor_out[MOT_2]); - APM_RC.OutputCh(MOT_3, motor_out[MOT_3]); - APM_RC.OutputCh(MOT_4, motor_out[MOT_4]); - } - //*/ - - APM_RC.OutputCh(MOT_1, motor_out[MOT_1]); APM_RC.OutputCh(MOT_2, motor_out[MOT_2]); APM_RC.OutputCh(MOT_3, motor_out[MOT_3]); From deed802d1a7781fca42628f9f64ecf18aefee688 Mon Sep 17 00:00:00 2001 From: Jason Short Date: Sun, 11 Mar 2012 23:21:33 -0700 Subject: [PATCH 170/178] ACM: Broke out the D term for the PID loop to add custom filtering. The current AC_PID filtering wasn't working for this application and we needed more smoothing. Bad pitch oscillations were being transmitted to the copter. --- ArduCopter/navigation.pde | 51 ++++++++++++++++++++++++++------------- 1 file changed, 34 insertions(+), 17 deletions(-) diff --git a/ArduCopter/navigation.pde b/ArduCopter/navigation.pde index b69cb24aa8..6cb96681cf 100644 --- a/ArduCopter/navigation.pde +++ b/ArduCopter/navigation.pde @@ -55,11 +55,11 @@ static void calc_XY_velocity(){ // straightforward approach: ///* - x_actual_speed = x_speed_old + (float)(g_gps->longitude - last_longitude) * scaleLongDown * tmp; + x_actual_speed = x_speed_old + (float)(g_gps->longitude - last_longitude) * scaleLongDown * tmp; y_actual_speed = y_speed_old + (float)(g_gps->latitude - last_latitude) * tmp; - x_actual_speed = x_actual_speed >> 1; - y_actual_speed = y_actual_speed >> 1; + x_actual_speed = x_actual_speed >> 1; + y_actual_speed = y_actual_speed >> 1; x_speed_old = x_actual_speed; y_speed_old = y_actual_speed; @@ -82,6 +82,12 @@ static void calc_XY_velocity(){ static void calc_location_error(struct Location *next_loc) { + static int16_t last_lon_error = 0; + static int16_t last_lat_error = 0; + + static int16_t last_lon_d = 0; + static int16_t last_lat_d = 0; + /* Becuase we are using lat and lon to do our distance errors here's a quick chart: 100 = 1m @@ -96,12 +102,32 @@ static void calc_location_error(struct Location *next_loc) // Y Error lat_error = next_loc->lat - current_loc.lat; // 500 - 0 = 500 Go North + + int16_t tmp; + + tmp = (long_error - last_lon_error); + if(abs(abs(tmp) -last_lon_d) > 15) tmp = x_rate_d; + x_rate_d = lon_rate_d_filter.apply(tmp); + last_lon_d = abs(tmp); + + tmp = (lat_error - last_lat_error); + if(abs(abs(tmp) -last_lat_d) > 15) tmp = y_rate_d; + //if(abs(tmp) > 80) tmp = y_rate_d; + y_rate_d = lat_rate_d_filter.apply(tmp); + last_lat_d = abs(tmp); + + int16_t t22 = x_rate_d * (g.pid_loiter_rate_lon.kD() / dTnav); + int16_t raww = (long_error - last_lon_error); + + //Serial.printf("XX, %d, %d, %d\n", raww, x_rate_d, t22); + + last_lon_error = long_error; + last_lat_error = lat_error; } #define NAV_ERR_MAX 600 static void calc_loiter(int x_error, int y_error) { - #if LOITER_RATE == 1 int16_t x_target_speed, y_target_speed; //int16_t x_iterm, y_iterm; @@ -109,31 +135,22 @@ static void calc_loiter(int x_error, int y_error) x_target_speed = g.pi_loiter_lon.get_p(x_error); // not contstrained yet //x_target_speed = constrain(x_target_speed, -250, 250); // limit to 2.5m/s travel speed x_rate_error = x_target_speed - x_actual_speed; // calc the speed error - nav_lon = g.pid_loiter_rate_lon.get_pid(x_rate_error, dTnav); + nav_lon = g.pid_loiter_rate_lon.get_pi(x_rate_error, dTnav); + nav_lon -= x_rate_d * (g.pid_loiter_rate_lon.kD() / dTnav); nav_lon = constrain(nav_lon, -3000, 3000); // 30° // North / South y_target_speed = g.pi_loiter_lat.get_p(y_error); //y_target_speed = constrain(y_target_speed, -250, 250); y_rate_error = y_target_speed - y_actual_speed; - nav_lat = g.pid_loiter_rate_lat.get_pid(y_rate_error, dTnav); + nav_lat = g.pid_loiter_rate_lat.get_pi(y_rate_error, dTnav); + nav_lat -= y_rate_d * (g.pid_loiter_rate_lat.kD() / dTnav); nav_lat = constrain(nav_lat, -3000, 3000); // 30° // copy over I term to Nav_Rate g.pid_nav_lon.set_integrator(g.pid_loiter_rate_lon.get_integrator()); g.pid_nav_lat.set_integrator(g.pid_loiter_rate_lat.get_integrator()); - #else - - // no rate control on Loiter - nav_lon = g.pid_loiter_rate_lon.get_pid(x_error, dTnav); - nav_lat = g.pid_loiter_rate_lat.get_pid(y_error, dTnav); - - nav_lon = constrain(nav_lon, -3000, 3000); // 30° - nav_lat = constrain(nav_lat, -3000, 3000); // 30° - - #endif - // Wind I term based on location error, // limit windup From c08fd5054217469420d27ae829ce7d034e159965 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 11 Mar 2012 21:51:49 +1100 Subject: [PATCH 171/178] AP_Declination: fixed build of test sketch --- .../AP_Declination_test/AP_Declination_test.pde | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/libraries/AP_Declination/examples/AP_Declination_test/AP_Declination_test.pde b/libraries/AP_Declination/examples/AP_Declination_test/AP_Declination_test.pde index baf0b7ee02..a77a24298a 100644 --- a/libraries/AP_Declination/examples/AP_Declination_test/AP_Declination_test.pde +++ b/libraries/AP_Declination/examples/AP_Declination_test/AP_Declination_test.pde @@ -1,21 +1,23 @@ /// -*- tab-width: 4; Mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*- // AVR runtime -#include -#include -#include -#include #include +#include +#include #include FastSerialPort(Serial, 0); void setup(void) { - float declination = AP_Declination::get_declination(43.064191, -87.997498); - Serial.printf("declination: %d", declination); + float declination; + + Serial.begin(115200); + + declination = AP_Declination::get_declination(43.064191, -87.997498); + Serial.printf("declination: %f\n", declination); } void loop(void) { -} \ No newline at end of file +} From 7daaadf776717cde720eb462e96f976664e8a54e Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 12 Mar 2012 17:28:07 +1100 Subject: [PATCH 172/178] Compass: fixed the order of rotations in the compass driver this should fix the massive heading issues that people have been reporting. Please test! --- libraries/AP_Compass/AP_Compass_HMC5843.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/AP_Compass/AP_Compass_HMC5843.cpp b/libraries/AP_Compass/AP_Compass_HMC5843.cpp index 6ec074d28b..7310b1cd47 100644 --- a/libraries/AP_Compass/AP_Compass_HMC5843.cpp +++ b/libraries/AP_Compass/AP_Compass_HMC5843.cpp @@ -264,10 +264,10 @@ bool AP_Compass_HMC5843::read() // rotate to the desired orientation Vector3f rot_mag = Vector3f(mag_x,mag_y,mag_z); - rot_mag.rotate(_orientation); if (product_id == AP_COMPASS_TYPE_HMC5883L) { rot_mag.rotate(ROTATION_YAW_90); } + rot_mag.rotate(_orientation); rot_mag += _offset.get(); mag_x = rot_mag.x; From 13dac4a93a6ba7d7e70cc284a8cbe7c3d858baa8 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 12 Mar 2012 17:49:15 +1100 Subject: [PATCH 173/178] DCM: adjust yaw kp constant down to 0.4 this makes the time constant for compass errors closely match the timing of the older releases - about 10 seconds for a 1 radian change in heading --- libraries/AP_DCM/AP_DCM.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/AP_DCM/AP_DCM.h b/libraries/AP_DCM/AP_DCM.h index 5ebe7f554f..7c7b2a4217 100644 --- a/libraries/AP_DCM/AP_DCM.h +++ b/libraries/AP_DCM/AP_DCM.h @@ -26,7 +26,7 @@ public: // Constructors AP_DCM(IMU *imu, GPS *&gps) : _kp_roll_pitch(0.13), - _kp_yaw(0.8), + _kp_yaw(0.4), _gps(gps), _imu(imu), _dcm_matrix(1, 0, 0, From 0b51d9b8b0e61649b4645a3589b07965ecaad85c Mon Sep 17 00:00:00 2001 From: Jason Short Date: Mon, 12 Mar 2012 10:37:08 -0700 Subject: [PATCH 174/178] ACM: Made Loiter_D 0 by default. Accidentally left it on by default. --- ArduCopter/config.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ArduCopter/config.h b/ArduCopter/config.h index 46c2221725..3cb5558284 100644 --- a/ArduCopter/config.h +++ b/ArduCopter/config.h @@ -687,7 +687,7 @@ # define LOITER_RATE_I 0.10 // Wind control #endif #ifndef LOITER_RATE_D -# define LOITER_RATE_D 1.0 // try 2 or 3 for LOITER_RATE 1 +# define LOITER_RATE_D 0.0 // try 2 or 3 for LOITER_RATE 1 #endif #ifndef LOITER_RATE_IMAX # define LOITER_RATE_IMAX 30 // degrees From 73e2bd6cd8ed0c4a11e5819a70617a2d82e194fc Mon Sep 17 00:00:00 2001 From: Jason Short Date: Mon, 12 Mar 2012 13:11:05 -0700 Subject: [PATCH 175/178] ACM: Got the sign wrong. I'm using the derivative of the error now and not the sensor, so the sign was reversed. --- ArduCopter/navigation.pde | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ArduCopter/navigation.pde b/ArduCopter/navigation.pde index 6cb96681cf..f5f5616275 100644 --- a/ArduCopter/navigation.pde +++ b/ArduCopter/navigation.pde @@ -136,7 +136,7 @@ static void calc_loiter(int x_error, int y_error) //x_target_speed = constrain(x_target_speed, -250, 250); // limit to 2.5m/s travel speed x_rate_error = x_target_speed - x_actual_speed; // calc the speed error nav_lon = g.pid_loiter_rate_lon.get_pi(x_rate_error, dTnav); - nav_lon -= x_rate_d * (g.pid_loiter_rate_lon.kD() / dTnav); + nav_lon += x_rate_d * (g.pid_loiter_rate_lon.kD() / dTnav); nav_lon = constrain(nav_lon, -3000, 3000); // 30° // North / South @@ -144,7 +144,7 @@ static void calc_loiter(int x_error, int y_error) //y_target_speed = constrain(y_target_speed, -250, 250); y_rate_error = y_target_speed - y_actual_speed; nav_lat = g.pid_loiter_rate_lat.get_pi(y_rate_error, dTnav); - nav_lat -= y_rate_d * (g.pid_loiter_rate_lat.kD() / dTnav); + nav_lat += y_rate_d * (g.pid_loiter_rate_lat.kD() / dTnav); nav_lat = constrain(nav_lat, -3000, 3000); // 30° // copy over I term to Nav_Rate From 7034b709d1e5c12730689149e74a2acf54e89096 Mon Sep 17 00:00:00 2001 From: Jason Short Date: Mon, 12 Mar 2012 13:11:30 -0700 Subject: [PATCH 176/178] ACM: removing old define --- ArduCopter/config.h | 4 ---- 1 file changed, 4 deletions(-) diff --git a/ArduCopter/config.h b/ArduCopter/config.h index 3cb5558284..45ef25399c 100644 --- a/ArduCopter/config.h +++ b/ArduCopter/config.h @@ -676,10 +676,6 @@ ////////////////////////////////////////////////////////////////////////////// // Loiter Navigation control gains // -#ifndef LOITER_RATE -# define LOITER_RATE 1 -#endif - #ifndef LOITER_RATE_P # define LOITER_RATE_P 2.0 // #endif From 10da3db15c7c39d35320de820f55ee9394f64051 Mon Sep 17 00:00:00 2001 From: Michael Oborne Date: Tue, 13 Mar 2012 07:15:08 +0800 Subject: [PATCH 177/178] APM Planner 1.1.51 revert posible camera issue fix apc220 units rts issue fix bluetooth comport issue - re andrew cleanup startup test --- Tools/ArdupilotMegaPlanner/Capture.cs | 2 +- Tools/ArdupilotMegaPlanner/MAVLink.cs | 3 +- Tools/ArdupilotMegaPlanner/MainV2.cs | 55 ++++++++++++------ Tools/ArdupilotMegaPlanner/Program.cs | 2 +- .../Properties/AssemblyInfo.cs | 2 +- .../bin/Release/ArdupilotMegaPlanner.pdb | Bin 1003008 -> 1005056 bytes 6 files changed, 42 insertions(+), 22 deletions(-) diff --git a/Tools/ArdupilotMegaPlanner/Capture.cs b/Tools/ArdupilotMegaPlanner/Capture.cs index 022f40fe37..44775cb5eb 100644 --- a/Tools/ArdupilotMegaPlanner/Capture.cs +++ b/Tools/ArdupilotMegaPlanner/Capture.cs @@ -157,7 +157,7 @@ namespace WebCamService Start(); // Start waiting - if ( ! m_PictureReady.WaitOne(2000, false) ) + if ( ! m_PictureReady.WaitOne(5000, false) ) { throw new Exception("Timeout waiting to get picture"); } diff --git a/Tools/ArdupilotMegaPlanner/MAVLink.cs b/Tools/ArdupilotMegaPlanner/MAVLink.cs index 2b181fbf75..a659e0b912 100644 --- a/Tools/ArdupilotMegaPlanner/MAVLink.cs +++ b/Tools/ArdupilotMegaPlanner/MAVLink.cs @@ -184,7 +184,8 @@ namespace ArdupilotMega BaseStream.DiscardInBuffer(); - BaseStream.toggleDTR(); + // removed because of apc220 units + //BaseStream.toggleDTR(); Thread.Sleep(1000); } diff --git a/Tools/ArdupilotMegaPlanner/MainV2.cs b/Tools/ArdupilotMegaPlanner/MainV2.cs index 26e42632e2..6e7f4a9643 100644 --- a/Tools/ArdupilotMegaPlanner/MainV2.cs +++ b/Tools/ArdupilotMegaPlanner/MainV2.cs @@ -261,37 +261,55 @@ namespace ArdupilotMega private string[] GetPortNames() { - string[] devs = new string[0]; + string[] monoDevs = new string[0]; - - log.Debug("Geting Comports"); + log.Debug("Getting Comports"); if (MONO) { if (Directory.Exists("/dev/")) { if (Directory.Exists("/dev/serial/by-id/")) - devs = Directory.GetFiles("/dev/serial/by-id/", "*"); - devs = Directory.GetFiles("/dev/", "*ACM*"); - devs = Directory.GetFiles("/dev/", "ttyUSB*"); + monoDevs = Directory.GetFiles("/dev/serial/by-id/", "*"); + monoDevs = Directory.GetFiles("/dev/", "*ACM*"); + monoDevs = Directory.GetFiles("/dev/", "ttyUSB*"); } } - string[] ports = SerialPort.GetPortNames(); + string[] ports = SerialPort.GetPortNames() + .Select(p=>p.TrimEnd()) + .Select(FixBlueToothPortNameBug) + .ToArray(); - for (int a = 0; a < ports.Length; a++) - { - ports[a] = ports[a].TrimEnd(); - } + string[] allPorts = new string[monoDevs.Length + ports.Length]; - string[] all = new string[devs.Length + ports.Length]; + monoDevs.CopyTo(allPorts, 0); + ports.CopyTo(allPorts, monoDevs.Length); - devs.CopyTo(all, 0); - ports.CopyTo(all, devs.Length); - - return all; + return allPorts; } + // .NET bug: sometimes bluetooth ports are enumerated with bogus characters + // eg 'COM10' becomes 'COM10c' - one workaround is to remove the non numeric + // char. Annoyingly, sometimes a numeric char is added, which means this + // does not work in all cases. + // See http://connect.microsoft.com/VisualStudio/feedback/details/236183/system-io-ports-serialport-getportnames-error-with-bluetooth + private string FixBlueToothPortNameBug(string portName) + { + if (!portName.StartsWith("COM")) + return portName; + var newPortName = "COM"; // Start over with "COM" + foreach (var portChar in portName.Substring(3).ToCharArray()) // Remove "COM", put the rest in a character array + { + if (char.IsDigit(portChar)) + newPortName += portChar.ToString(); // Good character, append to portName + else + log.WarnFormat("Bad (Non Numeric) character in port name '{0}' - removing", portName); + } + + return newPortName; + } + internal void ScreenShot() { Rectangle bounds = Screen.GetBounds(Point.Empty); @@ -526,11 +544,12 @@ namespace ArdupilotMega comPort.BaseStream.StopBits = (StopBits)Enum.Parse(typeof(StopBits), "1"); comPort.BaseStream.Parity = (Parity)Enum.Parse(typeof(Parity), "None"); - comPort.BaseStream.DtrEnable = false; - if (config["CHK_resetapmonconnect"] == null || bool.Parse(config["CHK_resetapmonconnect"].ToString()) == true) comPort.BaseStream.toggleDTR(); + comPort.BaseStream.DtrEnable = false; + comPort.BaseStream.RtsEnable = false; + try { if (comPort.logfile != null) diff --git a/Tools/ArdupilotMegaPlanner/Program.cs b/Tools/ArdupilotMegaPlanner/Program.cs index ec406309d2..c6fbd5b9e1 100644 --- a/Tools/ArdupilotMegaPlanner/Program.cs +++ b/Tools/ArdupilotMegaPlanner/Program.cs @@ -31,7 +31,7 @@ namespace ArdupilotMega Application.Idle += Application_Idle; - CodeGen.runCode("Sin(0.55)"); + //CodeGen.runCode("Sin(0.55)"); int wt = 0, ct = 0; ThreadPool.GetMaxThreads(out wt, out ct); diff --git a/Tools/ArdupilotMegaPlanner/Properties/AssemblyInfo.cs b/Tools/ArdupilotMegaPlanner/Properties/AssemblyInfo.cs index bb1b4de8b3..58eeae5426 100644 --- a/Tools/ArdupilotMegaPlanner/Properties/AssemblyInfo.cs +++ b/Tools/ArdupilotMegaPlanner/Properties/AssemblyInfo.cs @@ -34,5 +34,5 @@ using System.Resources; // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.1.50")] +[assembly: AssemblyFileVersion("1.1.51")] [assembly: NeutralResourcesLanguageAttribute("")] diff --git a/Tools/ArdupilotMegaPlanner/bin/Release/ArdupilotMegaPlanner.pdb b/Tools/ArdupilotMegaPlanner/bin/Release/ArdupilotMegaPlanner.pdb index 3b01042cf479a70bb7fb27fd7e4d21ecb96ad8ef..4df910db4143c026c3720316f89f4b9f40997551 100644 GIT binary patch delta 160065 zcma&P37k*W|M-8;z4M-hnK6@Lj4@`$zBBgSjI3p1Y!PBCMG?aYCG#eVqR8^1EMv7@Bi_CKjt;hd(P{1&OQ4%_uTuw@8HUI z!ENmp){1#1!m`GuTkdC5QC5#K2h5^g(a+gG+w$L@(Shd!c7%B@JS?ojuvxeFG?)#S zv7JXBIFz|>$BaV}RpR?UU#V2Ru(;eh5qlmwx3{qWXVWS++E{w>uB^@GiP&!IyT#oR zceL}DWxiiqC+t$K#=qa2{_TUVu2=WxyHEXZ*|^)ks~A3S$$^i5S^uAgcfI%FTvs^} z_s2+l{5FtR=$E?C^^$2KXCar8Lym2FvH zBi|r>9m`sX-=f8feoU?Z1V@XJCCE}_8QM>gE66h3g8ansa=2pg*&h>Qp5*8$WF@j{ zvALXBP{2up$V_Aw@*uJr?HXh@$8RD>kfX?3NFn}fk#)#=c^ypIqO{h|r{=kzBYQ_h zFW!60M(emSi?SLPWp*)r!@@eQKVDF@{3a7^hc)RvWN6Xm9wxyFTd*PZxuSzT&Cc+! z*Ts zzcK!W(r##p1U`U&coY0Lt&>mYI4!RQ_(}sbMX_IEhMB7I`_~2BLaS`0#nULP!;&@3 zq?*H$7ilYIdajd0>}0w8kQ0X2A~`gvL{4)w*JMQuEbA3z{BZKqiey_) zOY7mLWd*;6@G03G3f9W%>Vb-~VYtb(*R7RjA8{%!8)4$i7KtBW-ZT+%XrxJ&pYe){ zb#rd4>2jsML&8RyLi32~>zYM!X{5Q)6iUV@T$^ObC|vuC){Zha8{2xi=!ZK@V-uhg zhhLEDqfPgu|Jly8ab8Fclhk&Bq@u#nv@o+=s^4W&o#p+Fj9+UqWcquiLeavz%umL& zkq%o-Iaxl|R4{MLuCb=7dAsP;So2hvsV#YVrlDz3v^LK)F=mIHnrI44j`W*kI+%m9 zRMAmRO)?LgIWi=l&M-&j)udzg`e zbx|oX`K2vubBtwuLIv!WLzB&)ritvom-BU(EBBg5&0X@q6!V~YOw3dYkke#J{7kdhWXr~xq-2JCJk#85-j~j^ zD5}rp_$*HLx%@KAWNT4%dXOY+kh}*?XNsrjK~q2S+*rTh79D3iab}x%b56?5Cgtgp zH=C3XEGvg+6YL?mGTTgXHjFc}rV!=)IVRe5y<2E{YUJO~F}1?`(_AV{kQw)fHRTLF zA2Q{lXbMz~v6{%*A52*ZK4b<^?;k&88b(r!QI8Y)`C&5Ss#8(&AEy=XE}HYWnPO7` zR~MQ8nDnAwo-jqmgcWUHLXlB)`#;FSz+!snlxZn^t*pwdrG=qp3{ySEGi=>_Xb*H?pdbQvF7b z7m{~!mA00=ca!Y3^!#ozZms!+e2p)p9Zy|{{e!Y-om-e6t)npKrQ2RBZ1-+-nw&cn z2$M$ZO|+RO?be$d0zSUp)HmB?|9aEPAL~!kvqPO*hwY;hvw^z)rfA3pbE}E!=Ei8O zHj)=Z|2?sh!h29^KW$nNX|7^h(Tb<3>p+Kq6~0WWZ)Tugwk1qE-$iLu5LJq^((P&o zGSRP+aa*p9pB-fT7RH+_{5NiqzccKn{`lEJ;c0}=owAxxCz%=#05&w&_mc!Z? zw|J9LdCQ64O}7eTRB(z3#$W#Qb?(Neh6yh`bpIT=A? z*<}&}0Ro=YfT`xJ?Am1#qe^%4Cnj06m*@`eHPLc;7o}9-mQt8he~ui76Ydeoe(qXL zgvkQ+kHG&e+4G#~5T$9-GH5L3WT|8cK2J;kL{gqF5oE~o1c}1#yv!--|GN5@!v9;j zRMNlxZv0E*|D*KVT_T>P_=iX1Kc>69vfEU);b*%|c_**CzdnfDV;Wz}LH9jG6NCAq zlDCJPKPrp%m_%ps|7v_yjbkz1F4gxkac}QlJaN;u=+=i;IjQDpNq;4fD!&y`T=Sm@ zM9Q|kCKBI0dri&wSNt%cx%O$fw3o$1s6;c0XkBGE#aE=D!(qFeOeiun{3aGAt5Ao> zp}zYjd85cwvEj4(OywwT%ewH|B=IkhjZKo_A?F3o`NU1d>C^?rCYgseX_F~l0*uGI z264o?>O+Jgj*A-jhMT>>x`<#2O5pStO)}bc9tMJxl2MJhx5t=!?zSuqP|6Lk$g|x3 zqDhUf??{v~uwg`Vza=Bgq4$TnvWzq^M#w9nLtzq^N*D2)X} zYqRX%XA)(@OC}+z3VynZ*(_J~na=)7FihILL>xB|M{Ks-@sep!B{sV_V;aX6Q(PS5 zMvWYkYsoz?oAPoD<7=^)mx-k;u?)(VIxmxwL4GWulx&sUmrY{Q))JA0%2pG#RTjN$ zx?hX#Jkdob5ZxX>8p-`2x~x>)Z{m|eUOIeLqd3MQS^@7%_I{HcF~jeJYxmPA%MrzY zXw92TTuhw&;NaI^R7a3l6d*cuQgqF)4o{hYqo}n|+88>%4coQ;)yZ zp$^RdbvDsLP6y@S4et^7@joTFRkGppR*L}q{<0nYgZKl{}7dC-Ev3XcNK7Q>w;WtTnhpx@lUieBzLedwMPBl+R);W_ZM?N$y zqqM*1nE8ZU`hcEW>mvrswy#ApL!IKn;CVlSief&Z$@Ms8+OpQ2cZx>)E~gopA3lG0`#Ohu`InZJM#glJyaT;bJ+o zkPE8`YI6h|nf;MTz&CzUDOT2G&3-UL8hm2v$hSD+lN%Q&JJO9MaN5+3*;&H7l;nM4 zQUhERaE{#5w7SnqXm#LREK5%_-@h$ip$(j%R9KvSZ0g1zZF+s|OSB-8Wy0?fVP=W! zYDz^c(QC>?Dg2mRFOl4HTZefja`FuI-tEk_QTuIq0E6%k zux-#>o<3u$#5ZW}C0FMPl432BnTrEll%6ql{IU6MseYC~rwBB#x!iL0+Sb9_vPcyl zq8Qs;_LWpzMG^54iY3hh(sO!%PWBn)hU>cCAadxPQmIDd{3<6or6rYl4*8s9yzg6v zF4#qOeMa*VIsTcc8TDODFP`$UOIvo_=O!UOtyOVGv`$3ouMQ;1EuWi;@q>Mx7PwCP z#I_=EBSpRcbBgXX>6{~9eNKy+;~Q#s)kv0Wi%I2TIm?6FK$dF*DJM^!GqLf@`~aFx zoz<{BWx5ixIZx4iOw6TPOP%v3(;qnBmONE_f}(tDdGb76w|r|a;i0Uqkdx=h>Iykj z6jpZG7p!@_Eu6Qd{uc!Ol%SnjOMetLtn;Nwk)Fd$lU-^y}qQLy$yr6W#*U6!Dk6H$v2iOA2SEP_N9q;@RA+RlunY%U$STn zrKt7=%I`Bm?2w!brfy(|29&I?=nTh-!XmFr{c&u=KgYI78~OEusS(qpjhAsvQmmXD z=Ojz?`%a`;CD}xfw91rNh2&0kM;a~SRr0`Bl+UVbTR35|^D7gUQqq3P_=$Iqx#vzd zjP|fqa?%TP>7OxoM61n0*JrCFS8 z*H`HPRaSO>&DgO@Ui|vnGK2Q;4LyRL&+zOH-kj$zF?1#h&1_?df_cbYVpR05!WVvH z2H1TY$-llacW|Yh^DT>qWknBstD6!dGm0L&XnwHG(V_>wH_sSzOmcrZ5p8JaDN zhO??T|8LX5ZqlZx%FpJZFh`4GOHPh~brUU{o`2A4%AskuSSm-_ z<)!cs29kD*i<^$NiI*g|I-~hZ65lE;Rkn?EqUEm!5zzsidS8;9<)zyBO*U4B{7FTy ztsMTs60ais3;bBTLKQKUV1LWWKTUznX?y==J~J;!##QrUL=;xt9`n-ZZ~Kj7?HCH! zmVn(J6Sm|k7R~?LEH|e9(&~0i{%6~F^Z!MA2y2U>2e_K4XY2~>oOL#+b7Y*cML;MNy^gWMj@q^=KkKBN_YI!5JKF z-$zxYeivC@E=AjkoIVgkRYgnv7+bf93S#W~EaA4t*bTwi82ckO{`SP;Iw@bp+D%Nj zB$WXpB)bfrFUbRC>=xz=*`r95ONt&+Jq~P_A#wHy;ye^bfPL~yoPB@zK&_$;?hc*b zLKm6h9BM;5BZuPc8>6CEd;4}}<%(gUmUe?(%cK@{zrh|9?u_4HHOsXBv@%~gh(fRcqTYB!N&a#u74E9Q^rrEUvcT*lyBqz=8 zPRP&G=|MZwh^$bKrrB9|l}^WKEJnMfRl3~{pDF1?|FvvPw_ABZ>YGCnQ^l?eT2-+Z z>9*mybeh4rDnt}1zgKZ1a^vn*6|W95rmE}pOjTl9BOh0#de%rxH7{&oHM^eu*GYM& zn%zM8cQw0*#@VB~UC(L!o-GBBv+!A1-HtYmWmR>14ykZ=BwN-X@?Mft!|v=??bs51 zUN`Hf$@UudAZHZ?(P4H}l2ofnr4|)s*CYXKEYGY(nHS2*S~Q;B5>*@1uiv%h^EnYo z60B`EjXHF~c4v{U-tO3m+IA)xjIU!4B2(k)*e#;gob)V)c$cyV>yUQx5L?&oNNRKH za)Mq(YwOwtVd3nwg~xZ48jTon;yZ@Xbhr!F$c}b~b_~;csxD_5+0DtEJFeBrVBmR% zAo(4oV}@NLIlp7^=Hmbc*areDFxw;5o6@}ZwAVC-n)mRi<^jiT&F%)@nWiM~NsQla zUve*Xg=92iTzm?}zyG0Fs*05;k~>@<;&)Z7LNTa=RB3L9Zk(-+HA2xeo@8K zC?7wR8U@f?llf;Z^uPd&Gdpc@yzDqXHy@m z+cU}JXUbbJYLjo1E;%2TN-Evay)~?}(Gf}SVAr)N-dj3gPifugGggcj=fMt~ zda|Tva?bBN*iFrAMI1Y}87b8}(y~WB>gWxFY&myR>FA=uj`mpF1SO_3Yl|r|tuuo| zq-nJj^g!@d<|^giqV9 zqw;%=pO}A3?zmBt+7BN(w2_p#-Mw#DroUY-cckvb@j2|l{ojbHs2K`hGB{e@#GB1I z^-jKq3E71%OsbY#_K&}3d?%UK)vlVNYF+7-ROgNzs|lNA$(2G=Ux(fkH`xh8^mzvT z-0s2spFxVg3#F*bn5iAdP9D{F{P_IQp`3M`e5V>}>PC~YVZ@=~Lt#RvuO@~aZEhiE z9SEdmR4b9zdqzzO#pTAbjaUW~OIM9{u~(Lrb3+1TB#TIMf8PryXgzb$s; zztz~{yWHJwtaaO{hnc_&N0<#N5o zckWJZeBQs7#MFM7l*+a%rwk*S6Nu{D^B9meg#VepMnsjg&5vqfiKto;)hyYSZKtM0 zqMnMVde;AEOlf0vFOpAne*n_s*2Hv!_*I$yO?25RZtLDjj4d%&(~w$Qw}z~#*Br^R z^A_gQni3!GBqx23c|P}Vbcb`hADcErOLq0K6PNY0!(!E>DKUnT)y7ZBZN2S^a~7E6 z{of9=;j5(m6t0Tv<=AyHyaE27LrH#FFHAq}s{W@vL65I;WXGGO%cYzl?o5o-08ck5 zTDsa-Ye~i*?9kPc91n}`FO`()#K$pp{EU<)*}s(tqR|tix1C&hF6zrjFT5UE?Zv8< zpc$=Y6v8aJT{ zDqT>7VhSS#B*gl#usD&7qy&F};BG$JVv>wk*xF(f#xzWH!%;5xv?G`GwIkDh#!f%g zJ-Gi_g@jk}!%6nH(N$&5&r$k#j83y-b|!eHk7)V%9~K+oUHuT&UE`-s${#c0?n$HW z8HrvK{TpYQPB;w{vQz&?_)SIn;eS_&lxnoKPf}Vr?;Pztxc}#}DmW=a`q@cb zA^1xGw{b4~UySErTxPx8-j7S2CLwFhNyXnPcyT_ewcvkP28Cy@m-hYbiYZHo?Jzc~ z&tC79qgJ+#{B^v}ey|gry^iGFPt&ZUy9~*4qQC3qZ8dnuhtxmrR@eW$9yjui*>vE} zhj=AWjiQ?}K#>sb7oJbGW?n%bBgtu+ zWHcK$6en48SVtBOuv5#a$pB2I;T86@XHrqF+{P9A=>c|Jj_T*5*9-fXeZ6)UU0pGT zXuESiqw|MfYm^%1AYtmDDcn@t;~vd)UNMb!7D{HY3s|ah4YrJ+wGp|k=r7JNn{XN?WTz?9&R18?4zv@K>Xt}geny6+Hxo4B zbtU6AJE?RF*F#g~c~oubM%*-s=Q@cv3&pP`l8+O^akp`i;Mylw5A{L~(Ss0`uxP!x zIKw(r)OCl76g3HAq6PLv2@~z-b&GppdT)QB6{m6WY2v~CeL@`Vno$KE8(^9G@*@NvYf3;CA$v-30 z_q7j?@P^mkBCia#Q%tU8-e&4t8~CevM*r4f#Q$_6eNDGW^C3*#^NDQ(HmYyBrMT%e z#T<3f zNeJz?HCtU9X*37Ds_=X)_E(-Q&H-f}%0aK;ZVuc@HO=+T8}6Pwhy0~1B>O#xKu?&l zqc{S*G=kwQ9rYXuRlRfETfzh{{~Q7B3zQ7=wlo^yo{n=Q25Pw8?s@tWVH_d!JbOz- zQqzkhbe_?~biy#(?JQ18Eze|xn`kOR8&w6O8j0;g*!C!4t0OM0VWgedYBVOpFxi9G zp%Nx_)x;DJ++)VwnSqyEIrUU0xg*_EJ>X#lNGTcM&WU>M<<(OoH^9k}c3rn`7IHq# zVfb@i^0hr^_w`@ahz z20bUG?qFgbMvRvc)erJx(TQ0N8+tblK%9;>SABjnDhnl~})*lXsBgTBw&G zs{Y=OG&Ix{U#01#N8^@SiG0F6xc~XyLwM)sy;88+PM$C_H-FTK(W6G(ts501B=&Yw z%TGv7)7oCRH>k_dryB{mITXA^Xw~aVsjZ%pa2h6Lr&-n{H1gIW!wSR0Od}m$lLI3~rwH zw-a(M_+_IFGxX_B+0@$O7i~YcWP9WeA2n9>8huN`>_jw7$gT#dP<@7b^WDj4RJ=8# z=c$L}rMa8iQ<=N|G zka9P3aAWCwH^W$C$$ExISf}63FxFV+;8iY--ueOEF_uU#`;nHHlR7c=%EK%|2IkqR zNtG};f#{`N{NCb@6)B7I7-YwyI)-SAs9HiDC5Q4DqC-m*Jy|3<&`G{(5wS@81iOOF z8*69u^&V9F=k-}aeN6du_Tc`%nKH@L(CX?m-Yb0$wcI-q`#D7IGm9j4oZWz@)-u{e zr^_oV!yAP*HInE1@iMGl`}82*IYnIesr8w0c8yRk-JsJKpX3sqD;wi=l5r2cbRls~ zz(m#S{B&u(u-LMixKGstSSWGG7d4UtIy5zLm*oL1h9>R}z<{QsiRhv{pwkB1sQTnh z+ITxsmQSKin~t~RQkt0J5%Z2QV@FNGGPJa4A}l77xthqOhD~M3&8G%?JQEomr54(% z`JRAhK^x#U{9?ybMYt+6f#pTX_(zVJ=oaV^GMB&zy8*LmFL;HnF-E$4y1 z!DIzq4Sf^saZ#?xOkz&aSjJLB+*`2XUo4KLv}=;L&PhzEKn$ZX31X63!X(-?p)r?T zrtPtbMA05odSJaUgZYO>kh9N=P|wMZgO(%K?$caNWC-mqWdqg&u zrv6;^BVM7;Ei}^o(tVPhTz@m6ElgCse}5rxRyB(xfGd6aSG~8_t zc)8asXbPK|;tqT7m{C*ky0&W6aDzG3B>e6x5zf|dGUQ$g_GL^4U@`=+hkX-m7&_ZE zlSTK^FfL=#7n5|n3QNSI1=vgu-D{6X+R%byK1V&c|9eqpe@nY5c53WOLQlX%)qfw5 zPo~;kWakumT61sjpwSr~2yCvSRH9s-V%KT-zi*^P>lG58Y98GGIh^H9=|0uH#jM*K zNgw!Dm9%vHPj9TglU-A(zc|!|h^oIk=#{0`pIWx?7E!=oL}gYy(aMYBRX-+0A7YDm zRqmU{cJgVWT8WM7BVH|Tm}=LO??Bm!&03bIq2alcN2*HakxB$xj*P-xrbJM!otFA6 zI)n3lb`5Qq?sjyi)*8~Xbj%BV`jV8RGWkBc^Z&8=__7~JNBq#IAA#O`)scb^?IB6q z+IZfPI!^kZ{uo@A-23&?iSSb~QT1g%ky>0@xUFRE{WSMha>&E^`|YfT-oqez3Z0P~ zgs$@2dQrR0(?1JekmbHZ&UCw(e-l15G5>_Y2eht{MXRRUABDweeS3Gq^hVvG|2PR1 zj1{cJII5Pr5$_(B;p>9>?Y)9X)H>&sg5_Z})Y*>(NU%1HgEVT3Tm*F%zXA4xWuewa zqOl%a4{0O8ov<=|0j5H&=yVukHRP6EU8Fo6u%T7X%CwTK-mr5W{&huB3F(2bI zU~k{uA8Po)kfA0ROI_T+K2R)QuBd6lebPO!Nx)nK+= zF>4$;J;!*c=g5P4j!96@F&XMPra(Q%G^ppeAL==#%e>ikLz`Pu`-rX}h_^;J3u<(8 zp!VB&P@An5t48-I?s~qv0elR%*55*y37>#n;4;_;E{A%$C!uC(HJlFDz!Fv`1|WvosT z|DavA)n2q3>kCk0-3K++m!X!}D^O!S2(|8Cg*U?2WZXkMH#AFDJY**qyos+4*hgU! zJO;HLz5^S=6R-n(A9jTw!BD^Gi~D2T+TXQ6Z-r-Y4~L(@G4LE555IsqVqJhU;MeeR zonF6{W)Isp7w9_DyB%h(-9^(DnvcJJzQ>*gyY&Oqi@?iJhufc^4v4?PZ1@+{bX|oS zUeh%U{ug(y?;Zh-?WN0xq^E$VYOLU6C<1V~Z}=pP!2OiZXMF$dFbe1k@JUaM>Suhnh{nJW=w0bKYu7y?M zaaavf>Q)U%DOoikrC`;Ckv1bCOoR<#8`ucy7bi6#dtqbTMFsxBtG?neY>MJD*bH8T zEuif%SHYT)$b#LVMsyQwhkHEi02jg=;TqT(9)(@uFR(kj3U7j?sNQT?P>}8d^ zBMtU}b$tJNupjRFzMBco8i1SqV{0Jf%G=nyb~6|(eMDg3m%1c!*}60_#+$-|Au-(i;K8PxJ$!)7z5S6 z44jHP&UfDcr`ctgojAB3MKw4>WT@OO-&~ABNfu=0fd;^B~RLO-T?gz&#&62DOzhhI`;r_yH973tR!K z(Wo>BHQ-9zHH}ru^{9=t_?T+P61Dowc^YvhZ104eo$CIP1w9LH3@58NQpV5sTLBW?J=`xM|h>gIT`8jqpVb zZt>l{;7ho3e7BD3ui(~F(g=pZgSc~j_XtR@2;K!>lZy*@xb?VXKgQ5`1YaFs-+?;h zybA}xlTbsy568k&Q0It`;1lp;xD9>|LnFum-+c^ziNB5<7vQ(>EBIfisWTKAeKBYo zhAj06!$TvAf$G*u`W`p;*{mO6Blsg^-Qwz5Z&?4v-PUI}-#;7vjz9CRYj-caiu(a* zIaZMI+j8K)AkQEMZJQx0oP#(I%NGG+pBnr}Ztg?{4 zU?su_U=pMSTNU9dm<*qRm0%G}fuF+4@GQODs>T7ivuZ$6<)%CW*1;X+lgM0uBC-A? zM>=$ANi~BFuxsJ7x9{Hg?DFI6?TQ%P`X2%s~9ZZxvB@$`8^wIzqkcXg+1Xs*b6R$IdBssg~8ph z4}2Yx(%^frAN&&bhnF$4ZskB*$^fWy%|Mt6Z-e#VAlMELfkWUhI1c8*sqhY10JWHA z!_hM53H!mQlk2=b+}?c>H|a5~bnJN?R)>uFZns<{?H1cLqsqAVyN%^rKjm99e!13+ z2d?#MS%J099rITg+f@qk@Qx+2iLeZu1a+*K40U}n1*XBNP^;iRsOy30P{)WFuqo7} z>q2fe?hbGc90KRUd*CCG^@lazu^!qA)t*jSU7wV9+_1jir)mUSHRXtZ?#(h;rq;0^G7SQl!J>cbCl)6QLYBlt0Howh%P zv^47s)HeS)9ACh}mmE;c*1w>-zk?6M?;&+<{Rj);Wk~L=pCKo;eud}ZZ}1ZQ9oF_| z!@AH4V;F+}#lNTT&z^&2mg z@^0lDtFojglqy@m6G84Z6;GkKZRbWg07?1*DLJ<9O)e z`5pKeJOOnP{T|#7*&_+Q2tR}ep_a(&@Dtqc!cXDvzW<-_bKK!{zO%3l`~oJ!3s5`n z*Dwgb(Mp@o!A1Bu{1;@A<(^=mZi5M-5t??BeG!LML6yb4*@2FuYIS=R=6PngBci(m$1T^sB|{aa-@7=%YTI2@LT zcf&-eS9cZQOqc{8fyrSiCGCsPA&?2&+Ke0TQeYc`rw>AyoUO1sw2Ni(p513+xVi!alGU90q&CeAowS zPuGC6;H|iyfCJ$w*cWbsgW$7pFx(B*{zZ5@?qA?A_!rED1>y8{iYr(as$m6q2kt8H zPFNj|fh{4$8N3mWg?*vg^W81$9^8B#$(jJCz&ywkbgq5@oQzwa+P)X+oA9Q<-EeAv z{{K1$)A0BP-Ut5+r^CodW@}g$7Qkw7Caeo*!B+4=*bzPq2gAAW4mb}^f{(%=TmT=2 ze1|W%2tE#1!;yimR#2b(c><5!kndUs55Ohxbtv#{s5w0WSKxln=Oy3&C-_uR&T4y& z9pyc7V7S|%Ur>u*gLyUjR3X%vWv!&FwG*SfCkl+U$g|prHXH5Ja3S0zxmY?sl2@UQ?XSVAke2T*oL+~`aK8yV!y|Au)RNJ~=rP<|;BojO zJOSVE^>6#`lkh$KzlQI_?|uDGy0Fp!fA}7M!4Gl&4f)D?u#7*n#_LdvTdxeyK)rH2 z3wy%PV1LNhu7jiC7XfS50;mam9Da>I+jiEsP#0wCzXE=T`ze!bS(iB2rV99)Z=hp5 zUyNCAKV{e2Be5G;f&Lt@=4fgEff-;sFOK^J-j(c5%)NX0#=Wnv`YOl<{PpuUVYHC{ z3pt}@hkJ$Wz?Qgq35&ZL<*iJ?n{Y?Mevnro1@C|iD+TWIl$Qm$yHUJF#@+5M4_9Kq zcoWO9QO`;jEf@kUc%CJ^T)KmdP9K#Zlgke}mIq$}sxrWc>U-$wDD*M!Afwjta{o`EbwmP^Zjjx zJpGJAYB5ghhv8MHVJjEXjV-?6<8CdCf|`&!V0Fm%WZbQVu}~}O9(W6!0Q|LzQ+UbaTN36BFHYa#RL-E2$#aWa0S$g zdXZiVbVS=*W6f{$>p0~SJNq@b>7 z_QDF` zR>3BaOybQU7u&%({b%paY2Y2G}A2=EQ4ukMdI3HexYoQgv5DIO00EWRgAyaga z6{{5qKZ2#;cQ6|M1o@hLkY${kA)AKH%LRf-usp1!E1X0Qm;x>4_8>ExYq$(1<7S3) z-OOxOCER;q3VZ`rhHt?%$hd8#Lxx$4uha)G!fNm`WQ`E~71n^d0@B78MQ_t8Nn%X1 z8Wd%0wGSAxU#>jEHAge-w70c@v5>VzFah$OQMcE%hT4JK!fLQR)GL_|upZ2UdJ)fB zB-k2uf|;;0>;k*MZm=8d1#g1dOK*mQb*|~b!EijX;YipM>V*og*>x{eG~v^5_rrak z&xfG;&xO2FGWZA_0H1)v;2Jm_>UGQrxDAeiyWySiB{&)$x5~1j;@|=vcfqgWSV`G# zOO*GNgW*2gqUX4|nuk`WiAk^q%!h3tYb^J6+%%}06q>9>P~EHHeeh}Dy~EeP0jJ~t zj_*F(P=|11~{)m;wiiR-}!akqqef-K)Z2RUft~OYb}I&S-1plhD)KA-ZJq zJL*0HpOncv`0D4IvWv6C^Gas-VwKl2yI1vva&`x^fcF4`aUVt?jQfPlUwXi2Gp0Im zY=t`QZil)7@GKkzcfz~iUN{5305w4`!S~?H@B{b?{1P63U%^9=atQ?s zlnZO#U<7;dOM3;0G5PeE~G_nxc zj2uDEAqiEvtA=z#h9SC+UXHwgoIt)u!m1T;B5J86G60!?%tZ>3W5@->s?Ld!rbrKD zEHWF}j2uKxBbSlr8k8Q=0~v|TMGBD@kQ2zyNOVnXkZYe^JtEAqSL|wLlT?3&FI;bO zEZOl<h7Y<-rd@E~uTSa^u9MQxHThp^Zrrw;KR2VQ~wD(?yTN!kJX z*HUuNt9E;o+g~LduQiT4Ot`q$2$v_dUn2o|lJgqjYRSCU2v<*De9eB4chJzyXPW1J?n`dc(e-m!Ir^!_F}UQszx^ z+D_WNX?M2ys$$%moP7D4oP3b%D(M$}#I6uIt(^D$McIFuFWBQZy9ePc(@qqxq=1D@-Ex=PC>&(-iPT+L<3Tdw6Ab>+(Ox7^o;;3_AL z-X`Le(*5mXuWfimepKF1%c`HEQ)T?y6h<3yL)1D(h#Ms9m>c5pV?>!P`;XZzoa{u) z`>Ju=aqp|fZgvM8$9{?A9jADf$lBxf9DTIbt%kPmpt>ae-XZo&^1wUxc~uR2*RIE_ zU>3Yf36j@$IYCE>IpMvq)JVnf{CH+(hzv=2XK$e#DyNqAty^L3GqI3S^Hvz5S z4~cb&Jn*4C#d)rh<-L!(!biLh<+-BjA5lvFn;ROjoYSYZxa75TfZQYtPBWCgRCM;V zy~&Q!fmE+(_;xSPa7f{&_QtZhZj&e;d-r~?UJ zz!~l%ITH7!J(o6}et}0bcYnzXRR(#-zv=NbJ-(5q>Z*em@Y*Bi)%5TMyAsWm;}*2f zoUia|`W0Ty^|%Gia^6=YcBOo*_(*Dh4Q`NWiflRhHB;4+L@yl!{g-8Z!+J`5lo@NG9?hO_D79j=Vf2+rOhDyy1H;`yRh5lJY(It0d`{$nu2m zDG^$O9`DxU0p9U%dVH@Q-)JwXB&%zbx=D6k;=4J|745lXw}>y$uTbnTo7Lb|a^e%Sb|PY>-~aXkM$oDJ&>`;Y-DF0 zX0#(5{ES4iLD3TFg-l15Acv7Nh*ghC1!;=(Ky*dD965-bM#AcIA%Jv4h9UZF{RZR& z@-33kfGCh2$Vg;1vJ!c@0T;#}aPTt{-H@B4NH=6GG8@^997HZ4epdLi)Q{}j zOSb|TNf!OaYy92~bK>>IAYsm}X0o&jI0Xz(F9w{N;CukjKGG_jm>-fc;m)IxrTX}R z&F>6D$q@uDCG{h)OO`niPIi*_g7C8?-dxm;b7^8}wA}-G89Jh*u43MM!Sfgrkto^J0oUF`r1|L}F{ z9eSJ7#S&%GmUGRJE9D$s23(H#7JA1=^mv^f_bmT2X{f}GPE%wsl8>xxyen&~SysWR zX4*^j3Qnri{#Ra#)wpzuLgviJ61`ZfAz{iAMn+?X1x$b z1S?N6lALVbrB#sR)aRW^+moESN%Kn>AHh%`OVG}+Qm%N$9V$BY?caZudn!70luuT4 z?&XUY@ySjLlP}$qohIf7c_7)zc7Hb^-QiVQ$)shm{GLp+;=Qw#oGD;MrO>I%$zPQ) zcvs4$ICVi*isR0z!6d?-NpUJfw&Dhj+h%9}8O?g9vJ=MxzUh@cv$QnKUam|GTjW$_ zr>ec>cWJ+#7hrzAxpWhXBQ=ex8kUOwluS!?^tE3*((#(#HY!q1q!QQnaz543mxE!d z%Z=N+ytylBV=valSbNV%lR}Xk#nb1A$zRb+;b03$6}~VP7lRhU*8mz?$k_r z8;qH zK0mu~wkEo7eqK(qJl1h zs4Z@@F?`i}=33SW2OBsOXagAyot{+r%!bY&>iVprwzO*G2z7X}k#i@N*DAx=VSoIG z+N;hB9 z;0)iiqW|@Zos#iVAj^N<9N!{q=Tr?eBgzdjubmTm3tJO8uKvyO-zvY9^l#N3f41_& zcS&x0hPPdk(ZLD5)vbwqtZIImD*U*Z4osuRuUF6PfVvgxi>j_9uXkXIx_G@!?M$a? zbZcw^+||@fF3pWekg=Igf(b}^ml7vCsg`Z9OfPAfkcDOX^_J7JoT`%9(FwEL^^tX1 zP90qVmy9Z31W! z>wtcdJa8kU=OR}f>3tcaNw_q)!fQ0+IyupSOpLZmdM64HluXEqPQ;Og`luY@ke!t4 z)Xh4h?uhy;8Pb{1UtO<0g*yC3)TXce-Px&P!*{ZrZvLC)_-0}k3_4+u(pR4B;?%I= zbq4WWG3bmztG?2@D+cg7gI#LS1%rNl8l6@1C$Ls&lzpnb5(Vv$~sz3h^ z{ivJK_dtJD7Tk>f>Ob^>9%L~aeNsPZ(1XU3Bx`Re(eAdW{ucDjTzz@@wg*kF+4V-* z*%)!RDml~_;*NguMYdCgYvJo+?{^ES%RxU&9^jD2?XOc`!7sWu z>ec=HF<@qZACYR(lcnkE>rI#TBqnZU8uMoKdW+)D)oiBuGh$ccpa6Q>h+c9^?`cvhVnr~ z5q%rSDc*76N`8W<+igVG%JZ16%6{JQZavQPj=$IA1>SMBK^$+<;}+(1&ufW#otIte zb=C6<8%%-FpI#ZvGNP?I=sd0?UmbLk)%t$oZG)XSn~s5|xjoCbh#Nw5tEK)Br-i-G z_Y11uhq6lje)9b;iYKD5!d|b~HcybwV>2^ZXBwWADq4@2U zAw%(_mR-M{L!DX$3z?$zyOl2^=aAo!1g>c7A>EK+$aG{0@&a-K`5B3B#R3QEhKxmK zBO8#Hkq?mXk;vA}(nuyU0Le$@BO4I?*5H}edY6!cXzuP*Lo$&8NIo(j*^C@SP9v9* zNG`R~kd{a?5IKYVj6`=JLZlNi7|BQGBb$+f$Z6y<5}8Q?k(QZ@vff)Z+(`?R=gRRT$r<4^ z^WVYG`_6|uRU^1J86Lm%A8$f`9gV3VyGA(0KmAyH1lCDdkNT(e0@YMRv+bXnD`>*G z%NZV6CKX3Ip!sOlFK^C6FjNn-e>eqEWRitW=*KVRL^7Rv!ktc| zs0O~Gh4*^mm+y3XIGV@Qhk3>E^3nW$SJTl>H}<(780|dj1eOKl@l;-GUu}#N7nR6u zT#a;?7q-_Jr-w~ySC3&n6FEA@kuJTchLOm0WFfK{c^UZt`4+LVXy`~iBoi5cOhD!$ z8<3Zg(^pUDjB3J%)D(@EYRIvU04`i$0viix1@T zIL6!65;M-xEn;4YT|01|U^6vXi};xxym_s%{{`3o5s25B-Q$FQ58|A(yN4p@k)H5E z@3b@TamuC?`jO~rcs3XG71)Q#AxAsaUoMSznk%Y=sCZWDO-ihRG)cfz@dbyC-UAU+{ z!AX@)lPHYclc=o;lblGIK7oIyCsAMvCpgsttu;ouG|5Snv5%CBmNOHa==h!`P7^`0 z3uV>50IyTYbI*~K=QNCe&NnGfF>$4hiN4FkU)P_LRe7}h3nc&3On&<3bm?^YHqVK6 z)K%u=(o_5e;W?Q+k!*g2T~wB=p6E1>kIE{}p~kybf5a?#*(9oLt(;#^PSd>OnOc>Z z-tn#j0p1Vn`>%1zy6>W(*auV+Vky42%(UA-(NIG86b@Y;`CU~hyzH>8mwmqLrucMRw)Y1D@1OJDU&S^DT z-qt!}pGBjTp1<=0du=B>wHz9p=L+JY?zT+kir3C8ns~1>+_)vy;ZtlcPjLp=QCUSd zO?4i#9X*5oYJ>cIpHnO2GCd)oBRvHffJ{J^Als1B$YmtqM)b%4WP+TZ;XJ==I-}oI zl6y(A9*;_wF4H+bmwMB=biBj^E82bc``i7~oe6 zQe%eG*56ooyF^y|l2x?#&2a7rzd+cqPP?)yYF|x|Z!=<}qf-f;&r==-JK0`3hF|Cn zIyL=>N{&@}!!cjv*`z>4Ss8RHg;(mth(K%|&9YfeT0~nSs{ZspM(W(bhD$0m9iNs* z2AksFUN}07Cf6QC_owBjSxyzFJ3)VZj-RP%^q`aA+=J_Yx`sW-h#UH~*%c2Gr~`qx z8F<|f_XcL8$V3sj>G~h;%~M4diY}Y3|KZ-VC?Yzd$ler?hAE}nT$^^f&mjnpj)V{1 zB<+WmNb)XK@GMFAh)vi3c5l){C_1Bf%)k{xA5xA%{G#^B&w^gm}aIMTj>_{2~M~=&wWU)L(~qLw21A<5gv4`1yhp z*E|yC`-h#l`0<;Iy9fy&1=oJ+mw>hB@@1D5~s^>bH+V6E`2t zv`s~==R02;c2d$Gb9(k4KwBJ(%tlrsyOCqa1;pyi(2q1ldLW~bAhHtKjT}QRAb%kV zUFe@kCuDG!U0JQovV~mMt(S5Oxt3pFl(mpuduI+^rD0Zhbs4+J84$UiQ@Fh+BbIBh z&lfS{yAxVDsq_S^=nc~B36{VcWZV;Mv%OSw>ItWViQv(q@LJqb*WY~e3zRsn4N#Z; zI?>+0US`f@BQLnbY1FS8N!KhXNupI9_JlRy7|8X9`>YIGYr$E#^_h&>knJ(|Sq^rz z+~*2ey#@;3u*k5404{vSXn{*xtM(8`n5Z?7#cSCu^L>y!|t#&{@OI=JrC8@P(WzWX~-@USCVy z+$i^CZs0rP+GWyOYRA&r70?@1+I|Dqq$*OVQFe<7s~|;Q%eg=OW$0ev^2G} zw6HY)-!pSB-1q%`K7ajuIdh-qIqRG`bLPyMbKXVy{V4g;?npLYy>D}bxF{;~TAU)g zX40F<+~(M3JLm4Yon+a5aF2V>!EVA$+$lTN$*thdc%Rrv(&-Nz4{T-x=HA2MAJV{l z?{4^^;}1vIWt@>*$cIyK9sIfM!yyU=K{BL6J`}+f@as)wm9$SC^LNFyu;uLIC0?!9 z*xs52Ph`~l=FJuAWc=>$Bhwwx*3uQ=)euR&hkpe_RHW!;tBoEjf9r!lNM zz)QVdUd`rUG(R68cf1EW=%{K&pin7tLCv~9>8eo0oq5o)(@sn=pHP2Z zmaI=03*V)jn&SVdV^G5=k~|2eKqlnDJ~#!X5Y&h2E@@xz#y~4{)T)$B^?sbMc2y$% zqNJogYv=SVbVPVww~h80<)4DZ2B90>odnhZv_uJVpi~`N6a@UV~+6Vrnh7rakRtWi29WxcaG3frAXbQj{D|Ilw;Hf z!Zb^u(0V5jcZ_!e?3r_n0_ZKlpF5_r%$8-*TjFQ1Yhmu^j>6iRBykJugHv!F{QAVW%sHZ2S4EvtNyRU6gNEKm>iHmk|udnQnw1N z@{SW_eVUdiz5T#@_?h;l{CdLi@ca@eI_{H}|ei(3!(9o+i3dvH~FZrmpPF2rqy`z>yB+#mVi$&X3I=BJ{{ z@NX1tWbK!ZryXR(Y?5sqCGaap%}Q~U{w&CZot%ZwbIv&enOwuO#{1H+$Wh<%ej)Ei zkK5Y0nb*u)B2U{G{WVqRGa2%=S#?%@&HK!M3+0oq8BoLh>1)R_Rb6I$!z=W+Wb-#> zmHO@*s?-kAPtl(4a5p{Wu-TPSi*Fq*><2%W3uh|UleynI0@RO6XDiO~%wp-|Q{`1x z`+W)h&e5I7M||fP@A|h;T`M;B;#GUGO7VA&xx_f)49(&W_v$l_x9!Zq>iWH7{v$`p zVlk9LP(O+eq9Fm2AsuodAI|m5im66Xm=o5{Q3`K=U{gDUM9SQAj`zw6;XH-#o(wr} z7Q)J(d0m*NM91aOd54;bWr}KCK=h47UNA+|FHi`#Wb*~q8+xru?j@@_fMSBt{a z4ka6Y5n0%7Y1Yq_nE@R|W@{)V7t6!$Sd56};EKydc}m2VS3aT|C5VPfWQmo65>hZz zHkX(w_?}<(CA(!~Z>^&@@`N9-e^pX`FyH8so(Q%K=NDbWA9&XHB(c?xBr$)t)E-=( z?DfdlB5%)+w4N8`{Ez12c*{!!@Vtz;Q(NRIi4YF$ROOxj&8w@O!{*JQIL zx_Fsj=wAF(ZjksB20NJ(R4zKMM7!j&kEr9%hz?5p&!!bc8Nu}3{Xd(9@j(45k%%i^ z9a9pnkgvb?$ZJ;|(cZk?L}sfZuB+t{4Zn)0o6NLCm9KHqjw%s5;9Pa6NqMFy>K8=4 zWbiNLqMb@KSXqV0qcsC7$gpeHz2+K887^I~nWknfSaS{2m9k42tdz6Y99z`|v-1ah zGF6T}#;((^V(98R`WkZfy7e|c@dj62FIj#AX)oDx!*NLYn)R!rg`>o6^S)>_lXvr1 zBA6zrzcHxLhI{@m0ijSlFQ0zE1`ejJSY8?vqRGUa6D;iAgBK@{RQ5p z57b6_-$r*tQkBzIb}6TWT)s_bCtb$fG24-KcSzw%Id+G3WTo7=<2a`Bm;a}ui7|q^ z=aoX=&D}2fY^+8F%B&?gH-skm0 zG{PNA7|1BR&m&c@4_CjZJuElxlfJpuTBjdnnPk`7TY2xh=C*an4g4sJux02+Vj0mES~WW#Pa4%b2B zIj8|d!629di(ozELlImDEzZv`JdP3djvORFGAx5FPylD(HUuzM*aV_sILv@d$b+L$ z3>3d#4d@7QFa;Jt9u&YixD7#15*GA>v5@{GBkH*v6v8?1W1OZ2w1s{!0o1ZE>tQz> zg<{YK)8l|>NPsD@2y!7GiUxlWS>bcWceDnM*h=1xc8I2C+inQaS~{LV_*JfLpt=CV ztFp`TLFr#rt7ALpo?2DwRMuPAR}C+f=W=yU^HK?`!Q7TT z5?_N~0g_Qen{RtcT%lSQoSvbYIUA-Zlo&+rhhi!c`LOn>?Tp-cSbK$MuGE@ZbDXU; zwLh5IwV@U!z2syqqUbBOFs+v@M|y`Ld{a`xw52pPiDvOfrsPikxJ zZ9U{}ZA_CSq7KetNvfl5VqT0bTx*QeG+gU%HmKpGCR*N9(r7smuKi{EQV!R}hePhx z)fUqFrPd>kcV&A$GIdlg*VE$dIRO$^Qwx!P^(m5vWL$ksbrjyNuQfFW(Rg*J<=c3D z>hlnrtyg9XrEWW|x^1C!YNs_0?&R_9eHK_KDeY)+7ODYYo?O~# z{!HeVf5$P;qM)6op*Y-5tKak^k2e*lp#rs)4}Fd1w|dp!G$RXcPb^>gnEPAek8FLZ znycGuObj3w!?wwR_L}#lQD3>M6a!GCY?FE&w0glQtUI8x>CMI>xz$1QZtzDy9klv7 zAM+a-vY*4?jQ_uRWJk>7FyAagIueYvGHYL1tK{*>cgUfRTAkn>o?ujdG-6+DjXN&3 zHU!RlyJCPub)q$1Ed4u?&to2QZ)q-;{hhSxvL2J*v8=?QGN5$o@ygW2gj&O~>TG+T zqf{qfo$?)3xpTDYtTnMa-gOV{ti5b=4BMuOISuSy7p;lQDiWI?cNDclYjl*>#Filw zqqOdf|8I|?LD=Cw8>Mx#wJ)Gvor3G2mc*|CEuaS^!Ys&!ZBPj3;P#MRG4I=QqO}G# z_LGg~a_Q&pAFZ8Mt(v(bXUE65geOb60suU|-hTMIOR?s7g z?T#o@lDcc=%*a;5X$5v7bF9IyXZ9CJogAV?zk^@H^9YyMivFZ0~`BU4@xR?!~5g4o!4t{W4x~HU+(od>IzZiUgz~Uy*3`8 zMfgAI^_A9G4L1!ieXT=7@A23G&3u3u$gdRXIh2XE8Aj zgB+RdBRZ}`+vT#4sAD{$-4Y*fdR!S#Fki_2`0{uHp1|O1Y50UG8ubJQzshp!mwD>W zVPL;gNB(@m%u>rIu?Ub6Pnre4N&TuKC#+wU2l1!#@GhR;im{ibf@n&cm|Y`ephlRt6{Ku8*kS5JW%9 zxFMz=vz+pk=$4!u;&ai54@KsZPD8aip{}}C7R-UIhq*z5`e-vmQijqosU^pTYIAHK zNY7z(oj#C>!?YJ@LrR8eYR-Af;iRgCj2Nz|5xY$zwQ90;IJdS~IW%0W9~#@BJZ$yt zib zA4wugyxGt_ybaie@*HLsgUYEn8tlBe*B<+!i#PYf{H<9cfmDQH$t3(Wr$$if+ z)qwR&!r*fmmt+>3d3y7e=#rdFDnEZsMkA^$F{4e9c?#AjQES;Xn)J7pv!f}nIEfrX zf$deonsRiE7GU4oM7|uS^^x$gS^(b>MT|w?QMQi7Q%5;D7Ei;a={SVEryYx@f^pd8 z%87B>)Aquq^2k_iw4^^nO#ZU@89e#Bk3B;HP{B*aQ!ITYX@b_l{-Bw>HbHxdn8PNP z*P`T!_$%>>tSd)}`pBJ$W(l>NL~-yb*(6GKoup0DzOij^51y=T()f928r{be(lD7` zFxxUDb0^y;o0BQ_3UXRG+3aY5$;;9y1(T&RGX>#E*{YnTaz2G_XIrWI9Q{=$+VAYc z4QJMK#LgGr&y|uWV1tp65y71iAdYHkn>R{0nrx3+4O^2>VLl zEPlNrYiF5Zm}maVEW)TFw%Odht4PFbt-7P(V4KTq5^h)aK}e>18jJ)H#}WdGfFRr<2`Jj?K{qns;>dm6)`h ztF?7xaE~@0br;Rmg6x^KWaK|QTJM~z)v~Q|pO{PVj%#5y`E7vya1h<$`n)^)ol8x1 z+JBe$d34%cvUwiq4U(7zRI)4cw6@%#5!IBA^SSG?r79k(1 zam1D`trR+x$2aX8#2-6}AKQj7(c z>8%W{gX2epzdb`W>#>C1>n)kOgp1bYeshWTz0LN4J8hZ9hnFoRVud!$7VFMfp;cDj zHm+T%U9*+A7iTIhBR{XA-J_hElJ}|>Z9m%B8vD^!QCp9Bezf8T?QF~{j4#Os97kn# z4Bga_nGqq`TC}Tm6V>?J{9dtM^d+ld7}~Sd+7VjH?KxV_oE#*%>hOrmznNvc%UtKs zohkH_U3;5bLiXicS0O}BuHjLNDbs6s1nnam*788Q&fV@c?dc%epylsSu20I|ceJIh zG`^>@Vm3cTO?+1y>+p}~l2eZW#qUxw54&C4wB`=iD}yY{W!89q+zxFnr}o4STH^+xyzH8R9O0whB^?tSg9)%GaXvZVARmh0I%r8m2pwS%Oo4RBg?uQ2 zE8xe2Yz=4yv5*LAC6hIf4@Gbj{Krtj5Dmj&24q4W9G%afV(=SFU=Rg^U>0P;HYkK* zD20%5M8AceOBgDZ3SODu`HynpcF#jHZLdFv)^nl?o1D3%S zD1>ux4?-poAjH8GSOmF{52xTd_)nztAPNRSGNi*6*axTJI%ty^-k8LW3{e~mf@DaC zJSc!Oa1#P1lM{%B1egVxuoI3#F_c1(L>|$W=6t9%u-|!68hxnMbKH5+Ap>hwoGAq# zYBw1t-sRRt&=ahjPp2Y7y5@89%Wx;&VEd0N!S5K@z%)M1Ki2q z5Z6KNQ++YF)+TcDpw`YapnXQ7E*CJa;~KfZnpyC=Y(BzO9A2np z6ZxJ(LLM(EhiRu~$%(_-HAj<$EbXD@#+~|1Ytp{S6iy`!hgpybc~Ai7;5GzJrBXr< z7!EV0X2pD&bDaA^z)>wkpUV9E9BFuztmL@+AJsz3p6cfwL(P&~#u{0DO!I!eG*!+X zV`O9+^0i|7+(+K?bL1?|Wvr8_zVcm4o`Re&*nQ<;Um$-D`9|sag-uq@n1UBz?Z|2`WP=UP3WEN#6HW+)|2#D8?np z!>4?F3^|2j5sJA{LlTjsKT1 z>oZ#3Lga4^`As!sUbt2*=UXkH66?Jg@uRKN<~Lp5J6$#&IaLOKi+2`+GbW9edEaVL zWyO04g`R;TO%8p>bHV*@wWejti0@D?L0Ke&zw@cQYn7a375#y{+s(PPAu@Xh(7Sikg`CRoD?g^>*~kybt?zv*XyiHMtC1g;A?JMLYn40)`4u^I&Zm&{ z^T-AHZxV6dN1lS*ScAOUSb6QdPa&OGinS=h#)@&lw@Mt?;HoBx7qkHVHPk&MvY2_H zBOVQO%F+uyIo*4K7}sIZS2in)MHjS3%8H@sMU<@QXD|&*DNiWxlP~&sU#l!OV8Ltz zWij@mk9SuwN)`e%Rw?i0m-B2T--Mir0lxC9N}h{6UxG_~?1z*f-;DgAr1{E^Df#Qj z&&w@ed8Z$czk&RcB>mtM&Q>Mgg4`~fe`2I1GdeIpCjaP@ow`3#oNr>`8Yhol;#KJN zAAIt&7OnmkT0Y%X{)1uygXQ`Stx;KlRlS7&x3Oqr`tMh!$U>pB)}aw^dCgT`i!b?j z4ZMuktym;@qK><)wJ!6YfmVM9?emuZR*#YNzCZaS-S!jy-^C);psYJE zq+QYam*wEJlJ7!(OL;1n$6rPMK5_iN=#3_pHA&XqKEzF zljsZ#je{6gA1@cKaRK~a6WdKp3NUFmUYgzXX^W;R#UT_?<0Z#eaTZ0uCn!dHV~>xe z#jSbEC*t0>wEC4k#U|Nf!`-XGEuWj`UJUd?4DzJpmd{1q^mpWkk?)ZB-+kn3mHad0 zZaMV3PgAP@f&2*aFD2p+A9)J$fTPI6CU}Zyb8iyaeWrqz8JKZ5gEI-P(y-9bpo@MgwN`3-) zhMe}5*Zq^ozC@nojm*}Ulup0nC{Jk?Hu_iCY?8fy`jm?8FZ>oE|Jmy|r7sns$6r2` zB?TM(BsRaw+P{4KmMHnx$o~{qsZTlwmy)q>kZTiVUa3#Uj-d!Rg(8X-!Bt06lKN39 zmGAnLO4qyCoW`cR*Ji{2vDt-<@hvueC(3{B`b5z1Zxr957&1`?{OzMyi$XtxB1;ba z?UU5Ne~9fY@-^PrmiH$`7ytH2Q5rV-f3V429Z%n@{XMNk*(tfBbl;L2@2}W&kQ76&B88e>-mAJx==yIcAC(fNJpTl(@E2Nn8OlT*i26>)h9>{aqVkiVkhESEQRBEOA%rHZLs zzE;WaAb(3mQZ9G-BmWaQ>vQ<~$Y(40U&wFDW?%VLB`-x@D#0!v`ynn$_%3pT%>m4& z!8Vu@Ztn6ag=5(0e`CY@p^B7~R>7wbJ5@mW4@#Cm3P71Um_n>r!N>bnER1_t#7vQ| zE9m790HGC$`#y?+-ndIt+}C_PXJDiMiwy&*6@AiuSIHkBU!kHcFPDh{$T|CrNMr@* zjhp6pg7!}JaNEi!myC(DrhuqyyQL&RuWob8-2lB#WnU{s<)ls(y_$3l)GK1pJ5aBK zGtqJ~0`*=z5uOax>pN{k`}0)3Jp8y~x3XFiQ;7uG(Oi*<90p&RYL&Bkmaj#``Q}%* zdYE}=ZcSd>JXFv0dL8pneTk-rn}>&#w61w*KHAqa5BVUire5DXG#~F9n1}IvjHWj< z4^z}(BlD2Qdh@fi09(F#*INxHG=>3(N*^9s!PABdO)x-r#v{`l@Z*;s%FYFs*=`;9<2)X zAya#(s$P>^p0}L4IAOj;GWxlh)74^6%0o5NLu576L;q@Ks8g+98J6>=B|KbBf08R8 zv^w?NK|Q}9G1YbNEGWjflw3nzDqDT!SCw2x{y>6j_}ItSptUfNJ6FhyHT3eqk^M^H zL{Vvl{N$@>8p^fD8tX>26gA!jB63(!PH%2o!)!;shrS)E2ievt z5#LNd%<(!UZ_X-WBb2kzvf83Fn=Gp$b-Y+9orCz#SuubI<;u&uEob6y#HUP+4vdOte@ zL1x(57}yiXSYa2SVIsToC`}rYsSg=VG9wt&kO&SaO>>HLLqmNSGnGxdkVX{dZ?e4+ zexe)c(R|^%xe3SXk=q%Fd9RT^lo_a|tU+UBeaFhihGZnJF~-kYifu|UbF3U_jPWW< z*0u==cx^1-<}-<15}RP1uQY1b_lYJX;JjtmqbYWmymrY=v9rs`<|N@b8asm*7n%}k z3rjYr8P;vac|u*#4C{DHa}JH2@rGZUVg0-%8`~V~RIhbrbF9}XjjDY2o0EnD%Wg&s z{2m!+Wh}P^X1_>D3(RgwU<78B#nzGpEs7wxYR`Bg-x+~jTT2u02my3?MruDoi z2aUI?+wN8vRv+(4L~$!U+RnqPSreloNd*tA10waI4xUe~Zv_gGI(QP5QQvVQZbni^ z@}z5PLf#=sZB({eQ#stMgNNu#Ini1lZx5Sbg&5a{+R;Gb+hI1h4Q4GQt1ZX7mAtd; zSI5O|2=OI}Xp8p@%XCItOtX|}bFO@>#@m1Pgc#ippT8=z4z@q7z_uWAXcIjNENVw^ z6jw)r?${pV?h@01Am*)GsI+Cx9WiP8fD#qx5B0<87h_yv06g+x7+KCg(WuRoc zkvaNKA|;K~+w)FXPqQ>pow4R&VL)fBSxj147b0`5GaoTj^N{toe~8@btT$#3!L2Ct zZM%@_Pb5+uCw3vMUzI;Kd*DPDGIHOt3XdY>ij$?bYEb$`Vb($7yWu4d1vAXE9_9E{ z6h-v-WKR(Vbj8ac)5}oSCpWFLkuk%?v@Yn%Nm?oAyAs)3;(Cv|W%+1N4FR(&biETLuv5 zgXN~jP$?Rq*Rpeu`*ncc%u$Ium(`dK)N8r8kD1q9YinV`DFgMf^Oy17Ee{Id9NdPW zXL&CNJzzM@f=t*3g-{Ho5HgKdwh#-6Fc-368x+DhxDB=F5w(TkFay#d7xpFd>irZ4 zH^D!JyD3CL0wlvS*a8J`25v*Zb0iL;Apw#h9dcnGoPwL+Kb`O(3KAe0mcbS%fHQD= zIW2=0Te?i z)Odkc_7FFpKNBDwa-jguKq&;x!U$qv0;uo&b0Htjz)h$z8yiS~WXOelxB`AJqJvnN z1(}c!MNkSsb9nXMkw0-T3o;=eil7vN=8_XgfON=(BDexIQVARqAQ{%cPB;g*A$%UC z1&J^Vav>kC0B7B=6~xZxXch;VPylDZZvlZrG$gpge|ZSilOu+BCNHL+6f7e44IGzN1+(BMc6fdoi~HLw$kp%j{=lL$zLbjXJy zD21R50*5%50*fFQ^5G2JgrFsa0kMz>YR8)SYxt87MQ{`Rmtq9bkO;G24eW#>xB~vm z$PGk80?dL;*a=7B3ivI@20B6lBts_T!BHp%zZHJt{c5bh2;v|a(qS7E!WHmaNkGsM z5+E7UAs6zY2(Ex%CM5{1pdX9{wX@b5*q6C0<_TNQQ+fj?Gc|lluVa7m2YK&1|BrH> z)}K?8G1SK@=}+rwe~Hac^GK4yntb|SEULdZL7!-28R7av^$6y0#t+ritZ(6$|ME+A zKO6DN{e(bvTNujStBX__h8=@n!}Q+#TFNi~bzZx)A$%(Dv2zT^j!9v|b+s7QLiLMf zFNd4H{!zbnO4AYMujwQBMMuQ?bxr*`AfY2o-I$U5VnlMJ-Ua8xNWHqf_>xo@qc@U( zQFO}ZONUWdJSXEu@hthAJ7bjoH0wS{Ng_AVUnMjNXQad@>20`KFIK-wWWV~w@LCdK zej*X0P0Mkk^*J`Dl#C{mPH~OV&9AEx#^^1Wtg(2Eu0C}5bPQ2(8y};;U~hd*Hs;#u z$+EFLp|^Ig9jmh#xwUxWQlC%72T^=aO5JC;%ci(fpCNJfmoHgMBHtX(jd-~PPS88p zvpurJ3CPy5>>0AxJu=opRO=AlP_msKS@c9?ZW%EV*#VDir;<@d6ZNGO#E?n)cn3K- zG*$o05pd0J-6Vs;{53iAEY*N)Jj;VrYj?~veZK$vQ`Dg=;Fm=mgH|vIrobB531{FY z)OZy=B*HAng?uQ6QV3r~U52qR7q&qmoP*mClFdyOVj&S`W&1h(GCA0ty({J;Th5DA z;;z#0MV+<0nQ>$8&@xAVf)nuM98N%rq|KqLkRsdXFzmEZ4$skt*eBPK@VT6;N2UK< zD#D|ZGFShDxxM33^{*UHr894*q(U!3m_LsYo|f(NIL%MX>3KRGbeTF|Ur4|F)_na1 z$022#YpW~E7O=>@`t{W(6{o4WNdakk6X(l3EH_=s>IJNELvYj5^r~heD_^d_=ecS0 zVN={U(x_jyN8NQ75{Vi4{QGpl$1b8r_%yq1s|SOA)?A~^MS8a54HYFj21)W_U9%l> z&s?lC>$0iDzoL(M^f={G45d(GH3bi`kO=9J3;W;{Tn8Ob*zTdaxzSF zHJm2l9E<;}dWa;?as^0}SM|!$GRYPwiAoWxevT^A0%d{aM-8h-fGpF1C&t zq^p^;%nF`E3Ac_Jts{8rm?1lYw~iUNt1fewnFX?V87+AidDC(ZTh3+6(U+ULhL+RQ za>iNCV#|5cat>S0Wy{f5SpF=hr{#>ZoW+(?GKb}0_N_3JaBGDgF6WyY6-fujYU1C( zm3mWs7@7P>dD)LnKo=3S^DOAj%Iqc#HMKUsS1U?af#Bu`aF7nL!}s*J5> zR?v7N%u;0kbrExt! zYDPMDXY&ZwRSswKrpUUP3=`LChWpr6(YP*=t99=y^I@_WxiJd4f3Uo_T5sm^=i5ki zyRIfBqF2#pL`M466Wbbs4am_umxb3qhe5wY{G|tLGH|ZW1`0Ve3H&N+5&{UNn>D%~ zXdarQ>y^wyvq5N;#kuKbE%X*=9jgXGlC5L2MaZ;{)d;)nw2tc*GZ?a7xMOxR7k|^M zTA{1KbdHGgs_1oO)_OfaLe}UZm^EF)NNYD+`KyQLCysq?+!$*{pE?uWBxwyJwm-0s zrOLdjL@KOqvUZJLC)C$x(wG_McdP2$koGlt{fBz6>!tGLtw!B!GI9Z9VLQKNSTcMq z#j=hya=aF*a(0uhYl-e%mdx=+SHTp|T+3+m?+;sIHF#dp6tj3`cTW7BwVW(={WHRA zO6}M5SkFt2VKVhK-sB{4Heza8Uggjz-sJ3ft?V_>FgcG+&IVocAMCa1nn*{h@jAVE zSvW)15l$8nO!l#=^VoJKxun)FT5JjSRx))xuWLNV zTi5FmWmV_=dLnt1NIvpLvfoU|2A@ap^9 ztTLpEu%4XUsIy4qM!iK@M6)+yJPzZ*wdD1UdZXaM9^*!yls+aA8+o(+`$k^PdM}iw zoAmmXgw&;ajJb@1bE)6cHtC`E)LOD+lO9)AU?o@^&k%((Oe*B+-nk6JWN>SV@VWUsM<~!NC#pmSRQSzzCf0VE{N&JtVAXNT{$*+estrkaRGkmt)`>uDG9C{P4 z&*F8ZTz#|bb>lFJd<*$Bd9ko z`&>d

x0te3rS`-J4mLp~k(7ZRDLx8#eRq&(VBZ*|$D)H6_Dkn?#y32V3&Ih)oR z7p4DJpE6jh8_kU#Dw0pZ*98hYJ^#4P9Cq-xMM67;x?+eX%{&7OwI z_H9&=*~G9!*%6o|Jwrn?{_yo9B$>$^gSx)-O zLw6G30_0CLk;irtAnw2Ioi$|Ar}j#+b5q&;1KJ`?^)yU3$*r9{OKg&`T|PAH9C)8pKGRHoeP4fyMx^HlM7tQTOJ(W@J|(qR$zMkPiIjZclboizk-vhx zRN{C0*l$2?q$6+HTt3^)7-`GqEMxEkOKS)0;c38I|6}%GmVwz*&1KRa%%1X^?esOf ztjv~RHnF)>`q1Zk9Q+}Qr6}e%mw6xR&Fr}Ee5m&;i{QR8ScXBZ7ShP=<8!JT#c~vV zTS$&uZ^Uz2-H+(uo^ewpd&yPQ!SA&27Msr+_RC5o#q>&U=F_{5wH|AN_L|4^DyvBG88(h;WeMn7R>?Wb?>OtX*;UCr z=L*0h-I?mLY%l%9hdpt6UyjF0+Cg59$J)yKCu&&Ido9L_T0mM?-4rZ0IjV;(i=?q^ z%?f&mI(Pz8oezFu68VwdIB>C#SeKLoT&vMDXjc||qz43U@F-ObhEj&e_K)<+Byv9s zX@~hHWXk9%L}vAERL><=ZhfS;41R*e0#$ufv8tX6v3|@%jA1hSW2)0i3U;Mz{+Nqm zrJVR!pICM_yY8dhGf|)S1R$Fy2R4>bnT9TF_R&-F%2m<`_y2cK2-{CsS%j6{%5x5H zOy(R;+waql*no}xDmDk@@P2MN2R)`Lcy&wdEw%$Zsq~h*mJ@S8uOIlC$4F()CP@X9 z-OX&ea?1|rt;phjZ1h!x`G;ISK$w5{gsJLFAE|qgF#AZ1hqBFjr!wak4aqJY+aosZZs#cCmNnOi^^e&ErmOsZ}wpDUKF zkKRZ27MKwc3fU?!A1E3g;!?^cM|IoEfI~jLn6)SZR-+i+)>FjsCjx3n@gY6vVXsJa zXo@>ArqG$~l;|{1X)6^z(Fb|frXD8aKB2gB2xFft|3vQ=xG%~I$~*;&nA@D2C5 zzUF-nC+Qs?Hky1&OY3c9hI~p8LJ)Z@n5s8-<#n}!u%1!m=%?J7{MYbj*(yc|e*08! zS?0B2Azs(u^|bUaq})z>ysFq$!ShXWBFjzplS6at$~j!f9oRpL?elIH^61b{^uv0c z;Kh%6BE*+E3H_wqVeVSidM{M^!zvQ`jB8}`Vcq-1m>Mwgt^?DcfuG;xuiU>L)|)lp zi{;Q?c&ljyxL^83pXcyAzS;cP4DT1RUh7u|fUe8LU-b^2r!kw~0!y_Il|4P!UEw!o z_qoE&{kF*U+^>CNfrS?@cF+0hn z`cRkC?3~(I03z}&Ta}!LA+uwwa4U<@~EB)1IXKtIubm!!701UtMCbiuMEEA=01Q_&|TpwtjVg zqr2^k)mbcHa{+a8=0*hCj1DfVr)BfYmNfCN;!d;~i)^kev)^O$n=C17{j20SjIl1O zD`fLqVXZ{9z+ogaYvY!~=K-FHd}7-}Eh)}2$$cvf>+?S##b0gKjbO&VU)$ftUot;yLvEn&5cYrL*^ zg&A|^Co@Qy4cnj)&cRLa7e!34;LZEyx|LdaUefI%vVqwC3{w#nkun&r%6l%TB`$8B5Qy>%a;3yP>-y0M^ zM8P1K0n1f>x~K(M3abOWP* z^?BxZejR<*28|_{9@43yG0@Dyw1?RB=3JD$wtUjisOETyTpd)R+YJpSS$ThjH!_0A zMPwt|&GVAh$e8Z3l4$d*ZEcbh)Y#}pf<`o^O?^r-8XNN;UqG>D!!{^@GjJWWx2f^a z5#nG1%!O>&28D15?mF>PpOu(+Z7L^C7B zTw^&p!f3(macYFo*nT~B^#J>$?&6iqX_1hY#&!Fjv0`s!Ji;`v$X4W}uB5f1sMxTz z6`@4R;qRJEjWX1`%gWCY&7mlx zx=rM46bTlwbv0(I7hAdANoi(RqlSO0k#@6Y%jW0!q~u6f%(}>LT?wbFggr|9UEMK{ z5`?{Uqzvt5wCA*BbtBiyA{yBlrn_eV?X9@H*Pl6n{m9UI5k zWqz(67FhT&4P{MYA*PKI+><~zO4FW(o3)%udg8ye1V4_jwKRR)n1*ic<5v2kqe%a~ z$Bhtu4Bf|FQneSQwM)A8GG4&h(+jWpa=8}?StAo;DZ4f9<+0Qr+kSUUAL^j(P08qs z(RSI}m$duKjlRZY`<)3gw4d=ftA1|oM~S{6XZsmnu&(`^{rUBgobPXRWAV?h0X}J1 zFn}`rUDggD{@>k)1{mg2EmPwNyP|AR&O>q{&Ul5F_JiZixZr0V0Qx*d{EDMkDcw>={BBE#=M-<7qZB=|7bGjF81ctq{%pUl~gN zzY*Io^8bz09Y+3F%i3WC@}Zm8euede72CQ zygef?3q~02%dWNK%A$%~9$~b!S6L)44mUE(bo)l48z`qo8tiVo=zn}Cj51pI=PdH% zG35ou=H4D<1lx1U1G$;bxlKwms{4QKwcGUq7qcW9!45?Kot%4#obS7fq*;>DTDc>W zjA~4#n3+Urd@I|N$YgzHNYGYxkvXG{2>(?tdn2DkLnr;jNs+E(N6 zyGVMEqtqA4%yFF86{0^wi};DeKf`G?SR9Sh%Gz|#nC*MZ@uch>88Mz}^NuVZZ#Ik< zmGFBeULgElx=t{v+plHF!xN36vU7qF&g-9(N>xp46S?pkN$5mlj+$;ffeU`?L^=TR zORS`-mMXs+4M((}-zc2@QZmtsb`mj!v7Q>~43msW#zp_!WuENuDv=9fve~p=>_~wW zOeRwya&|JtA)-$){-C>ZcM6x8zx1DKtfS3LdX}hH%n7U{6`$qa$&IAdczpJLmh^q5 zv@LP6o~7=pO86|xpR`IgH2dExrP4I+{4Aj|jdM~l)02dlxtzOqr*Uyql>O6;-pW_d zOrofjOmjA#=B$wfPUG<`E}1sIi@cJI?+!k`t0;}Xe3wiR9sWCr*c5W}ge0XHU2ry} z7-|I50be&-g zCY%RJzHWUwY>-h4YdrSu-i3Y}SOMIkrpB z=V^}ZGVysD^Z+^gJi>i4;srA$n_eKiujIrFK85&t=|_eG<*J!iG77;nT8oEc8PIfQe>8_tOZp7%JYtty3@#SYKTp(u|E z%Z{|6f6_@g6=dpMilV)2P|l-rVlJ7_mH1SCW){)GOMP(LI~fBo^D)KanpdcU}5~Q3{v!-^v|Frx*>}*=v1+2 zwOLDpmZ+Bgbx$E~eo2iSE@u=nVTlpI4E}LTjB#d-o895;RR~V^g;?(6;2^DDdYMR{(Oj{sd^(8ciJPeh=Ib5zYOSj5dmnOMXrqR+a*Vv(!t<5DNQBrj?eg{bJ&1C2d`wsEz z7umC!)TK+O*J)JJWyI^~(%EMV4=d#G>&8Oo1RB)Bz4SMkGv-;6>Kvns-T_AS%y*)$ zRN7+eqleV;^SkE0`i4=nmg{<~N|ep7M6xm%^$IUA*4udG*?-7zI$S)bn96spA(rAo zhFIM0wTF!t>|E->M~ydJe-5%tR(S@9jvCpv4EMNWMh6Ga7#ofoVq4*Ecfwd@qX&NM zODf+r3H{1AViR}CS9H`|*3&@Qm|5aU2D!SrQ%@RQ>~!w;eq&s7S$%e!-$E-H1*b?x zCHL&p^r`50pZu24=rMnXW$Uq4YUZ;p6T?usXN+xhllz~=VvW1%e~kJ%o!3qmd5&>p z(;Iy--=9^tON=ITQHPWm<82+>he{0A(_8LN`jN_Io9@oIWE`~9z3ct6QCYKn;~sL2 zvrT7g?R7@9=y;js)886t3%bFmS{1WHq&~_qNAfanFp@V=PTt^o+3Hi3sS*?{wBA{MK_HE`ac{`xBX>_rra_T>`h;h+KmGq zmf~AHpf{6Sw~RMzi`=V!H+tFWjhw&D=;HSoRyw&&sFAnCJA_nC_TC|+c!~Iv$`|H7 z|0fxCSse(Q-wew#ycEk2_v})28O@chf8&Fl6aO~GtK0sCHbmR@A5K_BiT?*#qfAS7 zO3B!E7a6zbA@_)&p}6kzd^Ix5O6-jLBzBa0@qI3D?z|`er4M*k;ve8llamiPU-s2& zoo{f*>}qp%=T@0!b9P{$WUtLRo;zS&yR*Bii+N{KHODOJ1$JjNZ>SF0F`OxPm6Icp z4(E9Lk=0hDyB*FT+fnynhm%vAD>pRf$LiMej_&-7n@ft}tYWy5a;>6z(JFx40A~WX zjk^I(;XaWS==_UoF{6@mIwgI-l5>Y@&)=);oJU(45#$_5!;u=~9PhFkY@6Q^YuGs0 zIo5UHO)KF4SYw+Df}L}zllOz26u<%LUB$W7z9~=oRB^JcNEK%?EoxE-0j`o=AF$yRAqPt)bbXTF$nvgC1Fq z6>)eN5f6562*chs+8tQO>9)Dj_gemByT z*vdmRL_-23!!pN)Gr@3E7@fJLw#jzTf`?;*ivmg_8!*RF? z{vVJph=mET0CFK8&cMwND3BVvF@ixb1=he$I0H8!d=HVpSeOgjpb(0o6l#4)!N4Gx z0=bY6SHRCr*bobeFbmeePAGya?)j8%K7l|iB*HAngxzo)u7kFh@oI>Iu`m~MAs^1c zZ3y~^sspi*2#a7n?1NKK3PB%pb|3*VA#Xl^&cSVHvJWN9fMu``PJ!QkiW*`e5i%hU z&cSU6Il$S3elQjm!Ft#Sr{E^|A0+WG2$sPXI0ubx^CzHy+(7~)LoVb)5nKVkL%U)s z*m4> ziL#-wvwrYT@2l4{z}kr?$R@)dI%TxrqF$*^IbgWYS@bfA9CoRy_p6KAkYQAeXV zQkG4e)#XYvXMkikafTq++QeBWc))HeU^TtKP6V&W*(S8HsS?)I$(nzppxcM?cvELR zJ1%ou_`JEPv%TkyX{sE;N?(9gj$Cc(Y!l2Xon`4X2#)oc)g;ZtTtlOa5;>FCrs?Ji zh`P(vo>Z$PR4@+@sVNUzT9A`7&1jm_k&)ro$s3={Ue+$gF`*Wyy(!xiqa*`p3lsLsltco{7Zaw0x&WHKxkh#T; zgWvbD@GrBF#7CSO>Bgi^=yBvxsQ&OVRj0rc7>%42Se?*tPEu=r_V}VakpW)InpSw# zCArw8Nt2IkZ7JdrEvYpxQN$yU%gZgD^@2wpx4e4iP%Pm~+=?}I-e34FQB!4jS69jI zZ_ZaiHK#&o9cDZd?JQE%0i#JC|Ee_kiKoa`6vT9o*gGp`i3G3UYl~Fbj#ght0zQ`0 zt(+}GKQ1$L1m7miXtMV)XX|eXi*!DXhnbOhScHdf*$T+nhB2s&1(3)$fR8m_zs|PnIvht=9q0+Wg-fYb!)yyMSSyuI8shma}y3|%)lgEx5Z_b8M z#jsQY+i>4cl_712>Sdy0hqyLo+Rh>gcm+wNlU7V}e+erOWiDih=-2nnIz6~81)h${ z)RQu=t-hld`WBkC6P+*jWZ2-z)Ivvr#x{+E~f;FIy!^wNvHlh z;gOxN&BS)0k8LfP+le!_P_jBXtJ~Jf)=th{p82V%lGK^3X5r(B)3T(qllgn6|2s%m z7Yts-V1{YH2hm-e-g%}J2wHs=+6xjNMcpXu;ta80_@5w}Mv!E(kLiB75$#mN`TwO(i6J!`P>=tQycXm1POeUs%P91X zC=N;BV@~hvaBAdZ&iZomG1|qyCCyiH0)>%_hc@5KpO5*36w@8WW)xGtmr31y6njwU zucJ61=ezqv(XD<#Nw#6v)w@|z!+j}}&+Fv>+wPT##Nsy@$`8fKw(I1l`kE1{KKl=0N1M<)Zo%ci@ zxr)f^_i_f?gUrjoA1wS@>K(SnB>Pgy_3K>N2v8}sQ;3{-p6t<`nvA4Qf@>_8EFQ9kljxcZ{liDKMEY2DYy zM;Z!!7mAl;YhRy}ct^?KM}ADg`Z>L;TBXXke#k#SUM$P|Ilb$(rOHVq-;KOP?sCXy zp(XvDDP_gDxhn3uIhI_+T9yw6e zzJb)ft1@JukB1E?^u2hvC5L_Gt~lf$A-^k;aX$7lksBW)xBVy^{W^bC_;afAL5;jfX=+MZX}Ojf z?x<*LsGz8r7#Ek)+`y2xYe8yhNn%+y%Z)PAawE-s!Q6K#ElsKa^US>{pYQL_ggU>*4He*~M8>~XrVZSKz2EoPk2xoQy;dfv zU+BRJKXBlpjOsz%Q`!s_VDGmb`+?`>N{=$FY)ns1_>lvLWkk<1S17>VZwK~WFUXai z&gX->Uhv$e>J(HYC(rlvHAAeQR$sG{^)sFBvaibO^R1;$zLl+?^o^_eRG zgOXl!_}=t-tm04gHs-UShAyG%d9pj*>&|M-xEl4kGaSqX(yuSQaJTJdAjSCXVt9D$LC8P4kRO%j5c2e_2xJJ>7mI_^4N+$ z&tH6$z=5UyR`yjLZjayDy{$6|Br6d;zX>TT5k0?^@4gi**LWWDu;{PpO$PXhDDHI0 zTaC?KLc{t$86dI`$+HtT+ofY4=aatMl~d{7pLodW;|vKt<~_AE^JVao&|c9{eRLI< zywt-3-tGDJb%uv!lqJI#Hb={XHmfvxYRIud@+dpUr)#`*snC zs#knGlU3UHbB6f+j7{?^GN7OH@!;lH9_0>o;Y`U@GfXq3d%CHha)o3Zw)^lq6DvtL z$W}pH)6HO+bC6ef-TFHNI8^L$ZEY*3p07Axt#ebI`%FnvKUL>G)4O}T=NuNaR`XTq zlBsr&_iQVt(#Gqm+W^aFT(PZOnco>@e&?6@y}!)wTV;L+4Yd3T8%R#fH{XnMpC9gg zQ#U-18#b-K=PM}*NsMoO=f0do$DW>j*f<_-@45$#Q{!ywr2BYs+0JC=OnbRP`8=7< zQo?u)^rTN^VhEbxoM}5RizhI$M<=<)IPBslI_uf#7|)yN{K&S=-89Adu8qEI?pyeD zaFVkggRv!(oGVn{)N;S+E$pVb&%ebeqv~CjOLabPr!&d%;^j+{v&6A@#Jxjix!>_ z_;i}Vs9}QF?p4p;Qp;vAxJp-N24}J5`a909_J|Ym_B+llcKRxNA+M7&-{sQH-(~D@ zm-;=Fna5&me7%V;eHd8eAPUOO2RX&A&~n?D@pbty#`m zHajhRm)YD}^lWE!JFPl~r|mT2mSv8zq~YFzr7`ui=N4X)Gp!gu51QkwVzcdX*PrWj z*lb07Qpnkm#<%x8#!zWvkIiGm_NZjeC%nn?oz*$S?`LQ8fTrhZ%jXhRUWj@Wx^$u{c9cW-_u} zBIygrH8e+7&TIQVF?7*uIER6u|HOozh3Bk)^6`~$#Yh~BIiuQ zs^LiBUY@ASUqsY7RK;U0_m5aYTiyJMyUr5l*U@QJ3K;o9?NJ;`L0M=mI*6{J>fbXy zh&rKoG!x~Z-RK+&_<@H#)B`1;WoQFBhaR9t+wmVIqM2v|+Ksdy)!^li97O%lOq7H6 zqf01c2PdN*C;?@l)#xC)hC+VgIO>GrQ3}dH8_;fa3+X!v9BPH)Q7T%AHlcGn(+D9y zB6cxCisDcT%0b_tB6Jr;{LFFG4<(~TC?6d}*HF+ej6I@GC?3s3IcPgNf%M(@f!d>f zXgXSkHl^|JAbNm8_7F!;uRuLiuPXDni;m20Br5)D0z~ znP@fIhEAZ{C}=+cMrrN&*AJzj43v*{qDx3CWb7ApK&dDTZ9_+p&#&YQ)Ct9-EVLG# zLl01`1KbRXN2w?atwsA$nZL{~YqIw;DEcffE6aT>b@nzOzR4a3(Vw#hb7o^U9XH7@S z3%<Q(QRFw1`-0_!3d9d8xOkO_e zY#_Ie(hoQ-B}biU%-NW7jP6x+$vx)msotdLpJwzo;5a_Cf4bC%6VUqr8-;1J6q1Qyh3!hMpo!HaUMvy%Cha)6Umy4jFXXspeO&JMC<2J18elI~#@` zeAW{-^>BLENyO=DZ(5DF=8;9t4~c_ZTkJ^ob`AtVL0?T&B{l_%!gI|E0Kg9&(o*yq?Bqd za@B{ZZk>0sq{E6_wMxhOx^&J3x-ji!*9BVp2@-mdx1QT2_!6Uf*WIHoIr%K#v+gOE zokMIkoBPZaI>E$K$yMH9Rw8UyX|Pvbb0*q*c@5Fmd7UYed!1LY8(Ye}BlfCN>xQ$L zx|0v;m@l(rNzF%CbHn+X-S(Z7+;X-_izW9Zpy_Be+J=sxTPWlZ%>e3#hNC%XCEAIK zkk4W2D%2cxL&<0k%11lVC8Qm}4QhsBQ6id&a?ti8jNF~z$89Mnb`Ej8nr@S{`K<77 z^@lUSGR=25R>`eDoIew_RuS0$r?ZM95qH++HvzYCr%a_ul5m@+f(EkqHu<4}6x??1 zW2SHB9cMb{Tf3Fi`-`-EOJe?Vs^tSW?~>`~D62uT>Mzb2BQri>{WuyH2$PfYa1|S7G;XnlCTh<0bVEvhf}nJxYr2(H$Ntwf~_TJXDhYu}rHx zIQoxs8dGKp?{n3$_npyr)kOXN<~|`{4CB64xGbwi4=9PV=6hBq$ip$j(lc^6%BUy7}J&LY6CyOPnvLd26n_9G_W&+dRoFvBGZoepgv-RHs{?g!b1f zNy5Ke@W;{%u3y2^Ufr*)>7e`m#m_=1`Ij2JP{RHr^ZYws#{S2ajpN(c%DW?;brjh= z|1-Na&C*kB6&Fs@pRp}pxL&7tFZ@q$Ox@Yorq=~MZTe@~etIjagw}rgljOoAKfMhV z$a+6c36jfx`WU7N^>*qlZLzY@sauoFZ>jsZ>(te!&VzMbO@QyJ<1Je%=yM}WiYn3Kh0H+*Q2UQGuk}MFbv+_dVBdZ*&^qY&l zsaU*<`t;%!hm}x)dSmor9N>=ZaKa5OR_9feb_2>pgg@Q z*URZ$ZHeyI<@LUPDzjJ8$C0H2AJearfA2k}GiPYEJ1JCWdQHANxSH;;Ig;k{*~=1N z=HOJVXna23n1FqjN|0QJ1RnV zQI(T;g!-Xml!ex!{pb=3I7OgQ2NZ{s^$uEwFx4_O#I3JsxnHXhY3WH#8i%&?2+}?MBy-PZ3Q; z(U(ol?`_$w^jf^7uH8xxcg#$(sh&_%Nj>4HA{njpUnwvHx7sU7N^45or;^#4a`~xj zY^}dfb=>(m^5z#Z<2h=OAEe+p;^4B}c}{ zf0UljT!^tEm9IwQ8G=B;*Jg)zPXgzEq|aa;BqR z*RjH7lklc2GN|>k{)9@BwjJ4QIN@cglB(%mpOV(#Q?>C{eRTSHs_&wg^$@?;sXJPy z%iEKEnh`}!UePOAk+*LoYs}(a(L32bb?3dJ(}|ek-qndJlKUIqMQ=#`;Lh!?GwZIF ztnaD!C0K#ID9J0Ne=q$z2N#tOqu39x+3OU$)(lzd?YcB0tvaAMl!~&@TC^RVK(|qq zGn4|<10|pgv>NS1MabuO(i=7VJu{|8cC22@F};Lom51!CIEy7^nJ^kl)pkyTdy^LD z+)aDyd1`j+={`gjdwTcP)uO+b`eOP+#`nd|AF{A7wV=PG_aiN8%2)mLPv`*j?@vTM zAv5}uTzuNFzn;d3U(5h*k<2py({TwNNE#lOn1NVckj#OcKAO+ZW4bMs;ykTT^a#=+ zC617VNM;sONOs2K zzKNWP=jNJ-F_ft4EK`Q+TZx9&!*K5}Ny7+G5Q`}E*|s&(_zhgHk)Chh@+aB#22M^% z$s3e`7BXTurk7;-a8BqXdxq1T?qfeng0fF$jo{c|*{qN%#R>&ddnDm&DC0+#iJK!M z2~jU89?5CFBIBxNLk=A3|(|C6E+h(mSEd*_#qLyQBP;z}f5uF$(wj z@|42QGD0CpmXG4>F=89d+2y45XwTVk6DR<=qxH)Av!R}S5XF{9`8YgU52l}Sd9=Qi zr-B({%EaBJF6eL;+Rz8UYt1hjRh>_|tDv9zkUP8y> zKDm0BgWy&amgH~C#mAq_r; z9#%UZRnn@fFkL!NB$YmLFQ2Fn)G0_MX?i-gJ?zY*QxMOB3=WE=X=aA=Z``nG^>6PuaUhWq%bUxkC z(Y=0w;Iwo~RD^sk;0QHG z-B1e3KpW6*bPMSh>3g8|XgG4AMN+an={y~ zopq_+w{7KQ&yUqz0TXM(V9e@t>d&;x?YXL^QF)EhKAzI`Wy)MTvhJR44}jdujd zgU6i#zBcPv_eEyuOT=>0|Gq8Cxe5SE`zBXjgC2Cf;# zuxa5^xQ~b9#9X~zrAq|<0SdW9e4+NJpJaZlzn1+G{ekzS_D6b@{k@ga(7>dUsV|B34qq_OGBUMatzBx_a0PU#Zvk>q9_eS6NM@H=GO0 z^slEAPG+31)Mp#VR;tk1w3j?fuG_An`HYmgtMnB-mo)uYZ&xFk(9JxW39bk zr!6O|){rr364-=AvUiPMCpdvADk{(_PXKL;HM>kAKGl8HvK94NsUA&z zJoi(4h{A_SOXTZM@nI74R7!nNf!r!hTL^JMN?y>vXWoa|BdwXr`Xcla56%Il4~cNLG@JX0-QY?dnzKG#jD+JdjG z&iP!Awmuc5ip(}q@7TPPZ_3H#JbbK!k3UK9=Xyi?Ps?OjzW%ms`drt`7uX(6R~s_? zP5Cchk7Q+a3j~?ne7>FEdT_d#gaRymId6MD6$FM+?`1{d*>K{_bBxalr5XH8~o#PJiKH zC>F0Lb?bAPS99e1^?HNgS92a+hs$U`cs33E!O9xqilf!EzQp~5=S$o_P|$tCr6|r; zMQ-QVN@sep*82-R%J~T%kIem_;n=bjNPBK*g1Gy9slRNqCoFP*yg{F8w@+H)Zs6A6 zvGJI?{u}zOr`&-XxgVAo)c;oBXCtESeaFMV&+ew1^y9oD%#m_i^p70sI@VaNwSD&f zEqbjkZ7H*HCA~ zsDHi{+xH}E^KE*7eUkW@qgu6D}u0;`r9Q$Th0YZ+4|xuhJN zP~L>wPPik#*9X!{v;PttA!mNjd)oW3Ry)KIBAvG5@{$bQZgmqr+pag(Zw&Kxi3-1@ z>iKiK9_+wMUO8lpki;ML0D6g2e&mT~gV=V^E7;&}yn_xQwu^t#i|s=qWX?{#kzQq_ z*O!q|+`v#5t8j>^ky)x+Is&bV+KFN!a6H7nj*7Cl!8G zs3x_3)`PgSr+!u)jZ1R<7s|_xVRB=w!K#VhW52X#ORXgXTNML)_u!~@T>hgchBZLx8PtH#RmLzM4W*>gy@7NEx+=9;g{ z+{0Y+RmnT7-{G1oj*vs5Sd;@$#bMo~M(L6NI9w#GK$@ z)!+Zm!R;sXdcH{{d?zVB@o>0cT$yC=KrA!bcaknitb6WB{U<-;)zfyWC>z$+GO5IK zdaP}Zd)GNSn8uhho?|>{R%Ci++yy<6P#0dH=lZh(9~rx-*CVjKFXCfWS)88jdp1YP9X<`k28sPdUCq;^ax~ zD~v|ujdDC3jc6n}dre>2li_em{uO;Ri4%U6h&&~oukuK6O2%KM3;e7!y~d*l%Uxa9 zh{!a_yT&L)8Xrd1H>$1*wjq*pU9aM(IL0AeI~$c`|8)u`pW(btPrIIUzCo9Hr0lt& zw@`z+`FC(%{U$+5lBaI+Y4skQYNFMkWp0hmVe!tpUph+<)7-YZ>Y1aWB;Dijex&sOhrFL8v;HAd zFk9^(9%y$<%zY5y{_4JZOlc@hOX#X?asO7LjK8qrO&5o{xT^UV`WW?w9U+mgA)i~+ z+o%-Dpe(>Z}`e9nThP z*2clg^>!WCk4Z81Ak;8&mF*@2+beR}FdBkNreP)DN)y{^QfM01#xef*IGFKoLk(O{ zQ>NW~P}ER0xg!8mKWQ3ZsMY!JD$_#wDgfUW@=;KuqxXXt)5?qms>0nwVgik>+)QSm zu{464X#BXb&i1VPVcBc9JCf~N0*Rxn_`bTAQxJMzPX(l z^F;R3MlGg$)P9<18|d!*v~kwX<~vPW7}IPA-CwmZqHNTmN1rvGWVA7`r7?n7um&3E zv?R?A%c_=~cbG4FabJfSoHWu%$W^Vd>@0g)8S~l1qJL{nW}0PdgBKvOtF=Nz za&tMa>_f|% zzoT)9LD9u88+{w^CvL7GpF6}WYL0rK1T-BjL*JnN=#o3~6})w{`tt#-<89mHV(U)SKQ8sVb8wz4?oK9tTdsEJ zqB|t?RgUpJ`&Y?bC#3jQO50h9e2tVoBdcD+(=)Q`HDi=2HW^(Ex=uYv;@&c}2j#D~ z%;>>sW8|rxoHjv*_T;qga=9nRx{J|^wCyf2y^QW^_af`;)xGed=r4zlZGjZ@GD_dw z{8T2HRPEMI0$(S|lbJ1QoMwb$RIJgEdv-60HJ(rlW%u;P`fx#C+w7F-CXc8%Cf_Sr-k*`nCj) z!1}htj4-S>B5jA@Z}dp~jhBui$vN@vQ6r5?))~{^geI%?eY`nqxqClOhmYwX8F+?*L>%;x4tB^qMf zzNaG6#;%Mp(X3aGNHS8n%jHSNcic|zu~g8RQZm+9H!6tB)IzOLH#8i%&?1zNcA^vL zHq!Al0yRUOP#j7@%g_dN0;vmE{|7gy6N*PJvg7%oNtI+7I+5s4cF&zi1!}7;XHrPNlTvAtF+`mu>kjeqqTYEk zKyoG-ZE<*J5>;%ugIwwo((V(K`oO$I@83<>@C~l2Dfs zRp}}RdbIOAcWdK@CJ*d5YS0_jFyTXY>9})V!`&z@+457{GY^mCee7R3JKYGVbe*Hg zWqs)}G$mPL`q=6}blW}Mi1NLGySXwc-6&muaY+iWcizPQ6MVN`)pVFjgx$i1>10!l zS1PE3rL(Ad5WB>{mZ?S`J2zT&n(@4y`x-FKXkhQrPTo`IQSD@}GAFl_e=xJJSnKI@ z1wN7V>9iL=x(lZpOKmR>CuUPo7TSPzqjTs13VA@)huWilC>hN`YteRe0^LScO4i48 zv1QLBPgRuKGs#mGYtWgmd&e2%ZZyjnraE3$_FDZOw>FNvkS7K28FfSR z!aYyHYI4#M#(W|e8mh!CmJ{1-V=|4_l-X1dttEFh8F8@OnQf>yKkepFIo_6}Ipn6> zvUrZC(MkM}TBZ72E---$M9EWgjV6w$NQc~P$xak4#XXm^X2|)uoHauN=Xv^a%jOyN zd?#_jj}kNAh?Fasaa?h}QQ!A1tj{QGwQJXy52;~u<{MS?PiuM~-L3gzhvyr?yav2H zpQ?!+b3-$YiEOEonTe66Ig^5ORqkXG|3jt40xS6ME+8Oj^3?(Yk|rk?&=#f1`1f&n zOV+$kQ>e=sW$GxEvOrJim_-w}Np@us7n|JIvkZS5Te00+Xjps7b(_t7_sgc-9+UCe zI63BCoNc_~VEpj>V$QEEp-YUdw0cLEU>YfbO9@(vv|dVPcueLlHQLys*+B+;C4tL~ zclFxOc<-vn8JU-BbRy}#`~YuQ(EI_3ztnpjYi8PGj4D*tv=Jo!Qi=SK#P^lu z9}-fY20x^_@NLcui!XdbvvZ6Phk@ZH28qrw;(SvH!XjCiVs8 zf7P_fJ2|+m#gC=0LS6O>7v&g}{%K;+4iiwb!3@m1V2A%C2X0*YWF__NZZOhAf6+{6~(sJxN6ID zUtepKw^7(i^60AFmb}l6aZJC8Tt_~cAxZ0uzP!@kv(9+NI1{Pv$EF2%-ZVty8`UWR zt@Dj>4qKXg{g(zC=xlOd{+hs&8S8&z%=R-pnMzI5vp)E|e+%tKX9?a)9Cwk{Ta9Pz z{hpC61x8I-wAJWF7P-8YZnv+j-)0U;H6 z^t6=xVEk=(;@YM?$#PjWoBl^5!KPyJ?H$I?cE|5+JYSOYU8@F|-HUe_U)pKFJMT7L zNsBHa1yMhgin7pJv>g?pyQuoVG_a@}8jiBiT66^6LLvWAaiR_=4yB+Bv>I(gMd&W7 zLhMDO9w-6L(QI+rN`7odCy-|2yXL4ZibW|X18qRN(KX~_w`sLdD-?%P&@!|E?MCO2 z?yym*+O*~lTV~8G&)CaetBJ3@*9f;K$H)yo<1-1|?$3ZrRl862<9<~nWS{XnMgH%7 zl!K?F_I}dnDR=k%s)Bo4(hI4fK9G$HyqQ*TO8s9cu<=X~ruvDOUB8lBM@or8jx;?0 zw#iV1i?aBDRR>-?fZtW5(n0FLD$@F(ag(RF#=mii1nK`9E^{UGH*$HjgdV~&S~?!0 zUhN?Thj?)KNnSY2Wq*<>he`PZ^4npq-cY(9A)pOq$`RwREs=pce3{C?9ohG`96gFJ zRmC{QdGAQfF**Izsfi3?A_35(Xl-uTAJe^`WvzyO*9zRaG zZSKB)oX1jLTunKN|LtY{NqpQbmzC+3gq^}PNqU~bv|MH>QynQ#rkCZ8G98n~rwQ!G zvgS0FA2UT4Fzv920&us7yj;X%*g)A;M6?WKN-i-VGU*IqU(J+UI**K8{7wu^lfvI| zGEMINj+5^s{jBi{lN$D%#bqxkIcvOYzY{C(oTCb}n;@*)@cOu8#HlJtvKdhWYO z9P&Azi-z?w-ipK6OJp=wP+#JDBV^4b!+LGM?N6e&-enH4+s0+8h?(y6%W4?ovb4BL z0N<2RS3T8q&~aSuzlzH@aMKV1f0vxZf+-lLt_d5t6A%b7A(9j;?_QU+Zw<4Re* zC}*x4EkW1~;`!|X(&eTRYwyi-`wgBe_Q*-B0Y@83+nYuJ^-kxTMsMX}+dTrY=_a|M z$3Smf*$P>?`QJ@)Lk|hQ#hG&+y0(J+%`Gl@TncYl4U!es=whszNXKHMrM*d<)VN_Z zko;mJz&z|~@1iAjuR7qlQ<6ylc-7a-dNlsv;Un{*@>jUhM;N7v*3U%Ba z&ZsMs?(kf$hDlYyD8f!3Jh(J~2Phcfe~}ei3YV-T{r=*V6dC`Q(Z-Q7Sd%s@Y^v{N z9jpE~r{yGFW-4J%C5?{U!`^3*-jVuy^nSDN~b$y3+w87&=`;~$3P!(;fH@ed~i$eMqs zFxc1nA7cpRv&DVN5MK?vPxVn>`ad8q)|bo&rJk`d>jTb;li(7|YDft&JV-K2tPasW zWm+pGB{a!D57Ru8sTcjrjs5Ii^{-*5?Y$S~oAsQp(jaGT@yu@bzAt~V%p9$pK`abn>4BM?mS0Dw6qyqoVtkpBZhlMY|()<@hIQYM5ec=-y?R zzt|mhx@a=+2#>+}0cLe_-kt#S87eQ|Ky$Xk_OUxN$Q)y1z|K~|WX8!fcW8*&#zs}) z?o-JeZR68+yB;&YGd{Cw2b;FUGu=L?vYF+0p)Zerb!dvaRWaLAtTU^aeJR4%tC;(2 zl+(>s&1a1C{+@uwc-s1)YPe+o*=huV-Q%m7Z%`78s}b5g3e{v~bu*Q+6d8uqaoHGV zt|P=FYM2Me_N~KB^-f}LIG5?5z$BLl{F@+qBKRE_Vb&v4TfbMT-`CXdcI4XNNVA=N z@L<_e)vPLsk;FoZ%#9>;o*ZanElk05-hUTGn%~$KxEI$n8B*OL%cBV8Wd%Nq6vbHq z?!a0qvg*r}+Gbxz9Eodvt@d_pGsqY;%yXx&c%Sy`a3gDFc^$(1v-^4-^KgtqCHCn> zL|D;qGkQ=r+TwVWigM65Xg|7ym?5fFM{Q9onvRyCP3R!Hi-MRi(j0X|sVEC=LI=@p z6d>s%%!+BN{cPGcbPhd05l&7+@hBDLqn+qB3Lww5LOsxQv<&S==TL}Y(;A^zl!$WB zH>e2RMfFUAi{eo#%11j*TblNOA0hrWtpkcfS!gXPLU&QU08T^+Xgc}^?MFU=!~trH zV$pQ84DCmkkY0|PL7h-M%0g?=PE>^MqM-6PY*rpeD89UHeN2)qJHd?bJHU(|bF9=! zFl#u>u|C%45!hd!FWo+T=@j%P3BEGH9IPH$t#P^Pqs@?DwrKHtY^++R$zRvRp`*(_ z+aHjm(Pot2Z@8&3R+fx5YXsNux~=J*>A|LU>NBW(E|vYR4mj#~=Kvg#N@L6@U$#o| z`&e3!VNU|j*u()@sO;JB#BUwD2b~pnc+N4uW!bDq`^|?h1%LGz&c)_*6asbKhMP3Du=0_ zKqq{v$JNg8fZo{aqczb+V#e`pCf7o?ZD~Kwtl;0&T4b(z*MntHnpur2G+kg;l(k8w z&Tl^c6z;1+J=ptw$|SQw@PB+vP{pj8eWLDUuv8jr)(x&O@sYKfc`{gvU!cIojWrv1 zr=J{<%(281o3Z%i%SLrhzW1EcX;(ue=^N%q)JtZpioIp31b^*ypaQS1IYe^1^8MAg zab_cWl5@wAkSsd(>yRQ}k27lqc1U>?dk%I4<6fgbyo#6vM$>#mg?@-}uY3i#|}-h z!miR{m}dhr75~FLxpSB#%^+%abN|7MCVRqHx=X?^={|%>P?Iux0aMLeGNH0}}HV*^lMm zem+y=xiPd`i;o8S%lx-YzT7wEQ3$w#_J*u~%WU!R%wlzB5obO*MXF9V>jXdPb+4kw z#Qkv3oTY8;*_C0qBuyrQhpQdT!ll(T(tguqGeFtTps1dhOi>*!=RIzGQ_b+u;r~Ao zs^Vd|1XKLOqRaEjD@fB?60`4nFRWrwW8~DZ)vvltvVi`AnzvCu6UA9ayYceZ(%G+k? zu4o6O>D#0N%h@Snz4;mZN&2I(a7k^X6i+D=mwS}+b2u-OJ8zqH?M3NQ&PBVCkw%B> zfE1*0_`K!YWqt;K!iO-`omtf(Oi2tNibA zaf57T;+He6^ahVJ>{g!LGJ;F3R3fTNjPh)>G0L;i#;8XdZOD;nl=vX_$dJ40SG3wK zW0d+XBaM#Qh+~vzw~bK}Je4G`GMyxEHPtNr)+H_2RHBfrPyCv_BTJ^5rJLp)kdqwn zW#18UubaO6AO(p7?z&Q=h38TSsprAyK~X6a5~2joZP<{EAmJaohBqjxDp3;x&Ph<9;# z9fvEF!_w`Q7_(6JH?Yqu<3W{~)HQkUJ-Tt#3MYDIiFTVw{hsLgMrWeuHw^;)SM`m~ z437n^g6A8Z`DGmJ#8XaG$K;adxAn>KpjnoOYWo#Qe4RX!C{N9zj{4ereHCFUauTIr z2w#;yH`@%7)WyVZ4kv~tmPv+j-YQnL-HEb!7Ueflj)JhVu0{!HV+YgSv}TvA5NHDAx3V+PoNog;hansve+5Tf`9 zO?!)TJI#F*Ds`tx(tVEk3Vto0g9o?pYlr+eho*jq*P#lhswBsHs^0uA#PL|kP4x{2 z>8fZZCa}@yShaN$U8s*8x@?-qLq%!Ck5#pXXK$pjo@Q#>T=GZF`H#Y(THdi%h7Q{l zNd(r^G)5`4i(V(C9jdXO{U*8Xc?7kXpk9{rd1gZ%bh^(kQ&E<1*zXSxkI0ld^UVgq zBQibLQXb*2mi)gpW$t|3|B3tZ3*_hdW=%W1G2eWwarp(0!l=$0UnaMV9yDRpnE0U& z8|CrRG{Y?2DCvMq${>ih@pG}{@-uj`*DDp9DhVfeio>l8`aTnE@^4GyF$u_|MxEe^ z)96gH^#p4>D(U9=U0}tv=eJcQW_W&E#US7F`>RY^#0h)~z(SH?50}+hWcG)X^e3o( zY&Dz=N>=-jFR-pSVu9s+76=~p{-d~3`D21a()9^_P=|EE=$rNEu*ww^RByI&*oIon ztf{MM=~yK!eB?wmot6(wKNgR*iUHL`PLQ7On+=0`NorMIrKN<3;d%rx?|q`}`6Z7| zQUzjy>WHb_+Bl2&y+izNlb%^*fo+nWWmXP8>vdn6(i3G(7S&an^#!&Aa-FmM{^G1! zOXabJ^e<{HedNCiYl_v;<{6vrbVbkez|L&qFKeM06q-^d`Ahp_D(j|ra=3~u&R5m< zt%c<92FpBttFWl3N|C^9tF7#wO(^~*6l0gkTiJwSY#En0)F#RLY}(sNvJ02K+tpFI zF8Hep%}OOrD z|9Yrj^^`yAS71}Fsp4OS@+~Q|ii1uG{`lU*>q6PQ$ZQf^xZHD7%DD>aWVLe~n`JI0 zBTZI`!;^*QcZHMhoBvm%S*_)M?ZL!mMUnep00F0Ujz^LJa{f+)T;Cq zbTlq_dM58Zd;>IRsaf5@^RZ`(q3xIq&l9kXEtR|PWbFCDQgf!`W932(O64qLV1*~! zW#*HiypHldquL%m$1?7&Z4hI*IWTPtvlxECc;n{3uHWEx%*Wx6kjZP>Pp~S@)J`^o zeiH7-+y?#%W8fk93OoXPK-w2q96Sa`LHu%&J$dP(x!#5+;WT&#zHejKpR@e<7K`)n z3S{oO>po^@Eu;=Xwz`L&&9eiC}t$s~_a`x@!pJZINpn zBoldhQc#l1e$sbtk^;+zQjI6j0LPkqm4c@)YznJ-?W;qQ#TDi?hr?!=Yr|*Y6Oivax>~~)uq|u_Uxck;rC5GE$B$e{ zy1LfFwsaZHrtYslG%MH)&lA6m?5;U+E|XM z-cT}B*H(U2faG2m4TzQsn?Z81t2K1N7oc+Y5}b;;8=MY%!gpXl_%0j@XTni%4orgc z;CPq;C$j&NmdOv*5mFwKFD>&7NHKBEf?05`_xStX<4d7nzZ$YtfonZn3crURz&-Fo zco617)&2VjQVg{f@OQWpUf}xL$NW%}QCCA7MetL|5T6yGP?(Q75`F=jzzr}Ceg%nH z?Q1v*x*>P1eFGOjbwdP3V=0)6z*uGiqiw~^HMJk0n~bGx=SKnj5&i;qz=QB7cpNH^ zPQqQ7PkGHna5v_gu#kxZ=1oK1^3EQW*O9jFSz-*6nf3n#;Wpi0FD@HhA` zq;k~$gQP~9=CErnDlv`CI$b5u2`h6`I;5`94A>BwP{qDKq$*_f4L}i zS_Swz41t5;V=w_$foZTRoCT}HdA61;o8!k4EFvL!LW_bVDeu5F*LSck{2A7V#Fo|& z5<6OBnftN%nc*3Gv1tRW^@sJTqo;>+8!@1g)hMV@I{&Oi5X>h#$VKz zqt*O{$d@^)dZVwvijW%KDui92dRy8}PJUvB+Zm1d_Y<>fS}fM8R_YDaX*2{bX1i#7 zPSi^Bfv_6pI2Z=wp-SAL@Ci5!s(NBLRE^_EsLJr0urE|uCJrWIW*kZz3*Ut_FsewV zY03Qf2#fJ>4NQSFnHryibnS+zkU6T_6zE5sy$u6l8VrWif-V{kZ7QVU(569^c<;c0 z@Lf0p&W2P_+FbY+oCni+AE0IMV>TA=Ln;g{8>+Ik2vTmf#gKBUErqIxeFzW0Rj{pH z(>{TG(n(tli3M#9On{$4)qH*qIaeD6ajR{F`S3fqp%Fhe^J5>}0uR8g@CYn`XWE>iY>R z^~ba?)j_fT=HXNol1!*-y7yrg)kZld=4&#?coymBK!ajhB3OEn0 zbZ9TSviPwIi$(BbxCFAw-<1Q`z|Y`X_yx>^Dv{U0t#Cb5iTs63$}@)$11IySn7_qV z1$#48!QKj0u<6)Z!TugL#k?J=GQ0!60Dpq2!r28?ncnTtroRDy#XJHYfQj%3dIe;FcRkKus^)b_9bkW1qYC*bHS{+Cuo~G61hpJ-g!||{& zq(`7NfwcTuG^FL$=vunA!KdLZ*c{TxX)U0Soxy783){e_U<_;npNAb`dq_2}y#jl~ z&ajW2%Dx*vsOPlqkm^i(Rc7RyVrS&E#(J}AcY3TY#>2HfFc|iOjo|>O`han;9UKf* zK8S~X;V`HgoZ)aZ90^tWkCIvIc_;m`6s$L^#qjRUDsRb9l{a3US>=t_T2^^WfvUye zJ&fyF$U6;J2bcjDslx-HI6?()nDBX zRnglC`@o;!0Jt0G!aZ;u+zY>g``|{%H%6>#@>f`Z`5>g(c~(2jj{{g7fhtcPgH}BW zH4^I-RP7NjMO^;yETqG$?U2YX%{T1~7SH>V8j&F_>puQ~>OP`;X|7;x7zOJpQ~pX0}BEZV>?;q&l2 z*dBflUxa&LM|c=^hL>O$_!sO7eYme~P?d)6Fao{`ABR04&qZ2K$fJzb3&uirAaE7h zxJABfVYQchQ^LySPe8hES}s(%{3F@5!TgY6?A)&yUHAlBmF|33ff`*sZ#=CYT$z)o zX$veT;e4jRa`O2@Coz_jS~ywpo{yZ~rH7{R-2l#i#yUVhP4kRh+qBbMS^cTjCo6Uv0Ps|$v2m+aGqL@u>wC;>x9Zvn|AIUsXn(_f z@E^!Sfpww7umtlFulX4K5AzAA@j2(QZu4uy8olNgo|W88o?6@bd6F&$s?yL7s#4t^ z)`KrXmC_xcD$Os$_V5*`N<~*V7Njv*a>@Ytk12Gv+p6&MMt!UnK9d>Yn(bilQ6 zNXMJ$K$=TnExGfp`5kWo)_-SK>;5FRI`{V!R0Z;BSQ9=2RY7hJTfi3ZCCE<5Ry?+X zZ(wc>Ri*hHOoMGCY!maXJns-}8V#5lQfbFgb(I&Oy2^`CUF9WM2X=(2nS2?ls`?ce z16ASTmbI>!RqC-PuGLNI4pTArfOBC_Xk|{g3Nu@{QAKs8imQtn%FRt?3&Zn%!p7D# zR+!$zjSAB!7zD?_>M#jD4%r#X8n$8OigoA7unYF%VH{+^i4_AA;Uvr|tdk)NNUX3a zzU#H01(}sk)i;FReJtuIKWt{0XR(xQCRe}5F@N05hJkPnRNV>oHL|M9c~CtfX28a9 z0eli>!P0nAg?K4u6~^UIbt^uAgJBL-g*q3i)MBF{tJD7pq*_hW*6>4>YIPH;ROeyN z^_o|}^_W+BsS3Grr;5jy*nb7Tf~D1O0p^XEcY59Jfm<-2fZO0*ul+x8J7!%yD(>J1 zV~N^NusPfXRkiv(>;!*-z2R;+9I60}g!?e70R%-gyrZb9-9oqr9)M~*;5W!}6Dq)`uE5om0C@g?gb(+-Q_)!fD9uKq{u$&JS25btW zpc<;J1>3{guq&(w2f_xBo~hOd@k8>}Y29Hwd=|pTiWm1ExaS0qt#g8Y+)3!*tBW za4Nh9r$av{11B&Pz6+z^Ovsi)TG}jrG~>s6kUCA91E~wN_u>0cAZ1%y3@NJGQb>kn z+NS0rV`|IcpYQ|dpi)x-AwOs8s_r7k_Vd zwHw=(cpll~J>zBt9OkID9jey$Cm02H!A5X590K=B;~yC}^SmdtXuMM0AW8iGq4$gz^VTSrVr@GJr zEMCImW7q+H3SWk*_2>jQ!WZBc*i|O&WWso%oY_g^*aKS?{9aH6zYh$B{h;bJ41g-Q zaquNL7GrmUf}l zXcIb!E+O?ouNmruQc)IKi?*X8bQgs%HrohwLh&dCWuVn)8#;k*qX?cUo1<8ih_cXH zw7mii?g@U}MgbL>myOz@Sd@q|&}y_Doj`X{5D!C*PFd`+ZBajzjIz*Lv=bGf2PmX6tL9J#lz^tAWoQH1=`PsK z8iven0oi-aS}c#Py_Z+u{YN^O<=t04+G`GD5u>q>nfx&_X`lHd>kabunWK0mUTweG zn60)u?l;w9u-VGAKsN5DN7hpQRHiJ6EHu@o46herS}HRN&8X0&Z+g~rs>#ud98^$9 z6`&1LP-v<}%H@B>@g8aYtEo1LnXF95WX-RZw`Y|}m*4}I>6HVRD#@e+W)xU{z_d0? zzjlCGv8^TaAh*#v!6E-W?W`;#f3TMm^UiORV-hjCv?HXmjvu(iAO5%V)!*CHbRHVUXh!k`W)9;KoTv>I(gN6>8)5Xy>0 z)C$F-L^KoSpl?ELY*f9=mi?A*ghZS$eH_;}+NJJWzG3$38|CxE`nRkpf0d|w?Ih6^ z$%iqRyb>vSCz;RHMSM@0N%l9xCFPXa$dUaWTMMN6vSr38roLs%u2ZI)(c1LWB>VUB z)oDi4evs>@&1vOEFt4HRR=axor!JGGXP5<;S;U%{x?AN&OTTVh?tT%MTPpR>Fy_rF z@H3d!$?`L%S`&T|lOuntUDmy=79;=8)$*nF?_BK*x%0a@%~4^Scl+fdXU!_CVk|z( z*juzjo+GrZUdlRW*7F@n7+#cub7tutC(oBj)HuR*T>{Tj1xC8ZpErN7*|Oa&E;96G zc*0F-@vOq#cG*hLlb6kB9P0>@wMZrU3MrW{F;~o=tgxuhD*3WZm=C4*zG_x<*j|)T zH_XXh_mcqU&;wMxD)kQPgyPX0v=Z$^MTq?XwFuM-^*{+|I$Djkp(E8;YPu`?7NwA_ z^oyAQ+V&O^(?B}kVtr3LIe&}z&y}!ZGU_SiK<(>QP;9<#|N9rI`iI%Aa;!D!sC$`c zI7c)zkn}&ytGFHYr#ZX)Ev^($o$Q3#R=2r>pLN`%^qbj#aorfH{TIb1rX9<~{S5XC z{F|vy8e;S7J_d zJo_>Wk2g8mdCTq5GWXV=%opQM|Cg}Y>bdv)r!MoJyS2@qw65#6Is8AfDPMg2yV{<0 zm-zVqVrvr1O(&q~Xf@h~PN3T;D2&P!wMDTgHO#g?#;|2Kvxmr{LFEE`2l#1zH>9@i zAMUu(OMP9awRjf63^tx-9*K|LyYS_N?jPc$tLqo=`v2^BJAjpD{!xB$9BKKw^fCOK zc~`9rkcH~NAPx+9UAAyQ_skv|;3toFVVYi$=^x-6%;CxSIR9xTNjJyFKKXTd(e&@2 zduGAoxYsdfO+Utl{947z7Sq3U$BqF~V&Z>12jXL;j=z5$)*6=t_*awR{{A7sDY1|C zFjeJwz0CFZugv1GRsR01oii(|?&biw?C&4tWW33*LT_K`8|hcNkM98K9DwJHK>0=Y zmI(o6uKE=Rd>NARYbTk3{(N>Oz(0U|ygtxBT&f2$Q7odIe-&vJ=wG_5XMl_d#Qns#CRUWS!6l?S8M}hR5|=( z6wGgkOexO|=a(bihV+pw<@__eYXAmF&+^>BNF0soD{q(guTy_i-~YYphB9-?CgS~L zTt>yz21(!QTbT_jn{M@~sHPHOQ$nCZ%bw6H#d87=NgQq*^nVY(_Qu|l$nyS;z1s2o%E0If z{$1=U%UAGkpmOt-3jW{P$-CHBm2DOMn;G#|-n40-TW^ykD8zrQy+Uu<65`*$5lu!6 zk6`b5T4d&sSMsl7w6pSoO`9m`xy%u4Rmne*T~G5W`G2PpedJ^Qee9$9x_3P0U)44= zi!#0%Z9@mqHKf&Gl_+Y2+M|9b8O=c}(Kd7hT|;a-tW`(NP$v|RQc)JlM?29u7H|5m zTi=bww5orEZ&zBZs#3eEe_d8)cCPBLcDl1Z(^OTys_HM!2b@wRf>t0eySjfZ_U)`) z9jEN{S>1mkD_Yf$XB^s9tN6 zgZ4@7n%wa|>0Hx)A)&VRzPVe|Kg72VM~_Ny6g85kZmcamqbS>TvA-x&qWnuY2C6MT zD*Jla7t8gs_D|KqzCQNb|L5=|wD&Pc zDM3j|QAjaRP*G7aDJfAgDKRNfDJf7fX{01%MrOpMq!E`i(nwz^C^0DsDQTpnq@<*z z#Gs_4q@fR#xT7W;r~iHPS13R z<-owVum>oQ0AqCc?I>!4q_fuc>anrc+-!iV zK!ocAM7*k+#~O|&Ne3veaR?7a_{S<@9M1P+{Ey6WzS(Rv*Sfff0dRTgwwkNrFkz=+k*z2ULzs~g&<=55?3|;PSdgQ z1gPNK5fh4-NW?tdZaAJV6`+cA4DLd?Ekuld=)64RQ;#u+m(pYYvxV?d_jXBsd7X%v*;vunJ!N#*5Y!@s3KiKmlE)sT5G!{7FB)^$x%=N%Iq0Ow8o0xm% z9dL}1OVl%Wz*8+;qRv9olQ3KK*Yoy(Bj6Oc1l(`Kh6T(4OF6%~eU0^Yk5hLmY4H_Z4957&tc$HKcrm4qAml^f0BhJKP{z!c+8xQwiv zg6_{#%~R~2Z}e2Sq!TJ`DzcwYSyPR5i0hha+--eMg-%2E%PM7>F#|h>(rE}>sJf;Z zkK=ii@e#%!oZ_?8!k^uJZAY+f;vSc!6ulX*tkaEmv2m%JZty9$Q}mpgVGMKnHA@}5 zh$=6hf%PB8Lo)ozWW*TwgA&0qKA1z^+y*@QfGY!1Y zD6Ph0w(*q{YTFTIDC>!uthv||TH|Yqqm2iwD8A+&cNusZz;=~9-&i!&a|{*~Fb^bw zO<*S|2ggAhxC(~i%YY$ZK1d3Hcl5FDz6Z-dw+griP1IczdynCve_lPi0vqtOdvRL* zAFDs!Yuu*wwR?^EvK9}#0MPdUyFYeP>xSc(^kWtnVLI*d1;*|hH{mdQz#(u#9}ZVY z%k*RC7Q)@$izfM2HE+W&Hl{5!JiWd>aD8s0M9W9lzv(WGHSihfdIRvSs#<6~I_Mlq zzY>5Ytz-9Mc$7*s=}RhLG1}{;xi0FBuiR^Q#~I5Vu6})-G1ToK(%|`&+v5z!ujwjP zQyjd*8;J0_Q~ere-0J0Zr@py*-Ff3tTKf0O7ni_yE?#0x5-(M$@|PgzA>^ESr+RaV zal7kGol{jmV2s>-pW%)tczfK3j$fpL?lZ=FO~B20U98?nYVWs5rQBzXcFLTm9$SVz z$^QF{5ngXg8of4XKe|XImpR`JKkl;>4zUV{`j?7YdTl{M6%cN|iEy82mW~G`;+Kk_ zEHxZI#jI3)NaKY&`)(1E#*#WeWs|C3YJ|#ySBZyz;#3YJO#)sA8gIVCu1)gGiuSD^Nb?l-*D$rZ+pYMuUcQGa?KpR9}d5_)f(%wjw=6wR?% zbx`zAeeAEKU#$GmWQd5OBvb5f48L@vtGnw6d+t&MD>D)M`ZEt;stvzOO-eN8s=#Gf zROj6FzZ-Y43Jt-%nH7k0O1?|IooI~3`{iNe-=%)i#_?r_r|sl`TyA(}5~g%X@Ss8J zsxI<3iPY<>-a#)`J_*JhUPX8FNIF>GMqaEE5{wxhQ|C(sRP#f)9$E398%+CK({a)X zX#R&C(a5DY)KWilxnbJ=Fd)vW}G?ripr96l(ej7cx?jH5rgT_SLx_hpl$qjfL6pp*|cTO(K z{(EFR-^}s!fjIjw+pRX81V8v(fh(;zyr>lGO%gty6DNFCkb+)9gxy%8B&hIMaD3s{2O9& z@!hY1(@0ko4gB(eV7)^?0bk*uXAFdiIvw~&=S@3urbc-8Oh_g7G0veR^wV^)Y(B{ zI7Dm`e8dqP;#HN2k6y11ID+0F-p8MV-KVVGxLm zWHXRt5WX7c78>WmM|56Ug?l6TlAPNjgyeE!?8K;P7JU9Ug|M}@-Nc?nk&6LND?aof??x}fyt+Bz`gB@;#Pq$w{ zF5Z9($X9FXH(>jM=lsWPG`_%ta{MxlsZMB)TQlKQ*Jm0doP6WdbD72zXMLXbH?Vs? zX}CBoimSQ#N#p$+b3Di5ejAtxmVxzPE7%K;g45s%@EnI70GJO}gUw(+I10{#t6&tq zK{X951M9&yun!yor@$rPj_-j6f;k{5$m(g?gbzDGIXD@FwZ0e+AH{O~5gPbIJb)D2 zvJY!wwi&anYSVU%76V?QK71C(%a-(xk-tp!xH^xtF5`=3mZ``c#%PaylE_!( z7Qp3i-eJtdBcEy!<@yQA`c8H1zBm@X%A$P!7R3jcw*_QrFDmzN_*p9%6< zmh0vkiPt*zJO}@}T(`aBvg;%K@ECP(LP2#Z>v?0mtxn3*nFlHV7tqf7Nh|8ugYGVB z-V5;ibIM_!)8-g$+JE@&xzk|m?p6;MHDM>Z`au=G6I-A!q&$b0e^6!YL@gdv1v@dD z&ofqy{4;L6oZ4v&wYjXl-ViRT;LkX|dm)w|6VI$M{M4jEyujyiRrO~~#-qiqljI3B zAE}B$^yjBIkEhnE&ymRMDJe*wi1y8R-&Pnhjd}r>p7?z2AucPfKg0#$p@D-i%b6xF z5Zj5pFW_8OsInK(uYZyv$D&9*4)Ju=7toU{^eNq9zr0%Lo| z>JjHR6HB0e3B3Nl@>`O`vG+s0{)}EfIv`jtP{^r+za3DZUZ7T}o4NmRK-14e~^5i;T1!fuiFOk=$w z|NqlB==9ATw;h8M1FHWnM}J?IjwczTY0i1_Xo zjm@|s&3+LVg(WKDFZf45T}}R9aAoQA)Y_W&_8NGD6WVy;OK9UUFBySOXge5lr7f(M z0zRGWz)L9S>zbgy;y(%=s2)~3{kAx-=dpLWw9lCH=y|x+t6(U;cOM28fQ?`WCsYQJ4J>~-8O!&h0{j^H(P z*l`@$!11Ifj_!kG?oxJ6b#qahUdGsQB+%0U@kmhgvJpE{exp91f%SzO6I(6!+HXnt ze2m{PVQIGDOCk2(#C!^!4I5um`5$BQp#7-YFi6S~1NWHQ=dXr}i5!Vm+}xFKkO0))U-#cf04H`fsR{5229-?wyxprZ-T;WmUqg~e`O{r?ZN9R%$ zf`==PP~VoL`n;F8T*bYLR2fM1uF859GxuF7&@tQosCs6YL)6h%@n4H=fp}WXsaLOE zV=h-7<;cAOxxZGS<<~C!ma8m;k9`8+gKz<=d&aUPC3!VO-zMAw7jpsV?;s93r2ac) z&@gqj{MwDL<;tf5Q*|in&NhA3me;Uff-!3@j1k*Wn0~;OS~J%))sESweo4c zhn)3?)GxD5$G?-7tCZJqs7;7yQw6VMnzyOS*A2%rUY6sr$mp;vMF0Dci~1RFL%i0^ zDTr}<3NgM_>bV2B>96%QOuxNRrl&fBim4+}18NXdiS$n+{e4wxNhQ{Z`>NQGj(*AI zgQ;}e=JGicxvCDCyfOzQ)XOsxR^leoausn9b>EC4@tVVfM)4#pH$V5L@v=2Xg}#NHe^iNYVY6FrA39dc za8E-t!%H+DAs7pVeEL(uAd$@9`Rs%S@8w%++6Jb z7grl?xGNX@w(*9O@uvFbZDVfa8O-2I0B?)3i~wO^0ay*Tg1z7fI0epwt6&6vS`h~3 ztBe|B$n0bI*aj{G^A7BF!8EWKtOlFGUT_$k1n0pO;28ox7Xs%IxBCcgbOow_Be>ZT zcv7t`#lLM_YK;*5^CP_0_z#|&9Quwi75^AW)nZYl?-(g?9QHe5Bi=QJ89VR;L;DO{ zv{sFL+w~4au6x)1FOQOUjVM^(YO6@uj@tiu0?S(^9mVb3{VHof&`BNimg;2C=sM)V z132sK|3Y~dmUD9xz9Gn9@g`p!V$KJ~1l(Cn z{{V}1cTM33MxDO1xTpaqJO;1fGgjg42OSOemdp79Z8hyfl;Wh~K13-_D)&R&`88GX zhq$|YM0J0N3kQD{{E?A^2gy}_gd%ULY5oXF@Sx?c6UNidOMbHQizS;Iu`^tv@*9oc z;d?yRkI|X=D&k}0FH%__qgC)C>yM46t?O09C)g^iSIM8?R<3?t?I)=3`>OpDBhm?v z)Lr~7HnJfnQKx%U%t<5aTG&2>x&P@Gy+Y%1w)8*PV&A#kI!?!<2t4Ym33*CXP!mco zsflYcp0HY*YZ^Yqjaz)Z%BFJ+f_Uy`hhQS$QcT)8Enl`m0zGC zvsC*RMw320`}rI@jkG_a&;d zS_OZFyVC#mRF8dSEVO>9YGGRcNA-S%$W#?{2C`ixo_V=YB+e z_qL+RzVw#5_FuJ)Qak@(9gDg;pG952QlV$<_v`=u1IEFgv#8@4Rdv?T-{blAM+A9( zjr_fi{LTH>pKNT8-hpU*DWvRcBi50_y$wNkDE~Hl(7HApp<$Q!9ujm9d z%B$Tz@$5lK?FhmfOc8XgGf(KSGpeKA80UQEW~XcKB(wK)+Be29=jp?o)a>Kf9`5@F z18=&j{Kl}qpA79i!D?06-`Yp`-@Zi+Jn+q?0fTGKIh@r^K5UgDFKjFHIMNl=)8PM{$z6SI$|Q0w4fs{Fj+ z=`?GEdg*&(g}S-ZxXJ17Bh=vYaQ%)~1`5-)z&yD7{a6WxEns?$g?2(=(-m+Gc>1mEM zoz}RiZzf}Jb!Y^>XqBa!Mwm}ny=$WU%tt-+NM&O)6;6H3BAL_eXvx3Ua|!W|+Adon0A*wmhf`!p&7Vr?8e?0G3JEM}V1N zDM$lbz#eb}oC24DIT`7|Ot2KBfo)(PI0nvuE5I`h_twCCuo`Rz`@vCg4qO4l!tt%% zkZ=?P(!gGD7@P-JLEscDz90>31&6>1a2eo)Eg@h&NCKO{PEZbxgEnvlcuvFK2`m6> zfc~k@K5zuI;dK+1%gQ>{9DS$DbnLUhJg@?61$)5>a1NL=aN=MdSOGSHo!}@q4KB{W zhM;0MF1Q9cV-Ne{e#ceWG}Cm2h5tl^=3{@d^C!H-bMrLw1x&3QBg`N-7o@J*KkypN zS!G3-qg`DQ@v|z8Fdg49a8?}%H*ZGxMO~m?a{tdOFlQAv-5l+93(~lksi&r2yNqyF zwTKw!i-^E7X0|^e8inY~qhq+4t$(ufC~U;58`GT@sb8LUbsP8`XlIo-0~H&NGM-nJ zGt9{z&r4ChDmfAtY*%OCE4I}tU%%{oz}+Wjl{yoZ8i9O+UR9IIuie&mR;`E#_d~?! zSEW(|uG!AvdhHNy5dH;~a>VPaZhhnZ8U6K*g31=qsjW|>1( zStR-nZ5N5E--;u>r#xnvqn+M+mDfW5*XuiHRf05bBaz&>T>ZD=+I6C{a-EHcQHZ#q zTwmagwcem2=i+?--nCK4LdG!&-&3wH?QR_$hI@F&Km^)Ghy6b<^PE)=^122fFZRK6 z&Cy=XN+>%FL2?=&C97Yd^0nU6aEj2UGAa`5qarl&Ioyt=U;UvRqw%fsD1 z>~MESm41)!i~2=lBydz)Esyel2}#jdR-UhEj)o6)!l+w*w>j5o^sDNnyUm~Meg7t| zgZIxjw>hDMC&rk!JE1=xdJBOYW6T8}(e|^{*Mau?PHiz}m~&FOTnA3L#|*<)=acU- zA9X@oFFb%pAfLYni$b#sz1RGglWu?o=5l9!zWS}R3g6%gjCPp`4+Fx$e2@e-ft}zG zI04RstH3i7-VZDVXTIab4X<`G#9xZLJ_BG zP{dSgPSOheqzAtysJ{!p@kWvk+-%XBcZgcmLyf_>)Zsq3qo}pHftt8c>>sIKxH+Ta zTmC_9Eu{LrOpX75n!mxWIhJI6-9cxF8^?%iA-`w$>o2P-rg0yM{t>e2eQV49NP3+L}pihL6-4 zV}4KV#jmBbosminl{1S@qum-st;4#k(|O?=GFk&3V0h-Q)YM#RBTghoCn&*Y+MYoU zR6l_US|6iUAE9>aqK5uNE!{`$ok+z~a_r^Qy+iF9LG{Adq;&b%4%oFsTB_nU{03M@ z#68D|Drw>rjC~#6i@PIQeI#BxMr{XULD5=wl-h7BwPPx^cr-Q3iTSPgA)HPh@f9`h zRcgJP+d`R`~0sIpI^I(5z*rNJH+?nmxuO(yPl`kUZ%!~ zKj`}(+Cdws0pq9z;#n*HLEGmAYDX!xDVQ6Wv3b%eH05j9l?XD+@@tDC%^ z^Vkx42ji1v4Tuy6V?`pJu3N@XsZ7_#k@oN$ONkt~?>rOw{Ywgx!B^Nu8_zek7nFIF zYGnZy?`e|WiP|V*C-W=X{;yIS22nkxQ%mM)g+InCmhA+l{sjr7X?)?m}l@q9vp2`zXUHu~CyTwz7|Ce?E zF3s(ZGF&D@p$y_E@yzYwHX>!Y@0HnBjSYuBu+It>l;J_UM<$Q|tqkvz7Rh>vcDrml zV%E{_!R)s?%A$G(1Y}SnaPL7MpzxH0KS@n}nA#pI;o`U2t7s>`L(TN3;t7-Xa;jzX z+$ATLC62j!kvK{ZDIi8BN0#`bG8tUCJ6TZfWop(gYMprK=my$8d#K$XQafZUrT>F= z@(a|mQfkxt=zo2tJsYSAyQ!g)usucWx2TEYp$lcu)*fSc%Z=0&*`vDtK)dvLYUAV7 zWZAa_%b-rlsb++?jaoQ|+Ae*a3PZtuVpWAyk5p=L z4K-BuF*#khbki+RD`!}AjtNq66H15s;IGztS@fc135cv^y6_3q3~{Uh5+3asyy94E z#j%$C#Ppfm2jy6T#j{4eD+M_`tju>G`#i<-D&$P-rRhT@-aCZ(@D)LOMPury(J~8S z#F2Kt!tjE>Q8PzrMgK=lXF&5))H<xYvA1<>e z9XCaF*OkeZ6Yp2F+g@X-ooH$M{I3@eS0tJ+f(e@OTV`EA$1T)q(KzuBq5V8y>VK#$ z|EAXegX;GSHLsi6^&_=bS~UEe%zxXrjHqm-CbUrFPE&pAsVx=MO6kj7(RP`(P2v|? z#9!ziV(AlTUrwzT7axB=?dqjyf1RN49%@AlwLpA%f_*hbSQNus=14lxY|%K;!l{f8 z7p<0Q+9HEAa-5Vif@)QTN#>t&Y_g>E{+YoMp;Vi=i>zm82T1!wEs*R1)Z_$emSb*= zVu!^>GdvgPs86%mWVpX9ZJ}IAaxAq{V9#78Y?(+6JwQ#aqGlYV=F7;ax=1@Xh#Dtj zJ4GsxD;21g3PgyzbCn?)X&<8KgjRg-K-Vy4Fbk^lphn1<*WufvI=XfUPd~r+JQb4s#zCM|J zmC~fOGTDL^%W080RrV$AEZq3FpQvcHV-hCIkSUf)RP`rj=#bSt<{R4nH&YvnseU6_ zpuaS&{~U&g%aAS}M%%WRTI=uvYiY;6E|aj`jR8?o<36cCZLK7f?L?!@=IRoLSID*^ zdmZhR_o%tDg80kW>5@s={#V8)*HaTR(Ej$mJw(lt(cJJF?bM&Cem7BD#jX_16^$3o zzl-T2Wt-6`iQ_mL^viu?u^RJc(NECpvtSCziN@YGVO?E`Av z25Nwxgv;PgmM-jhli@)_sX4im`5`Zl+R;I+PopNw+SVc4i^fh#?@Eo4e2KGZmx$l! ze}s1HVQPwujS?9P@xAu&9E*226U6vZlN+ghzoS-5O+%%kk!1{z{fKINk{b0QwPFYd zW!3GplWVB8kqnO#zglV^Bk2E*-1P) zabSJ#&`!kw(_^exwj~8&v^`EhaePaVOozA-M&wD8Tcsj-w=z6?8Z}4?Zj^Z)`8S4_ zjiOqksg<8o3tyr}#ZyznQTa5;COrQPBfQJ0iE-3Uakbu~X;-^bTV)qeb|dXj$Cx=t zJ4!CNycW<751MgtwpgZVmTcJ)J!>Uj(&`tZUHZGy~R?q=I0sSx{q2HL9LJi`tdUmov%n-b8iXb zv&1D=ic9wUFT>M4sfB;1db3S}lVmCWUr>6}9sc)lXb%f>bzs zDZ?YhlU5(6T_9s9?mX?1MOxASF){`!|H+7s7pS47)Y$i_^%>Mesc5ha&eFFS?jr{d z{*`uyRIqj??Ybyxp&YMCR}7ym`S`VrZpw^09oA)T%-euH=AZq#=YDYD-(4giG zrB=zEESx z7g4P;{X%7srypi`^MllMM_<%SleD%l!dv`7ySU&cKZcjcR;(HQrMs+nCAA=y>L;Gm zc8qraNUFzas#hts3$9n^&(9el2~JXzrNDS8u;I@PZVZ+1AR445@jx^i^;1>Ykk^_~9g`^=5{97gMc>&(Q@&>${Fn4;iaPe_?`F8N)rZX?M%mPM7#feC^MU9i)K-UAb>p!Cw9F=WGsGLcptW`0xRzNAqslp{52dV~R~Z&A~4pt{QJD3Se6{Az|*tfDq8q{jA9Yh}sG zkS1=G6`}t&o?xdJ)A>j_IUQ1v>mo)}O5gPd(T-R{^>GdiiRk5QXzsQt3$ z#mkx(DTA)BpYfTp_N9EGZS=o~VnnoP*Y~u&CsMOy?Mo2{;+4+u3R(N`GkyCR6~0Ri zl6jviO`altqgiG_!c9yUKMIQDTfDzyK&vaYu#W0+E44}1wi2|PZn}Qia^}exiTIY` zov%{c|3;0}2SEDJ2x{F3YQrbgU@w{fwGQ7O%ZLc+>)N+zmx>FH@1WfnM~xLn6eqJF zUe79&kZl@Lvq4vla@yn6Lp<*^8@}=NBS$rzR)%JQb-X`0P4)N*9H#5A@ z(WK(@%Vf38y2yB+^VG5mYRfQcPO}`KQwCLs`1BrGM54rDq)2?YXpyAzmL_iyJ42S; zZ1D#vayP(LTzpmu59~)5pJT}qAD?v(BYX;}rGKS1iEmF_Pdj+1I2!Tkl{e8Y9Lf0D zQM9eHYUW>Jc&)hb#+PaLKA{!;UptxsF;e4*WZKQ*5hMReJLS*R`hC=vdTP)Hs_ell9-=|$-lNJc39rd`(f3J5Kkd;Qw7T4O;MLT&rHUBwkt&EM{ztK*= zgX-ZztrFMUjLPT=HLRoNMTnlK_O+q?b%G!{K!Y5h?>B}QNyaj{Ti5wD!_!-+72>iJ z#AC+3$M6I{YM;37P$$}1a-XA0{7Gew`0N5HAYE#hK93nP#c^cGGz@);;nDTfWbp&- zvR3p-U#H7p^yy$atN4>h+0yy@Gdu_H8nCxOyZG!T@!9pW8D0@b4VHP_A)~lYZYA}$ zGCo2MP%17vVhqEhWZ5qMmUd4hHKD++IhH)>yGkiIQ!;eOf#YQQSee1%zk>x-xN$HQ zN|(gm$ME_PhF1j8?oFV2&7%69qlW)mEBfDC_U%Q|)IHMItum7{ zjZ&emXBnR@cZ@vbiqLxv!#kzP`z5|G2H`lqCF>R@XjRli@!_tOwDV-zcuBfEsZe7N z<2xo%JM$!cJhfM@AL_*6^vhTamw#6j!zJ72f8AawKo+A)amm^J4DT0LTOzJFUtBRB z3T7WWt@%vX(nM{N^acNTHm7GC}Sx@cFCbxXn!lZpj2FM-RrdLW$Y z<_NV=cDqqgw7X^J)caT3EsmBDm+ach@S<>PPC+m~*dC|0*HSCesIlUTi@InBzd=nD zhf^wDP$AQ}S+-(9N13j!h}tPFQ;OEsEgsAh%&~+XWO{NiD{A(uTG9Ur#~4sGl3Er)&5(=7EOEJIa^@b= z*TvmT*M5%bA+EK_pEh1IW3P~H2DK!bnk&<>c^YgS-%_MM=qCA%8X>nx>RV~IFQ6uf zOKlMs+b4@jr<`f7_=~~$$Wrzcqg?_)(rig6Z`xxmVcCVic5|EnhEpo6BU=* zDzl;?f#K2OQd7jCbi<+O6KTFoO%TtT*iO4hcD){RXm|C>{4e~00Rgi8?vbW!mnIDO zfbq#v(Po*y*?(ntjGR$?4DF~}sBwF!1>#Y=XV4KP9%6X24d<_G9RC*vl*)G6V-;*NT4E$4$+VChHd$+##;FSO!^L zsbmy~Q(Q#(*^p;{P)_9 zJwkQC-5*n1r72S-ed{X>Pwt}z$brhv(=L;LM>Kv)yFHtl$5k=M5+}=Jq132erc0MN zrg(lI!BQ<_q)?XCs#7c|O3tuWTzHqXRJ3^1K55aYXPMr5hMN1WR-9evR5nfAe;HBq zIki5QT6nM6k5NmdZ*6idXq8nkaXicE9?W!&f1ox<1w5nzdG9dX!xM_*TWl4QK}K!U zC>G=s&G1;XzwQDLS>^JjBE^!fa~|WdR@u`yiPo0x^z(@2DN?u_nu{f z!jGseGL148(@vbu3Z+h=T|1oW^$E2!iyHYewM_Dr#?uZG*Bv0&hLKGS?|WM2f81vb zD3WPaSx>t{{6MF)1b(J!Kf@-esMkHTGZLwhi>TF-zDruf`$dMg2T{9|sNt0|x>MxZ zFHtt3Ub3ik$)GHi1Ek9Vyx(8}UC&Yb#M3qS(rysX86=nM&5}QEiR5diT65&G*-!R( zL6R{-rdvfF6S_V`Eqjz&QA|yd^o?>yquKuD8QjwSE8|0D`L35cstGb!yJW28_l|brbF4KT%^QQxnCbdi|YtrK|<1qE+@2MgIrP z=IE|=>~5v63S?S(%x3{XvL8selXiMOwd7W6yh)8-NKJj6+AXu9SN43BR~erCEELDL zM7+s>iVvyYyQp=)r^en*EfE(RFY`BDTx_Sf*y2x_&i@%|naqw7@t|4aL7T*bW}TAx zA1fKFeqqL3Ik3+J+J$Mw|+3wcXmvxmwiI01+I-74!%<*FaOUF_c5GjjKw=6y_A2Ym57N5`|wBxQwxVYYaIe`RO zeELr^-Zq{ZEDp+VEA5m|?3!b#Y-d2H^liE{x&L&A_sVqakagZ$`ZT+m@&3uw)Jkfo ztT9Eh#HkDJeWlgY3 z3--!b3YPTUvh%7H^$TXc3_qxLOr=T0>J}#OlWCgRKs!b3W*Pm34qq>W&?bYq zgg)QW2l=V6M{iwTX~(7W&(t9Ce3@5i z`$!8_%IesC5jJWQWduT`G$YN116|w3;fegXYWZ^Q}TV(L$FJOG`Thwl;aDi;+ zqvg7xP7aVP)2{nlrmvbpS6ARP9YldCtS`wuuHW{6^4NOoXE<02TD3ddb`;zhX;sIM! z)pO>^953-({v#Nj{|VJc{8r)x+IjYAkDm^S|7sGyl_!2H>uJeXM{O2Q?<(n{zGrw> z4YiwNJ;##jaEQ{N%~DW&G7}cc($gzTNu&6utR0MR8Y<}|U(hPrwQ_GP<2l-uL#UYs zweu0JxpCU5Qv+Sz_QAAkAJ zlaCC9J}J<4mg$OR3M7U}J~^? zp9F@t${6qZC+!5en(>z1N|X$#Na@OOnWNs1GJS@$fFDkrSESTDpb-q0;B=pU^INl3Mlz z)xVb-B>xI49YZ_LKKSv^g}Z3SI8nW2mL^C!R_UT%aevYMXn*a_`el>e`8n-;af2Ch z;5s?O6schK2TbR>jN1GwwOwX||BbW@rRf{x%p0Xe^2A+s5$ERm28DOWERAaV1iib ziUe_>u7epKDFsJL%hb!IZ;@!6T;BzVrpP9u^8)i%u|;w$>G2H6ZlczTqhO7mT;ASi8XdG-1{eLwXE4?LA3M5@ivL$ZI)@-Z=WUT|0?mk9$w7QD}B`vOFL1T zx>Y=1<#Uow9BoV+?PeL2$#U_Z`d@}e`cb=Nj0E@4F0^8n*ysN&2DI;|TE&xf*V8We z9|@N}OBdH%7sK!Nd{1Twl{L6n{DMs~ z_B_n^>J?NxNX|ZcGH;?Lh->bYY1urQ;Z6EXG0Uo)X?q*u(ud2&ue68}em7A4AEG8y zP)kCo4Kgbt@@ad^U`m%ovr8&cBxA{2S|WQP(}%xKZNEwldRFFt>1GD#SCHtMCJv#7 z!qT?uNNR$N`b2-mhrdm2dXd^G+XFuz+SO;NvHzy_O=dYovMAN%IIfeV#?4ZZ*rm+S zC3eKUwA00NwTo*Gl@qW@!3Cq3E}~KL&!P5ArdB*jO%*?o<0VZQc|RliebvPMLS2TYd@qN@z9<}W0l_0U3NX=K&Xcd?WsAoOo-5(^ zP-~@06Sj&yjaukL4UVGvyh-(&O6~Ne`hQF<-9(LQf#Ud=25dx%lhAcf&sM;Q%hW^>EhA)gE?v= z{>vf@NN#M1_c(awEX*8h%T1_XUVEnFoT4pB>O zRO@rpD%t5o&!!#kO)V5pS6D(j;25=EDirez?Y>>q+)vT|x@I;>&?imSDi`nZk1;-F zFk7JGHrmm0cQHenJW}#!i=Qa)W%^Rt3--LleCZ!hTP55-=RpQ!x>4KZ25_%jUlqtk zB3s5rrZj1-T#w{VVZM0LAknTB4DT(cCd=Yh`bXNezfyDhFY!Z%c)mKv?M=zpzK-!l zvYOSU()O1=ZI(5oa3;?<#W7Z1W4Z)!<&moGP--1Zg$HVb0b#s`YNitYvepkq* zG(oO_^5mA7*NtqMPPw$|y~_M~|DbksQ)5K4zoXrIjvCoYEj@#UPLKY|FBp(0eV(zK zwyS8NOqXJ5I-mO)pB_WCiWY~^4i;@zaWCPTJo8Bg7f6pL%TNiIp;9ajRwnKy+_8a@ z!-R`J%=(SxgvyfSlS?~m88zZx)Na{sRPahS$Kv+~MkL6R;`amXb{QJ+;(%LzVt9;P zn|BPM9U+s@Ybfoi8p$tXJ7^*8C|R6)r_s)^dl3|pA!EF8DI>a7TrsY_TQ||nzmr-a z<@LtWPL^`wN7C+*Ihdzc4)mLcY;~Kzr|l}cj)HmW(XP=t0Fy zuos;22DMh=OD59pN~T5~r1lQuNURsHKKU^VxI7r59f((IL@xxg+Ghd^0xql+<1lg&2%SzNP{$(RUEq3thjFjn^JspA+PAT5;;MY~YOkWI!=p^Wib`ddqp3`Os`vi8=B zzb%mhd!-BdR5GQMvr+Fv() zq4ZJb2egAuQRD8VcFRf=CmAE;y30eltRbA~@+Cf4W=);=@qF1D`-vY9l@%^E=Tl~k z+AIhBmf9(|FM@xh9VC7@S}Ki= z&qs_%{*CHqQcJ`EdjCqhP`0!&lFn5Qkhz8NUQ%$ljG>_A49|~X1**j{b~zkl!C=WK zP0}tkb-l#!U~&90MYR3G9*4Wfbn^v6&>0}|3{8wM1|DU zM`~C!p5gUVsBy!o#UE2c0+Qd;~y<0GWS>-22G@hu6mXm`kE zOZR9dOq4Y>-JN!njCP+Tv|D9R#okWaXC*a$5w*0ES}%^RPdsF?4CdlzW$*3rHzsV7 zH7Q@_u~nvD!5fSZkS+<8E(?|lMoI-E#6woetSOTFu`$vmCGW7DijCCD!8m_C{jypa z;3IvLm_|FMl-eN~T4ejvP|fh}7pa+(s6mpiw2F3~%!(}ecT~D~)I{;9JvXBLbp>3- zrKZa&oFJ|=x190*;u&Mbr8apnJZcC>b?r;EQ{=j>U#6eeUm4z$Pi+v-SSg;dE2n}H z8S^E9xW?AGv^)MpZI|#`DX2vc9#p*e3bi&#(!EYima$SGo-tawDq1SmE9r95#nHrz z2Mj*W0t(WpQF0a1A(uPJM;M;*JheB48hsbFdlsT ziwCsIC2*naz)HSh29LL>vG-7eWYz1DL7OZd(n~yK*E394CYM3=aze@CUoyt%c=Uh7 zD@+)0f*QPz+9{r|K^%?uZw#+*rdDjBy1q(HlrD*Kw18{{8^!ZwiC^)TS(2=05sq&u z`#lRtmIG&Apq(!sFRPw*qhoMRrycwr)$3hq)<|lv#J9-wD{WwSkvOtEab$^bWcKwx zbrTb~&ZAaJ!bF)ip?eq}FPJXwl(vOGES+NYQ0qdcI*U6=T9w^bonxki)0h({};wbNCkT2#Hz9x zUZ(w@u0V#PhT^g6r0G568oN-gx9V36y z^5&}{1%sGx2>M+SKW2cyes}3I>{5R3@=@=1cKFIJvai6gA2goj2A|cHV2#DW!DetATn3hLc&|A~0$ageP!0}*li)nK z3fu$HRbUI)0Zs$YAQTM3z#Omu>;nhDDbNNkfXl$5vfna?o^#_;0Rj>dn&oZzY ztOuJx8@K>2gOFgf1(*+(f+VmN>;!wkVQ>tb1ZTj6i5Qk(BiI4|4$7ru5QKp_ zU>R6F2?scU4@W>7uuR6mz*3L|c7k$n44eVyRo!9puaOI;p>e=AunX)12Y`uv!c4Ff zB!M)r7aRj;zECpM^UT_ke0awA| zNc|39ueZ(N0T=Oc!7Q8%SPwRXBj7kV1=_%66@#Q|&D&;R)SfwLAaEL-0~diy6dDLD z1FOL{unX)12fz_<0hn_!FjdRj<~olt(WoWZs$y!)@g7I-LX(5jD!0bGB{cAE6asdE zeV`3o0G9bE0E_`4U?$iKcB+ONb6nJx7<3@m15SX`;2gLJT<$>~K^Ry7mVwRSIJf{T z_o6rzbi^DUdkh~>f-_*$0<<@n2IhgqU=7#-_JIB11ULsS0+(1E284k*V1X(+Vor@b zwh+aEOW-PSUxcE;Jg^w70BgV&umkJ?N5KhjTG?uG8#Hh+8W(H^+rTcc4_pA3fh7(n z0Oo_GAPJ;_O<*h73(kW};3}B61cwGIz#6a-Yyl^L%Y8Tt5D3D+g8MMdR^!8Zuo-Lv zyTAc(8CaI$;9x080%>3q*b4T7li&p5sU>`UDEXy%8!7#8C zB!M)r37i4v!KEDhxeDALL?ystun}wld%%8h2wVXpR-oCy9IzU!2b;kzun!yn$H4_K zCJ|>1(!f@*6YK@$;4nA|&V!sw_~ZT%4h|-OX4um)@dTfh#m z9~=Tl!3l601g=D-zyh!g>;n715pW8$feT>RDpUxBfURKXsvI;6K9qwq;5@hl+*hL# zU;>y1=7AMp3)llLf-Ar?1qTJoz-q7=Yy-Q%K5zgW0mnfbxBxB#%OhwZ5R!vGGr@eY z73>6i!O%xh0Wbkf1M|QNum)@dTfhl$4!EpA*MKlE2P^=q!FsS6Yy$_t5pW8$fy=;> zivBn8XDLVmXeh696*;1D`5+B!0$ageP!6sF_b1Q>U=&ybHi8{s zKR5)gJb^}Y*@%OJ5nvfu4c3E`nW#H(e-e!b_JIB15I71>gLB{_xB^^$hjKs|m;)Ao zWndpT4o-m!VAv*99?S&uH;u!P!G|=k32X&B!5QG5h1!ErV1g?A8#Zzq@o@{-0rr6X z;3zl&PJn%`2baKA;Jz7$2h%oN zR$Aua!wRqlYy?}t4saTb$i~4z7?=Z=f%RZB*ar>(%QNUbFdr-hX zf-~SexCGquP(D};R)CG*1UQ|CGrEWmE`LP9U<3#RbHDFb^ySE5I7CF&=+*fIVP8I0TLYmwZ$R1cETI9&85N zz%FnA90A9{DbNOHZbxr}rQ55bp0w^hZsuF3sO`t`qSBS>?c;c}_bT-RM8!0ih8opi z2H{Q7__P$CtdFQ?8q7&flS9;-4R|MKXw44|<{d89N$Td0k#VxROG}t~QcHw-i3`H zeA+)ps-vHq{y4#JK1VsL)eT=DIz`RW@`&2-1u7L9qF&Kvs5<)vZYfPtzNb-v$!ZA% zFKyO`JZ(m!MrTi(i%_H6Tg=HSzXjoIT2OR^+TMbqlhxY@M}z*NT<*()*SD|3p|>JYV7o1yCEuaIMs`dnL+mD?GdN9q|IY|a_< zM!0(H48o_Vmk^F~|MU#1I!(E?LL$^GEy?Q1RwP-eUenep^_`a0%J(c@PMMjWs!qv@RL#C*^zD5Nj)P}FkzaY=xHUvJRX0@5Ot37R| zsW!Hu;X~DnZRTgzh?>XR&3mnSBz=Ro$F8aw`>pv;D{A4}fo96;K+TtR*n8lq4tt@m zXh~L|YgwuOt7VnC{X0}^wR-3~94SRT2TS#RhpZ>RGbcDDhp2ylXHGRkEf!x(fEOkj zZno#m$n4F&S#H^JMKOCYDc(eUciI}hUG$B($LPDla zn|i%MTa`zrIehun>(OD8k#VdPy~a%!eOKzHxoMdxOV_R2xW;jax%z7e*NSI4d+}kD z2b}MoL26c~>Fc{^kS<5!Cs{0xs$X?i8#>L~e6P9>h@X5tzT86{)bZsW1LDK3*Kg?! z>ZeX~tnbnr2E>P7k9RTD?LU}fouJSCVBYL>*ieuCVBY3;*cgx=&Ecp|l8JET8H;yj z*8N}_zINMD?`hZ5x!crtD96{`HlUmci{(~nw?j5{>yPHGe)@LhwewEKON1qU{f+uK zqZT`jQy~x9Jbbk2ILylH)xUhBdih6lY|iC@@vE*MCe2gli%m{ld;g?|?^?GZ{m!&? zPo%8A)-8;eW?!wli^H(Zo^Mln+NyPHA4z@mT6%^{`V@<0BGWrtHVsktT)Ptq%{?d1l_1vLQ7&O~2GO zWrH5J7#-Kg71P)&GWe%o?LnvUD;-nL9weO_hKf1n)X)+3s;8ws zu`y-C+DF!HSe2HVvUa0=&SHpMI~3DN^%3D1TRTRmDL38k z<|N;?G5Rp0HLaq6L;P2Ytx#|ONpzT?kSi{)}_iHz}{38`{P(u;)!s|HV1^&YLhG9(B51x@lOjns^bfvV}f(5$C=$ z*j`6JeRuL&dFXFP9m~s)gOCd^sB5QBwGTap^ftJ=1Oa`gx)euf?N+j)8SX zhpR1FPQ%ryZqwb@ZcB~BF#sJkIvt_@(GBNy8V!4`9Ms-XkNMNp#9vU4`O^o)V*okw zADgZo`UOt(*uZ$4r6d2L8M+=;!!~5F{UfU|by`Zzd%u`9H(*JAvJV@UN7UPW<}9aa zA?jCchSp5^w>iiai{Y%_u;hoSr+%|9h6lAwQQv8qT68mh**mRhiETzvqs=JVgNIWl z7k!MdmCDVEZ{(~}v#faI<7&0mieCeysF!shHgQ%PH*rpg3{|t75IRXc2}`v)*$j2a z$rgkoo^?W|a5dN&GDXdGM&hYzgO+LPWi42E5vL+tkjK*nc~+|FE=aset#v_>tJN!7 zQq(s(@DX*Bt8JoFc!-+oYCr4-SNmaKb4BE2^^KM=b(0(7!qr?iSX0!K+M23faYM>! z>KkoEsKJ8}m#pRvg0)g@(6UOstYx+Oe2{It3UWt%+}&;d$a=fGZ9KBx4^fo}x9(EO z?zSOnpS#V5LJsQamFlcJPCe2C*@k-HG*+uw9ymsd+VKDNbtQ0BRa^g@d(XKz-Gdhd z6a~Rq9Acgn6=zgZ9LNDtMg>6vwbYjyW~JtY)52M-oJtL|NMCB0np#%)zMM*X^h(Q8 z!^+B+zVE;Gz600a_r3f3>H43w{(J4U*B;J3!@V@L#+!0NX@5g&KP2j2L!>sGx;Mg6 z1eG+xQ6%l>qbR!92mypso5nbbrQF8WXx{K_Z43?)-Wb(nk)??UG8%$5G(l}oH$iQ= zw6Tfok58MR)-WW{I&n!x69Jzx&)0dppe?*V-ltzeN&Cs^dreHOVC($gAE4P(lKnG)sV!Na~dUeiW5J&=uCd1wC1N0e#DiSTcISG=~+#dcjo&&Fuvr zKd|C`R%FpFR*dTnMc3X?tkQ#rHux7_)tl(?~i9 zL2-#N|JBEufDVXHv<{-PtXP%^MJ%0z0!i@dEBat0i%eS0B8x7t$R@9T5IHmw0)L2| zEAMCRY03l{<@blP2s+pw1(1FgQ4~G^GX+x|g8m!;^2q_#DAfF5 z0L*a|Kae9D$Po>MlT11X1uFL%1pS6V&}R<&}aY;~gO@bnt#wT(5Sh1NEXgm}M!8F9$gXRo@e((^iteG?y3WV@3 z>pKsH{;wh6=TOK{@N+41s5PE055*wZJrsOghz=F&h3_!%mk$F!ZJ0HT&N3EM%4=FmL|nll{ap2N`t zSg+;|N0J(jfaa6oq6Zp{5Irz*1PVmbY8Fv+VFbn^Do=rkq4*SJVNVLmJePu2#nE0? zv=|A+Pprr!|B+BEVMW?VD6(lOEB<7~C#=Y&2O}{Jrj9}edX9o3jPgf;ab*-3Z?YnS zuCgL&G!(5yLlH$oMniF!70Xx=Lq}NAc?=YPu_BH_#z3)w6$N9U$fS)>@GxY7TLG!a zMGg&wpu?%`C)L`;91|K!M^Zt+s-24Ij+OZ-2;2@}5lIVKMA5;gL<(-Oh#~*6a1~pX zI@Y>LM`G?x#9;htPP`E zldOGBaiP?GGRrV3nT(?0w0|;4;dFpvqkM*IS`TbWDb;3v?51L$qRghb4V^kERAFlN2_y1ou_jVOWYLH*Bbbygt1dG4!TZ7mxa;zsVH`KDvE7pMFgFL0u`I`&}(z@pdXwEchNK# z3e^2>9?Y?HhmSA<@^O?wnJm!#`A}xjMLxd14}uN#B4aWS7b7o&pD7o$&b;#`cW!9l+^hQ3) zrt2(nsLgVe$))_|a-8j74!>b^XE`bhr;rukM9}mVqQ(1Hpp8*(_~7P;iR4td78CUqSSF{;;r8cv_CLnlO#X+5$YN#PK*VLhrYSdT#v zO&ix^6gDI%zG6izH6j#?qrQX$>|y=$gtPHAMu&h<`E@oWl|#|097S?yNI8n+(!z4< zKtA1^E4L1%aT{O{+JOEFr|}y^+P7{%*Wi8}izw>8Q4F;C8xd>_9b*wok2WI8IO@Jh zv^jqh{ASROO;Co>g-z(EaC)>!v?qKsD3LUs1roR!l!&UUo2@5QY^STXZnfT3d6Tx? z`X8P0uHmlj=AHQVA~^5vvih0Sn5s|rShMsvTpKyA(llIL_EdV-yV~T7*c@E5$eR?> zZoi1lru+jUob?B|W;)FxitZn5Icw&#K*rtd%CTXMC0QZzeS2;$iC>W;L^F z;ZdunNzJNSecbw#8D4LlKv1#d`yo1Y-iPRcu^(F7BcS;oqT8>r;yqTN524_d;v_1> ziQ*)VaLsiRTl-wx4nK)4Z3OwAvTj3&@1C+g%YAYhotRNoa@zVgm9CtDt3N)n)}rpK zXRN=gYIfCybJi|R=$&0wPik_>8UP0&mk>=PrLu^kg_kg0qv_L2=>8b;y^M(FT!xzw zm&F1;_cHQ=tB=cwD3fknMj7mEu81)EUV$wKcYhH=E*-go)f;E@dsi@_CSHY$*sEw1 z7PPBiN6?C^U`NskKEg%FRgvhBFQJT~bQZC+nnfI){t_YM-hks;z7vIgWo=2#zp`3s z+*fcM`jr^*Hb&N5E^@p7xZhG23XLqp{8(JeN9Ah;u=_ybf1+N z?bmS>O_?lWXgv$;sjj2*8Hrte>e=_#Lj( z{)d9U!*$x^?-1SwC}{R~)*wE|Zu|~K!|3#Pa1>7WSwv8W8zO-5H$?Vdx&b9RlSK^O zfS{zCa1nGQk_^SX8i=?bIOcSM@c-9dE;cTrt~yI7%d8F3d&NEFS# z3sy88xeHbd-Mfq0VyVr~Xz!ArxgkHJAsMvvXP7hT1dA+s05hr$sYB5m%B{l@I;jq} zSo*XMZgGWuPb8@CJsf4y!h53Jk$WhRP51A?`?z1=J@gl3GndByf{izxd#v~cg~I3r z3-rq`@Eb=Re#H?koqoj;0{Inf#1jTS!n3Mh;WwKCe**=V5x>C}M)QAzGMwJ!qX_!u zH!yKi;64Oy3fu=1R}6fFn*#Si!ReYs96h>^av2o;J8YSh`#Y3bw3?4{s!sfFovUH! zRQ3AHy3K-0uA7WqsN^NH!DHuLv%xd>8$OC6FU{b!YKUg=;GM6*mO*chPw2%e%e7X^C3J;|ld>BT)7NbiOEVy3wJ8hp+u*JY|wis4aIo$$Bk+`oR zs=Np;sx*1vD4W7PV2dhC^k3h=Xr;bM0S%1dO%|EuTh+~L=Gtg`E5nagHZTTgr}1z=kNm5kzQ?N zq-bN=Fd`6MJR8I5dkv+R*7R&+BUxMA`guWaO*b1Gt9KhG1>H|+B!_1|g4>p3Re^XbNWt z?u{JA-kk@7x6zrt@HR$i?{VB{P-`063^D#;53M~NZe|S9%GoI*ZBLzjj0swE&Y`2; z!P-o%hqDKkv}&_y&w1*W3^7)4$;vOesJG_hk+wYR;utrmO2H?5;4@e zxsj+%Wmj;JMEjZ>y|q8=hl{mN+ypexkJhw6_nxsg(2xGzf<1Fe`un5GKRANzjK1e| ziq7(CiLAY6A3eS_y`}M#+1_wpy57=A)y8sp!F{q7hTs`)DaPw$EtWe`3ou4&i`gB9 zWq~%Bd+d_{<9Y25)?o;yY0WuMgg03`!#bb<3TurVo?*|T&1+kupDuIUjvQ+AM{6Up zS+kzl*5EU>x1yLJ7jx|>lBP}NnzjcS-5cjBedGE?g(c#T=91bFJ@P2X@X|W5H`q~E zFs91)e2D&%daeL zBaV*>CvW00thY{qVTNzOaYTiej>N~LiyJHBJYf2qsS0L;F6j*|*E zyV=b3Y>IM;ZK6`ui)<0XSF)dir?2wk?yG;^TG+-pZS`|~>-25d!YS?$l4 zk8-V>t$vh>a*z_EFj;2N#3-Xh+aTM*NF>qTLQQdx`Xp?rR1<{>?@yKB_YMtf6^-|? zoc#I?m@%_IY}n3;4?MYL_Zirpq{L{$$6T0ml7gcV#BEA|(Btt;@guIr$0Nw5#w*G{ zWS##*Wzj|p=zMzM*QO-FqNF+w{B#0rBe{o3jS<}Q&;<%^TZ{4|4nF6T2tJx}>$F7n zm7o`-Aes+NexHhC41bg5DlLyeV6n6ZLZ6w4A8aKx*6^8NwnZUJPvDgo{&{&syZi9Hz7|bW9&3!n$@RXvI zP<5Q)gB9qvvG{_7vsv}~x?O0W@rp7{Gz$^GfrE|zPs9Tz@a&Zl=K;5N@B zZ2xjr<{t61iTo5aTnCLfdV7hp@Q4l@QfA$h0 zj`RP;HhR+kU+zoTMho}BPfW&(k^g5D;fhBF&J`kDbCAuS>f((S0D~Ri8OrE^!CA?I z4L=Fc)@*06L2nXdEa$%Yv{HdloVx> z+6&3NnDhxqtL%X_blWxbP||+K*Z7^b5Vvu*4z_-x&V0zwwKiqUCM+{^dF$HFh}?&6)|@YZ^W3ZTPCqDXfptGWaX}+5x_nAU;jp#?hh4 zNhVe4L@9lc&tkwNd+?6Dav7*BN2mgx)B-xn;wQQSq5suH#rN^5Q5FVUA~X?(s`yCF zU`k?5E;Qq)?z)+G$5G00Duq@xXbX!}It&p&_biC#yKb)aeur;8RL55#KIp8RJ);u3OBmEdq z--Y}7eh)T3Q7@J}oZbdti)2xn210AE$P=^F4n?FL1xX9Bbq}QUenyLU3;(RUD@6WV zuJXg-4EryhvK*fB9iB@6i>Jl^#nU#2r=1Q@NB@hblmErjmkv+gNKdUTf4X^^QLh8A z<7q8YU_uIO2N?clOQ1s$#flalIsJO#+Q5%024i%N5<2Wa$Ft6!B+tiAg2lp9s%^F# z$9;>j5;j-D-8*!>TRG=iD<61I!&LO*tdbpcxJZN=yDuK3)8wj(WJ`AIy6VWdPE~ov9 zV)2tLQym4BoOTQX3iRdU&cytmaBgYYG(2#*sAQ!_f+avI71mZqJFlE7PzHm6pY=SPTez8 z3Y#-+ZkfrM-XNv^G;nW(KWv3&>GbhNygYh=sw{I>=-vwNF{*Qe>)wjdCB5BkZe1}A zHpjK6r&7Nw6y=3f*SQ||sBj_ru&>c@L4Hm-3=#G~n!2TIX7b0d9kE}3HdUSpx6?4t zN@lz`*_E-TN?NMRmRIyPY>t5qTcXQ0CF2lmSM4Y8ruYGskuGEZoE2HBvc|4xs?o7KfsIEmu{}JIf{4n=M5%YhdI1iTr7*lsI}B0nSKU&?jG2w%J2% zs-!x`9E?RlUr$q&Q?eWix-Y4(6{vVwKz6J1^H11zI&J)|Q29|2^h<@lu@CUW0L_BQ-cPxeDT*!qXTNq$XqG7}~u*4jdQ3HpP9p8xNafTGhI(95;7o%vuam8#~DhYpcsa_N=|I{ljT{x?bN+pE<7t3xPeAUP?jz zPFEslsmf=%Ea>&v5^4UMssuZ1k1vt!o>!Ft&I;=RPY8+_HzC{7Zn*hr))V(+i45;=nOHR@~23Axl)nkvDIJ z&sFlnr>eQI-LxNji|pKB2;p{?PXYCBG^_@@JL*m9i;>aee(u* zq0$k!{;UFQW+!_;c2)Z^m2sg=*a}LX*Os8UIzC_DeRMH+U@YNR8c|Gd$*yUIgs%2(tddQ-PT8u`4rLVch zps$iMx_&HIDFqZYm}1;%%+q98eb(VmP=I4%w)O-Vfyn8dNA7X z54ifKs(9L)=h)-3e^&iKVPjCD0VT6&PI(Xk{r0;StQLCj;>Zd<5v&wE8PKS@tv_$7WkCm4R*g z{T1b-Eo@L#HmMYY-OGw^*7@v|<8o4*K0tl^*tK?YQME9bZfuNnvTY zA=v|Wgp$)x`~>Ae1Pr;ODhbTNr{!a}AYY~mW^SRQ5V}n>DNj*dToZ5lInB@lrdmwS z+q5m+MsMEqIb@rN`#L@zCS{G`aNa`#{Lk}ww~q;fw=NyMbrH~>4#ZI8I7dKdwq2r9 zcv3IZ76{XCK6GRvI?c=1qy&&HUG&rwRL7K|WKBnyRWLQBQux(B0<=-_1dNo+lmVj} zPxF|gwlMK%O2;&@H3YWrEKxcCB8&WRKwebCrCQQ$7R#yOBxLMA{`I4ErU23A%~U86 z6tx#kgwVGHn3NAiH5S|CKogb|uF_5l3HY< z)Qa&YU_L+Qp~LP*P3u{5RrWb=qKR~zz6}=7F5f;9_zR>1#d85Hwk9} z21_3N=YjVTH1@=u0lX}E+t-_vblD4!$fTT=MLwcyTqI+=Ntr8oUjoXusrxA`AI4id zOiCYV40+Y0d?Dd~0Q*WOiB!S7Nw1lda%ub>@FNM2y>3#lx!^%nPPS>_9oxkdPqbs( zZYO+xk0T4}8Y*SpioGUmd<5?=z}YhRnQ!v^68?&*4m?#OYXMh($eHZpfHK)QcV)0K z6PF=!*yxK7I|uSfz|PXwZK?rJ4W`>nU;lTLQbuZy*_(n24NdQOoCi-vAsVrX5(_~* zKocSKw_wN=2HooeUY7(Xlq%Uc@T5s8kj8_6%_wm?M&D_`SP35i?iNtpNeR<&LOXB@ z3%E{q3JqWV_&GjFa2Y(bFN4+e@Eq-*juT@DoyDPk{bL@y=b6xn)FMQ+i~=C^wdZ*R z1Q)@uj*8jvniOwKaY6{a2DCIu>qfOqOQDBce$JDHx440f6RLvYey2hMpyazByavIc_a1v*_+MB|P!5K)&5c)P4CQ8m88Sq;|i8E2wgC;`gO@8DPE*tb_fPs<|PL<5*Mdz6_;67)nW+phx01E}Q{0X>G zr8_e*8rJ;5!&Wdp1I(8&?oVD&S*z}$vRUx-1vGxr_!D4j2^&A)iUqGTsn38n37Rg_ zxD;@>gjWC?O5QhA%)D0r=BXg+-3OR0q3tgR#8$T!JoTm!`Z)YiU0=y50`!r-7E#Kx z;OwA62>sgzW-MeCbI{m2Kvh7TvZ|RAPS=?8Wn(ke)!Jt{X;!mxff6rx;LFj^8k%~8 z!e)cv(bSBGgM#sd&5Y$sz&&1OOmv3oXH>zwR3EeQi!>(rnUy+9nT=CL3$v0WX)lm% z4rr}#xp-XCzHDVyGGu%`1I&E6flzrgfrqc{8$o!tPN;qnD*X{iK2qaN*12%DueDiO zMWu5QeL|2~nIRx{>=`hsztTMBv<)_6=@6V30sBbKDXL*(Ei_G}<~B9_8&-zBZOqCS z8g-wGfxmzfp;F(ciEO$0gjpHtAuM|P7)}a1#RXa=tooDC7_yo)z}^yW0?d~@or0eO zuRPX_X(7Vd259G92TYQ@j#S3H=y)^EUV?WPFoJB{%D?a~-VF+#hkCyubsmCKC;&q5 z+K+R?bW0-OO@;Q)Lkl`lF_V_kauywF4}_%^-bxI#6XL0sEd%Hwgq}6btYGbGW5L^L z^RXWLjxZ~|NS%-BMpMdsF#3)(D`$j8Z#2rRr`RX60*2>Co7lnl3<%N3uDM)$HjERWR{_6kpL5=6|1S z#>P|F?~v_z*ymF>7OSM#A;lpog;H;xZ^mlKY<)PObZnUj7@<=4QbebUf3A@sF) zl^YfSj;R0hrm{AIES7F7aFsyom0-jm|`T%y4yacKNPu)kinSLF&!z-wc z=?kWtm9+w5NGC3YF&{T+u~lbdF<=u3=K&6vyiceSJT-{UGrdbOj|M?M256<4g~$-z z|9AmLZ3g!}8?l8M$C`qfW^Ab|Ux4OCDuV{e+y`M9GY2s#l>UO@Yq<}+R$>egbrE0s z%%#9ZIPoo^I2`Kf&zqGU6uby-6e?!Tl!a#O+E}B{2E?^7!%i=70D_l5wcuf?f5@U2 zwRjPwQWx{;qrM0~Pf-eMUWF!5Xe`x$Q%w~3A{O7yub8p36vS+*W}^RUZfz}!>Ky@3 zO86sSIwdZ}0<*@f9FWRC0Ow2i%vy{$2^+67D-$Hl1)L}0zl64C2^_39EB&Q%A>b+j zEnZ|++UxX)gNoT~Rzj%sbsnNGVTfjI;ns+dG6AQ_66XQOm}QAJ6(}tkg8-M-D_paK zXOt-H`Kkk2k^x`A`x>YYSCMruqv7{=^Q0HV&U?&wABdqP67ZJ>vX+hq%}S(XOaLsC z@F&1=5)OEq=ZbJK6!5ew43q60y0aK3=}zyMabrSIMg#ujqUe39%(#*frWXMN1hnh` zY-y1J96f4Q?g}+_0+mY;^rPcu?07|)k3KMCZzJH3fUW9z_BdfyPDs;Pz=jfD01On+ z@-twA#xfm$P}x$9%%V?e|55~;{~0I0aw&2#4RBmf>h%hec9PUrz_K)F*+pmkNS@>LXb_Z$76Owa@D%kihXmHuhzEL4*}Ow%5uQ6b{fC*$h^O(j{Pld@8s+Eo-Hx6<1 zp8g6T-oE1+PXLORHrHIrC%S03C>HiqK-of5UKikLA5EY^3oWK)lho2G!xk5EyZDmW8QhZ+gUzCiE5&gP<=3 z#QB%GKU2yYIBMHR!#1+EPwQ#=`noO!#2cyzY!}&r$8(&fTpfR!iyJo8W67B}3@Tmf`yXq79bQ%QdB~SvK|us$gqgnTF>T!h`2(UQroZHUM^PAc-H4 zZ8M1NHt`S^sVLd3DcfWj+ZIjvKtQ#IN||?ZE3ZGo%N4+CU3k$q;vtqF*|s2kl~e~J zzlgX6{GVWGB@B9l*LgHBNACnUMbcN&Jmz`qa`M^&Zj#1hRKrH|Zcd3P*$A+QgaZIu zN;nxXP{R3u{t}i0#z|NMm@i?EJ(@C5!cssV0oC=CunjeBfd)fs8`|+Y1w(_OEDS%u zFhv;j5qmXUdJ4`VD&tb$LSvQ2IzTT9-i|Dr-_Vq?Dt)>Q`=beO@|wkJQ}LS=xE&|Y zB~t1YFd4#xv0Ju2C1}vJ1Y9} zfQHSADC6-KuXF;&0}haI0icJ3F9G%tP_3rw3OM}=nm}oM02m~peJdIu7CgDQ5QHND@ZV>_^rt*0wEv}`)6DIXeieFuU~|3t(67D4_y zb$b;7T>MPKH#%6O{{dJfjR&ZdjYbX6TwyE(oGsyZfWsw>yx=UI3YagnmJa}ZR9WK} z|8Ov{ux7jlry2j_(C9A!ekMJQ{KBc72`D}3*IioWqC;!R2Sob0MYu*td>u|NUDA{= z>8ZhGCyWCOmD)VOy%Ks~al)f6IOQr{!W0DbP4G?(#0Ns?5npm=h$IvMj+C5ZRK^@U z=!MXOzH-)?B4FKXxWTLL0^_U@dedt>hJ}}zfYKqBlwxr7FQI8AjF#U4{p`6jzUEV~ zDAUCS2fJX7fLxajG{~M3+}+&`r~jZEv976@U!{ z#B9iT1Ct{gU*-qNayC*|%(&cs17qkDs)0%US_u7Kl#Y9CqImac9lHYo#{qgvSOAE{ z5&lgxqAC4Ncv}lqok@7pUyRcgWPq!06tCkVT0mbwT&Afl>>&vAD$)lf+&0g7l@FM|R2xv;~M=O{(+NCPAt7bY?`f@<5f?ReNAl5EG%PGLO zu^{e8n6n3Pn~D!0%r#Va0Ac<_OCa`ganM&8+LYt=z)0I~x!${U~=^$K80K}34 zZ@75MIEbizho)E>r#`9U{3eW_(QOzpA!}INlt*>qNdFILGpOz$l3X%e3|ZrCR5)vd zj=S!x)^`E6mGB(kVFA?_sPb)8=rdBsX;ARG0D4K70EnlpT>44CRq1bzfV7#2#g zRSJA-gxMFRxF-efl)eWgZmX~uC08bwT2z^1AJD(BY=AZv}BFfl}1>+ z4&&;haDuLMmKbZ?#3P8coGMvtkVl)uk-j-i$7l_HALk`u-6pLS(z*jy56U=#eBn{T z-!Tl1xiqJw=Bi7BH%Y*;+=s@Z(flJ=ME@f7eN?Jb%2AYVm7(JnityK7YI?dfcofZ? zG?ykvYMz6}5T*2`fFDRWB-0U_o&wl{s*j-&VaMR26vx9Q>vI?D5?}*a`PWp?Ygp&cKKWq&J?_Fr@zK%)FDQMbCU*Aj3U1&N|=|_mF?l^o0 z;EyzRl#KpTGZY$ondwq93mQBylEDwo>m(!3`%$6cChQuD3Q)SN+0iPb36Fvsb) ztJFk5WA~dPHDg_xXQXDHOM?fR>}Q8dgR2kLd<2a>;#*Qv=i+!$*$HrbbDecXN=*-! zW}MVahNh=%=VqyS6`Hmbb{uUGUe3G9{3tc|T$-j-`yp!bo8qh~N@{vS(?R&vGXV{% zL;5wKSXtR_Njm_I>^{8;(B93T0@}M7tIkPO&~B=e*A>t{2;%_e3duw9f#_O7yiZ?Iu9n#XpPSYCb{} zPT;t!^mxa``VG)NZ5~Qq<7rM_44_Pv@Ze&WrNCKhIG_iqCy@jod)5;H?O7iVC&tm#BxyF(w`6(&oW*49M7&k#>)FOg?$3cBT9xaC9I+R zPvGUfwK|^vrhI}026tuIVp~VYV4UoBc1G0UJbQF{$a1$Lnj}6M4jXLf^mO_n_zV%Z$zP?Gv z%b-luKiaJ0O%h?;Oc^lZ`RY98jNHzvG8^>#3bET|2Mef%IXmb!bN0ZHPIWMtJa*8X zPZ5K$L&pVYWib$$lJpfK#8BD zw!S;5*XO7$399#`3OBIRpeI^wQn0mar&yfT3t3BG-Qmb11W&GOB)b^Ju zuMp4mDprL(T|7sbetwP~b@7Z=HHzx$c>ph&e%IA=xUmf1jOc^+#J}&2w+a;+*v)gi zWgT8rwqMNujhq2-$vegE&zz0a8O{r!Hg*MI8ceb4!P&benl=bpPf{!Oj?D_Sk6 zS>nYo%Nmtp@fT>_z4S-s75g{a_+K@4N%Kl*NJ#l|l?L=MXz$qd{n0~bBRg&weXd%; zjGh%@ivSy-ymnoiLpqL0grC(wS1`j?xt+!$P%<)AlHyZxECY8aJ&S{ zv*)kGwOY#2GGsaO98!i;wnW+^U6DS>BSRx(^DRE#E#{3=FB$L{h z*g*1f=L_@7Z{c@Fl%86nUf91!jLFZc7s%{r`h$($70J11OQE(E zYW>1-AH*N{v!AJ9A}PGktqCEjw`91sV`i6sQvho}sZ4CFU8@y<&jL zGhwxe!L0Vlf79)TVP3c>$sTB`_-do6Dsu;#W;gv0sec{(Ys)nbo!SIUs_Mi`{XwQ~ zSoYnT)F>G~$W#eU!)oqod3um(c{BKNRn$eXV71hJ+$mDDx)((~6p=5;^5Tk(D17x% z#LDq|O{<$Rl^u+KI{uZV)!88kk6lRn%)fXtp;d_qK!li;jqmMKFi3Y z9pOoG>@O283+6Z>vSLSg8A^qlM3rDVHy zS=pvWOtUq_OgU7rl4F2HxLPG+CHYAwJn~l(b1EzuYNAbT zi5Y6%x2XyBlHc%)Sg=}CXsj7>t)4^5hM58rDf@?++9p;m4>RpdWl0~7D^&&!$JHjV zdbsIg>_^uHejZ^O7$4m@^d6};%5;wZKUEA8V?ZPXedLn&(1HhD@4d>Y28I)ssv^ zW8RQclTEG}D1E1xHs%9atmr1ErkE$p0vVJ;cUT~^bIc?=`);|OW9pcNrM_48Pc?s=*0SdT&e2D%Jz$R5KZI+)oPUUdswZg=n>D7i9DkVf zmliX_++$|Tpc$r@y|9dIn?d+9a&`tOJ`?cGG^LGgjg)ean7VezNa^^9X>Eqc>_^D# zM)BpEF?Pf#nVd_(x0H3criU3Jzvr43=21!ao2{mcocD8@E)p}#JZt*Nx>=-Tu6#Dj zj4@wIhes)%ALYYGIoXf$`=h3t7Ek-fNWxZ`^qA>D@dO?-Y2iPO)h59xl7Ey@#K|); z<|iqeN6PESq&!mYM9aH*1k0CedFDZ9>o_B;3QUU3n{6Up*UJ0P3eW^3TU3RBWHRRYIXn%>4anPkg< z{~Iw#@(O5~zsU0il<_a}VF4vU9+Ov761}C{YWjU|8MoT}PA(@D(2}RUfc?{w|AJez zpT0oRE=sYzqHT3NGFi^O;|r1cYfPkBB(2t%UIct*jY%^B*|Wwp3y$}v>D-0=TZitG z61A3^|0OVJt-0Go^mb!3RtuR_njU;?9Yy)Hq^>tjh%{Rf2rOGq&HGyWtkCjOZ3BaK z`Hdmk{eF=8vm#1xRytm)uMPSn8MpD~7}{DkZ)C{H#J|Qy`8VCp2#%qxCFUgt&MXwe zq}fZw0!&x`w)l^c)f}dd+2~D3r4K2)J?b18|vTglP-~Vx)hwC*Ce+KiIfFTmW-5w zZRTwXzVydow3F?oj4y{j<{OClxI}_44Cg>ee6?7JL9Y@b9RHy*ySV=W{DqZl zh`C=b7gwb1AV3KMOp?Akibb>-|Im{7|I|s|+F>f$@XH;hobzj^;Nl?qHPhf`4m!U^ zG?AD`$)wlFca-G6X5yT(o&RsfH`F)^<9brN`f_J^FJLN1TrP}G@?STxQKKeXme!RHo$DoLCplU#=^lFRfW@`41vL7Tn0%S6YVE~aC0^mJW}BZJgmkvB|u;)})dF>d&<(b)v8O!T^O9Dl>aMQF;jC^yLdH)&&qLCtQ0-bT=~U8UA;Q$6NvFsRyNZf%t8-6k%6 zW3ki}ma3*?qvY>4oo_~Wp6DWDiLOaEF9nkQNo1^4*<)hj3%zvks!BnOMYQPqO1C|x zTi6S+T5yi6-b2eQLlo2H&>q%E(bN2z{I;8o0kcHNa9EMbFCLzNwQ9b zHM$w+Ed0a%#y*viTCaS9m7pmuoHOcE2^ZW`8mpwNPAeHFWsaKi_LYuO_o!)X|KqZP z_>VGyM9A|;DeFpd=qQtKYQP*bNp{#_qT5~1Cld~oEGsQfFf+KW)!q{Ly~0xH_pvDx z_5rq^U|Z}u?67S9nDie(6D_AczB%R|ma-@D{}BK3((0s1@|CYo@kz|!unJP|nUXQm zaxm3daFR7fzGReq`O=HB$S`z@=6~T+vi^L~ zUo#Z$#^yV1YR5Ea;F+tpj-j07v>RjgXE0 z$ta3OV}DkQC_yIv9TsAqm0rE=1fRzKtX^csNx^4agdY6F^jq>d2Q^8yRGeBOQj$Ms z>)`$jdFxYCOZwr6`nFiSK50eLWWnc5*U!r0&rOwxe}d|AGU-!_Z)r+Mv`icvQil}A zd_fA2k;3lM?2BTpX}bC!$3I(E7xzD}{wMIyk%%)yozuw6Q8`)tnJFh-&Y0T4A@#7# z#31xzY_~O%^=C}wm~BC0oeapPwOD2?_9e(~XH2b|fvTM)&`AP)(MY53S)%PKp=?v?=^XME zn!Z8H3Ud4m#k2cM2FfM!;g?Ld6|9=dCjEOd6O9&)(*=gReXkGX){@Vo-VtzSQMPqS}MoS z(_fa#{#_xlOTK2EOUKc36^yWo1qiK2W|4jdf1PT3;Ag?u-|6CybuLZ+slhB3L3dz!b z7J14Emw6W`=ziZau&gje%dm0T({7G}D`e)k6x52Fdp9An?OPL)Sls@>36sZ+9zW6z z!}cI&IPQhH{4Gn7;+AdE>PkiX`wB_?&cxjkQO@Ae5#HQdVS}feB5`mzj-aZ z%xg2yw!K0ahhk;hcZ`uMWY>2rFV?t=lEY%Yr+2XB8G5v}PjY956i#b84;4;pV~K)U z$X#1h@UFxcd~f>MpVX5dzc(XHwDh{jOjbTH^P+A{d{;m4^bh7|n+xlim(0t?beHU( z8OGZG%&eEK$4yL*Ec@9^vFZ7xu9(K=3(sQ66;sis|2}fXv^C`d`>&Xz#)L`!HS<-( zJhvqnD^iXhB`@=S!IU=p(l4gFO#}Sv7gH0DVI9d>^ZVQPIynEdYG-0unjep@SlPsH^f6;WxpxL`n zDuvtSq~I@xl)Vd!daRBHZ^*2nC6m~NifIv|$RB3M$%Y8_g9a`yQP^~&WYFJK0XxZ| z%@=u95WJv|!mF?frV*WAj{j|PZBBXTKjur*T+(ltD`DYS9iH!{FSye;mepcmz?K9& zJYU#^s}Pv?uUTqL)5X>78vNVM9>c%8>_Mz42Jh!0rjD`8voh>pP!E)G#vUH$^{zqA zt?@OL9}Gj*z(AU9|7t=tou}tZ^$@$VbDES~36FS5Hbz9W2-Nr4OK$Ghoe8zegqFhg z!hHEps9m(r+9=HCdI`m~`EqZVT`A_;{GxIs`PNS9b({j+sUu&UTpei_4ir)HJ7Im% zgzYbh;dYgn{!bSL)zNjAcHtzm%bh&EE!th)7VR!?i*}dn_YBT^DB7akCGHk2K_l48 z-6fMwgfJE?DiO|ceuSL>HhVY}VOPPm`bLS^B_-_Y<-JlXUVXZmKoPYrVb`+BK8wK$ zl2^j67~y5rSfjip`|c8USJOWbQIhD*_fjpAh`*Qgy{vQwM%oWiQ%RS@%gNL zxh$_KD$8ZX-BK+Y?36*#_E6JN_D2)ofcze9KOEYRQhsQyyFC|dp!w$3cJaOJkFncD z#I5u;-D2gMv032VX4f>e0-bNO?+JAtT5IH)Q(^IeedX<8hJIYFf}P~VZZV5{*sbJT zJ{RHz$4dC*!-Y)GLYT-&R*8 zc{$0B;doDy9p{*%w)EITopnoa(zza~l5D5??x#E+m0rnqXF`6JLI>KGOk^+1p=4Wk zkV~duGzO!+(k#Vph0lX2M1M`zrP$59AZg}^L{+wHgJzZOeBC8HmtvQZbCroGR{pH) zM&!obvkG2!$mlAr*UMFi=_UEB3f1$HL{;^|7F4zC*kLE+qpEgY<-b+!t{P|8YIYr` z)d^d2^I82YsAfl+R`Pr`dp4+-rgpC_BE+xIvdKC-3F z;}P*vwFZ^?cA#4g62PwVteTYh%W}LXjc2b!q+)uFGW+U@uz2yO+8Gf?j@jcT?|72FY87aog6#w@#NzdLz4vT+OgU z?EC*mvlvb2a|BuVKZ-w9u>!@3)>65#U3jx>sSIySPM$|$WIl(+$o9r|;pWCtF-=gf zL_Jbco7jc7%$CYH{6kmazr2ksX;Lh{&s0%>;=?v#H?<3wlS`#@QxvOF{M1IiY+5YD zYbbm#pr|C1nie}nN;3ki!M{zWRBB! z{{+i!PO$YTzWSeFhg9(*ic6XDOLMz&%%#l2X5d|Ibd_r@7*@MVD-S6x?ZVxprLwpM z$=^We=CX&wnC3Uz(EmGdaQ4)OP}p8{gyP;vOB!=q*{`@?Vp`cfA{Msxc8oLSd^)=Z z{#JJVh!a7-dUAd!o#jX?JDQ3++sYmpF|v(k-q2GGX>CVGEWg!n9)32}v$8dF4z+O@ zMpSb1Y^)UNb-F}+$+qszVV#`XNJ<;KwoO@gZ-YIh`VfrxDrg_&oo8Pg&f}GvvATN; zs!MI`4AVT2l4(1(nIP5L(%>gN<>+mLZgQ?`$;d!KTYIc+o|32ztT-N(=^Yp|Vr8>p zu$)(%m9ib}7TmPy)zN0-*X_51D(V&*e=mD*|E*71R$J(}7jD+=!*hC0n4Hr+d))9T zXm$6k3=_pgM8g!?74EB5DYkAOCYNuwtEB4!TQ9AOtFp(Ab)#ap(7J#mp!Qk1`D04GV3EJF0l`mov>Vk=8Ir#ni<`CsVZ4_*m1o!VA39w$MCvR%tSL) zwOD?~Q$~2X2{=QTOv2PE7Dfv~SFBZK;~n-r@pW|bfxkyQxc@dFPq~uV#jX;SN9gN_ zs&l1V7u&r-c=ZmuOoh|Ikc*3jY)Hr(&&uI0bh`TJ*CMLF@hlZ7hJ47pQFep+-mcJ-Ju#MTEJ)h}H1|0l+#dQHXOOb_nAjfnB` zBB|bu80QgN2sWy}d~1w4n`%DeF9hQ#o~p*galf4E#_-S*^)^J+_bb!nl(& z^qP>r1s>dgn-X^fPtj=HlKn$unX=kr7HBH4R!dj=f5z7LH{H79uPoi6@UI!MEepox zrnKFJ@#BXN%?T#dO{s38>?5p(E40<7uF+K2g?WN3c+Um3J(nEJ|3P#IFhjhA zmJ`#JHRPqbVUgWbznkbn$ic?tL4B}4R4>-phjX!{S+lU+iF`?XJA?Lx8za@_P)|F- zu5M&}c6eMxtac#XvF!Am7qePwpR6wVFEb+7?`3zYFim#__^ajCk9XXhg4pt$RO-T2 z;D%my>&D(5#{V|stHGefLRu{ddU{2$MpAx^OpqpbvZ81FyVEXPVTf*u@;AnV`!A0( zg?_d|p1zaiQv*4QS^Ph4FJYHT`+V@P6=v<_#+`Ot;xJ-4h>5D(KkuDO>p*)|4N33K zrA-aJI8sbvgE4U_0cKDIB}wUoVgWSj8nO|SQqicVAwBUjE9J?ab_KcA+m0@)VYi{6 zqAdT)U=7Lsp48yPo_3@g_W~009dYLe^_mz>dJXB;hq!kTydNfWFxkISO7tS`6~pXE zeF6)c)!2~IJs?p{=V8kKR=0xS*@%si3CsKum67YVwm|3`F_hjhF>}zLM zm~k6Q{;GL!|7G?KT~;8=``SGz>nj7OlBThq{>fss$gCUsR)JKw%dU{-Cz=p!RR7k^ zQ#mm^HG2H};(xx-Usm^~Tn@g=WzEk6>{2rJPCLBehTs`m7fZmy8|omQ!ikEzmYCR?hhGRea%?ePW6LqqW5`KSch z=N<3YeSd0+0O$3PdgV~B#NAr}sd^!vAoV}DLuAxlcBEYIXO|(0sQ$FtR7vYkpGlRz z{aM$hO8TMj`jHJRt9h`Edp=bgda3P0YB!W4wVa{i+M?c|8BUdm0d`VfH93dLbi5v3 z=b7kOpzSZ!6m9)6Dv!?|n`7x*r3Ink%1{ux;nHw@QEOzjCF+?2XpL&p36olQ#l2W$ zq79Z38DRI0&y44oze>eg7)#C29+G&EosgDC=txXd-J@6x+JP99v?sWKIq3~7hRy*r zuxa;jxmQcfQeQ%Z?nmp%YRRObc6^J*Zo+pHXF++(%0e-&SezQst#LMVZ_{eZya;M! z+|0d3a*{|YqTF6A5?xf(lJj-L;u6&)oV05q`)?@9y%sF-4J7wVD{#yowRQ8aEx8{j zX9wC%;@cB?7$&M77mT5~l@?P+(gxXWcy4XnAiG9mb3OPKt$pbLc(=!LwN{$Bv$oGko&+5fdg49XopX_?#)S>Um$in`3qr zFVwHWWsthsk%5;t$d-HUN{MBNzYaF4e>oVZ_7)nfmFCWfKFwU3WcMqX;LC6iXX#-h z_fR{Hud#dR_L(N`q1$Jgx`*_cIN3MY4oU3EnSQIxM9G;x44z4wF=j-6elWvmn%o#n zt4u3aUQ===56>RwJ)WR#DoxUd(8BOOlC7zf-`w92;Q8Wlf9 z_RyijC+2uvd=4?pBZe?ynD|oBX_($Mb-P1irRT#YL<+JgrQ(rH89siPu9CIA=wOs4 z`?KxX#H++NhxoLLn!jAsY;}-IlWW;_l|;>1nPeJ1t$l6KL<>XK!dKn(A?Y*hcYo)06< zgvMRZyVBS;ni{X?4yPFoqj*9UroAVqQ$!}Xrcp7h-<UePf?L^V6+93nRP&E69CIcJQuL?$` z>i{+60Ytqo-Lb$|$JQ%bjqhD;^!#1Y3$rCy@VDP|e2mc{C0#1wBDxQcyG?8&{gyqLYtHtDj5lULG{&%;F5EX!Xn zI(Z2S?n`J3D_JJh=bfLD2+)fvxrv`c52{oiiMbHl>3^K7=r8 zkB$7)J5-;<{wmwlPXE8JKO%#*sDpFiUl-2s523fVicFD#6S!veu14akrh6s{T3W$B z-g60!m+cc6hoXt=YJG+k)bW9$))%`1;{eI)(2$EI4&C_C)?498uk*Uu$&$?XQx*R8djTY1DUjzeYT~9yNHP& zlO@GWB3+Ylv_3LBce0(7egw;CEP1NjI=HK-#gtOZTMEJ(eo9L(8d~S7^_W$W9+>@9 zELima1`D>`9BfY_+IIgfW*;NF#@Pw(0HIMvl9E=KeDX$7N^a9AW#$y>UlV%)lQ&50 zz&DF>u4@o#ni}!xvZH|<$C?~o2JyG#!c9(cj4nH9FgYxS$`Ic<p)UwcDR!`Lh` z4pe_8s2^3Rryj|i)lgMCz}`7NB8 zG9>>2hQtin?%}wHYaU`Aq4;E8Ku@?Hk=;04)n8K@94R?lcRJnDnSU4@a3_1HC#oH3~X=D&y{{~HT z>e8~ykeF$9Y^jN;Pa-LJ#qE{Pr_u|%PP6;PSJjIa{tkI?|Ls8`O_e>rJXM-}W{oBWKukgXP29K-+C!Y#47s zhIW42k=)bvp!hn?y-?vgBnJQbV!%_qGq||PY{q6kqUw=v7uAiHT~kSaj18Wqk~Ncd z+*Gn>+FA9ynN3fjjjL{O8-GFYEDsi*0`d}Q=ma@F({2>J>s+{L`U}dFbhrtD#7FE; zLvpX;_HO5xo412*!|wv3f8oaR>)gSfrN11Ef;x4ThN+NI!mr)*HmH+vEbI%*KrQC- za15*fx%#z!zVfes0;C1_{oLbl6?s8}Ct(r_fhlkmtPD3o?z#A*cyT3)J)S6PGsdcC zm9;Xhc-AdtSr?YI+Tq{Sy3Jj5=rXV#|241@tu*{qmx9zm%DcDb77*vLg|afwuF#py zC%;w^doq5#DOCrunzZUdodz_~ond|4V|e?DYL_rDO-Z-I@(%(fdw->cU^iGB^1`#fE$js~?Y-du$VRDKA$P$=xbK#f$L%II_k0FCZdb^< z2XBpj5Y*@gLybNgYV<>)Mn4>C^dq50KN@QE_seUK+w~&cn>!?WCffpbZ0>lp8tX); zu}*=y>Uj{RLM>p8bvo`kK{s=(H3K&t#Cil~LO<*X^I&htRi%4YwzS<$&4V-WpAVzh za*ndnks6Zw1VhyQ(*JQgAuAu9rsY|vX;}<4hXOT+%b=#^IjA{&9%>F(LCs--7FZQ& zI>(NT@NOs>tG!p#YcbKN*F%kZ1JtNrf*SQEs8Mf$+5)!0c5u5an?p@|w~&mrKvw66 z#OA(+R!6k}jEAf?+}61pvPRL39Df_QAKnfRz&oK9W*_)IZtaTdz8fCKeIGmmN5hYx zc15n`{W^A>fRDhF@EM)IK9TIXc9+~7h70c=leu}HY7lm#@Ylc3vDbC-8OXZd`VzK) z=U_{C0d|8wLQU6CP}{qvYY4oIJ3Hte3a{YSbX|p{C)fIggQxNM6)p`LE{DJ4elEzD zgZ`W0ANcPHy5E9-<30s%zzaeD?;u(9-%!9v23<{1Dah#RPlP34OOxv<=$%$19`sJv zFbhWErhi$bAWhdQ4Oc@Z6#sS@3(vwb@DeN!ufup4W-|!F+AtBWg_?l%FbVgILB5h3 zROq{VylCkE2v&xl!K&~VSRKYWT-3s*P$Oy%YvCRY>p(xO51)YzAgf<11AYq|!^^M< z{0laRC8%DFC$}^QE%AtknXp1oQ4zMqofvc{!49}HU`NR9JL`7HZi3YrvQ)M1fc>CG zJOFmZJrZ_@<6sXsEvSD8_Oh*9|7;HKM6n$9hO1#8_#*5Jx5B&OF4zz5g#+MMa3K5{ z>ItvHA-MmB+3-ft|G#iJZi}lYwX@*}+_%9|c9`YYXCKDMYxC^+5sjHxa+z#0q{n>w z2bAt#q+X4(C(Emc&`bor3<%-}>1O|D>S% z0r;bx%aVYD%P78vS0Tfx^$WBqgu*SxwQfLqi1jZV z11*Pc2YENxKNE(+*)R+~55sdgpvJ5S7=R@pxw1;avye*_{}mVueGDL4A_TS=l>CHo zSt00O5nklPHG=L&Faf(JLEahk?*kL@kFw@i;$LY07O||rTUb?dA9YNrf-)&s9VxIH z?#e;8w&Cis{aHIH!n<8;=o;B^C1P{yVx{{~4PX_R0k!oshT5t~hC5v~gF4?cj=F1$ z7H}HwmT)d?1((3q@I}}L?tq!_0L+3XU|aYNYzMD0kXh|H(ALud>U7f)Cc)cb9oPxB zf_K0{up1l)yTfU)H_U}v#(A)>>{(<#W;#jMVzwC`Myn&y3|I}$gxYZ*k*SN>D}3Cu zniI5|8?<^dX!VpF$I5>91^H{ST{-t&yh{<7ImBNY4uQI`xew}+WEf0_!=aY^NT^GI z(NIT^F)#yaQgt0S33nSf8R`;ZDjW|VgwMd~j`jFUQ0?iNxmF&E5Ak>$h4w%uFaOVQ zA=C#<7sJ7j$7S3evlOzRvz9|vS=RILUAPMBO#A};2Cjo8X|FHBa*(@O{?>34>NJVJiT&BQT5l8E33FAmfF#2hw}2z3?`;57vg7qcr#q zZd#!0t`FbCO@&(rVGno+YQsMQC**Q)j01|t`V^}BG<*Vn26ZYw0}J3;$PF^{@sqgrI*S941-Id7N^bY+i0Bq>k25L^~GV1}DJsa3ZV)r$FsrQ{~!n zyNbi@Z291*iRZ1Z^yhdCirdrOpJTrDV^$I~O-vMg6u0&)Wnz$(AtmWX$3q|PrRRK@ zjsLSy=deXk7wbzxtj88Z)_XtDV6kA-hQT?@YnpN4zj zYF$L{-&)fR^?s z$oyx02jk#HSPA|JtHGaOI=l>-9IPuaw*v>PKm7yYH8=(S0vUL%-{33oclbX11AYXr zL%Of^C%ggwf@SGx|3F=Q{|nRMe<8hsZ)vgafvjKs_dy4afgwKDFF73Wq?dmd429Zd z!(l#*fV2;*B-{j}AoXmO_E~f9W9?f3_ZV0a=D><&ZOC+h)utqATARmyj`oVUvKkNfF z;{Na+++*P&_#nI&@|cXPpAV@H|57*<>L=5N!5wfoJOD?)@8L-JUpN|uhtvP5KYwgE z;~1<8$HUri0&E5+!nTn5^$&zo;RyHuoC2poKYR#20Uw6>a0XlndqI67MoW4J^uxVy z7CaEn0xOS$5Ae{O9)pkLJ`v>Qp#Lv$PGD|VQ$&{tR3mBA*1Z>)G64Z@t#8V2(-uwRS>;cf;IR z?@9XZ@Yvi<80$&4LLKzC!76Y&)aBAEuo2t=JHXeVrcsMbmz=wBZ-j5aU63y2e=n&2 zAm~00_u~H@+y^fO^}pyOpaK30di(?5!Tm2h0NK%XPZXnLFm85mtwS&w^2(~84Mpn% z$i|^{1hNBY9ram{&WD=7XCSYf`xn4dP?urqzYOwvwEsDiz+MptoACGoz7sUi!T+pm zTxUNQ;oU_yyvX6c-!^2u9UgJsXU*1<|6V4o=b;;JmOr_k3H2vp(6YP)iP*XVwJfi~ zrtlinrRFd24){Cl3;%#4;9pRep8vq7p$YZ&boug!e+6zn>*HSw`B;ztWf%eXK)$Wx zKdNQPxa2>L2cM(ypND*u#l1+>JpTtbA4qX`m()Q09J=bVNG}*GVb}mGbI^3Ibbi1yMvoww4aUeZj~FWgZq|OYU5BVuL8+v ziB&Re4I98rs2A=Glm7Owoy^`~^PvLwM!SBEP)k1bcC;~QJ3;LR45sw9A@rWMH+xS8 z19ZGx-oRR~8){}qt2?9%TfLy}Cfo@%5sbn9YOpV?5Bo!{q~I2E!l zZ#@XLVNZj4Juw~Xs^%d$0qTizg6^4c2LAKlBXGH{ZgM$ThX<31|8@8{)LNVaFT=Tz zeN5{q$iAgD4~A1@Ps2>e%tFUBlsa~36Db7_||dQ z5q<(Y!LzUn{1V;^&qLiRya1=d?;xvc>tZOYn|U1kh{tMp8S*Bfbp^8Mw5~xGm)5WF z1IWDXXDw*`0a>eAe?pdG*59yjOVFlm8+QKUp#v+z5XkIf`5?22oAV_wJZz-5{Lx0T z437v5UWX;%d$1&A1hsf=*?$7^rnaAtBUm>$;SZ3)@|@VkOhRh`q9Q0!Qw*W zjfV+=(VOhOhC9=#Tj+GGE8Naj6_%pSv%K(^fz_dQx*AaXZYrz_`GTl>#ljau-J2|Y z`qRBQ=YyX9=IGO5Cgg*i{*I9EbGrAZ8o{2pn?UWPEMNQswbM1@;66N>!(p%`)N7PX zsMjc(?&+{C?uUYWJm^0Mvi|Wu2|K`rup3+j`NXYz4bu~{3t-&|b!UZjlK)M}*9_Sd zV0^iYg9~`v4Znl^rSDc-OclAjmGZe4U!56-!0Ip?wt&OnOgIASrh_IkKj>ZwN8-Oe z=-wLCzXwO-|54C=Ea=t=fESVdU%+wjdpI8cMy}n6btX`c5c>QC7zx!~7V3%Xz=^n< zLOnrN(7zYVkwe?;2@&3Hdt)7PKbP2l8dh4p(_sdD2(qJU&4AP3OsH3cv)~5!DAdw> z488;PtOww1+?p+QAB0cH=IwS1r}aLbrZRSX>Qm_TN|js5?sYq>Pu#WH|8B%I5a;eF z>t*zPlJ*Lv%}0aX8AG7Xw|pwtub20HF4*0S$D!CT9aY0XM>v@MZW7 z+yuXcTOg%rZG~Ex+o6xsz5>G_i(h{^!(*VD4;|`v;Smqjt(Wz0%K2C9d+bN{OY2uz zH@t;9lz8?+ovQZ15>U+};eOoOTi$^!;k!^$!D+HJ)BG)5*Yls6Q6hj15L=sFp8Vig^Srv_;r@-9lXgpGO&Gz z{e2kkfG*o@f0H|eT%Dw6Uqmd{krj~)q$e^8nTM=J4kG7}@Jg&IkWR=DBoA4E>_bi? z{~%?Ohy&@0=%(sYWFK-GxsF69vjRaflj-;qIhcd2MRp_Skn2dr6e2--BBPKzWCd~( zxrCId%&jP-D>4jOifluUAQzC3D#U@bMEW2TkvYg(WH)jK`K<~=O(Zo`73qnLLh_Im z$WG)Kauo@$#>tTO$Ur0qS%7Rnjv*J3$m+y{v_$$K(~t$ohU(k-qS=ytc2)C=RNKdU zw_Kmg*3ZIsE!l71%OfAW{+`Bn9_H_7OZ7c@ZNGgtho*owBT(X&|C11T|WF3>fcyQ_UEtZr+D76V>s=p zcX;FfphUgP7bR{;D`1n~K_!_&#rVOprnEOu>h-l8DCSl3BfJtN>m%3dnU9F3pX~X_ZsPQdv*f>3c~&?2sNF!H)pfJg z?N+kTdalx+;QB{eed6kJ z)m1|_e^RWr!apVE4wCX|F~1r3g%4%SaTAmOCm$w0dWf3^g)QN#hM6T1r`;Ovahh0H z$;{LCgU+6cmiKky@}Kd>)Sf`K&nTqeJN#S@u)F7dOI?S&S7iR@40-Pb&VFvcXh%Hd zb`8Tb9QrJc6r8n(MR?uCSbSn>Xc%97|I!|1n;C(*=WM=+6bLl>+TLqN94?~?)rWBO zu^EZ})}BMtP5F)|-FAG-7dA$C$Jg~ZPmkNtI$gE@JG}PEc{P3aJG&w+lj9~d$zI>% zmGM1ZS$f=rmN@r&68oZjrubS?FM>pwuIML+F534*tcvr}(Lea%q#t;v|9W8R4|c%N zT+)8BM>^dqSn}2S67jO_Cp*KLgsb#g6TjpVANP2MnO<|z!VBF~{SM#iSD=1g8@XwB zRsAyEc5~A&^D>b?oIvDPOuQ_(OfJ^T=F9Ye<3Z0QKjZh0B>qg!YDmfzGCT2S%7S*F z$2;_RsCRr_k7wy|J9||{Sy{8h9kT5TuL0}{ymrNI5|g`+QS>Bo2??)ZS;yn>DX126 zR96nBA^Jf5Zsa7w>cuLLbV7z8dB_T6Cvpr4sl)t(v_}RabC3e$2yy|5P9p(GA7m`D z6xoIxLoOoWb;$&hS(l63ejH3g^x5ehh(0uY6$!7$yo9tzMj`qv&r)O?a<=HCo6 z2@y^V-_K5qz^=N?j&Qogd!J1`TkP{SohVXGAkDS2PcI_J2bz^|VjYswEy{Vy3=Vu2 zsOA9w^6e2|VX1U%#nL_4x_2S-lIt=kr6c0%^&~ z=E}7=hY!HU5#e**@j*S_tj9gdO(PKn$WG)Oave!-us!P~vt%IO!HcXwHFxIQO-_>2 z`9FLcDWhbfMEZC&cVY!+04a38Y;#VnddiL7ht^Ei2{EL>ksgNvY&K2$oeUJat+5r;<}X{Bs^fa9h{@8q!@wJ_1!EZd}7waxsLY@C3 z<7@FSdtPm)B29XAZD&n{*Gi2w&ihG>A$6Pr+G4;?b6zquuFZ8B%08F0dd{2F&<`MD z2RG<+o~$F;kMjWkzWUBY8bo@!(}Vh-mG0a_#h+DVNV5ixP>IJII3uaOW(}RK_JzOX z-p{FokPOmrSyD2HpW@GO-nV!DEu|Wx%4_7zp~#{dJ8QIPK*TTqc;}q#eYbHUOG!8T zgNHM}UT8v>e@LR5Iz4imvhUgz8HVWl4~r0em*WU>2?^nLcrwxy8HnT{OOb8JLF62A z9f{6h=0MsbLy&36Qe+!)5IKi%ac=2*6ZMf!$goCM6Ke(si;zvoKIAlV2?=S8F;X9C zj|@a6B6E;}#`#%4FKO;nbzXXl1u|b{rVAbYZvy$B1+-h@N zZJJ}V#uOf8~Yf=#EaLuMI}^B&8$eSI;#H3mVC?j>M6Px{K`RkRMCYIBu#N-Htj7^+*|X zJE2G3sy>A}l)D$9kM)*+Z+9x2$8Ob6>V&=>`c=JUc_(tP>Q;SBXY}pSzu8-wcSir_ zt@`b%?|}Z(-txKXKfP7o>kjlC(f`_89=e0`|9Y$bGI}5PPeMye*)HU+w4`(@mbTBPsuhx~|+-?cIUAlE8_qX4wKA`G5P!E;Ms%AZ2Joe$;PrUFcqJFNA)a~xnVu5l?@QtePhCblx%gM#=w7I~oM%{W~#GRhdkNe02J#PMP zR0G+iiXJE~_K~l9P%;;94cNCQiR+0zL}qfxmjYJzELJktRNV`8vc&hIX(ivPUfc^c zHvxiMt7p_jk=!3N-0ugARO$blTM@{S8umI#qf1BvcU&trxvKlP4x z=<%=K@g+SjE!XZL{;GpGt}R)Ei2ruaYms{Kbbxy0dR`&-;>DU?L$uW6fOnk3u}yDS zsUM%+bT5m}i=N`N8ih#8y#$CJ%yF`J+)0mHddEDVUy;`8+U(Th9Pjw59xw2YYYyRf zlXpBsj}LmsOZE7IcYI8bExA0zX<}ErOWwMdRZC_zeobXiHhz7Ae%rF0nz?0~a3zam zBEygw$Wmk*as;`6@G_PAwp>ft2bqQ}Kz1NUkgG^|GvYz?RknV}L}VVa7I_yrgXk-6 z(ao_#GLa$8xjdi7fxfu50eKfWgIq_VxkFP2X^#vrV~Dgzh9J|B1;_^EAaV}5 zjzkl-4jWHSZ0K4JcelyUI>D7&8M*jGsmQRhTpjl3ThqmUH-b-E4|A%7l|%FF|7s4X zCJxQE|J9@pM^hfn_y4PzkH!~|hEGTgcM5++BTBB}A6fzbCl*VE5l-O`MMX*95hxN+ zEL$v(jBqOXmMvzrB-j4pb;q3}oT9H~UsJ=182(8NBX17ud`5dDr%Xf4T;R6i6WWEz$|zFf4q|%`W0Vm zztCEqo0evN{CQ{x!_rmWf6279$n&`x)Rt`p@Yu`LB z+sm`x(u>F%-1JY5!D+3OJrlWfUFm*fM=nluB4Y*?Ga)1<*)KY`o3EtXBu?}-C(83q z^igC~m@J*-M91V6OETB8)++shkOUtWpB(Z#4)OB(M5nGKPj)HTVT$4`QsnN0eQ7du&)t9yPo!K0_Rk;hMQ z>P2N_dPP`{;1OabQ5y@sGS!1i{IBHsDfE|b$jP8gpM3Rs$rQOb#ffy(Rr-sP58f== zsX4Uq3)nrCDJyfF#xYL?Bi6d%!rdxxGrDA|6Cyh&Ii=;wIwwk!)p=T-&kQk9lBv$? zlUOS6-tUW+AvjHe%v#Mlzk;Mp<_de>RGM)o@+Mu=!uSEpsZO|zQs=SBj!!o4_JzqY z{0Q~gREn-Z^m92<>H()z#M)qjD#*3T4!$(bmg7@25{8_OTB*nbh9q2gq{) zy)UP&_jUW=Z>@br_6j>BL!d>Al^%anWi21%qSTR;2Pr)sDz9lO%f<(}$jxgLm^{t7 z&$z|a<}8+1r#t=Zr!oU~JmfrWI~u=!w_kpn;nZxDLkC%kY(vfU~delm8KCqOWQ@wz4$T z*8H9=mmJZpF+W#>D~aLvMpE7Hv;89SA85Fy zLi6rAd2*mB`tbgtJepZ66d$aUU-F#F&Ibg&vct!3v(9$PI9GA)Ro9T&jK77yF1lJ>j9bNdAYyXdO-GjuJay>eh%P(_j3RQ)t>`6pg#wYAlvk}To1_h z6MR+dY78H*KX%h2PA<)5h`RP-uv3r%5PDQ!6@1IB!ggQ^4Cp{Kj}0J{`ge!=ArxC)V34> zwEe-lz{;nbQie6@q^Ia$2j}5Qg?&EHd4%z6YhzoYBr=V1&K1@q|vUwVoQs-WQS z9gZUUX{VNHmk_W;QKB=?a(u2lSw;b#BLeI!ty zuXqMGdtmOPf$TH+3vjcLb)Vl<{buorlfrGcD#C8;78xYuc57g+IB_=DGOL$4?J8ZT zTp~MiexyAz5SfD%AUiu2Zd^S_lNm=oD@(N%j{Zu)gcXcqm3ae5v-OhuyK7Rg!kH6# zjBwXG>LPKaQ`I~y)mE~z|8Q?UI>gfiudkxi^`2<~8DqiZ^Ak;$Atlmgzo$GWXk3B*qoG<7unLvlU^^f30hW; zzlcrQz@INV{A|X(Qg$QC$E3qXlrPDFjYRiS;KoL0jNw{n^vgsrQJz;kCdU=?#ka}n zV%AEpO}H-0>`hKR+ZrsdZ*rb?4h|09+giJsynZKpHlzG*uzVEaOw?WFAzPd>5fqhM zrekIMgG_x3wm6&2_kmVhNtU@B7{1NnXJQ)$CcUCnST-K((FDuTJae+o@foCDIR>h|ELQBKwfj$Ztp_-M%H#2N{dxAsafmcWMgs_S{?C zo~yB(pE2fBACmVLS?D0ozvWCZ(6ANM78%b|UaJ{eJZzf;zY_Wxt-{NsD9{{O$%>vdh%YcDpoj2Xt}M+}SkJ%&ww z%x?>28f}>v^Ugw{4ax(ol7mM$>jYG&DCp_@}+jdpQu`;hC6@1W4j&e2?wY&1yXQ; zY3)7AsVn{m9mDP~C7!3jH4xI50WgRMBS1DN1iShcB+M%Q*bz~UO=(6FZ@8*x`Nc_j zBhG#4^|2$`vy{f0eigsmOf-^Y;m3~I#&K-i!NzaJhp5$!q{$&_H6K5y_!vX+gLYjC z4mmPNl3AaF4x9Bk>ae*EGUhO89wr5c9qm#0MBQb}&BOd0vnBFV$6a$NdT^t4@<| z6#O7B>!|Egv~pwR>gO!XDXsyxZ}^DqUUAdl!ya0VXdNcq^I`9COr}ZPTm`dddxfS1nvkT#b7ctNj>>&!NNcGjK=Y`r|%{>%z^( zt%AE8w;Jv`-0HY*;0EFD#8vj(xNPE`a{xCK_bXgB^Qs+s_xaW3;unwNU$_yn^0?y> zNBQU0yXUqh5_rN~|}tSZUWQ!Ie*koBj`iuCmQR=W-piTJ=pW|K0z1sklM8RZjHkRpw>v5OMIej+tnRoy$d|bd!pF-B2oOPMCw0M8ST|@d{2DmMLK~0%DIc? z6L+g0F_0^xe)O8-i$Oo4w@eQEQ1yO-5^4WarPcyPZItyE_1#aHVR8Rbr9$c@6y9e? zPbGCkQG4W~57p^1)Tfek+0-H{qitWv-pgiY+*5Z~B>KNz85<1#OJ87rSG8L71qJm2 zL!{)tOd5NVeGM@mFLnJ~8D`4QQ2k_@MOD8_nI2LUpPT>L>NXS=cLlo-dF^I})5qNV znS7#GQR3~0`IbFCLgd^PM~uZsGojk`s%gZm7b~u!wMuqe#p5bDbJej~{e-q(z!N*) z_=wam%x^Z59ls!NBxioH*6CA!<#+gyEcq4oA=&w>W54n>{hFhtR$D`n^J zY)qLgfj3auDZP|4PI7J_dslWSr>Fa1djSIOZ&X<1gu)ju7FRr+?_ax^ni=s|x! z;QRHi3qD`YVjRn!wwT*=ZM$XEZTf1aqHohzpSXg{zt!_MRultLfZYDeaa&&aG_LAD)klhr?x$S>5z1v#`{!L>wRto+`Zw`8EdH+~0 zD7_*}FX#?>Yb5#(k=U-Bx-#_+vuPidSY2mR>vgMjcX%M-TgZ19K<4rZJhYd|{<~;T zzl#A;6c1*1F}zXn9r>-8RQx~8ht&Ru`Ih&0+RSrD1S*IhNzy+U`P4G9;vYvn*B3jj zAnQnZ(<&iB49;6}B*JfGlFFznQjQ0^{avYck7l60#NH!m{UqleOAr0uC12Dh;}6{9 zVdIMMJA=bJtkqxN37pta6mu3Wl_O*Iz4fIhKFq3GR5X7DSns2W#)M zbg!n=d9KSoxl(<87u&sKq)v4 zt^t3Zej-2|7zQST1z^KqrqB0qaTeSFK|>hqfSw=)Ob7X33pfDEz%3BMV^m8p0HlLF zuo~sp%HJG-Wq*2<9ud2F3+u=@Q) zgqoky9T>`)g`c`7g=(=C!-qY!@e(GdYHN*fZr7&p#>>tytrgD2Fv`AI!t1b4rBssY za2F~I>u9t6(`tAc<^2(XjihZ|Ett=0_NuFyyIhXfCA3%MZe6^+A~E%}k8D54&3f8= zp1N|vwH7#=!?oWTwy&v=%0qIZKEXXKwgy@s+j{BS0CKzJG|(3L|H0dpX5*h58CYAI zMNq^3kk|P5CfF>%h|5?FhVON^~SnzNAHJYuWo^Yp6BFiE5~s9|)S> zkeKzCjf(9rM;mH?+Rn(qM);^Ew;O45X%urB6PI^oYhx1orCe;RCE2G`lOf?+2p_Q{ ztHNb$6HPtdzurWPGKSKo^{D6DrhVk|2(QM(LnZQlep*@XtoyZh*lx?nSN&%xuqNkt z#z$$BSti&KMdpx$u`M(q%TBb=-m*1t=e8u8wm;mPqqTcB+c)mbt<-&g_lefpXLjPa zrmZHfa2B)F|0Z(cxDg^r?X*Nih-jscvH17gZKe??0 z0}=fGrZkMz)Q*Q>A|`iYwFf*C>-dh<8tJ?SZ&a1NTn1O=AOV#X-lWcz>#>^mt8e`z zrZeh;QRgt%&hXYeQ9oI!_#yBdYTa3D5FFz%wUsf<9}7iZ-vs+w2sr7+2_6C9vP=S zZ*!b`QxkJ@*PX6fGuQ8CKHB_hTb*ZoH?0}(XJmBK9%NXwwHwVrjQdPCt-Gy5PioQ# zFd5{5)nGd~1TKI(pms7n2S@~|V0!Y7gtu+QJ+#I)z8ua76;AJ-3Ru?+8LHeDvQ1**#O`l{_vMJc2EnU5W2)avy|{S9f~-;B(Y{Rv`+tg-IQ zAg-WbKU7~H_^(4fD4E=d0eCtlSp&>?5k@p~Rp$nnAvPGu-BlSl(7ap5on33-eatd_ z2Mxk^Rf!tp^<7i471dCR231D-3RIOSPJ!}7`sG2^vyw_<%3##vW!m6M^&?PK`c$gV z8f>aJ9im11kM_`P&Sd=m(-5jo8+i!{L&U>FG;@wAiMwp+np9cPi<1asu57fZ@07wS z34Exsgi;?uVZF@op^hkOmt6FrIt_(lkH=8c`W#6G0aR-tKn#b%BbOH;@7IX`f}8|tNt)|?WOC(rfjyli<7O^-LL9y zsDwXKnS#lW5cEh{Xi;WeIjg8Fx%o(C)(#k<)%KqrVU>gghq0Tk`Uo=*O&@y@Gb%nc zqS8mpWPB8ReWX3W)7-TYntGZuE5K^R43u{!SH{GDBvgq+jx?#qMiSNIvc$SG{gf$% zvvS*q8t^F8FEaK~(~p@|yA*XtPCV-Kn~q3<3z66qtwC5wq?HPD8mkT)H-LI|vH_n2 zVx-Yj4yS0(+V)AWQH+uHNyaGc8JdXlQJUH{-fA?l>L{Z|YifpWZK_sFHjk#S8Y=ro zYmLH&HmWekny3 zb?k8zPRd=+oob&3j6va)j2&ZUn^}ar6!oi|7*kn<&C;RjNJ6?vnMJTdQC($6I`Qu+ zXVS^AM-y=eiHG77Qp*I(N7?MP&Pk-rw8T46L{jguj3%! zR3x9}8i(GSa&(;bi2YcUJn)3}xGWe?NHt{rcs$i`A0AHzP{+$N$d-pCZGzU(UZsVs znxH*L$l((!YtiJ1_`BkztRIh}hRe-~W)8K=Bs+KoER&plO>#4}FKwIL!zXELHEwTa zF&;cEO`g)au)ja;DLSf8Wc^cQdrdi|oVDVbf=YqJPC=zurcHr7E1Q+Wx#d$BM|PK* zQyGA=J%0ND`jhEX34N3lOs&ktONtsTwrQkov_ws#hK-i>)9|DP$+c-zfW;F2G{VKw z>uK#GWBTIWSc-oJZ#5+OnaYyhq^Ksc{}~d~L@qv~9kV?yJEs%FDRObTHj%M$(hMH* zj>)+hkPl1XOzvKkl`~BnX31ZgiH-VVdzQ|*zC=H(g*sXfx2f+M_peCArf1RVC;OF7 zKe?)OQYv-K*p1Id@U@m(RbOrwSAVx-Z}TtS=e{{5pI)Thv;>J7|=H2 z)q>ynt*K%7T}hh5Fg!%o&mqEWQF)G9c4-a|z-<&&S32d=tHxS=j?4_(v?h zO!5D*_}0(CPgDG03Z>vVtS+~-PCtj%8VZczL&i$AXTA1yv2 z5B{peJge3(x0J?Fvmf}^@FR6M(3)pe=jM_YW* z^YCL8KbSrZ)fV()rq-_K(OP9``Oimdy~Vei55LRe^A!Jq#cx;qS0-P)0Q#H+FTm(+ zNn3zXKe4?)(3=*Z6e>yT`na0+xU+ztG?hvbjTa*1JbiUNbs;9=EPkEhhg$qK#g9}x zPfvgWtP^Z7tkuU_>e{LTP;3)krw1CF*_TZUp?!szYqRZh=PuQFW3r<}=WCDJhPoH# zYt?Oz=1nm44u(n!wBxob?s+dNC1!dGQ7TmqnNX<3JHBk{nd{Mtv>?Yx?_F!|XmJyY zQ2$ld;5h0uV`8Q$+Z{rRwRl(8W~v*o`OUXh^d=WGA4AI~+9$M`TUTgxi&wzBsV+Zp z)o5-h?~uq^YVB(!17g;2H=>!x)GI!$2m;1FJy^I07yJjpx>SAPx)zQ^8`e1snin;1&oOLju5n z+5AZdd0;gt1*gFs5W*wRkO)%29IyiH0VlyV;6I*R0dZgim<$$!4WJa9 z1~))J2DU&v7y%}O1z=r43RAYcO70(ycJFcsv3P2d1H3+{lBiLA(h0U#Y@ zgTjdg2`?0X;S7|(U0SH!?^(Hjm)6kX_pCz(*RMKFN_T13m>u4+TN_0eQ~f=L7=_aH zJ-Wg|ciMYeb-S&LWbM(0+TM|ad$gBq8IraaVTOC&UMl@t55_MS!3 z20n|VrIaV}uK%I-F_F6XA=5Ulj5*def>+E#R3zeKt&qTXevIX(Bx6(Px_XjigLD^BL10|ADV7wj(}#uOskJ!iUQwUw((; zC&Sm5GroNIQTQzQ2Xs_mRWCyz4kThi(}u5_4SZ>zM}1lwA0L8SrCL ztW92$(3#cw&yH(ND|Buvznqa|OqWPLS`$3oqpGHgR1Mf^eclGA;`25;tRz`PcBLsnB%j6A{VgLF!=^MPsMwEYZiO}P6@B6hEukV}VP6ulXNlM> zN%+zy6LR4VP7X8Xr^*{&YTn&~nQ~bPauB?nD)*iA5hR^NFbl!!sWQ`7uv-Z@bIjP6 zD&PAGB2OWhgW!`?>37P<)Iuf5MQ}b<-u4w-R|1YLGk!{yI$!ztNd5}JTm=85`fhH_ zl>G?wJOlx9nM<~227b*j`JpuSaKA$@AOAJWwV9IhHU8(Jb|g(+gYviL_%aQd)ljQd zd|C^r_B_%r)2tHqn@sJEZ<5Q7WD*grdWaX*y2d94nzX(1}qQCLsvlPD=o-=oR`E&5b68J5T zi}9^btonY7U@3xk9+#)S)$XtR&f`|P)YJC@D&$EJN{xcA$fgd?S8D{oWs2)8-k0J1 zv&W^)SuMUIK{F6k%SZ6N#~%6A`K(VdT}DAKKp{qg&-v8CaS8Gv+*eA$%W6KJUY?RD2Qq1lfPyCx`U!;EUn2B>FoaJ`3Iu_!VPh)ptHQbWRCY zAXqy_j56Q)uy3uamZX+x0me$iACHlz%6xKQcNsab3c=Aa6*XmMnNJQxm1FoN6t0bt zhsu3?u0&96HG)4YeU2>m@#*@WG^|0Pro?>jlXo)||1x|%S?|kVR{UD{&Jz5CkACtG z@ay0cB-fWetoZftkI8jkKK26qEAUT9+65mwo8gUD;q%hvy&qZKymEmlcF*rdA}=D{ zfOJv1bo)Qjl}fr1={Aqwvlq2C6@F{}i1an2J59d>Dg*^e@H&DoO>dQgz@HFsnxOHG zC$u3y`Pf^iq??i6@`QHeC!d(wE+Ksb={=9%e@SN`)!#%KF6%G(H2T*SzXiUr-2E?4 z8GA1In9R70a4W(dQgGSFQ@P@|!S}U1ZMp2@Dfzz$-$F=_@?ULWMWRnBemndW<*AZS z`Wb!)e1VD?Z)IHZN%B!8d>i2kE2Mu3`(8o#4#IaWpNp^fL}R}amLS|~`TUnK_A0`i z2)|W6`RLj&nkLy-eFENzhVd>M-;b5^SGCF_iunbvZUpru?JCi|@{3QPo0V`ELRQdz z@yW2rU*UJdCt9A$e)S1zjS{|xaIo^kM78k8qMCT=U7bBE|24pK5tZx#nXr z_&UP92w${IZo`~mnFNxI>~uT=a& z_*mJ0!>94nZ^C~JKSZK$`tVus#wYM=$H}UjJ~1m-f*#p-=5L=Mn%qI~6@qWa%b+_xf|UsLuMyOc{dasK8+e!SPQ%y9sHjE91{2O~7G{T1!h z8yRKDU&$ysulqDNHvE;te{A_1{ZL?anPaQ;C|l7mzDMJz^2zHh4+RGPTO-PjjUUjs zZrS+dp};Egvt6$o)~{C@7tpw+k{l+#J{0Ksw?>!)jf-g1k_3ldIhLEJ_#ffJWvefL zUGYD`caSj6M}L$C&+)NFPnqY-A6EQj_{nlz;}{8V{~N2r{}=ulNz;A!&5HjSezu(O z<--iUQMD`ZOD0s*mv3~vQ!DR4*jjb&?D>wPdRK1BPBX6u6CP z{TGC#Dk}dY%y3c)zal&|L0)v~m1D^>2&!E}@Kt4mRyp;`2a&%1n7xjIU9$XrQn*|3 zzrnkt+?S7X!T$~)%)2{2`YRQG1HPH;_vKwx;BUfn97Yu%{TYh?1D>-~eEG|Y{}Xo(tA z)x*t8^<=HrH!pM5qjUrFlGnZJ>JjFp`G6g1UY09`hUO&?*>&|s=B4?d-PpY3?XS9e z6Z4XX?YjE?=B4+6JAfBVxUQ==GwBmwu%M{o6jiA;7F_f0i@Ka&jzZ4UQbDrU%H`i#FbA z3(@@v;!KF%GSoJ1Y&n-}>P=mNeCk0NY$(^O;j?8eeAZSzxvDCU*3!dV|9R3S?!ZF&oq zrDN*pb>&7~J&5%^sJaqSkLz&7t98s#%89VFHYiD?rFC3gH@Mp&?V9NI*ov6cgnW2Xa+>Jl?9AaP>&5qD+?uX2w{!i((sRrE z^#OL~Voc+ODA>RE7%xS_{=clIq_$a864hypCxl^534zthri9Q()-=^0<(x57FQgd; zvc|}^X2dSOnI3OjVF^|%0rMdUMsk9%soXe89G`cDS5~CJsEuM-zu0vZDoY zo%#TN`;L{Do2nvu0JTiM3y<0q32cR0fu)w$3Ue#QdXlug6?$yxR|W!FV_@%Cso$Ew zzqPnRIM?@MRg+`m^)*{EWmno7Kdi{cV7rM#$6z~=ljN|lAqLxnpYYf|9)sQ_32uYl zRO#9Vy%#OLk~ZkA^y-zhL64(el!dsq#DV9|L2dPsjtgj*JM|C1I(W8}$Ieg;*VRk;fP*kMs?Lf`W7;pV<;yY58CQDLBy(6p4 zXpjd`j_1dF;(ELz^?cuWso#ko9j`F!A zwjWzu37q37M&G($t!sBd`?@8Gi$nWXh75{ByB2#viPZr(SGYN_RZT>}9sdxy9;Y{T zbeQ1D$97%u)pLT>R}DsLSIkY8^<9bMGjg=6-qA7Js~FJ@#U&oa0o_pCZH2K3fuj^P zvqd@CjZ!+~^%T$@PhXjyM%wKYt^6;9w7H}po(Pt9CtHK%Tz5ijCa!q>QTs%X+MIaQ zo>FQZc{SmBH?%J(YJtS4>!1WZ-d^I-%}hY>zGZSn0wzDQJRFC2FgCU7;GG1jiA$0a z@SffSNl>Pz4i@yF4%T*W?V%sDu{xL2ljuxvZ|+HoY`Y}Ao{OH$`~kA(%cBh25x}>21t!T{A5F9tskOHQH)u05N1vfzB8OT8< z$O9$d2)F}6W+DT_KsG1@v-j}lB)9`Yo<#u+1KFSu8~|rQKsLs~FpvpWgA#BS+yM1* zSfmE2U^>_U_J9lE4rn|J+aMF#Y=E9%JeUJEfIZ*>xC0tLkB!;|#4NAaqa0zJn zL>|QF??`yaRy;y)%pRjABlHIL(cjCqGyd-tC+knC{SoT*kOj#+p=HbZWFAVgIUY~{ zlhf*VkJK}4>}qI~qDM3INlMYx&TLV4E978`K9IW_qqtkksdTzJVq%fHdrfv*caG8A zu`6q|u8y3VtL~WV7;S3)t?u5JsK?B^DUWgYp{%#=epYvfB`npHjY;M1xD=%7U2u-3 z>Y?_ZFG!WK`u!4+#)#lm>6nH_j*Lyy8`*N)3)A#RIA1}^AE&3fEn#DDG9+n?-j;rA zp1Qjtd)3`-xjqJ)MB%G33xIIgj}`QFlqv3g53)6E;Js}~AB8cR?O zhsZE*3w*vv^lGV=+$mw$3YD91xy92K?%43?tsQGQXfG&$Oaq09&icxEvHU{M34%mgB4&qI07z!JIno? zej$ZySSs9+@Sd$Wo64FfO|ta{jzl)Qm|r!?(I27!hUQQJ*^-;XkRV&O<}iP>Sq|pt z$@c0EC1Mt3)mH}2q9XK_tXcZ+Y_c6YTR-MVTfml?AFA}h!t6O%cwDy5p_m_+Q*(5& zrOTvTeJ+m{*K_q}97mMyI)pX0=Mb$9GQ)hE@qpn$o0Gv_=Wi`y;YSdbic8FO;R zT)n0l$?8Axd4zRy8PjCDug;}@+4{O8=Mjh*_+!GTJN;n1rSg~=7V@J0!#)Az!q=- zoGp^y7Ba7x%-*B#IrP9xSK^A7!0&t)|VS)Vfyl zW>RKdtBJGXMW(u%IFktLI#?Zz6mMOtsWVBnuGQR`%(1Ssl+HTqni(_C@kyl>1Yua$ zY7R~AEMf|(v$d~f$bHQFL@YK#HGNK2M7$4?uZUD1V!I;d_z=exvCfCMrifA>g6TDX zDYJ<18hYL0C1!wKxs(X&dX&13x2|*4b*go}MqSUbuJ@|zb=LJcbzN#*-&NOT)-_Xc zb&Ho;=DCyz>zX+^%v;w?%wgWTW_B)AvX`0}GH)rZb!XXVIR`E0qUGqzOj#4l>18=% zEoYwPY_yz%mUGc^^nA;o<@Ba?)}*e`Qa;8HMZldW4*dHmVX2uGN0K!38=` z|J1iGl2gDBv5R|sf$p*+F?*WQ<$8$0CxDHds`AZpy?$U$RqHK0HR0ysz$<1STR&4p zV~<|ih^kC4Sl78DIQluYP!9_36=3PBSLpnyxLqW-kV)V?9~u^#HxonEyChtmP#QaY zH0&lF+?w}5YZqbk1COjBM%AyOi^LrC=g`C)>Oo2ovy8v_C}^faZjnly>`;28MdSt{ zjZ@FnNX}h5PY1|OjPt#LU5QG*j!9Omyk#~ ziGtJWOGb)InAhXe;0BXiqIoo$W#>AL$ zQB+s4tjr*3BJehdM`+m!LxL}MzDfLfxC)EApl?9teNyc^U|D2uV!AFO+xGC zloGG`t0rNHb*-8NnQUE~Z9=|v9jt!u+pX)!G9JHHucXi9$PP81Ueh$0rBp5mX}_^j z4?*TyMNRA`QLC6y?PjZdU-apW^ryy-sXW!Ko20E`W;U4*I;w=KYNVSMS7IQ{*Js+8 zspi^)Dw}R>$<`a)_kKua8K}zC%_gJg@VLJHG}Dg}FOenpah8m?lw79At}hW>!?4QW zs+jb&mzZ_VsAJJ;hP`m6Os&tk?%nY0=~DkZV2jufx1 zSj-tI=agV6K91B8V@<^x=SWFjgJ2ng?@d9Zyt+njQDN_tlBQwrRvr0gjsAe^mM2P` zrFnO65-#RR)~yZL23x}s{Fds%N(yoLsey0(@>=d6{$kurQOweWEa z_mP~nR3$He7~U8IKfkX0wpMQ*JfA~%RF0{i0ghk16ino2(0iTUvLcWf>+qD0rz3Uc zm38|4!ACrv?)P{~P@d|@@9Xqd6`rEj>x}~Vh@Wx8qb!l>feqxD^?I=VMqPPfy*{KO zR^{j#V+mkZJ*o1F?%kU}GG0OO1cDcNcl;H-dEFQ5d5g>uyrMQ^oiLsjh&H^m=wmFQ z@RD97;BokA8E)xH!W>?@TmGsZ9PFi3y;H49521o{O8u*}9H-Zj!)34P5y1mI9=$6k zJtTO8uIk0`4dm*0Ot+Jq4a@|!t52v6wf+@}zO588P#7$c8}+7PgV{!`a#!uy>r|H^ z8u*m^!IHL7-{{$_H&Oy$!`lSBHIVkN`IJ_!;wQonlFh#SO~q%zkCgD&smLQEtYB2K zuY~HqPF>BCGemPVP*?s}bqRotP)cou5h_-WBta60-^O|3N2Rk~jHO zs?G4mlklq|<%>-|wLfe#Mkgb9$!oOy33k^u81AezTA*~Y(5cbT6L91>biUnOu~bjn z`33<$g-#ENc|&i-L~q&~G@;(6b*B6}-_$z>PW6PWvPqL2`{=y#7x2c-$$hL~P5z3b^LonN0}N7oO4=4CwR%d<7Fv(X zjl6|ubvHeE-O=9Fb5iU`xxIx@o+cE3iQMWF`lPMo)-&)^8q1(J*}SlQe4s8RTj{{2 zG_EW!)q(Y@9L|aV7M=G!|6;)+aSIhPVjD|fD?IwD^HJ5Qm-O96{CdgQZDfP>&iP2$ zx{Vy3PJp&1o*X_mo*W+cxxKO!n!H71XQ0zS2EJ9Xbz!6wzz58PZ|U`$l<~jS!nPg1 z&!RI)qPF`abQ-*o4ZpOByu4k1z>fR*c0IkK++ug&F$aZFlD5OA+%_wI7W`;A;me1; zO=M=nA8zVNNY(`Q>OA%~O~>J;@=qscZF%ACik0$_au^T#96Z#L>u>X{QA@(#@u@di z?;y@a+(K5q;}d?l;-7<05Lby0pHxDE=E6T0B{NI(=5?Nn^40)HaA9+1d0Oxrqa5}{ z$-WX2d@f3UDbXLMh3Lgr7d;QJcA2!(Cy#b3eja?Rl<)KjD(YSM=i#4}q<4Mv*T4tN zhkvcPCkqlXDUa{o)q@>SoVdl=)&XvxaYuriNH4(0(dIJ2&5Y_%uiAEBwTnt^A!=pK zrP?l^-|+BV2wp(&M{}9AOK)z+ePb6rnfKRsS1Bw)VR;L=f47g%NxKm&M(|+^Dc()@ z@L>xp&fc+7Z#lY~u~OnT>hq1=)aS^S-u$$h;ocJdp4q^ry@#nKn0mIQyzrjhIrv$R zruxaME}HlC${4j=dyg)!k7pzP`{p&rN!O6FZ}>`6Ym4Ae=^Dk~azDhnH-|F$=UoAK zJaLD|zoqZ%)m#PMs7U#4I^4zkiDSL@^ngI7A>Y!x+|A_pZcvALzk>UP_s_OYr+V6qO~~*|PAyUPZd`r?{_Oll*sW{>&pJlrsA7>M`PN z@De3gc%)cds<$S&dr{F}B&-Q?v6Sv_f=An1N%~6UeloVNBv?+G<>YdNcvxSbZ1xth zdPL}}idgyKpz*pmJTTM|=ZAXD;MaZPqAEjQiT+S;8hBq!WnmbSRZ61bpQba({*cPk z+#^&maw=hnbw;;&0(oEA{h=8YcIcfyWaXMZ>?3Oaa?-S-tql6eX9%}Pd>{ZtoNLz*4bn^)AMq5JZ7eKS7M8%e}So5uGy)_k>%LLpz|%ggPkXVnYXD#i*K?0fziKtbCw&=Am8Q}Ynd$N z!+6sAww|bV0o5bcC3ojq(M|bm@Kv#yj~tDFWZc5JSPsc z8xJyOE3k8N%y22U8!gmp^A4k<%Nlvv{0b#^rGE`~s>8^$x%|yhjm>YOWWD5HqgXf6 zUDm+J=C{;3^=Xby$TqpI8xOh~m;)1=U!a*L8DbdqY%OJyVLZx``(eZA$gsn0cN!#d zlsnkpFpn3Gb{XSb)+oZ}H&6=xqHwpnjCflu_jQ-SX`U^jWL7m^nhUCmxde%>YRtCN z>u;-S6uazZ*K70ZXvR-c1BhU(hwET*Wr}<9fAj+3tZrL)Q zdS1fp;QGVkZ;hn=L*+SM%_wv&H@i-oA78k-Obvh!O9y8ew(lZ$b;^@Jd6B zY?f)e)-?XM+i7z;*EUAlzijI+u5J8Bb6E|9jq~$j+VKg)h;U;UHRMb<l;7w zJ99NKo}GPzY0KKhv^*dYq=KnnG1v|cfg2z|SWp2yK?;}(R)Z375?lebS6~OEfT>^w z*bYvEYanDLHoyRo4(6<6QEmkn2f$h2w+bVm6Bq&}g9Ts%*aJ?3YoPW^1O$eGOpp&Y zfkU7S_^fKqT8+yNnL2xkq8aznV74)Vbsa1z`BAulsY1crfZPzbhz zL*NqdTgzlHhy$r$I#>a=gX7>52v~;>=m}ClHYfxo;0U-fn?KrmmI^^UNC(+q9oPj< zgKHq<6|xQt0O=qPtOljvG`IzVUd09&0kT0MI0VW-&<4T)i69ls0V_cBQvRFchB}q%Pj$xuz>Q7Wqm8+{BnulG z4RAI$Hrle)<6L7yokY{339>LrZelbD3(Hdbe5?ob@eXnygmce+k0z$_cS^aV1m16` zv+M@n&t012+;23(S${ufC&;P$je()BnD5lUnBuacX!EOYeWE5P${3)|(TSpU zO_POD#_ZnOYh*rX4SIqUFc~ZW8^9iL5?ld(ucHfEgG4YM%mFK2H_r!aX*716j3aJY(-0kT=Y(wQ#2cwZA zbg*3(t!L*6-(@Z9!f}789T9#gGdfamAIh4J#ye`krW3ZtN^U3P12Q`y)@X{85le6# zWPPkLO??dY+RONE+1aRVr%UVI*=VOsnq)qtqi{HR6=QEJ|BNxJ$-1tFzubW5B%8o4 z6i|1G?P3gN(-MQq)T8LDj7^&-0Y-HAaL+1%Yw zOTfQ&$8Vy9#}j6vJ0Tu#cE@8fGQsFTc@!j&T#>`d`9y3z=;Z72{Xqg}Z)gv6qvT)@ zA~s5HD`&n$KWLaI^ptg0Aw5V)#j^Q9qeWP8s=eZ;bRd-WqBgaQ3b$6SK4=WKS4op@ zJ?RBG+^6*nifesOBh)`E&GI9*r#a>7WKSx8m|W~hKw%Qri_!^~zP*gO)Rd#@?zG(P zWwf>XkC8ULsbbY7t+z4Pv3ZPLX1}6`2Og+Hov%yFMW~x4xDT=4EKz+7H>1+>KKSn{ z!HJMvB`VQ)64}Z`D=qQeNXwl>BSe3k3ClfFvoD#tN4oYkp26AK7q1`5#lA%3Rmtc_ zKECQ+(vK=+JLFCnKt<#f&V>U}+9kUO689Q%b)YfP?w27W2N}KDmAHNoxw}oy3^G3B zu=$OHxjQK51{>Wuax;90PaNh9AwTcR${~b**S&v;VIHS4=^<>_k~PW+m!l6E^I60n zKGduW)C`XB9*Vaue1i{fTjcUkBS+N*vzBHLL)1fxhS3oAke$Ow(Rhg-PNn=na)%R< zp0ay5an6&g!-)uA88QoY$isMBAsG)-5mrdi!^RknRJr{y5jZ4KkKi1UB_Rd!Q_bgxH+@TezPQegfWq?(JdT-pT}hP2-18}ZjbP(Ln+AwbyKD#6Vy%j z`eb97&33=UJW8b6ay%JL!BN@yDE>Oj%}0$#_&UhI6yiNz=A~Fx%yeE#!OD5DjUt`r zC2|z$Tqi3>VPwA?9Yw7!l7XWMp-5(oHVRbsnCXmo3~whS_A#S{N%P5xY5dS?thKkdE97e*XBv{F-9BZjviyw zVpqkqG2~3SY#l>_A7HBltz#Q`Hk}6GW!ao=s9hhwtGnY8Io7=V)>!hSodiE&HXkOH`2Mq|nM@l;0j?B% zJZ;-iNg7Z21#=b|<;PKQ$y?ufa!3zHgC5jZ=MDis@!X_He+ENr5BAX}Dm8ZN=SqFD@rwNGn^Lq^Ekd#lf zg3Tm^W*lEeJe$eFOyfHa18=1Jov zTEDc(1b6pIqrK_|T4&&??_{ELLJ3;o6ilX0s>(IlXl9J1G12p-S{6MvCz50ld@Wg+ zMV+iAd$WwbN-^je4Ay(f2r-^OJI2(mBSW5|ac(2?pE9CdJ@Tz|@zLa2fpz5Tr;K2J z$^Y`7IE9EaxjMz@g0p6dp-w=dmx$)<{jO8ZcEU_x{#5ibWb@RDG#5{!)=nt!)NXU3 zr0p~Um>|8Tk-smhgfg+t}cbjVL+)C@CLYiD5Z8#y|ovU!V` zNl$yd&@OMi;s^^=XI-xYZ83aZ(qF$G9KY{l*-_P~XYfk!v>2#m|w-FC_Xo8u~BX!=F=qP=ec)XRNhz{Nm>4 z`RRQvvGbv)xv$RW0hi9_`T`=9Dd7u^0%HHxLXymJqYJU{qi}-7Wfe9JPD}PAhc6;V zyJg@aT9I2aZxKTv&U7}bXwYI(cT=JkQ^jt|*u}Bb^|N(+TkoGXKLHJ%v>MJnM?)WM+K65x`!wf%#SkXhys&AJebO?R+BssyK@R@?8t*-MdZOsxmyIgQlg5fCGW_n zVsnuARxxd|^G!KlY&2JH6)|3*@)QXz>SZYx3g-a{TS0op%J3EZJb6uY1;sgAZm&Q# zTVht?oR^H1#v-;|-CRlBv)%1i86Vkri{SQ4W=)dB)pSGE-}Xd5ZDC*wX|;|C;VrAl z!|JkowebVn0oSY{qjt#AHPqM%lJqhY028F>Wh2?FH7}DnpGx>z`dq$Pveqc7s1ujg zlIm2kts`t+h+4-FeSz#)$5`nzxxJ3ma<=7qhH~1w^7wkAm?@mw>q*cgY5$7x7UQUk zuMln@srf3Z$;8;~vMgH(7}DF-(gbDiU8NssMj zP{^h)&v8y?nFjRE1gZzK(~(kbgRP$)QjZVyxi4=t>eh4pnW!?u=2tESi}aLca0gtcKB@};8yUv$=y#5? z%KOb2!5GH8zQwf~!JPk%X}rwexoJ0F>PH3eX3Ot9PPCWnzZ?cD=dS(wu5(M*M|l1NV%-)Q@St zbiIR*6SCuuG0sj;f4)7zw!2HQ)sm#UaP;RUcT#aZP`yyO}T0~ z-&dW_8&2oPbT3){&Kia*bDfm|Gp!6*SIs$sj^lPUr_fUrRCoT#FLGg!a|$_qH^}*x zYUj5FJ7>|lM&IWgOly&IpL3kcZZ_67zfY{W-Wtwym(_mT{Jya!BYio)^L&m zhox^#=OX(Xo1|Y&C*S0#>6}cvnpO*gFUyWv&PVyF2ZlOl(>%JDhB{xi(dtEqIp3n4 zI~V30=de|G_X>ADX>&~|v0|TU&8Hr(?`-G#)Wa290Y@|-;8gdT2I$)+xdS7eZkucQ zZp&YsmFlvFr23e|HgY~Wdpolwhd>$7Hn9Z-bOJ-bbdV3WfCJzxxB-GT^E?dV!3dBE z^1ueL2b>1iK*$@+(}6^g3bH{V*aeP*D{nC6slACY5D!wpbg&wffV1ER2-$)mFa(ST z3&1+C3mgYmfVP#{MGyy4z*MjpYybzqS#SdcY{M4l2~xK4d_9$m6<|9!4laS9w}_PN zXzXk>d%$)k8Np((0UQArK)?>d1BoCN$?#fRMMzOfUpY1&cumI0CK!?Hz1@ zIFJISg4Lh|oCeq4A%p6bumKvRfT>^u*aI#Bzn#o|fkcoFvcWpA3!DbmK;w4_0AzwZ zPy&vC3*Zi@=f*x51~S0{unrsn7u>T^;v!@hDFH*kWUv5i0;S**@Y_v5AP%I0>7Wp7 z0Y|_E;QyYVUj&E;BS1DN1P8!b5b{1H15&|sumv2L&7WH!Xb&F22#^O>gCpPq2-%BA zkP4=Q6<|9!4lV)zeFO~R!3Z!FEC!|EGzj{D(gvwuI>-l`z*$i127eltk}@z1WP-fX z9SK!z#m$@%Mm8Tucx8v&-^^Lx@yZUiGVtBX;wWd3;~X~)8na%}GRoP5G18M!&L}+x z?eVfE%GoG*{M*(Vpm*8ud28A5d21Vh`Gwf$tuMqrFEP!X4QxnoWYgxV0g~O^833`+ z;y2?2AAiTPr?z?7{rvo%mov?2TC*j*g_BeA2zdWa>D|KF(2mQdlRA>u!r8&I8p?YY zXz8=jsx6mWINJu-ez!7u2Il6g=&_M9!>-X&?0A}`&G{;Nb#<31HBU9DVqWfN_0{Fw zEiqq?wsh8&1w>eGv~&i^X|7yPW~NVmatd1#cpKNr>%`H{5X>b+I~(0+ykD6PUD>lq zw~y>`^73;wgVgLsN1sDH!=*gh*(Er9Z)H5Ip}xS3r(WH>G`EcgnU^P?X1iywc}Y}R ze1Cz-%_A*|)vgDewOuFnc|w))mPF_ZTyWWk7N?S;a&&>zY~^ek{K3Z-?cJ}tKnAvQ zwhDgfaHTeLMQAT+MKN#lp;dAg$bLot?nA5WT_6SN_E6nvUa~j1X>hwwEA9DLXh>>n zr^etDl?Gu);NuWY^HEhr;4xO!Ypg+71clUw+mC%T15EMt*3P@#^j#@R5q>@zDq-c|O6ya8LauFeXB-$J#Gg>|)Rc7I(ZeW7G=@So3a5Tqwc$yduGC6>Xf20-ht>u1Bo!Bx|vnd}`wi z4)aoKgTM_8$CJYMS?{2Zw{<>(=V@)J9CPtJg0JK_+cHykqOG%UMIDc9hd2-MOeJn0 z!dA3Lt%tI01& zV0(J}Y)NiUQ1b{XMsnMmaXSMO@H|ZZaZkc#ED4N|{JBgI{_?h2w}*Ei&*!7^>v5UY z!Rg&mn$0Qz))pWbCwDtIz1vi>Wq3zCEQEjegv{#b>|n=zFV>k@kz#h0u?-4^(v)Ph^KwpHQhivTR>>k$R3vcor!6*5}G$s>Hk=`u1+llcB35vzTVmv$|xv`AB z9+BO#K3VJPjF{J44L|JxhbgZk1G+lBn?y+~ zQvF4wsj{)Fv#mY#)W0(+svGj<$e&a41~R#ukLUFWjY5Q1PRXYTg0Gyia!S<*RZ$j+ z-kqQ8u&=xsXjPO&zS}B!X{bA46k#TSg$(Ldz}J?#x0zhbnW}c$o$dtfO;vb2HKrIp z$sXm(@8VYEZvi?IAMey0FMO@ZXQhq@D@5$e<3LHgzyGy7kl^$lW0WnElwc)-pTCyk z1m^>G-1-mlVQO!{VLdRKpWxK&MW>}l4>WN9rEw4q{UuCvm#aOTt#}~J>f!WmZRMEx z2MJ*{;>%}b)q_s&4(M#Th(KS1;6VxO>GW>orgrs&e;J;f^5u`h8*AZrej|VM^f8ps z3&A=BzkDMTdie-;BGA_(h?jG{d_suo4gU%}hsyW%;n%gV*HibfGBZ*L-=A%Xp!P3z7$=dIX|;Kq#@|A1Q5 z`;7DE_@;lwk92*1;i`R6@pEiYy@;Mn1c4ZGPAHUOQi=xp`sM9Tl_6eyi-=zQwc zN&7!Ku7T*hh0af2o%R1mCs*lgM@Re48y{i0Xbh@4%0d+g!4%Dtxdrt0HTQ22(3b5Pw%L`vyB3+P?d@Jb4J-cOrjO za)45s{j@v7 z$;IRCZ7Q0OQNz&Mht|38<@sSw?;&g1auh+p2MC-$cuFPkB_=9;HrHp%z~LmX6rI^J zZMaW&cN9KgKRlBH2)V9a+q^7Sqw0`h42=Dgo%MpRdhB|)iY^t~NN1?7hM(*r zOJ=Ob7Zs9u8dxezEN81lraj8gsw~+V6#VdyRx*?cHJ&t0D1UelHAm~FiMqNPDw<~M znx}Oy6-*{8w`IHdQPU^U<5fcInmF<*p>?gS z>-U-37*D8ZH#R>?{(nr~e*Tju|6OZn6aG~rB2%alpPztVPRcdpz~&KEk#**T*x{q}5x_V88v?e3L70z2&SO^iA%w z;Ht}KNZrY1xQ%b}sJ+*dPSdB#kYtZlrUxpENRH>oVXS0UPiL?s^`hUG;n{y(^}Fyv zEn`zDi3coWvr;m{yAQj^F-uj;_^JfUQ2VfZwuMuP=5-a@+wu}uYztT9cSe!l8;bnS zDe^n7$nU@e%b&0WGG_*#rm_(4!9)*Oy%`8|cX}8%1xgYd# zPPVH~>ZJb8&ut;@$N^5bk1fo7b%=AQZg{#OHZ9)s>5;@y40kni=Z>PaPjf$P3|-!L z+zDgUuv=YO|2AWc846`2ajbK?ord-KxztsGDbDG(fwC}#AwJs7<;GywZ=5s2PCI$d zIOivf7uS8qIn8G8den39*m!4zZJZR0cP_Wnl(kOSHo+NT_#RV9Yts(N#?Q?XUr!_w zXq_&bz!f7V;UO(jJY+0)5|^jtX`LCEif`{q$4R*AoXUZl$KB^soxj>xC$lx(In(g8 z_-tBT&yF#@-*v{>-#;neyz3lkSIxP}&H<{`_VRo9ykW9)i)x@*hAC5=TWF0nd(U~) z$UW@|T6fR)Txv~q_OrE=%&81JQt>OW;r~>E5HpQN%axc-l4m#D?l7;dEvH4SHM zVLsj2!T!k^nKa$mUNwS#fo!vsIfJvC%wRO}4fT7JgQklVZ^WQS`S-c2f6mHh?>pN& z>d??=eh%BOGtGrYF)iEF#hzs@}0y@Rwgq6ZM;1ch$wt zucJ~I?_v}T?L$}4V-&KR@j?`bl2A6SB3ghppi?Lh1^>Vh9*RRrXaU-Qa?lO* z7zO{x1yC#+jb@?MXcxMHw0#WYp%!S+zEncUj}>Sex`G~~%KI5JLH*DKv;u8I7twuG z_9sR|Q5;G_^Uyk!gKi-IpYa2=LA}u|v;yrz7mmq? zaobH+9B~d&Z{&|M(wfillG5xb zkD-zhf7DqjtW0a~b$PO@a4swI)E_OjwYIv>QN{c@kSF_((%kq9ABIc*QD@=qmw8h6 z81{c-PmlH3(@tcbti;~$4)&{Gm0ylM?H}ez=yBQx%hU_pSGkpEFK|`pi{2@BGUqtM z#3kkMapz1vHWz=wdC!>estU1j!7qZo^XXlC!GTv%EP74`LOLrd;elm> z?G;4OHgpW#K-w{K5o&I`?xZlI}8H*d{4;~b!d ztFsBrgfq?%{ZIqVN-xP=N_X_DGjvA}HIUaYIBQ7W86J1POTigl>{XMAXK7MZlVxX} zUDTWN4VP%J_@AR*?jTjpIn{*YLl@ZZXM(aym-*)yH%OPg=bRUK7q#-dQ_b#F4zezA z(fbSi`#6i-4p+C_N6)EzI2m52N73r zi#M3%3EM3m&ny0PCfO6bhN#=T&g8>Uw|N!2r>V^O)m~aE=Q$gwJNY=me4Q0WYF5IU zJZC36dlwe`**X%Co5t$+KU{ z`iEBG;WV{vRoEk(ek-jX@sj!%+4_i_Ut97Y(f&=6DvxRRCQ0&R%e2yi(~q5#Y49B` z;Ho1FoKb|Jj{3c&fDlYq_NwGrR<-^m=gy-$WEH(jB~;P-k6nEs**cufVO#e6AhwP? z_^-1r)=&N=OzR}_iL*#a2$n`RR>qtJ$?&SB3hC zAFl67q*Jd3x;XWKg(MUIQM%-9B5y8aRsLo;2kulA4C_2yI~8+H6BBe}Xh zg2_PL481AM!TE-6O$5(Vw{YLkLzv(hWa?^ydIyuM?30NmSJ@{kP5lF=BQ1$~kmh{K8NZR`AYF^+tf3Cw67k_=S?NezMpj(sptjJj$z>R;m&>O?)pEAwrP=Fr9 zEdEOY1c1yGRZOqNXEqNP<2&}Fis4^jaup*?mzDjq7e2EV-;* zIlZxioaM31R+ibaU0JRxv}AX%vgDh{a4h!}TBa$>99e>;?X3HFxIWWiyXQ`*q(AW? zff6DJ*gp5h2$fGhwIaf%G2ve=HY;CKXR(>rF4$w2gq`EWLT@N`)x_`1a;_#9Bo@8l zt%c=7X;%wNzeR=NRhG}m_F8(^)C_8l)o2&Gf*zxg(=>rlE7TLEpbWGD?L$}4V^scE zTCk`$Nfj8L>Xu`I)JVq{XBs|ZBTENay~Qq`K;P{WyfB})AdO`YLoBB%8c52C9uA>zEI`Q zHg(9K_hd{Ris(J}{5m?*x$eo~x)gvf#kZb5-tG*LckAgD6<5{M+o+TB>T%LoUeoDn zJK47N_0!6>asxfW_dn!6cH?RAH2-bUp0$lO@l@U`OB(3ka$2{B`WIZ%XrzDdqdfoR zMZLZ9v?AM0dG4b--rX+FYMY9o()3xpKR_*Mb`4 z7unr{D7YhcTjO=WHd1xz~=17-TIK3$|T2Vo;wx%^v z+1wr3T4$=yHJRUrgT-Zk8_GWWaVYec>TNkuq<>pXD`kFLoQ#$IZS`;M#m39WI~=b| z&g*&v%ZwhpZk6`tZ;*DQW!M{*=__UWTrRz#S95%xW|Q#xtP7|dqt{cZ(Bcj1^TZgc zk}B!mdg<0$s**Bexz~Dfp_N`zF2?A=es7XeZPI1ZM83C6rPNL@X+_wfMAm)vZl}lC zHoMoi(`hYCckgdcwa7hOBZnKpf@vbBT}Bzjbg?Sz3h+ z3>tK!khNiyQg7LQ3+ZzJT|wGK@-vD;ZBTENf)=Aq=oHFB!IvmJCt(h?LE5>7VkrkMBinHIw&xkxn!$dg-aW*NyJYeUfW> zW4b0m2_)V%iB7#M)UU`~~OJZTO~|9;lv@T-0VGoM`~^-7NX;_O|xo|Gxy-;>Oi&x88o z^K+8kAD^F-_5Hbas1)=kB<-c{08m=`5AcSh7a`d<0QcZjc^7zy{g%YtWNiRjqVrvpN(^_(q^pEHiyq8=g?rtO#QU>2g5+ie@ z`bfN*FSAGD@lUdQq?KUBN0DIFq}eDusV2ilQE1X6bTm#rly(ZsC4IDholG-$48B~G z%rSbhDziRsQ=hV7#@o1gP5QsBTdM|gl(U8cW)UP7^G5K2P}&^ojST}1a$+281Ypw1`}O+ky%HgpW- zA^i&d7}NswLlaOo+JeraJ1FF;_No?jl}ZftL(@?<+J=sy$0+z34>J^tMx$A11KNjf zBA@F7ND7wdl|pBdfYUd5vb*+Dm!y6Pqx;7s^y!}{w!!vD?`-lqMfR0=iTj?uNhW=) zmo|R$)zZ{R$yHhQv0l@+0p50YAO4sqcJk82uX%>AwOG{qhAlu6vh_-S&v7I(L(1v) z=OsH^_YcZs-i8fd)TVDk_bl;WMW6~Su`9)gPQwTGY%vb3%4Ug|?2s>YW zQ=`SFJVI;9>`(RO^hfHh)?1dlPe=oAkZn*b8iXdGd1&2@jnTu|TUiaUeWsW7E6-)` zXGzu1^cwVWmJD$4%HuPtwrw);Gaky@WT6N7P3t1CAoNL>yDP&T9o$f<3%6bqlQ+3WD8BHlb&C||GBs|Gw` z?n+^f(#5upV(hb?;1t>yzVq85my(!Mr=0GP==D6icSwQ<>FbG-9kRrOtyl)lUi9on z)y?dXj-&0RvOdRSe`dNUUsN18twTk&ObcM!GQE=eUKA58W`C|1jur;UL1kYV``&Vw zpFzF7-l*GGQMuE4XDn%IOWU2E;;>U@Zy;nltjV_2$g`ZaqM9zrf!r z_}f;3Ht02j+A`CoFg{escX|A^rfTl8{FOmp=uxt5gRY0}vORm(*>}*;r<+3Ul5-n~ zp<<^&a8T)Q#bY5|lQ+(@+tD=hE00m$Ke9x z>L$ICb0t@}nf+g5vPEl_R$TFZmb?3A{dJrDPjRpMT7TDWf3(nDW2-*ZrW&%}(2(uz z4)|8JciXzFZ_^Lih>i!_=@G=Z>+aCc*zDXvv0eHn4s{)CsMgy5I%k(&x&0mr@D=nJ zh2+wNUDJu`Yo)_2rod&Rbgvf1Q2-QTgd zpF`g8w@1tL@AP-6nyhiC^50Wi9hD{DTea1Q?`eIUD`F}sH*f1r(0PuBi`w-4m>4>bKB3?LMz zjKPxhqwY^*apI5kcy@|yAB}^Z?#O+#3$b0eU(dG(v77l%v_LA!)}J_9Nv{5+tIYxk zWl4$oSr2xmlV;tA{8wuvw@7QGGC7QW2Y%+{qjFB+oI)9?e1K~3y1U^4)yDW+ZXMKX z+8+#%KR-8E-tvonhmcf1L_3;m4$jdBszp6HdWTm}5w|yy&mW`_ibAbWPn3kFqjhKx zx`G~~vNvf5pw1`}O}UvFy(sI5UfKTR%Y3HW{+3KRLJVJ(B}eo+j;oB|7LFm7Kgzwg zly*mn`Ia*5sD6oi?{JJh){nRK;a`bGk%C`o>lR4KGelAo>2iif=RYz-p{i^@LwENbX?@n}D5aj|Jh!YrtE=Ju z+sbrY!p>PO%D(3?{Vkd2^!kp!FWEg``M!A0(>n=1PbjKL^mz_ex%@u|_nc>(Ac@rP zD*5N1juVV3lJ;##dxrTg&^GDoo_#_8(a(s#V5i=&vAMXlC@Sfi9%mEx{%bTajdw12 zjy3aa%+&jaoRsD6AckX5KQtX>qfO`l zx`}-LBn40d6o-<~JhToSLpM?IZMv$c)$NVZeQa4bDZ5*w%1uTfwhVJT9f7DN**T`K z9Q@GXlnpoa;lyb8E#fd&+TEh0<;s{_w0>Jl-9PDdu(CDnPvY=>S^p;^5AXBEV127f zUu=UV`?en9C^y0(9Xc2#CFeGUv7DT{O(VO$w9BJoIYtiV=`W};+zt0|UpAktGC>;V z(`lJ53-i@jhHTH*XDA=r{Ka)n%9y_h#L1_&5r6Bo95s_1Ql_&JDoKBHiJCI;Z#sF= z5^#qs*G8J%q4YQ6lfZb_NUq+|XDjcl3r@ew1^3IcyX3}B5 z(n#t)p_#Vdef)_so?va8Ar5tMtD^U@8xaF~lE6u5I$Di(p|j`?^3S7hfnGwL(IAwD z7N8C20J?&-eCi(50L7qwXadSWtI@7}s}bm9RJOmk(_6v#7$J1hm-rZUY;o>`KE`2( zisfwGsKsFPLEQ+qed@lY8+Fw%N4RN3l7rfrMm0z4e9hYaSGnF};<|$5V-G@I#xiBQ z&1KZm@BZz5v6Zl$!E1-V5yX{mq0`Pqp1K@@lvYxC=C;9lN zp{jL9F-!xcZZV?^rfJHQEt`uOHNmA~MqBUKEG8Ej3{-`jPX!b=I&fo|#f^{3b3>6) z#us!5&qW!eWCeG_dIs}9?z&&7Z&2A+W%C_lAVKKX&{)p33mW2hpsa6XwB$1Rjf`n; zo+1|Wkp34%6175cC<)C%E6^@<3f)J6+lY=iCA25L}zBwl^WMI-z??v`EHzwPC)=B#oMmfdd zEsQr6e`sNRZ5zO#BtBe~f@m&$RVutrP3!v%Y8- zW?vfaNqB-Y{-3 zG`cXx=n>hO2uecJ(F(K;okDp?zpH8G(MzZ^N_1CfhqsRQpR>2tO+C!|Q8+;R|EeB4 zkd0EMT?g(jRgyc9Q_jfl4#r%^zxZ${kH#4rZN(aqcHb{#M=Ws!&&L|CQaM%WXv}5R z=+=&$yH?J1G)6Ei*X}gLBHsidmA z_7c#I6i;QYsBwWIk73=7n%uH`QFo)BS|WR}2i7mh`kuy7+hKQlyfMv2FpXXY-z9M` z>&0Di-Jk?R>`T6qkDv1?EqfA-h%Qq|ngwVB+J`Qp`zY`qYBlr{>WmW6bd-&@p<^fy z>Gw!x)C9$#erSR_x{vXj&Gs8(nnt+ew|km&sO*|cdRZ;kyne*i?|d1@Q2p%Y{fY8? z8P?xWqqCUUFRMQe3go!Qs`voX*tjn*4=~hNHAdcc4Zua9EE_+%I@{hXjsq?ha3B#pDcUukhpxiZ_Gs+L*jK;ELun{J2 z4l#azO{`eb}h`%GGZ6Xte!S%>=Yutom5F76SjM-F|Vk# z%t|pnBNtgUbIdr7r%L~Eq(G{B_Bg6g7QbJ5ha|iqCC3|m)miezDPCwqTsQqCd%V#C zhnL1v$rg*_YKdqH%6^y`Ju+*OQJ$^E)%V`3Ov1-}J|JY2as-UFONZ?YK$~y+MR_)3 z+cnA19rB43yRC4F`*rqYF)I1x;^xpR@@u+LxLoMEguZK3D)~DH zPIyn&M)e=vtL?Cafs%aBQQbTIcU{tP=llbAx4C-L&uopK9$CNIRVr(;;a~D5NB=46 zOXvP6qb0h#?U^qfC-Y_7TevGO<0c!0t5&YdZtR_ZVqd)_y>|8frp*+pz}wicEAGzCR?A+H|?-@1hCti{FmHGB7@{2P6^NKvg%qzEM zQ)w4em-MMTH(qleo@#t#d-W!ftUaO?hMJ&QGzg`k1!x1>hc2S~DDW}u1JnlfMk#3V zvu@jqyCeCeEg^Xd}yJlP8DC-PwkkBGGaV zRpk>&oA`9nuo&7B z0x~?UyTutsgl`Hb8cmXJ%z)LBYqf!@+KiwEA1vOkNs_|bhU%WyHLTpozgPVIjfJDdCN zxqu>kRmLp9$yN8l1;!f=-tJuei1VW)bg{9MXW;3@n8rxJ5`s2ank^wmRFK(AjOOe_ zcu--N1bl2vb3`?ENVPGx=G^qjj|plVA1<-lzE%{(EhUEEA!fQs@=~i2eBl#f=D<<{ zFi@^8rMev`LD@zp`^d&JXSoqWf_;^ZH>>1QHc7s!@v|hq|2#ESDb`()4bA$*2zCTxxQ#)gJ~4XxjwcAqW&S5t;t+&LcK-=jZq#&q zhO^?AoG;6`&coG6ppphdL_}c zL&mK%QuXK;3kQP^P`8v=Wdu2}k~%52?Ez|Inz%4p*93l&_itl!VC&UG`7e#K z8lxO^F*j~D*f{4$ckUJfOSY^2jWN^DAp2P7M0nriQ{h4Y`4+aKCrRu z_}-`}3w9f^WQ*M0w6+6f<9EhU$8r*HL=8S~ll?uH`b@TePtbCu?jBIjy>gH05k*VE zUgMr|%t{-ZR-dJ`YPS53Mxsr{NR~SI}cr-i{j-iw2=t zXa(A4w`E4p$jUJ)^GL6fV}#pNqvcQCSStZPxEORPZTHEF@(YpR!^UMY{k_8!ffiEb z2+7mJ-SG%HmiNr*N2!L^$W{ejOe;Jm)sIm=M=&v1wclj_F*52HDNta`rQ_gd>96pY zEIe*ibk~pLcO@x#f{Lz^G&^D3roR?>l1q%0_>;I?Cz&V7;OzB&3d^R__7s(8FWG&H zuEG&%eVWT2k%^~C^z(B3G*@pV9e*XDjb!4l#z~enbUA}Bvl+J|=RT3sXYi$p7-u;z zQ=-q(Myo3a&l+mnuJ}2^@}e|5XIK;0Hsn!hEl%<~JO?ipvBkxN1z(wQkubiBJe&t# z=d$f&$#sIq_Gj0r+urEzbw4|Y;Elau1ceq_smF0j2*bdrHf3a*EW5!Y=xeEv%k{pN zjtY$>J=aR+L%Bq4tQ6!L)+>4|YU6&V24qL3-?`psS@XMLz0BWrmspSZgF|yA`VT6N zx$g8o)S$*4dEpiTd|QUy@>JG==Wv;G3zu(8?k#e~EJ^s&8f4k|h^NiIKRI$xE)}tA za~rE0l5o3-D`nMDF5Nbog0MWIe8yYSKHrE_yQmV*TI|Sm4r{>Cn$jZQ@TVqfmv3}a zE_OX45Zm&}B)xih<7(njmQg;*CnPhDF<-trfhye5bLvK~uTSfl>N>P2b$ zx6#!8Vs9yzXVj1le;fYxF}&{swd;_ z(Ggc8rK((9RCet5c8}z(CwN^_dfq1%Cin5iLgooRPO|(yPeZJv`Er|TUs>+TKEU0& zLU-qsJ7UXM20b8V*U6X%l;!Jk@PQ|Sb8@-bOAoo)66x}gJhepLduXJq+qMEy_7R5; zOT$M*^kEtHs4!_G$uPGb8BHB``aQk;(z66J<1r_ck~NQsLN=OyZ1kl}zED6}86fW! zP-Qfb_oUdG$i3fX{%m*DZLdkMU+L^_C}x%= zR~;;7Hm1JvEpE<=-&HNLh= zzD--?nNFV_YR+@S_MnGXl?QKZX|n}IHnX(ZgW`Fsw0X!z8QfmhY;4Sm_XITB^JEVU z!zCNYh7kldat|{HQp)nf2<<6_GP0taIe~IgAsnk~vNhcNf)EcbZyqIkH>+T(w-B={ zaG6dDyzs7wf9Z0tBENfAG$Y8o*6$VS_dWHyCD|;flG)NetdHy{YnGOzO2oosnO%v{ zd2*di%a>)_*mmM#C3A~yiF;vXlfl!&vZM;3yraOkiK=i`DR)3s6|;g%&41o^o8R)l#n+M&|==R>ryFAg!IQjhWAy@51` zO{ZUTA(;I0nJ0(&@rU(c0UBQKyfGqWuOgcAG(Qr{8&MQ zTA@LH%=I5?`lhbHunpZnnv?HHpcs^bGSDt`3h89V@+cM!LJQCabQaw~l?`qH^+OZT zINOF={$&an2_B z6<+@eXPqSQ@n@57ortM(Zo(+Dj6%AFy7M@)Zj^O|Pcnu3s_-UwzESztDD%0X^f8{m zshK9~9ulPFXtP?-ytkiOs|hFxva$QqZ}uIL%+W;7DekkLY*o(djeT~DwCJ@ylKc&G zt@=pN7_(A96Yo(KV4FmbGD}Hd1fLv@>S*_o-eXL)CGTt;`muc2@29cy^%%2a&`(9Y z$wI?D(|P(9nOZV(%y4VEjLIE-CHieMJm?p%7wXB=C zSid57(syXD1Oj1g2%wUS5Tuxug0j7VESwj`HI;Q7Un5lata6u1DZ((HTJ%ba8Ti~G z?=f|X%6WvjeIlzo%8s+*yzMxmflX+bp_n|5;PcUraYaf%t~$(aFMe$M{|?F6?44&< z(j|!7vA%c}+P_HHNA^#)!mUEo-?PJ*iuwMY{McWTr;+#v-ZA}yN{{#WR=Di}$0nJj zvc_|0srQfywwe>vU&6+lrGkoHXVhr5oO5>yxjSyW`4VY5e>|aO=NP{T**@N^W<*Tz z`0p+K{tJ9xd|KwCCy?3L$Hi~z1bI1`C)Jb*X4#;r-ZRu?xvDlmHcl{KczRO4I*E;4 z{5DUJ(i6?9L7TnqRm`hWJWx7LBo-N@^rDkJ)amhRplqCImQshN5#qBf>`|jJ9%sIj z%<#~G|BpCSx6WYA7_(GZRB?)apr$n?GD}W;7I7+j;OQi@QuXSSJk~1oDjyW}F)3lB zl`1L^43zDY$cO`_-FWjg;;lj|w{?-*TA3=Zr<#R3ClR6Qz$FeWOOqX`X2pPIY0s{p zNd@YhtTeO6)A*^IMgp)JokG=(pA2hWN;TU)J$z6dW)~GUxVf7~nd`#`B~>mdti^_? z+bAiur<#8BwVIJnfK`ieM8#T0IxVjwvO67ru2`4J<)^*+yHYOQ94Tq<5~)LF#=BMt zKlm=L*xAIdqTGGgtQk~svgc|lt<+T$J^NuK7TFIY(X$^0ZA-NuMxs>-d-lUf6ty1) zR{0)ONMO6c!d!w+Q;Ou0JJX2K-roLn+AyZ9%N8*USQgf==QKn2Y1A|`Y1DS=1rb02? zDzvg~8l`r>_gG=69WJM*d2-lvZsm6_>R`(Tihu9vW}wX>$T+u`6DIJ}9&D#~HuK1oO9xU#>6eVrm6guG9<>b(E#76SZtHK~f`5wd+Iwe2aQS+2}9 z1H+0s9M*r-sKNa_1xXeB5fU_u0zSg}&}LXnn5LBv*R<0dxm+X^>M=J$eO$9r(8D4T zr0OwVk8NWd_w!k1v7iz&pC!1=t5{P_0M?oEhzNVk?er^8y9%pcia1d* zl_VYKm~Rk}C36VKZ35Cp_RgU#&}R0tT%an}WX~f$;|F%aNtR`ke8WMy+5#tOxSz7J z_UuesO*z;!+l-N2ADI636?3H69J6ZJwhBaQMQe0Y8~nkuJ5(Xy+e&I*NunZy5abbp zp^~0q*7O~kfkPSmfm!Cis?7rBEFWioC}+&2%rwds}E6x+XWlbI<$WttW3 z@Xt*1`N+&n&&3NX(a}YscX-0v!$$P$|MYP@TIzmiMtkQC zvj|d2I>u8>@;;=kGsY(WHZz_V|GCt$V?5Cmr9N;!#@b^_Vm-fiThZtFeM$Y!@ca%^ zU%TJn`Mr5AHR%|(__vUJ#D~gep5?2x9jU5Z#t5y}GB`?joATA$b9C@L>x3B~=!Q3_ zDpRQ_A0riL@`OIFN~&O-HuqVIsH7ev`K|4x!ZuZAjJTSnrDOHyyk|~SwP*QIDJVvs z#esTOj*%|&d3aP<=&@F@tjY~h!}SQ@`uRlM9`8|AGpiypMm4}x7L3d?EBW6chF@9a zIbYH*@}6QumZ?5KlAfiSG~OeH#p7*RlSQSr-1->W5xIpAes}R<)gpObXmYIbx>wgy z;T~(Xvt@M_6~lx{rtawku!2&EkFmCA6R!))nkq(Pt+M8;Vvh4wgDg)dZRsi`y0ipPZP~7=Q-dR8>?i6u}LoG!%F2I-R_#(#^m?1&0E`An|s*X#Mf(0aB zii9mJk^}oM#NT`PJ9n|nS%|-Ly{8rC=5b=X&CJMs4Cu(sh5UQ0e)%jigIUHFy2vaO zHm=Ams+A^nxtKazg@2rMTtr+J_Vea1BER3~YMo^JBD0RIlWgYt68I6Z)?g9UPTqWe zMJeO`g&5m>#I-^=5HNW7XvJmzL;v7M_`QfRrdQ?eM`pO=)sKtx zYkMv>-zx0K<}5aYeIF2r9+JD5oZRE%XAy<(+IYFt#1$Rx>1!$v3tulsagg3J58tP+ zduA;$%R1-}ORoY(oc3Vy_IT;SOUHe@r+mD`obCu4i3>F*mHjc}Ds*N)HtUBTARlp3d*Ky$7v6xxiIxj1 zLgpW*HH1uDOjB*+eE2G4+FV*k$P}Tpu8_GIX#?RyI2;oAv`LUxK52YOO0zLuG86j3 z6ZTZk9jjN~49KLNhAIZmKn7XTnC7c7W|HP45*hzU3xvgC7z~6p;B&A(ECFAF!LT(f z3CF-PFdc@&nOWCX%l+vx zv!oiJ+5U-H=7p9VRTa{!P&Kk%gC$^FI24jA(vl##B5fq>05f5%1T8mf+UfMayxc6E zN@htTcD1gMYiV&%)v4+(>Hb(|H3OkL_T^wtSRTg12>2GP0eizbP@UHhDt}&rePDA) zcRTGZH~%%vK-Nz42m z{1E#Ya4wwfJwDfa{3Do!{c5-XZiI{AcW?FECet8(|&z6(r`hO>iLG45^{DuOWABqhn#8U%@Z(`+frv&gr_9vQ|k0)5(!c-bF>(?S70T06;^>aU`_ZttPlTyE#OVq z4*m(d!93Up-hnFT{{u(CdvH8_09EQeg2!P2r2fSYM_2$P2EEtZ`lHoKs5~^}J3Vs4d!!>X$+y}=&^>iH%@4*Ss zkNBGid7fxIn9|fBMJjwAro*!EU8oZBJ=hCQ=(BF&grzowRr0Y?ux|fHUET zkjg@v4^{aRxB)JJlu>OFRK@ILcoeRHB%8Jhc7UJ4L2xxpglix-p{;MjkB|6)Wg3pO zEpP+;2J(>@W;%sF23VfZWN-yq+vvRW&=#iXLw6Bo-!BNN~GT8sLs(_u%tQ*R)l0Vs~*UQsvh_YHih?KTX-L;YX1RLkC=zB zKYRpLJ@6R53stD6z$cjB^O{xe(HyFl>L!oYo2_{iMSo6N^2bhvB><|h6oV=(#i4rK z(K}9S0!zqypEL5-N7isw>TGP)GdTmQ8tp?^2F`^Ma2||;S@31J0Jee);j3^7>;sp= z0dN^igP*`Ta5m4Khaosf@3TM4*PhJ9i7 z_`P>Uz!yllkVD>>(UVnCIQwGArm$nS}0Vt293hB>aZ-V0V~0HNFz}_q*Jx3{7|(At;Do3 zuohemYr`)gi}llX!n$x5YzTSCX^r7S*aZ66SttY5h}O$cwaHt+<}eykoog*2)w%XM z>;_|CcRQ7P2Y#r=cPyL>JIc5(O)jhiF z1gNq@U)Tfohw3>q5Dtffp~?n{GVv?kOM8Z4ZCY1Jm})N(&8s!5q>X~Aq>Y9ZA+N)% zk~S8qheHZ{5xxW4K;BrSy$RX6e-oX{REge1+D^e%W#w<6%F5fI%F5fJ%F4T-dSrbE zRrB?Tgqz_na4S3nzlDe4Zg>>(gn3ar!H=U@oP;Wi zo`zPH2sP5~98`}U-i4&O;ANNs_e#ml=Fn8n=&(&SJ*>Yf{HLvD{pG1s`IQgVy;bz( zX$338O0Wu4wM#Xq>ZV%oRahIwz&cPB)B11-YzS5QG=|e*6JISgEsGy7V6hm!2(w{R z_z7$VSHqX#S1=l?NN5SagKWNOHFw*cS`3XG2vGmdW<7&83WV$Ggok#wu)8 ze0?hEZnFf#+R8S3o!6Ex6nHx#(W>*RRYq0b_mK-f>!CqkS_d0j2g>3xdoFQqDtp>n z9hBYHVR8{vCF6Uj^6nm38t#SR@CT^;Whd;k6!;TVF?|4L!e5}OzjI(VJPK9B9*5hY zdSa>iPnmyKE!ETfIDy3(cmYvVb71qW5@&_jnX! z>c187>b#fLam@6#EPqtHMg?G&tuuL#AF66%JPwtI zC*fnvr@ZE0;lG&A!Y95mV5|8xdw7O@Lj*VX^CVddsIvGgP!->nFaoxQDvQ4cRk3Xg zTfx_%%IfW59~cVdhyCDn*dMBh9{^Pgav-b^2f-KMUQ z4XWFm0UN>hp}M_UQ1y7`z&GIsus_UzqhThT4Cg|Xub3l|wiM2X>tPmD1@&k6y~;-i z`SB{jItn|(6R~RbJ0@*o+Y|)a@8GbxZ!72$$!BVgS423md8Q2Jh!3Pxz7ermB)s#B5VX}!p86g*aW@?*|OM*&!%u7=9i$V5u3qO__74;;EDA| zhUdAs%9=@)`U*$YRa!xHmDW&Q1gfCe|&Fg6%PnhP@$cL#$hW8;--Q0y!SC*24;v;xw=Q49K*4s=U68bH|~! z;@-*lO&Q7GNw%KBF&A#$hXIhCiL3_1EbAP4Nl^9sK7f%h6V``wVPOQlikV?pD~yYw zYDg@Bec)0!0A@p#Oe^5Ka1|umr)sPDp^CM-3017uVP57nFNYg2ukccpa^+5yk1w&` z3^&2TdUrSGEtvOt-5rG6F`tDy;eD_DL-;*roe5vsUVcQ{sQ6(MxDTrObT?!mPWuUV zgFnMTPz7KJ`~|ZbAy8D~Hj1-g4m=2tK-J+t2J_)@$gqZX5;Cm8G&W+M-m7++AF5pa z3QNN?FdUwTs(f99s;PJxs;1&^usysA--Oqp>Tu@5Z{hEdUZIu;Re$mycpIvK(;w3w zVtxW2!_>+S23Pn|72b!9piQTd2pzC9biz2OJm?M$%ssq}hs7`_z~XQ)%)*~3P`RH2 zgR!Ukq&*M6h9Qvti59BUcv0iJrLkbk5G@SSa@WEk4QZ_+RKu^8U@KS|(hkVVYAASWJ!XIE0cm}?xr}8M^M++?ce5n>-0Bj3ssAzA% z1~3NFveMea<}eoagB{^e*cHAHyFnT@S`SEjM2m+sEVN$mH>hIdD(s8701imyM|mDA zgJC^56gGt;VGJAvd%-dAb2t|M0LQ~)a3Z9lw>+jISM^F-K1_!X;AH6MWHbbZ!l|$l zoCev=M@yZ~j|Tjh0XxH)kUBv75K_jqEcg*z0N21pkc_H*1TVqG@Nc*Tl3%QVkPoy^ zFb8_gq`$Tjb4jnc6#Nu3$!ltB`9ZpB>)f;Vm>ulA^E>wgo%vl@W2=1+)noPtSPAZf zwcyXNFFYs}eq>)dc5v`&QaV(#ho)BMfO@J_h0nnVsN!E;=y_NZvx@&nSQplX>WNnmz62XU)mE$y z2f(IqG;9XdlkR0W8Mc5k;VW;YA4As(t=_kyp%1lR%gg$b}fR1dv@ za1tC0)8P;}1*%X^g~KqbcpVN^Xp`U(bsNe2IF7|gsCs9kp?a9T4X?r!_y-&c^Wk_| z_Om%qy;+r|YGQZg157*bA?*&BUok7)cF-J=s$Rkcqgtp1ibIKL3fh8lka|HEf}&6x z)DKNS3(y9XgKnV5D40RmTBsH3jZ)AGv<;m_cTfmD$0*e1IUcyZ`H_M$&^ojSoke$0 za0xs^ZBTDC0nI}j&^~k)-9dqLj3Q7g)Dxwk473jIK^M_|B8pX8VWSchmFW_o^%j5}=BXA!~r!{#tv1(rEtMzTqE+aso0)HPF?mdMs4w8`qp z-^#R9DjYS{ehOWWVp=8d9W^V3t{SSABvM9M*Tfj4b`hzfv{QB;HPwpZ;>U1&N}3%r z)gCY7mFcRiIc9nLn=+M7vi=lB?38sM>htlJ`Vyq5(@b-_D$%FSmW~o!wT{ZR*{5+|UbdfR z0I-d_*{{4WY1WTePeB=I6FPuyAT5M!gKD8xs3%H68E7@yh0aRQS+m4f^~`;?tn+4N z$NjB#sW!nk%zl5Xe12O0hLzs`ASCo{CW-Z6E zZ`lA~65k})c9FSl%VhsW)6MqU>6b{~gR=P&>ob0lTbInq{)3p7P;aN*N-{~l!s;}+ zYzEou?UX;8`NeXvN0-e=eN~~0jaOLj_S$bOrD2u!Zv^8TS@N5y)@)zLlvm3-J#@~<+q)>JB7BitnGylZBJ?_fgHQFdQ5 z3wI=WrAT7-CKuh8fa|P%spTGX-TdBWTjqWt*Boj$Ja=HzMtj!I?)t+@$8&#}jUC?* zq+Y^|iKv^T;I|Te)BMp2i~8h|FJtjqQ+KypW(fxiYKG;R<2!T?WvK>AL)mBx%0V|! zU}?%Tib4I*EVKgcLZ?t3Vn;u%7HWlhmSKVD{;a>u%4*;HznS&d;x8hmp|typbvo_k z>R+V9Itlxm44SJPsBO7+|7~`)+Ydn}^gHGsxE*%aoLPJ{ zSIR)E(Vj9kwHw84zFuHv?Nd7j+-Le|j8wT#afxBg@@?JtMr;q5(=-+j>L;wtmq%^WV$zMk9W>so75p7^;s*jl>_{9HfV z>YODK@(>&MYPC=+)ElLsd1xKlgU%u?jM~w#Wtpz>zVUvVA78*QUEz+TH`Vumnu%v2 zOFyHLuY>ou-o-0tO;@m!AsfFrZ~oW*wec(-b5-)A5$w19P3i7(HSq3V5ij%Af!-Xr z`ljsQfbN+Q6z?asW0{8+=%=$&~oe;xLoUEDexR^oqxHg25f+UnlFl6D*pD0*Y>NQEF* zq<1eMRX_@#tDSLADUl0xsaSJLxLO#L2A&~>Z~UcJu&afgaxgsD)!weMeXy&B%F(|E zyS}0H4+|y*ca?NC@Mcw;_PO%YWv~6HW7&QQDh2l^Wnt~Ri4QL;_ zi0-4na#ZZ773ztS&~%iIwxAqz1F0!qA*cb0L4(4nLAKhm%2I>0=iyaFs+4tAvsICH zWnF5UI_t|yRb+EnmpIdKzc`!+!g|l%ZslAdHn!j|hkG{eEa%#Y`zPgGk+v>;#Kff< zM?=G1k&ZzQO+JXXHN|{Vncu-&XR1S)Tb9T5Y)LNfQf;!e%CuBYWAfIdj2JvkvdSb` zOUbW5#J8&83gjYT75SZ1!Bv(Ued>>rU&`fAp9n zRahKBYK9>1Yc&U+7amvFV5mx4=h>YcRHJ5FC(Asrrk~Gx-%rQtQZ-i@khzvy_0;W^ zB|3uosRq}(*FlCvJgr&*5m-M(<5AkdqY>2pz7Gy!ahb`sLs8{@V=|?UR5=; z-m_$Hz3i^RV#$moA0NrC?(*S#6)SNL&eZ@8IY(f!YFG#UD?n{);D03k`${q{gM4|9 zR_H&sPH|OB0%dx2lCGkPU)ilfq@v(+vDGAF-Kg&Jm%tjX!Y$b=OF~U>{=Bp!hIg-PXCw1-hy*qZQ zTvk|1sVv{IJ+&0C-K27)E6~vc(-(ehfE61_w&x4ak*=DKQH7R)hu92#OC)(dT@FW5 zrQB&Rb85RjG4AnJQB`jBJd3eo>bP1kzhQPAR}WfNxpiDK4Nv^ov=2Rdv1dfNV(i@J z`6$;b26tth{ha6Qm+DeA?)*P|y$@VfRrWT1?-dZd=c<&Lm?)^2lo%)|sHm8flqi%m zVq#w9nv|%Rl#~oIBa@gEl(?m&kx5EQN=iaX3K}Vykw!{NN=iyfN*ZZoMjDye0X74>fJ4A> z;0$mHa2tzwKp3zPSPSUCyzK@K0d>F`;4)y~kj5W~0OEnQz}D*0Dc0Yc&Er*I7$)QR z>bNlL?Ph#_Dl6Q2k7eLy^_Ot#N=#0?EOxkxo`y{VzMV4-F&|es)2x5PJ8}}HV?&m# zN~T-&*E5=@TlIS&10$?Y;a0LD!a5Gr9O3kT<09dcK2r&iNdB41jKl`6Ky^l1?=lyw z&>2YnU*(u#or$e*=?o~7RObxqBlyu-;!NxBEh{tCqAt&oHXN1flP*&!#&e}I&$7OU z$JJ|RS^3u52rC}?iL#Ecz;(UxGpZaPg&hEd6;als`p#m+Z0kh#-@`c3XjRey-Hj@A5HoOOXL$^CB&^s(TTzgX0UoAF|S z@r$fsI_|PX);&Y6qO4K)tzj6jFc4*$&3oeEkncv9;F08=*da#5TZh{0`17@Ej^j<~ zJMaa7!=>)GN=Nm7y}4fg@eFai^`U_&$aHHU7Pa<0_ae_j=uRIMcrW_OXP%pSv(>X^ z&wbWqE?2+tKI<@#3dDIFFHyVC>Uy5;kZQUQzTpi7?3kzid7pK(_l|k`gzLKVj-x}1 zQ!z`f`OQNrZwZpUiDYljQ*SM?-s=6fB-0y3q{ew!eUkOYJ&9INn3z{0Mt_kCO0?eQ z{W5;QqVv}g^|o%2awJ;Ed0*_O)_!i0Do(WC;vI}reH~jb7uvnz`1aKScfpJM-Vd*L z7!|;ycK2UfqfjyEJu0Cun6KWt-|G5){UOzh0PnXDa9FZ5r7m!6QT6v*LuKJRgx7Z> zG5!wVaSEUH{EgN15a%J)ssoN7;FtNzveY`+`xnVXFF(4yi&gYWJZ!Gd02k{goyV9L z>xY~*m6Ga7`hgzj$K)5oDLKOfNYNxa$@x|9OWy9D?xUPpmO`yAF3~gYK|Jz(Cdq1e zJr^TAsmzI3YZg9e9jYcK!ugL{W*y;O?FyBCUaUf=;Jjw}GR)C4F=}Tbw(JYPFng+9 z%dq`7-Fbb~bw4jw70b~5cZgaKmWNZFe>*a{icGv8>z73Duoo-e2duYy8+TpLNuSRz zR!I+7XL`ROYMqnba4%K~eS>ategJ*3s(%1u^Lf7*de1EtHkPBTU;BmW`z3Vu7dRW5 zwH#F+x8Qn#dNaOQB`-(Smy22#IM}InR{fC9?%94x^adTD)Lf3L4~@N^lRhP1th|!3 z(!ef~G5l2+{_kVeGszhK@B76ZgqZQpXO`8kQ7@FZNk z3OI)vuUvt9vv}pS0$l`txR0m0%-+gRk2~HN0&>668F1~PE>)Lg9WnS2`s6Aaau+7e z{dcSHldSUw`=h-hp!)y`uH3DrEwfHg2Oq=$``)7-*1}mW%)Upxq=lg?t)sk;ziP{e*gFAs_SkiK{eSi zianB4kD}h=AZak(OYDDkU>Hh@TLmXjjgm&I3|!hqFS=fk1t01{o#OBF^2E2R^b=5^ z`Wm+z_k3%1-4Y*Cfvb_jQRMKTio>Pl!Nux@Rp_hz69#zV*(Uu|usX2{opEwCw&?fa z^IiR%U_c5I*C6p~6`Rt}2Ngo^fgh`RJQ1(nP3h-@%nk&+hk(L(b*saACz_BB)j<59 z&EsIa8()uk#es7U{It#EBWUz@ONU&7L9F$`{qacrnJeC{`j%G9VzazwTPJmGyH=uu zd{p^E)`z?vce-Qrt?K@Dz)dP-E$jdue)d}H8q3@Bs$W@aecxhPKVN;a4sKxEBiJ;- zUw-n4^|zM8^YL;6FkB!4*I0g;Up+0&x^sZ#``GFaH(ECh@ZxZqF+H5Og7KSiD>%Bk zelvCJZ>FjL6e_(+&XQ5Zm093=R>zx-7Fu)R}bG} z{cuS3ZY*a9fjZzUa2fENfISp27g!2x1$F~RfRn%lKtItl5ts|C1-1bPfMdW};4)y~ zS5f1ES-=utGq4Ld1RMv>Pc#oTUB$&P{K9h*5Fdoay4buY#G+sPX}!@Me-p;*8v=J? zhZR*FyVHs{0WQ%F>_)ZkX{>NdRN2#*zDty?5N9rDpSDhOt-BL0sdqf0=Iz1> z(T+!GqGMIg)0j^e_hKKfCtjjzEEMlUg4{k!b}e5Z=ij*KTn>QVE5~;v}*NQ<;UxBCKB)dU0B&A4$i_M>1Yav`n>^;rbk} zp_fP1hdzhfF$D5abvHHXISlPG75*IZyIbX{<<}}saoiL zXJNfEuvW*TR<}y9a~G$&pTl9;Mg)5z_$~xb?HBB!0-i@7ohri0et*AQ^&mc=x{IvS zZM*tK_f+=h;d%e$eA4$Lm9+=`^9lOr<@M@r1=m)$2Yvl=zkHC5X}QW#*WCC=DnMDs zsr`H4jgB}|P4GVQ|4z_=1RkeQO2c~fv%-vPkobBObOFgKa4%}*nxScXVVuo~f3GUS zWzfAF*ju_gbo3SGerq5OLB~pOuTbrXZeF3>i!tL?s6bK-$x)1nw?gHUs*3v+*jJ22 zMd2=E6`pI=U$2*23GK#Qi$wtnj#B9_Sd|67Y0!%}E`)no_M&yC7afQhFO1P|2HUgG zx)t|_S^IGJH%vvA;K)C$Ii1u=;!8{D?nV32-Q)LLC+c2=Fwcv)eOd!t?6i*zX070;hm0z)<|&eiASr zSO;te4gkl1bHEi~C?4gS2+RkT16zOs;1F;eI0sw-hEBpAQ|g`rxMM0t|J;sG$YGap zJASXOXSE(b%`3Sncyby9L*}Y%sO@8#7U^Ku2S)ySFHX6aoFxrRpF*KG+6Of^H;3K0H;)n zms+k2^)S@(8HRtq7kr(1#rgsk8t1FMw!Mml250LYCo9x{LM^Vpfh4JxS78eeAOLrH zYRt_R*GUduQ+v=l&RB<#fp4(+cr7>{tj|7Zb-i3XN#PCP1g}CI zrM`I$)#rg>l1eB?tc{2jr83Lm>7yh=?Jdz*Q?BZcGHz7I%HdgZRYUo;$(N+OUPID! zB*mX`Uc0u3N>Z87PuK)~9_}*rn3(Q$*i%6IAaEPJ=>=daY`{Tyw$ z{&bY292F?)aRgunS2$;PMTOP%B9|n*!x*Es1;JYnyQ!bbJg@h)10f!n2-$a7J@bb3 zReF;wlHgNhuzqhCdW-bAt|kgVmfy7x`%SbQ%j{}9~wz7&h0jvT_G ziar^Nub9>%qW8aCd13(dg0@X{zv(>Nh81AfGy?rrN*3k+c75$h%khWeQ!)<2oeDzpkIJymiQHo|u}TcSTM zUb%DNFx6gVojPCz`gF(v{EQ&v9sD5#J?yNJKWnt@9c+ftx1YR&%`ZA@TDA3`_||jq zQR|zQ{7UupQR}?y<(RgcfnC6U;3#kkxB%cgPbPn07O(_Z3+SJZ?gx$nCxP?8RbUt% zkeCF_2UY@GfCAtka11yNTmVeBBTpa#h{t=wO>1$n71#|Nx*h%_0bj(#UiDp^8BSG! z@8V8o>PfY}6n|rOd(RqzKXZh?XZ<%`b{u*P+ww0}swOLb`D}H#PP<0cT1Qw_lf`LE zrp4>kn4|9c8}=J&oqyaYskQ1KqkN;K{mS;f^UoxZ@N(7nu^D(%W%g5@)T;MY2UX)f zKpMP4^8@D}OP+=_;A|6qlJK!LQeFN4w^dWC-RrFS2@hzUZ(*pb$9?o4Ra-sAalb13 z5OzBLL+eD8;=Ep~uiw|#cOYM<>XKHSRla|=J~ZbzI^`^I88AYy^#|qy%YiLG0dNR7 z4x9t707FBuegLyV(V5YEj$6kM@NB>b)t#STJC4>&P$kE4SUW*A9k)7vHZixsItd4d zX$@GRuT&Q{SZnpc;o^_c*4y#9JnL%nUe*4wv(vI$&`l91kc$mJX-6(Lm2(0kb(1PS zffL+6tF9BcqnM6VxeD#eQOqzNXu+b)NDRm-EayAvgY&3 z?^B#37pf#pD^<~_IBLG4+&{wxVU&v0v=*PmLpxXChe$YME>OXzLHDZS)7CWo&iYFi zP{gPf>oDU%EXj|;U1)cv>i=!{s>Bv+5V{pT7>u`3SG1t>wyU-lYm;u0vki5hqi+8A zs2*&^U%7t)Ghc|8v%+Zvs)RG>9(=A{(>c6x8x*E`&!9>hRB$U!o87(D!>!gu=5|#B z5nnd%X+_{>74#*jNF{%X0eM@seTibov81=uTX5es`|>RUmrZ+Eb8~I z3O(yQd;j|djQ8HNi13}NJZsfI()p$ns-bN-P{#ZAZf&zJbm?|M=jn%Eck4D66%HPw z#v~4Oe!g9&@cbH?%uoSeJ4@N{HA=Z(m3(d0pXJJKM1(6k!iUQH8|U0|s#bmj)u&FC z9#rQ5p3u7QRQos9TLyeL+;Z)6Va~vH=d2?J#Eh`0IUnH!d;d8YSd6MTXDyXJo}`bo z+MSmCK|5+N3_oD%XGC+qMc#fY>D%kJepss};Dz7T+bt7()#T^#cBHJ=+(UJS+Zxe( z%fCZ}y(;57So+@T;_r~F4s%+<+4Ja;K{tyPgbo;dvl?>+uLZ}cdUR; zU}(+C_C4(TWxTf&2BbEAk9=cQ-uEatc9eRl!@67z|G|2L<=0Va@b_@+u86ySKp_Y5 zh`!U*x&{osN&Wc;t2d0iCdpBn9In)~1z)yqFxZ@D&1=YDi{OD}Zjoq(S( zKhP@$KVjw$Rkc4kjlg=*8Z^+3iBdBLJ`{Uc!lDaO}Ew+%G5RS$b%z(sSl{|f`o;de`6?|2$+X0N^9 zF24jq2dDKIF9gcm{;nBt@%-*Ka#-nEc>gX}XLtdCwcJ6i~8D6Uq66Jkq7d+-#K$|U!Vdmy5G3xHe(@XL)>kM z@Tn@-^j)?4Bm!%5SdeJKQ`N_u9 zu+5~~jn~Z<{C;e75Srj0ikexgLqiRmb;VZKOfm4gC^*J2<1^StUl?-PqzUJa;m9RZ zrG-PajjB4WdP=oH<+ayo1Xzz$^lfhVk>fODD~7mY8alB?Pp-;SLEunGby$JB)&h_u)XUfZ|6U4zm7Zmc^B9ge zI}fNQW?j1%u&5dY+~SLX*Ces?wamyw-|N)j*jqni^AKc&fv&yyS4xMl0~J?Mip;HE_tu0DX(2S zxwfcQ1cZ-5K$&FF|90#gZp9Ac5bH%$(G{+5rS*Y*mj3O>E#4pXD;HX*Q|B0XwQxVR z?zJpcJjb}pjQ*U1=J=t!xyoy9%I zl-o#)YD5HgJjm@~Qr+_m*G&=<-hqVUpdWcq-@1+V!BY&TIv^5FA9?V9wD5nujkBn3 zWZ^y@S=^_5=NscJ_aUc4IC%NrZsTrJ`{o;lcZMtD|9LNGQRWy_ClGnn9#pr+7_K7& zi*g`fAfD;*7*PH{j*s;8>3=UbO0~uq58;L*`cC7a0ckK!=kI-w-)RgTfO(*X{C9w_ zx&+B3~&h;8U?Qk%mS7G>wxXRKHvy&3b+91_koQ7CIRz- zrNBm@V77U<=^!rZfHS~Fz-xJ_giuRmIN&qIn(2j&So4dYDJFJtaJe7 z=|CzLOUX)|MX1vH3$myf0_Y+%-9Io{kfBmZ(ok7XX95!~R1 zBYTZv#Fn2a+xC;oH%dIIV1jtaGW_a8XK1sMt5%SU;>h{puyWs_oF}e66hrNt|51w> z(D)|V(M>KBpI;(AKk72|P0vgGm&xsql707*z41pFU7=uE14;_1FD)gf{+VpsB=f(m zh>8XoyKaf-bqn={4sx=zu=hsFQCrA?Vl%bRP%cd+H+hn4lgaJUBc;Dm?ny@f>zev5 zBD+h5#S^UNsf^J<-JKbql9)5&pz*nr;8DVK?_?;S|FL3%i0KIQU%X~y^m z`iQl@#(+3+rM|+c;upe&JO9XdS*2w6*U42E$>ww9Oj!d0>nNv>BL~kUSH^%*zNxR3 zil$6*wD|mvGn8YK$bI7Bikm3sM{P|(xQBE zoqpo!s_=_#UE>mQrBSj5_?}~iT{x$5hX0pxjI4T%ODWeMCD+_W?vX{QT=b3Wpx5)i z3%7GRqYQDWNk1|{udHgp11LAVOAe5Iey*Kz$=&2sX=#iML6w9T-_CISj?h_7(=oEw zXqo@!2rANFA$xy74)Q1Cr8mxmy^-X^C&LUbcycM83fAe1$5Qr_*^w-+wnf$yUorOF zQ;b(L6aG&p?8ZT=<{;sG{P9-HMY5Ysl@`T_r}GtVyP5G4r2>wdC`SsnSSVLrWr1D4 zl9PmEvVWnXw2SN|oc06dDCyD~X>sA#)Q7f`+fI{PJ|maZk(0{Fp)#cI!uCDXC+sF? zCy4{;-9UwX897F*xHXY-q>QnT7+Y{G_1@y!+wP#8JC~d!94u@WZkfYypXpA%*;F%) zib$ESNgo?-f4^3*z1Wg#tvqLTCwh0X?e8tP{5ZAFBGGUnjrFQa;Df$ zj(F5WIR{7@!UBVZb9)#+`R`zqZ%Xr_!uB_Et2nGw{83%k)F!jTEEz=pi}A8#x`oO< zAxdUfj~HRD%%Y&r8NW~V4Nbz4$QKh7FRv0C@snv2{uC29i$_r3_@Z!{q?4^6-j2ruiUzqQ%aVelY9yj8*Ksm!GfSwq%l;u$W>tdB zj?P+!yUR^$nb=NR0rkayB>UErz0=YEx(5OzVxLUQSgB#xj|{K%C;Q1NnEVsvP+@oB zR*7%Bli~HN$#IguS%$1njLgdIUjVsK4njI)C^O!oK09$3FWje+y>iKpc5;lY9d=pW9GthNxDJNrx|5r>liOuB z1jw|^SwnrYOh2EwlmqrT8L#BLOhs`RIdddAu#sH#xUf{TY6@j@8M*Hxa)WFRY*X~?TnZ!U7afxi5*RSR0O#~W=GuTl5d^9H$L z03BD+J(Ro0lRIQ~tZ^Z_FTO9pKtm_ddZQSzeMBPe_A z6TK`xed3C9pQS#ulkCVRXZK14^b6^9PZUWP`$-KGC1LV@hDS$|gC&C;JoKT{`N}O` ztqe)9xM=$Z#!nkc_W3)x`HxP{Hg(id(H=_9dW~GZfZXd(j`U|iO(~RZmE_b*c zHmPvUebo2c$^qhtDsQ12 z_%^vj3a;#-+#@ZHnngJ}n(U)(4=^Q2&7$PU)&4g|XpkF};xUwq50GPn$lVW-9aZE8 zD>>%}a;4Z%qd1&c@vNyQ7+&(2%>Q87lO!i( zOBW?BwqY*yy+Ith#Lp~kL=hYlonzpcjr0f`dOT|hYoU8D8MEo2`Lvb~m^??+B>ZOtr{ z{Z^5^nuxqu8sGk8C``yC|1jB&RmF^P=z!xkqYjma(dQmHN;<DcB&OjbUFoc<%ZQ|j#_)$&Q8K2F-#5tnz_UP{0I+$B4z4 z#dPzgF@C#qQp4O@c2H3!r+N7@`Rw;n-zK~M=0M8HQRGe;+0g$`4iuYjypeK-3{YAR zW!Pc0Im3aZKDzl}v&@SuFcpi)9)U_=y8;lCf(QuMqf0hF8{+TcrZN z{}#P$Ia5V0t)||62svYKHZRir*^=TE%1wvK#h1vXvX-?yL%CkYvhg_O-e1UN&ylP4 zlM_B9$E1^UWtNwWmhkMOaT|}jfgLhbC9d=ixyX}@Lgz^WS<`ACqFlC^99l(oH^{le$jP!pG^_4)#!cA)av+o^ zC)D}{#@dD}r5&;VpqzDq959ufBP(37tZ=!q!u6bIcwQqhG(0y z`WP`-PAPpqqny8o+$fy(9p&O+a-S@PoiZ>*>!?qXm99f7jECTz4f1)9Tv0?0cXl+) zs#DxW;!Bdj4dm7_x6c3;96(bhiOK!NClfyPa^ikx@GvrP=y=Zufa;)@7tk_tM6l_O7=%EU{ z1O2Zr65Gf{vLsZB(KX90aq=97+hhsyk_v^sNPUkFxllHq4)N&r;nc^8M{gI$+$euP z>dXF#5lY0mgUTtljF1eafMT(QAaM)P!kwepk{V%OiB~L(Zmh^XvRIpC_IJv(&Ccs$ zL6IfoCh_Q@>nX?lom?WG-2O+(S*|0tjg;HOgGc_Ga_9}Ln9mr>&8}HdN!dn+ooz~c zmWo_4!iq;JC%TprF`C+yq8ID0|AlhrbL6c31f!oFp!{br#bHMN^;YO}Q(Fa+Xw}re5ZMfNU$8 zCNV;TxYnW?%6*TJgT=MxNKbX-QEz*O93{4q`2pqb$z(4#a;mItSZbWJE_Q>=f3HZ1 zc%GbfmRunP#7Y5K|E1n{135^hXR7##?$gwli>q!ETWPMP-p^0cO()we=zmnk)F-P` z_!pEzUnP6TlY^v!0rM&MN(D1z8un#U-&jZPkUuEfM^nzyV~ujUFOo~nk#n;Xcu_CA z^n?J)iQ=mZ#aHLVP#-gg94zT7Wga_ZzGt~{tTS5~uU6tEEv1|!F1zMV%GtH!c+nu! z&hHz_8Bt`Pe6rW=RQfCO3Xa(6La+0*1;apgWTM9ue79~0uNXtpUikcvhr zFj#6@(@TA^Y(#w9D3{8Z=Sxo{CQ7`0WOte0=I1HLNrlp+LS`A7eCGxX<6kWEHC4Jk zMw2h&BQ;po8`28#a z(vnhf#g6r&7uT8~t~Xj-Z>`+<70GN#YGV8ZiSPXn%I^NOjo3=cQE&X@A^~F=k-UrA&GVOX~*Bg5q^+BoRrfP{NE$^92IbDo9^N*C1vZX76en&;# zWwLKL**lnAC@$GvLpgXI*(@$Op_6ju8{~HJbb%jAe3`z@vK6a%kNWKBB3=}UZ*E3! z=pLzTAXmxI)PG7jaum7wW^%Y}Tr#C%(bK69ZXx5bd}n^ewd4e;n1k`MO`)=irG3E& z=2yvWACPm#kdq?G-FJ|CWP=g)1m&PN$@$-t{bXZfKPP(eu(@J{fld#L@ox|pn-If@ z?lM0UBPja{SN?}`t+?2jR?7B;WZQUhp}5#oX{mb!^>O*+rpe^q`@tyRRCAt+EZH>b z50vO3@DpoI6&Kq2CH1!Zgy}*}g)$p5lc?{DBA0$cP8YwDD7Mum9<}|fYyQh_w{{K_ zWc`cmBVAc8+wKhEHmP8_7*~fs9ZRCqr6TPgnZ8LpY3l;Y(KnHc_mX2qqy4(2d55TI zmoZEf*XsKs^}%UmZ^T(+Jzvj~4P;Sc3<3)*7 zBv1~|+N{*K$*R>SK08)sN6Y67w?9wL6%U#I7s|=9NOip;vT(;0%H?uYl^rC;mntqd z_Y+1a%OZQNCAU08_Sr>_nMqCyCb!Dpbt1)P66EAM?G(d%rGZgW(X@A*`fO9 zE^XLJIrj^)`#0pOY3#Zd>GD)@NLe`y_qm50Bc3u)#<)J**vS-Lya?;x{l5(tg&I<9IiLQCx zlE4UQZRFe`?8;JuTyZb;wTU@DN|d2&6n{`9r(iMJ^2fe5 z^n>n+PBAXqaTXBkAoscop3Zog^4E*>U!)>0kR!#hbbU>^<12E>CuCpAuTXjkj-S8^gy0ie{e1{2)2<+#aQtrJ!i$EL&$cy+03|svg0Xo(-d<1i{zr8os9Kg z7K1LufN-(aa@pBL%9hL~UF}`Yc=>mc+hiXQm`6EaG&#{AH^z~>UL&XfM6MX7dlK`{ zew7M8akaJLYJ)$bzF1sr^zSG)-$@SWCAZ4hcFRtvOgw3vba_V>;|1L<>EzD}eI1bX z{0~3HfM%I?;p`fdyA)V*8^e9pkpt;EP2~?$&JgYuPnz6Jz4tb9(lK&_v&DD-O>89c z8=3zd;#wVjjOhC*xhjW@$>AL1j23c$WY8?GH5Q@Tcw@x1b`55{)J}4YIJh>nR>$+Y zmF)e6%>Skui8z~_P(sf2XT}Zbl)c1-BDyo9z>VazQRG&cZdH=5N76+~I@HIRE=khG z-Ri2*`wU1GhvP0sFiA66fg&-&UTI;I?CWF11A2*rYL;8MGMPn=e=*<09&&j%Ir#77 zwCsx#@FThC0=e-Avb%6;JLNo#neIZn%y0V{$`z-{X?5h5GIB!^xm|20>k-O6OUWan z5_wT7R^2m?a^VE^%hSf>?9wHa9m4hDlmn#8i~d5nDwEtIElvw%&*gkez1IZF^(QG8 ziVXydBPx|uxKr{AZF9!U#y16-uv_-;Ws%GvvzP3UgvCLW%~j;GmE9Vtm5-y#@^rh0X`Fi`0@=cXDNkB8XUDk$9krU-U!Dku6<75a5#ia*`G1iDnPaMj4 zsp8VTW>M~t3N$}Jx$#x;5AGpUl!VxB)jo1p-8PT< zw7+7JijcmyUdnO`4ddh%hVT2!5Pw! zrc=}>-A%65YXXKmSIVu-maeK1>rN75u`Ogo_qWOEm&x8U$&K=dhG@yyF4HXi8-|CA z%Mb0NoFm)yPI3LV9O|=chVvrvH{`s3lD$z+UDHhQh(0n6n`P|!ERt?J+2<{C&mYLa z;z6_Sp`4sfZkHh|WV$J)LJ0^E7hNS81j!vvOA8amyh2V=tp&!I>>}|~iKD2F{VTa` z3%UMBvX|`e+^zx&B3%4X-&d3? z|443;bBtmc`b-t@9R46&BzK_gJ&YE3iCiImF)NmGt4!*)3d$t`7M5{8H(GOmTO);_hs6z*8&k&Mxk*s(=|qpC^YuO*Wq( z=ZY69ks+u$MSTNWtB0mu=1SJ@#Nl^~y9<;qta^YE?SCbEOIHRxO1VtNx_I1tx0Y80cZk;zdmelaG85qma~qoswNQo+bSQ=cd9 zGV!03?J_HphER?ZcNr&cCr*0AD|<2{I36MQ%5;yEF|v!%^=xE#+YEBUd%_YwZ!zU) ze{z}hWRSSid})C9=M49Kg`8dUD=!=}U&Cc9>=1{VH;Uml8H&J6%Aq%s>m}p*k15B< zeVngwi`?;+3wO%2O}*fZpKS`4F6myv45FLJSx=JtZXuTkl6ySJ88gXw;-TZ(DHnH= zBgLqL#I|g9>J!8fCtlPtEV4>GahiBwFKT6yjms~~v>k4#;s}0;rIZ`T6^sMvfBD~P@k18`;Ho^X^B*z`94NS6S?+o%H49BQ1my-eZM6a$`EaY;WBcf6j=Tu<<I_E zNj8wRGBl01P#43UlRv%r>e+?zO+`|3_fkd-ypwDf2jnhe>vfX)+9${j2gyE1$$c{BwKC6Z zXHwrDLoU68Y(7oSL44=@k9v>_d`H|l8@gp#%@Ge)`yBN(Qo+t(%29T5eg(OF1Z^lr zHXfbQQw>iuyi$zNUCMJ5%lcpO7e??|Eg8N^Zn2ST^U2|IV%WI*kF?mQgmU=@ zwlJOtU}m=)>KC9v{819rQGORj-~7CrN!Z67%y24hyovH z{EWBB-D1?qqAyz};n}j9*+(&h3c0_km5oD`xZqy7#f_5H&RvYHRhH=r;WTl{nNq35R7=a9Qy z1xf>xZ=}9WHY`!&w49CQcRd5#e=nBl2%z>|5E>Ab|_ImF7F zE>ds)mYjKxTz`ffC>)BROmx=hRR;7Fk@JLoWV-kjP+yWr?v^pk74{3EzVdc*qRQNl zd-CAND8`6sbjW#6jmX8)VL`HCs&Q?Yq?j7#}$!T_SLj^fg{9cxL`daY{ zed6ik#F4lCo$-6}$z@W3!kcKyKC`J0o(2%0mbQokuJoWBEOV_L-p9En<_}>&ra0it;gsX#B&|#w zZJXGBv+SKq{vh$bAP4@H93Wo8CKb+=bnP1$?khuFnIdaqnIvqMW8AI@j94yR);5>2 z&kAzkLXpL|qhxZ%($SjQq8Xkgem3A1%9)a1Rtn|fljwilMP4h(>5IsI;#Rz6DazPM zz4r`>mr5?|Cb!D$iq4>%B}N@5Lsa=^>MQ<6Zn>MBo-O;6md#YudeB(%Wz1s3skceS zm6CDvuc8+RUMdc}QyjS8ClW3Wyya`ksWPoAzo(qtAs)L=YSvcFfD%`Qq$2GvQy(K0 z%=wgZVCY$m|@r-3MtLg_!I_Vj^oEYW(UF$LamCrLm({6H^IGjSU{@~wJU-c!~ zEW3wB>B1iIyv^eo?iEN5ZYTGR7Fl|-1jTBb^SupvJ^y3Gb>@oeO!^BGbV*Aa#6~h@ zh*X)dCp17ZL*JY$RAD0#!=t?Z`l*4c~a5v6S*XToGixG93*-> zxm9LKpm@j_@sJhbA(N!SiBB_r{`=$v=`mY0<=oXW|GnR&qTD$q7!uS>cTtp7tX9S{ zLsnB?cXnZujA_8Tj2|pU8!EepzBAO9$k4PuLb+)_*|AyXf0ASrTg8B~7s$P#W1qNG{RLCq@&@r_Suarz zkYzVVreBfhGx8W7yMi3bW!02cPPykUa;D^0Jdbk4Q{-&B1Vl+jNn$j9Vq8%x8PWba zx#K5tjCjUg8LCDZl1z!$EeA6`;sJa9%yiyq_bcm-5l4;o0#CVC~>2hU<Mrz(69zOcB99yh7wBr9zpC=B@u}$Px$nAe6M~@%}{EHmt zbZjuxK5-oFG8^*6vpK{8bx6UzKQN)Kh}>5v8Ob8m7D>6XmRuyWCwvU$%o*e)8PdQ8 z$l6i)ileHznGyWNQ3YgZ`A;+4aahttkmJM;rHda5l^)J@ zy)-vU3T&0z5Z^sa*dtc&D}JMG3H7llBe%XF zj;eMS6&cdP@GQzfVjDdY9wiPcTJA&gQ7B40mdY+=b<_mJN6kI6rN@R#Ceqwm0IIu=>VD7TTi}4#Y?t#G`^S38%b6Ykx zWx>$9w>>j$r`gN&*>L~7oK;Jl;WvyqcnkQYHw^orrv{B5^rV~DsG6bb zfj5mfqs}WVdfr_Bf6nuGELt6T(>QD?n4;DkHttM5ZN{g90XK`uG!$3}ECu!hhk#SS z1>iC;Yk`)1B88>F1#pQTd;sRg^ zuoBn;)Bz`fGr)Pk6U*r^U=k1k%m|gXYzOuMX8=zeo(uz)1G|8|zyaVGZ~{0DoCD?#GnrC=jlfo52e2F1 z51a)?_@EFV1Xutp0k#7Lz&_xhe%D7GF8qh1MZhjBB*%agz{HWLH82-Q0d@e#feXN8 zAOtRW7O)*S4@??`3Il6_UBF)80B{(%0=W4hFCYcj2pk7aW#hlIfH4}i1;zujfF;0o z;0!Pfi^6hXGq4NT3mgCr11ErUz(wE+;O37)fUUqO;4)wYAa7ti5CUug_5lZh>?8QE z4mb%68;f25;(_JBW?&m|8aM}B1g-#K<4_2&5ZDN81$F@Yfuq22z!;B0f$_i+U?s2) z*a8#)`+$SvG5$wzQ3rSiq5{BjU^B1{*b5v0jsd5EbHLCEFe+dnkOFK3jsh2e%YbnU z3Iw(Q1;9SwAW#RK0WJYofryDHXCi944HqW>w;*H;Oa#J!xxj8^44V+TZ?_d(o3PIk$c3>ZH5U2w@Ly<4A8Q2CK0FD7C zfOEh_z-<113 zM}gzODPY7bWC_dy764m-0-z2!30wl^M7z@xsU_1~4Yyq~bjvC{Zs9mwB z8*l(P4V(im0#|^ccVjGpxxi8&1=siCek^nPEFsX;$GkmfOAe;ow z0Ox^8_o4#8d>|fJ4y*+Z1LuH?fZKg2444Sa1r`EJffQgPumd;+oCQWKL4m+5U;(fM zSP5(a4ldC?4HtF5N#H8rnTTEh{DDcp<@+%Xzd;7T7GOJY1gHZ}0%w5pz$L(QDJl%C z1vUfQfL*`=;4p9kI1O9`t^lKwvSFY}Xa%qkNC7qi$AMG8SzyF6*cA{0%mVfS2Z19% z9dHsj0}OirJqOGOmIG^n&A>6>9B>72TaI1>!hnUq(ro;f0&E5L0~dhHKu9vW3s?fI z1l9ptfCAtka0ECBoB=KYR{{SOC>U4^>;(=0$AELdMc@kH_8&dp*bbZl&I6YKe>;W^hydmT@xXFmGq4TV1?&Y5 z0B)-={zF%xOMoz7Bd`_N4IBcF0>^>NfN3=<1FQtr0b79Wz!9JhI0>8wt^%GZ7!JT6 zhya!Yn}HL+Y2YF-(Sb4@*%*6VECo`4jlfo52e2F14;%%K1E+wqzy-iqgI)o~11o`b zz!u;Va24=;2o(VQfe2te5DzQ|4gkl1bHJ5s{5NzhED@Lp%mo$#OMw(%2e2DB1RMoU z0cU{=Ku9VK5?BB%0k#ACfI8p|a2}ZdFbW2C0egYNz%k%7a1n^Ug8zm-g2I4}z<%H; za2z-VoCPibmw{R9P#CZsC;;{W2UX<<#*J~8aCsFNmWDewE+>pa$qg68Q2Ew z0`>w2fWyEs-~@0QxB|GPqvgOTAO+Y6Yz6iMr_y1W7jR+PguwgZo3Np|j;3VMx7#aYq1vUfQ9-EKaAfe}w)hCGR$48g?$ zU^`F%90ZO4b-+pB5^xpp+=|KolYj_dJ`fM=1B04ISnz_46&Di8te0`>xjffK-K z;9Rb59WLDd0J8!X0x7^o;1F;WI1Zcw&H@*J%Yf-A6bvi@Rs#EggTN8sBya|}1Y8A% z?LZ}fNk9ZJA6O2o1vbaxziq%S;52X!xB|H4p|!w5U@4FSYz1}zyMg_{A;8#)E(gZ% ztc-rayyqh$Pj#F$hN!(C8GdHFdgmkKcJnIry{6S__{aFnWs15Rq+&ldtZK){#zf1M zHR>%L5K{g9$Hwh$=1?{KB%)7IcWRod9@7+|UO9$n;q)Q zW@CzF>KZlpQ+$;)M9uirxLrklio7>}Y6PlOeRTj=$mcJg;)`lw%JLbq3s+Ml{tQCr{BP%J%d1eqh%?@l8FyL#(1Qm#^8Yg(-a zwIG&P3t}y3K`e*b)Pj12tWmEZ0QLH^1+@=VBR@B$E8ou%ZTaU$Fv{Qgxv^N~X~p@^ zjTqGH)-Mo$x?1stahpp10{Y!w7y&5t9j&*kAHP81Q`E>a2=3Iu@n=v=yLt=?)aFlT z5NoyiTuUj+(hA9;rnMT=EUVY3^;!&3e`-Y*q3TmDO;H|SLYk_keF-T{J*+8Qy`+`X z)F)q}$EGWfuRsxMwx&q+*jI>RSFb@*nsGVnx$(G19 z>fN)b$yD|IS!5WdhPR=ceb4A>x1m)LYEzr>A`%V$8o>@V`)hnF5PkMAM3wqAq8<3! zXi#3|wjtG9zA>WADEFOn_>k+W>Iv<}Kg_7j$nTuBS@a$HBknt-*#4a}<5!?S@TZ#W z>OY!Rsaww@@@lo>JW5MZ&uGb^K0J@!K}~->Z%j8r@O4L1pf@HMZt&7O@ZHI!9fl3P zwWb4+r>GY|s<;E?oar!vRFl3kzQ=%vt7+dO#x(UXNTq%c{XwmdP@jHpOrGt^beOxz zG}CmKV{`n5O`8|l(;QfrhMV;JtT0cVVIk8(LPEl(_N$1$hkEx1W8_GG51m%RLrtc! zQqk=L)z3c|WBs-d>=!=edU%K@^y<_-mYV`yMLAWjtfrbw6C|s%&Zt`#T5cZXih9;l zExKR~ci-iubD0!pxp}NB$f(`_{bZy+I zmvKoknI=no(+#>>`x7nW)Zu2-%PG6+<+yHW+ip;Ue=KBgerb(mc`>L@QjcM8Qefx#O7+n^&Z=|y^>rx-x?AWw^ z&4x{@*QGkvZ+=v_2t$6YQyEVh)Xx@%VMj63^nWD3mX6^eH#%og7);w`Bq`(6j~9(8 zi&Dn*t613eQMlmL$JtZY-#_KSdmWFaKH<2QDZ@CzVK8);VICf@9_}(m-+Op`zdX_V zuJ9#+&cE-I&qf^xVe>X;tJPPZ&)(MzaF1I);Ts`x5W9;3dFksihF|AyU zorr;&X?n=9`HufNovCMe;r%SXV4C{%?--Nr7KEkkISYcPt4}mVs6hj4GnLl>1ji4sg<_HY-2mHk zEVAzou<5&7ca$>G!xo5Q7kMBUn=nn-4QN`We)OmQ2){TKCKV4LT^|1Tb-%@ zU`3Xz)w`Nf)X!Gi3`@!yb*o{!1NB^QppQe^KNh39CJ$bPH&rKfMwbm^~^Baf6+_N_~>4${>aBR zW{`Px_4i|JUs#aE`(sfHY*s<4b1Vw-ABU!|R`bR=8~d0hhk9)sM(5x-jL!LSdUUD> zjkn!=gE_2v!Zh1zvo?k4h__n3uPH_SqRF8qM4%O@!LkUnA}Ioy?~QP_;zKCVihpWC zXGLo3jYRO;NCbzg=OWRbY3f5w)73ALXitQiG6RH0&T!WEr5Q-NN`0znwepw=N>MXF zDsm<=+A`BNQLUSa`W~8zEJM`iI!34(Gz&CE&7Osvr>gau!qiJz8LmFnG);L#fu^e& zAQc&<^NKQ`oCm?PGxuV=&3+jM~c z99Vj&S~LeEFh%`g4sw{P-UX?eIS9To=l|>LOTenCy7$jH_nhl^4U0aGB}{1m}Sn8<&+rUupDwg%hb}uiOdm8Gs^)jzp^y3(sD}5oWAt?ziaP1 zh|k~OeI8x!UhCa!uRWZ-_u1#%3q0Ip)FK)l!f8OX2w^^pNIDRWY*BQVg#&+R9U_TF zut=uWEK=wki&QdWZQ)ck7PXF#MTsFaBNib{kA>$$tibS$wRNDItcdJrYr`Y7qpd5Y zcVtFKTRW8fm=%v$5#I@lNLttlS#ml-@qH&`agf;=3R`C=26eWzq27#^0U?f)FmW7R zY+W?R2pZ7E)|H1p3p-t55lX>b!9m-z2&1iCacSU6W)V)|-Jp!1*I7i;?rz8sMUNrq zQ8$jLJ0eP=h25dYol|$PQpmRl1g@qY7;8x*XnqegS_mEJftv5{VXLyVr>J;vPo!J+ zgp={CK&P`}6)P^WBAm=#P}q8LF}65HK!TK6~Y<8;Dhl>G1)!*y`MmQaSp#7}Z z3=f!q2jeQX(`pu|F9e+!i~=eS z!AuoK!9zrqlURh)(jjmXQFLaAZKZ*5G7^!DqRolO>!9QjGLosm2#~RGj(|Cp zR*XPrV3Iw<$q=eO62eY>M~b2svcP!?E5oSrC{c9WD5S6;Kv2#o`2BtquHHy8M~h-( zN5j2?ri@0hlSjjRXtXHyFV?3}^E8N5N=n0s$G&7WlC&xfv`cB|4m+7+ps#1KZGLC_xPmyU(Ia0(p@KM|BR7FP5>r_lc_(EsUBCQ;vXq>^cVI!1B|ona*= zmke7Eo?eG!h|#_-0~|Y@XAw%($DwMisV|E#${%OzgEqcA4z_Ue8;|NmP~3P7kaO&@w{?bXjv8JRKGXJd6%c*j!DzrRcn8^1=yew8=yz;lJ9h0I zQF`bCG4_%cAhb|gy#Vdonl3L8r8md{r46M)(C8er$G#j)UlH_>^^p|25acMD&B8&) z7utHF#=h?&l}tleq|oYj!Azwq@A4qSh9eh#F{*M=n4LD{f)h&DScx?>4|NQqq&&oo z-E$ScKA62->n3F77PGg!TuckR|BYHk7mkjBr}bB7)8@L70&guoS5%8nP6= z9JFF7qQ&aXsbs275GmA`MJnYJipAn_hLaf2%RseLk7cMsD9u=g&YQjrg?+kAT-_Jh z+=hIYLxfWtiwK&{0t@GIWG6!+Q^XSm!;k$G(R?45Q8OiIMg2Jv8Y9)^}QkhK!&ot1uoSY4a*k z+bgROM-&CDhBAcWR- zDt21yZT~aWh@#4yY)w>}`~wcyqBq+rX*BpW=z~7C^*7*kYoRR=)jCyZ^F<}E6k<2G zoKNNIZAUYOQtWnw(3&P}w|$L(+V4PIA@uqVM1q|wr?92mAt=>%LK#L~c0$>PX6!_G z;q=)~*dpi}Dr({s9A_4fQyWYY;b7=S2$~ zK9AOkq`NGlsQHhG%|S^&!X36HKZ1fS@Q<)z3;ZL3!GZ2in4PgUXZ(bQ457_Gp~{sTbw zITkq8{+TzVKZD%uXR!^P@UyKsH`VH&;S(ER7MPtcp&)F4FCi1g!zCy&nvtSSmyq}O zOJW0By%gpM>QaiJBk9djWEHj-~OmR=W)bdm+O>o*`GsQnFii=;FbQMB|1+&Jjy4P?aZ1|>bXfyhE` zA|A{%H`yW0zKIs%M;bT54x!68k=I^i-r{2LEaOib!H0Pp+GJ{b8(C6tEPxc&+}r3? zo}+GyUNy@QgPppRffGto$}lNRE<@%|pheI+=;7%crx3_JRM0`8_mE1Wqu&^ATK_NwT!$F?*L2IG~jIY>8i~ftRG^sC}W6e_Rz;K z1$n%e=|_i6vx~m=3s^<6u@{o#Nm>*2_@A@}(s0WQ*%CP^BdvzyT&~C3YG%BCnqx+d zYExiy(;#nev!mXP1HbVcBADcj_!Q22$lG*SSfAC<45Uug&2IXr6a<=E-5jcCaXZ|u zZYJtke@Rq}#`vItsvUI&f6~W{)z>obbW;?zww9?=NDZ@-9?0Ie1;XjF8fLT}$n}e^ z4a%JwDC0D@e{@Z>VIt=RYDVAHH2dk>IBwBOJ$(^lJhw1H!y`jqv#Wm087WqqTIS38 zZEizXx!v?bT;z>fsQp~#p|lh|kSVwQQ0}4H<{*8eyQ5pzf%|HraAzyosGts7DMVD- z&y1k@erAlG=ycGXw)mMH^!N)X1ODdf@!X%NU@cly7u_4}tY9trZ(Vo}ABoC7?xx8YHav`R-{%z2R&|JR@ZNH z7p!f-Wi`a5a+|vu-8V|l;(i5cMm3*9H^;k^OE?+GRl&#{rRQ={qKz^dVc;t~@I~@u zBaH8j7WAv=&9KJii&d-P_?Y86#B~*y@1n+N`--CX`D*^VF|M@n>^!~++U~aVqNqh* zHvun^o!4lJrd;c!)TXzZVszf-Rz#a5>WVv@9?cL=qVpQ|rOnOEA$mNwo$Dft*PHU- z62Z=Ij$lu7ROky#D$P;aAuc@fd5nYcj21tSPCCTRDaKHh78pa-c&v$8>D3mPPqMf) zalKw`fr~Dh!_94pq1>w_uBdnp4ateR!qJZp#--LY7(Kd{I~Yj}ex?Y+eKw32;kJTd zkUP=?tuWYfIfrQ0kPvpj@nQ18WtJ1&y(++d>Sp!m>D zyID)!niu0k@u8+3v=v>%ldkiVNGtUqjc_$EFoo(Z}>Dh}&MQE8}ISDiwSLd`nh<;e6Jk;YTp?aD^=cyj4u$gEF0IgST?Go%y# z>OlY%v@vVz0&xHae-9x*+Sj?EdWd?5p$6Bb@TGzw1BR0QOl4W0=6;IOP+EEeJ||%&pfj|00iER?_dtUm7D{fk z8){SQQe2qnr)_Y`5~uuEN~1|Vx7*GhnCyYs9=OI0)%_F`fhNhKVG*KYIe2mtONEhU zP1N!f5(7j6{n>~LC8Y@-B{g+X`XCYNN@ODuM=_BYr>7_=5`OPfI|!pQp8S02VpVOc zC}&+>f2O=h(FuXHMFNKaD1F@vc!=cUeL-rJ2=IGo1B4cX=PnYbH98q-`Wi8;1gvkgB7Lc6X~8q6lIJoWH;an3FBX8FQPvD-f(>h7XkkAMBdkj;Zd73 zEdY#>@C0C80oC8B<%?*YgyDEWOB%oTz*k;zYp(#lBnfR3@wS$P)g8D@rK3hv_M+&_ zelCzrj&?$`&js!YfbI=V;$bd=PX}~HI18|u^!728ATOBwcND{(s89)>r#6&1@3^5_ zi(=ZN7GZc;8X=8i096V3b=#g276AqbX#EcG_&^G7hvBp4fTC0pYX8lEc;qWS7-a4b zPfF(~sDlWq?LjdPJ7BC2qQM7+&rfB%6lSLlq9_waoV3D*L4l+0hKG#W$snh-`A3{|N#21EIg2UfbT zC>5l(8ekm>n|ZV$9vA`mmL%*2>_kDISM;Gn(YP4?_WpbX+VN>neW5Af3`<;rAsP4UKggzQNgDrHoj# z*%2y$N}WXeS=^%^I7w?aag@OqHhKQ)+a}2vu4A`S+64zARQ=PPc6KQVXGjB zgC1wCM8Y-jun1;3^N1CCJ#78Bk@11e{edd$u0NbOHBaYzB38Y& zvM7LtcQ$JWc2G8#bA@*}ogWpiV-!l3#ZNgVGx{l~+^Q=s)lI3I*-+8zKiLFW4Bfuc zl`61#!rJLFiMDT0F5iwU^S;6@#eg15pWFU4gU^H8yGm^5u}%)vToj1d4$>)4L7poVmP|iLbdF za6`Qao2S=O@O=UKQ5B1KzjFD?H}H^h`S`s?Prl4@`9_w{_(r*m8Ras*TP|byd`rva zo9HS}Vb&JTMPdh70RJOlbL`a*3m9|*u=p97 zx8T<-d}NM80`i<#;kAipkx=CXsVd)c!dYhd$X-*vgUwGm_!IDXk*9)H@x$-?G~`4r zqaENJp`U5-{sIZSrY=5SZm;sP>WDA@k8<1Gg9R+B@=-ZkCCy2Lt&`$|9}g(}|5mWM z_ZRrFsirQU^h0OU%eVp6Xc5oL=eqaDPrD?z?C|CKs8~fez*f{yYP^)@PxOeQ42v(< zChn1-D&r;%hb>qXfL}3KfW#bk0Z(=-_GbwgCW2UV+=NC*q&pWfXDd_S*HsPNgT0cP z{}MdOW)A4DDlNn?GkORpma%I`Uq=FKq4*%b`@^b*19<7<>vraPz}8Ms2phojCe&nga9X){m7mjKv+weoEw zuDV!b=c`Ir+<|~)-LU{WOo@%X3o&iGa!h-d*A{2?xlbk*KbctjWa8r|6Q4er_~OaL z=_eCEAyJo#1FQH1@yvQJUv=Lx_;6D?Kj=B{l@#<6HrL0f9fa}Wa?Z#B)>o9nNYrpr zeV(3UD37yUrY$UP$<#w3{H-fcOLso*Hu+&xo&5VFLlcUE@b3&}nDZj9;lAPFuC^+Z zDU+Fbl*3{lZQ=}9SE=rMikeFK^`jP*GP5~7Vljp43_yk@@1w(<<@+l9w|eA*_rSyb@{&VcaO>IKlG`u%>KR72IlyPaS34SSLg|7Vn{y&AC?5Di+&m4`<%9 zgGYJE5Zv@{@JHL3vc_lbLkO_MO0@P`hCUcxNmk26jziSA*=qT1W>e!M<`<$+PX2#L(;fks^XlbbQmJL zcC-~0Lxha>w5 z8V%v!|CXw>b5iRnx-&D!Qc26F0%mTc{SZby{K(KiDtni(}OOTn@2II^J5`p5-YNxjHiuGI8Rxn_p|f~jrfhgpf1y|9!?ZJ)t1VbGJtG}2=g#Z)hHW&jWdAWlsOC|S!uea~^1}i7Qwis4OgC99qe>36SY?FaiPqf&(2bs0gBU1 zehU~tnJMDnMN$5uJaE;1w1u-Q4AK-U6(*qp76UdEP{o3p49@rD&*CmcK^XVCX-X;C zM{rQzQzlz#Q4Wj4w22A7_tS8$#e@KFwLd!3**F18(nu#1ZLydhajp(jCk45d57CrI zl$VU&3G`k{3DBX$bT+LUswvCaVa*DTW(nL*}C0t;_ ztK-m=gPf@r;j<_&pE zA5r*dKpC%^Mrs;zzLl>jiPHEh zAVvWPIb{*XkbtUYzAzn8p^mTEZO5q(%`nWlUtvz(y|oMr4=kqFs7X0rS$JStgCz2O3UsMU}n+JTH0c$vYjquRi2UP8c_Dbi;Qx zxmrP8P1(#_zFET~4Z*AMk%mQG1V0l$>h?(bn?_~esa|Bu;No|>oBKGRY;LSt4mPG2 zxyFsLXb+Fzyfi$&18OE+-KP@Ju<^Oc?1H_Tl1J)Diw^~k!})aRK^{AfaTs+QC}tdp zpV2S~V=oLz!eICx;t5G`UZ6rYCVZhOW2JFFU=4~HkNz(KjFhm_5e?t(XRTUD?Z#sz z`wW_D2HhHmjrH;4ygCT$eaeGXtN1l-9gh{U4Sj{A@yFLZc298j)}&@4Dk6UfW6cR3 z0702Btffpgd?LjGDNYDs`~=!iNsFXXrVXV>od2zp8XogxPC&F90sRETe3&o+oHr>Q z!uaSE*GO;<0)|RX85J|90bO9uH>Y_z5FDQp4XZapwFlW>1t)=eLl~Q37$!Lt&S*-w zi) zwovwKD1SP|ybe#*X&8i2>pHKrY%uBr21rgjDr8P~I>DUyyWCPGuY*H?=>l5ydz!LB zrCYCKG_1bQqgF7^1ExvX=>boqtW|eX-XwUs1Whezya!lcLf?m6u;7J}`UZGu&^#}V zO91;w_$y!~$-7CJ%xm&rz7#~cp8}>xSnppK#2&X4JoPUjj1>GWKVQk20$5Y}dY2L= zgR_OwA&fsOTCf}yOhsk?1ylvZT2;)Pc65O`SE^Vrv6fEeMzdLzGZgb}1s_^F881QE zr@&slng!21;lpU0i*gqn$DcyAPc4s!N~=TmK>~wY`g(YRjIj8m8N5M z*ww(Ie5X_JGz|Xv6a$s|B@JWCZ>=m!&kDj~ghX)Duv6Tf6~bx^hQ^e|j0Ef;;Re7o z$*V>|Gr(IPX~Cr-!r2Vy zBDgB#4`D>$1rVGhfMe|icvYdTGf{)ql*yzel*1yFHbGdM^swNOl_YegQntj?BM2j- zmqpn@na^2$C?pGWa!|ZQX-{evihG3;vcTxw*MjFUtTAf#vnV4ZoC-LW60*U&O2yzI zx(h5?(*p==&7l@$iAs;N5YlF{XTx%gdP5jjUa=@YQ$o`!K2$9mB_2uPW-Mk;XQ_aR z7o@mKKQRCA5fEVgItYkr1BSu7xiZOmIRzJ?PEE-hZeNJoR}x!SwJ<9twi~ z6`+ku-a_->q4nD^dcDdW&qnn*8qAtW6D`xO%=*y&4f2C*tN07m<6~^!q&4m0Kw}< zrQl(%f5f6Y)tQ4_j=4PjsB_>ai4s_|6`BB{v3>(MN~3@|n0>?Ev0#%ah~uc3iH-6t z%12a+tj1};Pb8eV$b#2|g!U2O5&?tq7h4p(BOyL*-FI5@X7?s+(`AmdC7?-o1hA8Y zm6q~6!Y-}L0c#rc7!he(S5ojiEN9>2cWhP3`~h%`fNCeoo`)cpueIPc8WGL`!1-jK zhj_cK<10sKXS<>H#X2(Q!(pEfxdj9~4$aVgnzv0IZ}#7Cc506`E0O!LuXbE&8wp zD;+}&hCJ}pk+g;B<4#y`_rr#^R{;O(4AXT+&Pfip^d#E-8MezODIfm9l_Zh;bZqUJXnYD-L&9$WeI>l? zf%gHUq}E>7P3Q_Jvjx2j=sI_A?+ly;S7HuqO+{wyle%Mv;lwtk~Wdbm{##Q9hZYB_Eo@z5~_{d zJiI572VM(kVx%!0(AnS%0Z&PP!>ELL!<)GMeFfNC7_Gidb^HxRS>NX=CLhF@W^RXX z0?LjxwB|bId(rE7*M@oH+!|v8U=ta`2|zr!kOK+v)r8wc>CBPzb~S>@1cZNuMl?eAuH&U4kl{0c<6q+Ck?vnYAMU zam&JRg$JGh#N5l;>mF@DH1~v$z@GY@Aj^7!oHOZSmniNaH1kzkso+o@~rlwTn5c{X#j)cFk~E-f3dDiy8(%mJ(@ptdBF zwyr?I{u6Y}u)^Bd4OI+=mGCkJnolWcC9;N2!i*<*#{pjvP;Ew;%&Rj+$E_$kv9<%e zuF}aBm_nOQ({Y#~e9s1KC7`xz8a-Z#l0TTKEB{JWL6!&x?h@YP;Inm{ONe~U-qe)` z5;mBnV;7{phhTQUt>e8&L1;Q#$6>E1dM4m>XVL%8(Xl~dvT7mwDh&P_LKuza>q=$G zZw2_XOyv(UZ`i2W)1UjT?-S7G=i zU|k6>0|rQ_Y}9e4zy#Hg3fCfle$b>z<9@&{5?VHKWdsjPc>yX@pV~nfO<-t8F$Hjt zA`O`5*>DDi6k#yJH}eF+9AgBaP10W_bsetqw>MM3It-KxABmN69Y}uz;=~V-x0E39 zQw<2i{;`hN7K50xYYShe>UzL$0NYAv-OBBmxgL`&P(7(^2MNp zJU~o;>}MZfXUS8kn0Xbqaq|gdN5Hxg4hO{Ch%DH`+TRE7J!qn&@jJjY2|E;uX^&m! z0M-;*ZCxQ9cpuy6QS<|6E#Ac=yZC)Lt4-b?psxPZ62iFjwT{CWHW=-`;j%9uLEwD zaLM;Bh@#FN;4Q$uk`Vo)yUK>`n;tKpn_Rf?%n%#z|ADHaJ~th~&7U=ha! zz~<67rizad?#y3!wiTt}X#{IV|LPt?rEaJWrffEr{HEjRSHyYps*9&~p)xkU_Xl4g z?92KYpw@*hzK@w}Un>I_V)hnP^Bf>ve*jdg(ey3IQ#-^^P700n3Sg>*R&T*7-;+w% z8rR0aPE2HVc;H097o~O^;PVpx=poz!#3>4j@&5-f$hp_<<&-RV&+SWvTTw`bC_{N$ z`d9#n10N1`8DOx4M*(X{cpk8>g#Q3Kqp-I%FhOxP>n=b)T~xw2)!xA6FTDK@O`+F~MQGHYHeEo9d2SOYikdF<*G zAYPedc+R8!)1$rX(Ry{{USKY-#Dy3-_~jc2<6$SRQfVQa)a-2FRceM@} zV;2LPW5GEESX07Z0juDzo?uV(XBUdwj&EQ5E2UAXE3?>yQw{rexM&7V1)(uQ09%oL z2TFVeaEpLyRr20}5_?fg7I-&+MY0q)Bty!`>}KGcQDnRh*g!&CcNfIgri^(bp_wg= z)|-HeMi;kZAl~e0DC=dOT>LSa-V$B_93o*vZv$6~@IM(aQ^IS2BL&2X`OTe(>Sc=A z1u$+L*TNhWi$MT}GU*sYQshj}&91m?On{ zDGo~UqZId~@S#l3*Gh_>QjC;hmK1BG*ek_%ECn8va%!a% zMM4;7U*gfi^}!cYgk7hCJ)i|j@uC!iq?jm0t`r|jaZHL|rBEpQGi0wPMWhrj31N&M zU|^QY-iyXt2-r%({eU>Kg;x7*0L|Eo3+)k9#X_YXAje)b?UjLsvQ_dI<1Z08y=(`> zB*hMo0OEZvK=nn6*@vt4x4|@gADsO;#K40t$39qU(+OC3;{{>V9co~FW*)^^38!(n z2y38B1<4d1pELJ4aPhV=8d@+ik!~V=FO!-z9t}>**vko#M}&D>YVJXU$2c4~ruJfR>ZQ0fSlU<< z3}1>=7rErv?TVdQu&)m?Hd2~Brs zoL(0y+oIUx1Oayyld71m)RBx_b}L_K!jn4~?^jG4(KKgNL(~ zN?EfH8l1E9u+~Sp2VfOIIj~e8DrR3n&^URcJ-qQA9=6cTn+;7Q@dbfx`&L|T?A7V& zgrxi^D59w_1sp>rztL_EUM^)#GiaPm)m3WZpmBCnrqsOQ(x9t3&pM=^lTC6|YEF1G zWm0n=8Z55G=vv2D$m5^pzS6=0W#dxfSEjDw)iUnQ@scWrkiNw06KYlB=3-i zcg({(CwSS1QEcIH6kBPG+nYC_^NMT=*in``M)D?jcvAqKeLokl1(o4im#n=W*5@8p z37~U?R3h~olv-`9t5j=kzyv&_-G|k7bh^QJf_#yeGA%KOcRgZAOaXMxN!ftT2AJp3 z=6bZt07FH#pyPn9ul5XhY6JN_Z1_gr2`n1F=Fr6xnCHu&!ndZOvJPHoC|B@U>jd_2 z9mswXt3h5a#ht`mpo2yuX=LRac*IwH68qGHfOw5qeDFn3_lH$&X+N_EFXqj&{S=1x zB0&5y0K;v7`0^v5c6BiYpTbkCYNycUgQa=S65dM)=5oM92_FFB^o;Y@S!yU31PrtP88!ZF;3?Jkv_MlrXD%+sjqf0rA0`j8Ek(Q2iE+dH=M+a9N}jCH5!5Jtdi z-qNzc=mj`e(!X89lQ`$pZmgwS>`X1-OTtkC)pG?jyabJev)mHi_sXP^3&u3Tz*cb> zEV!HtSu_wSquDy%K(PmF2f&UNGD|Qb-u!^a8mohH0bQ@e4(EzFKU}{LVe_ZLGbsOy z4`}Ndg!DC3pGwuN4N^6KgMsHZf_2QPIt7)NR9$qceuE147Vu^LFJNDThM&P0=uMet z5w3%B&YI6_M?Nn4?5x?Pd0u>Eer3J3Z@`c~97m5mS5JL)p=y_nqc1gDJ1yR?sNQ4q zPD}0jUq#hhcr8`&Zp5aRUj4LBmmfmRP^_*r^b_CoERq1qy*QZ4b>|QU`sg#0mXC&ia(vE^_Gc~I5p}I_4Qh^@# N_KGd)6z8>1{eP3(0BryO From 00c1c6f1085aeb64dc6e5ecda777981739446ea0 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 13 Mar 2012 13:26:17 +1100 Subject: [PATCH 178/178] Quaternion: credit Justin with the initial idea of using Madgwick thanks Justin! --- libraries/AP_Quaternion/AP_Quaternion.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libraries/AP_Quaternion/AP_Quaternion.cpp b/libraries/AP_Quaternion/AP_Quaternion.cpp index bab1a06ef5..25f82d303a 100644 --- a/libraries/AP_Quaternion/AP_Quaternion.cpp +++ b/libraries/AP_Quaternion/AP_Quaternion.cpp @@ -3,7 +3,8 @@ See http://www.x-io.co.uk/res/doc/madgwick_internal_report.pdf - adapted to APM by Andrew Tridgell + adapted to APM by Andrew Tridgell based on initial idea, + discussions and prototype from Justin Beech. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public

bk!8!UqOH8+SyE5&# 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 z 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 diff --git a/Tools/ArdupilotMegaPlanner/mavlinklist.pl b/Tools/ArdupilotMegaPlanner/mavlinklist.pl index d2b4fb4de6..3debbcbe90 100644 --- a/Tools/ArdupilotMegaPlanner/mavlinklist.pl +++ b/Tools/ArdupilotMegaPlanner/mavlinklist.pl @@ -11,7 +11,7 @@ $dir2 = "C:/Users/hog/Desktop/DIYDrones/ardupilot-mega/libraries/GCS_MAVLink/inc $fname = "MAVLinkTypes.cs"; -&doit(); +#&doit(); ; From 706bea5992269ccf1645d1c49dcd828f5f70668f Mon Sep 17 00:00:00 2001 From: rmackay9 Date: Tue, 6 Mar 2012 22:15:02 +0900 Subject: [PATCH 008/178] ArduCopter - added OCTA_QUAD_FRAME to comments in APM_Configh.h to help user select frame when compiling with arduino --- ArduCopter/APM_Config.h | 1 + 1 file changed, 1 insertion(+) diff --git a/ArduCopter/APM_Config.h b/ArduCopter/APM_Config.h index bc2cbc74b5..1c766e182f 100644 --- a/ArduCopter/APM_Config.h +++ b/ArduCopter/APM_Config.h @@ -18,6 +18,7 @@ HEXA_FRAME Y6_FRAME OCTA_FRAME + OCTA_QUAD_FRAME HELI_FRAME */ From 72a775cc2a8031f8aaf47898732827cf6b885d8f Mon Sep 17 00:00:00 2001 From: rmackay9 Date: Tue, 6 Mar 2012 22:19:19 +0900 Subject: [PATCH 009/178] ArduCopter - fixed typo in motor filtering for octa, octa_quad and y6 that is suppose to correct for props speeding up faster than they slow down. --- ArduCopter/motors_octa.pde | 2 +- ArduCopter/motors_octa_quad.pde | 2 +- ArduCopter/motors_y6.pde | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/ArduCopter/motors_octa.pde b/ArduCopter/motors_octa.pde index f4e78a99df..8f552333d2 100644 --- a/ArduCopter/motors_octa.pde +++ b/ArduCopter/motors_octa.pde @@ -163,7 +163,7 @@ static void output_motors_armed() // this filter slows the acceleration of motors vs the deceleration // Idea by Denny Rowland to help with his Yaw issue - for(int8_t m = 0; m <= 8; m++){ + for(int8_t m = 1; m <= 8; m++){ int c = ch_of_mot(m); if(motor_filtered[c] < motor_out[c]){ motor_filtered[c] = (motor_out[c] + motor_filtered[c]) / 2; diff --git a/ArduCopter/motors_octa_quad.pde b/ArduCopter/motors_octa_quad.pde index 034cb72dfe..3032c6d82a 100644 --- a/ArduCopter/motors_octa_quad.pde +++ b/ArduCopter/motors_octa_quad.pde @@ -113,7 +113,7 @@ static void output_motors_armed() // this filter slows the acceleration of motors vs the deceleration // Idea by Denny Rowland to help with his Yaw issue - for(int8_t m = 0; m <= 8; m++){ + for(int8_t m = 1; m <= 8; m++){ int i = ch_of_mot(m); if(motor_filtered[i] < motor_out[i]){ motor_filtered[i] = (motor_out[i] + motor_filtered[i]) / 2; diff --git a/ArduCopter/motors_y6.pde b/ArduCopter/motors_y6.pde index 2824648bb6..a86d63ec6a 100644 --- a/ArduCopter/motors_y6.pde +++ b/ArduCopter/motors_y6.pde @@ -119,8 +119,8 @@ static void output_motors_armed() // this filter slows the acceleration of motors vs the deceleration // Idea by Denny Rowland to help with his Yaw issue - for(int8_t m = 0; m <= 6; m++){ - int i = ch_of_mot(m); + for(int8_t m = 1; m <= 6; m++){ + int i = ch_of_mot(m); if(motor_filtered[i] < motor_out[i]){ motor_filtered[i] = (motor_out[i] + motor_filtered[i]) / 2; }else{ From 8b256cf92452ab8e858b59d085040d13ad3b0785 Mon Sep 17 00:00:00 2001 From: rmackay9 Date: Tue, 6 Mar 2012 23:20:30 +0900 Subject: [PATCH 010/178] ArduCopter - fix for stability patch and motor filter meant to deal with engines tendency to speed up faster than they slow down --- ArduCopter/motors_hexa.pde | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ArduCopter/motors_hexa.pde b/ArduCopter/motors_hexa.pde index ad7435148c..10eae0b73b 100644 --- a/ArduCopter/motors_hexa.pde +++ b/ArduCopter/motors_hexa.pde @@ -77,9 +77,9 @@ static void output_motors_armed() // Tridge's stability patch - for (int m = 0; m <= 6; m++){ + for (int m = 1; m <= 6; m++){ int c = ch_of_mot(m); - int c_opp = ch_of_mot(m ^ 1); // m ^ 1 is the opposite motor. c_opp is channel of opposite motor. + int c_opp = ch_of_mot(((m-1)^1)+1); // ((m-1)^1)+1 is the opposite motor. c_opp is channel of opposite motor. if(motor_out[c] > out_max){ motor_out[c_opp] -= motor_out[c] - out_max; motor_out[c] = out_max; @@ -108,7 +108,7 @@ static void output_motors_armed() // this filter slows the acceleration of motors vs the deceleration // Idea by Denny Rowland to help with his Yaw issue - for(int8_t m = 0; m <= 6; m++){ + for(int8_t m = 1; m <= 6; m++){ int c = ch_of_mot(m); if(motor_filtered[c] < motor_out[c]){ motor_filtered[c] = (motor_out[c] + motor_filtered[c]) / 2; From f1d67c5638a7ea941427bfca8f8ceb1f3f8179f3 Mon Sep 17 00:00:00 2001 From: Michael Oborne Date: Wed, 7 Mar 2012 08:01:59 +0800 Subject: [PATCH 011/178] APM Planner Fix Updater --- .../Controls/MessageBox.cs | 1 - Tools/ArdupilotMegaPlanner/MainV2.cs | 14 +- .../Setup/Setup.Designer.cs | 183 +++++--- Tools/ArdupilotMegaPlanner/Setup/Setup.cs | 77 ++- Tools/ArdupilotMegaPlanner/Setup/Setup.resx | 441 +++++++++++------- .../bin/Release/ArdupilotMegaPlanner.pdb | Bin 1000960 -> 1000960 bytes 6 files changed, 434 insertions(+), 282 deletions(-) diff --git a/Tools/ArdupilotMegaPlanner/Controls/MessageBox.cs b/Tools/ArdupilotMegaPlanner/Controls/MessageBox.cs index 8d08925fe1..a399796751 100644 --- a/Tools/ArdupilotMegaPlanner/Controls/MessageBox.cs +++ b/Tools/ArdupilotMegaPlanner/Controls/MessageBox.cs @@ -7,7 +7,6 @@ using ArdupilotMega; namespace System.Windows.Forms { -#pragma warning disable 414, 3021 public static class MessageBox { const int FORM_Y_MARGIN = 10; diff --git a/Tools/ArdupilotMegaPlanner/MainV2.cs b/Tools/ArdupilotMegaPlanner/MainV2.cs index 63bf33780c..f7cb7c990e 100644 --- a/Tools/ArdupilotMegaPlanner/MainV2.cs +++ b/Tools/ArdupilotMegaPlanner/MainV2.cs @@ -1552,10 +1552,10 @@ namespace ArdupilotMega } } - if (fi.Length != response.ContentLength && response.Headers[HttpResponseHeader.ETag] != CurrentEtag) - { - log.Debug("New file Check: " + fi.Length + " vs " + response.ContentLength + " " + response.Headers[HttpResponseHeader.ETag] + " vs " + CurrentEtag); + log.Info("New file Check: " + fi.Length + " vs " + response.ContentLength + " " + response.Headers[HttpResponseHeader.ETag] + " vs " + CurrentEtag); + if (fi.Length != response.ContentLength || response.Headers[HttpResponseHeader.ETag] != CurrentEtag) + { using (var sw = new StreamWriter(path + ".etag")) { sw.WriteLine(response.Headers[HttpResponseHeader.ETag]); @@ -1683,7 +1683,7 @@ namespace ArdupilotMega // Create a request using a URL that can receive a post. request = WebRequest.Create(baseurl + file); - Console.Write(baseurl + file + " "); + log.Info(baseurl + file + " "); // Set the Method property of the request to POST. request.Method = "HEAD"; @@ -1719,10 +1719,10 @@ namespace ArdupilotMega } } - if (fi.Length != response.ContentLength && response.Headers[HttpResponseHeader.ETag] != CurrentEtag) - { - log.Debug("New file Check: " + fi.Length + " vs " + response.ContentLength + " " + response.Headers[HttpResponseHeader.ETag] + " vs " + CurrentEtag); + log.Debug("New file Check: " + fi.Length + " vs " + response.ContentLength + " " + response.Headers[HttpResponseHeader.ETag] + " vs " + CurrentEtag); + if (fi.Length != response.ContentLength || response.Headers[HttpResponseHeader.ETag] != CurrentEtag) + { using (StreamWriter sw = new StreamWriter(path + ".etag")) { sw.WriteLine(response.Headers[HttpResponseHeader.ETag]); diff --git a/Tools/ArdupilotMegaPlanner/Setup/Setup.Designer.cs b/Tools/ArdupilotMegaPlanner/Setup/Setup.Designer.cs index 968142c6c3..fef84a1f1b 100644 --- a/Tools/ArdupilotMegaPlanner/Setup/Setup.Designer.cs +++ b/Tools/ArdupilotMegaPlanner/Setup/Setup.Designer.cs @@ -128,8 +128,8 @@ this.groupBox3 = new System.Windows.Forms.GroupBox(); this.label46 = new System.Windows.Forms.Label(); this.label45 = new System.Windows.Forms.Label(); - this.GYR_ENABLE_ = new System.Windows.Forms.CheckBox(); - this.GYR_GAIN_ = new System.Windows.Forms.TextBox(); + this.GYR_ENABLE = new System.Windows.Forms.CheckBox(); + this.GYR_GAIN = new System.Windows.Forms.TextBox(); this.label44 = new System.Windows.Forms.Label(); this.label43 = new System.Windows.Forms.Label(); this.label42 = new System.Windows.Forms.Label(); @@ -141,9 +141,9 @@ this.groupBox1 = new System.Windows.Forms.GroupBox(); this.label41 = new System.Windows.Forms.Label(); this.label21 = new System.Windows.Forms.Label(); - this.COL_MIN_ = new System.Windows.Forms.TextBox(); - this.COL_MID_ = new System.Windows.Forms.TextBox(); - this.COL_MAX_ = new System.Windows.Forms.TextBox(); + this.COL_MIN = new System.Windows.Forms.TextBox(); + this.COL_MID = new System.Windows.Forms.TextBox(); + this.COL_MAX = new System.Windows.Forms.TextBox(); this.BUT_0collective = new ArdupilotMega.MyButton(); this.HS4_TRIM = new System.Windows.Forms.NumericUpDown(); this.HS3_TRIM = new System.Windows.Forms.NumericUpDown(); @@ -154,18 +154,18 @@ this.label37 = new System.Windows.Forms.Label(); this.label36 = new System.Windows.Forms.Label(); this.label26 = new System.Windows.Forms.Label(); - this.PIT_MAX_ = new System.Windows.Forms.TextBox(); + this.PIT_MAX = new System.Windows.Forms.TextBox(); this.label25 = new System.Windows.Forms.Label(); - this.ROL_MAX_ = new System.Windows.Forms.TextBox(); + this.ROL_MAX = new System.Windows.Forms.TextBox(); this.label23 = new System.Windows.Forms.Label(); this.label22 = new System.Windows.Forms.Label(); this.HS4_REV = new System.Windows.Forms.CheckBox(); this.label20 = new System.Windows.Forms.Label(); this.label19 = new System.Windows.Forms.Label(); this.label18 = new System.Windows.Forms.Label(); - this.SV3_POS_ = new System.Windows.Forms.TextBox(); - this.SV2_POS_ = new System.Windows.Forms.TextBox(); - this.SV1_POS_ = new System.Windows.Forms.TextBox(); + this.SV3_POS = new System.Windows.Forms.TextBox(); + this.SV2_POS = new System.Windows.Forms.TextBox(); + this.SV1_POS = new System.Windows.Forms.TextBox(); this.HS3_REV = new System.Windows.Forms.CheckBox(); this.HS2_REV = new System.Windows.Forms.CheckBox(); this.HS1_REV = new System.Windows.Forms.CheckBox(); @@ -176,6 +176,9 @@ this.tabReset = new System.Windows.Forms.TabPage(); this.BUT_reset = new ArdupilotMega.MyButton(); this.toolTip1 = new System.Windows.Forms.ToolTip(this.components); + this.CCPM = new System.Windows.Forms.RadioButton(); + this.groupBox5 = new System.Windows.Forms.GroupBox(); + this.H1_ENABLE = new System.Windows.Forms.RadioButton(); this.tabControl1.SuspendLayout(); this.tabRadioIn.SuspendLayout(); this.groupBoxElevons.SuspendLayout(); @@ -201,6 +204,7 @@ ((System.ComponentModel.ISupportInitialize)(this.HS2_TRIM)).BeginInit(); ((System.ComponentModel.ISupportInitialize)(this.HS1_TRIM)).BeginInit(); this.tabReset.SuspendLayout(); + this.groupBox5.SuspendLayout(); this.SuspendLayout(); // // tabControl1 @@ -972,6 +976,7 @@ // // tabHeli // + this.tabHeli.Controls.Add(this.groupBox5); this.tabHeli.Controls.Add(this.BUT_HS4save); this.tabHeli.Controls.Add(this.BUT_swash_manual); this.tabHeli.Controls.Add(this.groupBox3); @@ -989,18 +994,18 @@ this.tabHeli.Controls.Add(this.label37); this.tabHeli.Controls.Add(this.label36); this.tabHeli.Controls.Add(this.label26); - this.tabHeli.Controls.Add(this.PIT_MAX_); + this.tabHeli.Controls.Add(this.PIT_MAX); this.tabHeli.Controls.Add(this.label25); - this.tabHeli.Controls.Add(this.ROL_MAX_); + this.tabHeli.Controls.Add(this.ROL_MAX); this.tabHeli.Controls.Add(this.label23); this.tabHeli.Controls.Add(this.label22); this.tabHeli.Controls.Add(this.HS4_REV); this.tabHeli.Controls.Add(this.label20); this.tabHeli.Controls.Add(this.label19); this.tabHeli.Controls.Add(this.label18); - this.tabHeli.Controls.Add(this.SV3_POS_); - this.tabHeli.Controls.Add(this.SV2_POS_); - this.tabHeli.Controls.Add(this.SV1_POS_); + this.tabHeli.Controls.Add(this.SV3_POS); + this.tabHeli.Controls.Add(this.SV2_POS); + this.tabHeli.Controls.Add(this.SV1_POS); this.tabHeli.Controls.Add(this.HS3_REV); this.tabHeli.Controls.Add(this.HS2_REV); this.tabHeli.Controls.Add(this.HS1_REV); @@ -1031,8 +1036,8 @@ // this.groupBox3.Controls.Add(this.label46); this.groupBox3.Controls.Add(this.label45); - this.groupBox3.Controls.Add(this.GYR_ENABLE_); - this.groupBox3.Controls.Add(this.GYR_GAIN_); + this.groupBox3.Controls.Add(this.GYR_ENABLE); + this.groupBox3.Controls.Add(this.GYR_GAIN); resources.ApplyResources(this.groupBox3, "groupBox3"); this.groupBox3.Name = "groupBox3"; this.groupBox3.TabStop = false; @@ -1047,18 +1052,18 @@ resources.ApplyResources(this.label45, "label45"); this.label45.Name = "label45"; // - // GYR_ENABLE_ + // GYR_ENABLE // - resources.ApplyResources(this.GYR_ENABLE_, "GYR_ENABLE_"); - this.GYR_ENABLE_.Name = "GYR_ENABLE_"; - this.GYR_ENABLE_.UseVisualStyleBackColor = true; - this.GYR_ENABLE_.CheckedChanged += new System.EventHandler(this.GYR_ENABLE__CheckedChanged); + resources.ApplyResources(this.GYR_ENABLE, "GYR_ENABLE"); + this.GYR_ENABLE.Name = "GYR_ENABLE"; + this.GYR_ENABLE.UseVisualStyleBackColor = true; + this.GYR_ENABLE.CheckedChanged += new System.EventHandler(this.GYR_ENABLE__CheckedChanged); // - // GYR_GAIN_ + // GYR_GAIN // - resources.ApplyResources(this.GYR_GAIN_, "GYR_GAIN_"); - this.GYR_GAIN_.Name = "GYR_GAIN_"; - this.GYR_GAIN_.Validating += new System.ComponentModel.CancelEventHandler(this.GYR_GAIN__Validating); + resources.ApplyResources(this.GYR_GAIN, "GYR_GAIN"); + this.GYR_GAIN.Name = "GYR_GAIN"; + this.GYR_GAIN.Validating += new System.ComponentModel.CancelEventHandler(this.GYR_GAIN__Validating); // // label44 // @@ -1115,9 +1120,9 @@ // this.groupBox1.Controls.Add(this.label41); this.groupBox1.Controls.Add(this.label21); - this.groupBox1.Controls.Add(this.COL_MIN_); - this.groupBox1.Controls.Add(this.COL_MID_); - this.groupBox1.Controls.Add(this.COL_MAX_); + this.groupBox1.Controls.Add(this.COL_MIN); + this.groupBox1.Controls.Add(this.COL_MID); + this.groupBox1.Controls.Add(this.COL_MAX); this.groupBox1.Controls.Add(this.BUT_0collective); resources.ApplyResources(this.groupBox1, "groupBox1"); this.groupBox1.Name = "groupBox1"; @@ -1133,27 +1138,27 @@ resources.ApplyResources(this.label21, "label21"); this.label21.Name = "label21"; // - // COL_MIN_ + // COL_MIN // - resources.ApplyResources(this.COL_MIN_, "COL_MIN_"); - this.COL_MIN_.Name = "COL_MIN_"; - this.COL_MIN_.Enter += new System.EventHandler(this.COL_MIN__Enter); - this.COL_MIN_.Leave += new System.EventHandler(this.COL_MIN__Leave); - this.COL_MIN_.Validating += new System.ComponentModel.CancelEventHandler(this.PWM_Validating); + resources.ApplyResources(this.COL_MIN, "COL_MIN"); + this.COL_MIN.Name = "COL_MIN"; + this.COL_MIN.Enter += new System.EventHandler(this.COL_MIN__Enter); + this.COL_MIN.Leave += new System.EventHandler(this.COL_MIN__Leave); + this.COL_MIN.Validating += new System.ComponentModel.CancelEventHandler(this.PWM_Validating); // - // COL_MID_ + // COL_MID // - resources.ApplyResources(this.COL_MID_, "COL_MID_"); - this.COL_MID_.Name = "COL_MID_"; - this.COL_MID_.Validating += new System.ComponentModel.CancelEventHandler(this.PWM_Validating); + resources.ApplyResources(this.COL_MID, "COL_MID"); + this.COL_MID.Name = "COL_MID"; + this.COL_MID.Validating += new System.ComponentModel.CancelEventHandler(this.PWM_Validating); // - // COL_MAX_ + // COL_MAX // - resources.ApplyResources(this.COL_MAX_, "COL_MAX_"); - this.COL_MAX_.Name = "COL_MAX_"; - this.COL_MAX_.Enter += new System.EventHandler(this.COL_MAX__Enter); - this.COL_MAX_.Leave += new System.EventHandler(this.COL_MAX__Leave); - this.COL_MAX_.Validating += new System.ComponentModel.CancelEventHandler(this.PWM_Validating); + resources.ApplyResources(this.COL_MAX, "COL_MAX"); + this.COL_MAX.Name = "COL_MAX"; + this.COL_MAX.Enter += new System.EventHandler(this.COL_MAX__Enter); + this.COL_MAX.Leave += new System.EventHandler(this.COL_MAX__Leave); + this.COL_MAX.Validating += new System.ComponentModel.CancelEventHandler(this.PWM_Validating); // // BUT_0collective // @@ -1271,22 +1276,22 @@ resources.ApplyResources(this.label26, "label26"); this.label26.Name = "label26"; // - // PIT_MAX_ + // PIT_MAX // - resources.ApplyResources(this.PIT_MAX_, "PIT_MAX_"); - this.PIT_MAX_.Name = "PIT_MAX_"; - this.PIT_MAX_.Validating += new System.ComponentModel.CancelEventHandler(this.PIT_MAX__Validating); + resources.ApplyResources(this.PIT_MAX, "PIT_MAX"); + this.PIT_MAX.Name = "PIT_MAX"; + this.PIT_MAX.Validating += new System.ComponentModel.CancelEventHandler(this.PIT_MAX__Validating); // // label25 // resources.ApplyResources(this.label25, "label25"); this.label25.Name = "label25"; // - // ROL_MAX_ + // ROL_MAX // - resources.ApplyResources(this.ROL_MAX_, "ROL_MAX_"); - this.ROL_MAX_.Name = "ROL_MAX_"; - this.ROL_MAX_.Validating += new System.ComponentModel.CancelEventHandler(this.ROL_MAX__Validating); + resources.ApplyResources(this.ROL_MAX, "ROL_MAX"); + this.ROL_MAX.Name = "ROL_MAX"; + this.ROL_MAX.Validating += new System.ComponentModel.CancelEventHandler(this.ROL_MAX__Validating); // // label23 // @@ -1320,23 +1325,23 @@ resources.ApplyResources(this.label18, "label18"); this.label18.Name = "label18"; // - // SV3_POS_ + // SV3_POS // - resources.ApplyResources(this.SV3_POS_, "SV3_POS_"); - this.SV3_POS_.Name = "SV3_POS_"; - this.SV3_POS_.Validating += new System.ComponentModel.CancelEventHandler(this.TXT_srvpos3_Validating); + resources.ApplyResources(this.SV3_POS, "SV3_POS"); + this.SV3_POS.Name = "SV3_POS"; + this.SV3_POS.Validating += new System.ComponentModel.CancelEventHandler(this.TXT_srvpos3_Validating); // - // SV2_POS_ + // SV2_POS // - resources.ApplyResources(this.SV2_POS_, "SV2_POS_"); - this.SV2_POS_.Name = "SV2_POS_"; - this.SV2_POS_.Validating += new System.ComponentModel.CancelEventHandler(this.TXT_srvpos2_Validating); + resources.ApplyResources(this.SV2_POS, "SV2_POS"); + this.SV2_POS.Name = "SV2_POS"; + this.SV2_POS.Validating += new System.ComponentModel.CancelEventHandler(this.TXT_srvpos2_Validating); // - // SV1_POS_ + // SV1_POS // - resources.ApplyResources(this.SV1_POS_, "SV1_POS_"); - this.SV1_POS_.Name = "SV1_POS_"; - this.SV1_POS_.Validating += new System.ComponentModel.CancelEventHandler(this.TXT_srvpos1_Validating); + resources.ApplyResources(this.SV1_POS, "SV1_POS"); + this.SV1_POS.Name = "SV1_POS"; + this.SV1_POS.Validating += new System.ComponentModel.CancelEventHandler(this.TXT_srvpos1_Validating); // // HS3_REV // @@ -1554,6 +1559,29 @@ this.BUT_reset.UseVisualStyleBackColor = true; this.BUT_reset.Click += new System.EventHandler(this.BUT_reset_Click); // + // CCPM + // + resources.ApplyResources(this.CCPM, "CCPM"); + this.CCPM.Name = "CCPM"; + this.CCPM.TabStop = true; + this.CCPM.UseVisualStyleBackColor = true; + // + // groupBox5 + // + this.groupBox5.Controls.Add(this.H1_ENABLE); + this.groupBox5.Controls.Add(this.CCPM); + resources.ApplyResources(this.groupBox5, "groupBox5"); + this.groupBox5.Name = "groupBox5"; + this.groupBox5.TabStop = false; + // + // H1_ENABLE + // + resources.ApplyResources(this.H1_ENABLE, "H1_ENABLE"); + this.H1_ENABLE.Name = "H1_ENABLE"; + this.H1_ENABLE.TabStop = true; + this.H1_ENABLE.UseVisualStyleBackColor = true; + this.H1_ENABLE.CheckedChanged += new System.EventHandler(this.H1_ENABLE_CheckedChanged); + // // Setup // resources.ApplyResources(this, "$this"); @@ -1599,6 +1627,8 @@ ((System.ComponentModel.ISupportInitialize)(this.HS2_TRIM)).EndInit(); ((System.ComponentModel.ISupportInitialize)(this.HS1_TRIM)).EndInit(); this.tabReset.ResumeLayout(false); + this.groupBox5.ResumeLayout(false); + this.groupBox5.PerformLayout(); this.ResumeLayout(false); } @@ -1666,9 +1696,9 @@ private System.Windows.Forms.Label label20; private System.Windows.Forms.Label label19; private System.Windows.Forms.Label label18; - private System.Windows.Forms.TextBox SV3_POS_; - private System.Windows.Forms.TextBox SV2_POS_; - private System.Windows.Forms.TextBox SV1_POS_; + private System.Windows.Forms.TextBox SV3_POS; + private System.Windows.Forms.TextBox SV2_POS; + private System.Windows.Forms.TextBox SV1_POS; private System.Windows.Forms.CheckBox HS4_REV; private System.Windows.Forms.Label label22; private System.Windows.Forms.Label label23; @@ -1676,11 +1706,11 @@ private VerticalProgressBar2 HS3; private MyButton BUT_0collective; private System.Windows.Forms.Label label25; - private System.Windows.Forms.TextBox ROL_MAX_; + private System.Windows.Forms.TextBox ROL_MAX; private System.Windows.Forms.Label label26; - private System.Windows.Forms.TextBox PIT_MAX_; - private System.Windows.Forms.TextBox GYR_GAIN_; - private System.Windows.Forms.CheckBox GYR_ENABLE_; + private System.Windows.Forms.TextBox PIT_MAX; + private System.Windows.Forms.TextBox GYR_GAIN; + private System.Windows.Forms.CheckBox GYR_ENABLE; private System.Windows.Forms.Label label28; private MyButton BUT_levelac2; private System.Windows.Forms.ToolTip toolTip1; @@ -1722,9 +1752,9 @@ private System.Windows.Forms.NumericUpDown HS4_TRIM; private System.Windows.Forms.GroupBox groupBox1; private MyButton BUT_swash_manual; - private System.Windows.Forms.TextBox COL_MIN_; - private System.Windows.Forms.TextBox COL_MID_; - private System.Windows.Forms.TextBox COL_MAX_; + private System.Windows.Forms.TextBox COL_MIN; + private System.Windows.Forms.TextBox COL_MID; + private System.Windows.Forms.TextBox COL_MAX; private System.Windows.Forms.Label label41; private System.Windows.Forms.Label label21; private MyButton BUT_HS4save; @@ -1751,6 +1781,9 @@ private System.Windows.Forms.ComboBox CMB_batmonsensortype; private System.Windows.Forms.Label label47; private System.Windows.Forms.GroupBox groupBox4; + private System.Windows.Forms.GroupBox groupBox5; + private System.Windows.Forms.RadioButton H1_ENABLE; + private System.Windows.Forms.RadioButton CCPM; } } \ No newline at end of file diff --git a/Tools/ArdupilotMegaPlanner/Setup/Setup.cs b/Tools/ArdupilotMegaPlanner/Setup/Setup.cs index 57a374d2c2..fa9c3992eb 100644 --- a/Tools/ArdupilotMegaPlanner/Setup/Setup.cs +++ b/Tools/ArdupilotMegaPlanner/Setup/Setup.cs @@ -58,8 +58,29 @@ namespace ArdupilotMega.Setup if (MainV2.cs.firmware == MainV2.Firmwares.ArduPlane) // APM { - pwm = MainV2.cs.ch8in; - LBL_flightmodepwm.Text = "8: " + MainV2.cs.ch8in.ToString(); + if (MainV2.comPort.param.ContainsKey("FLTMODE_CH")) + { + switch ((int)(float)MainV2.comPort.param["FLTMODE_CH"]) + { + case 5: + pwm = MainV2.cs.ch5in; + break; + case 6: + pwm = MainV2.cs.ch6in; + break; + case 7: + pwm = MainV2.cs.ch7in; + break; + case 8: + pwm = MainV2.cs.ch8in; + break; + default: + + break; + } + + LBL_flightmodepwm.Text = MainV2.comPort.param["FLTMODE_CH"].ToString() + ": " + pwm.ToString(); + } } if (MainV2.cs.firmware == MainV2.Firmwares.ArduCopter2) // ac2 @@ -105,8 +126,8 @@ namespace ArdupilotMega.Setup { try { - HS3.minline = int.Parse(COL_MIN_.Text); - HS3.maxline = int.Parse(COL_MAX_.Text); + HS3.minline = int.Parse(COL_MIN.Text); + HS3.maxline = int.Parse(COL_MAX.Text); HS4.maxline = int.Parse(HS4_MIN.Text); HS4.minline = int.Parse(HS4_MAX.Text); } @@ -1068,7 +1089,7 @@ namespace ArdupilotMega.Setup MainV2.comPort.setParam("COL_MID_", MainV2.cs.ch3in); - COL_MID_.Text = MainV2.comPort.param["COL_MID_"].ToString(); + COL_MID.Text = MainV2.comPort.param["COL_MID_"].ToString(); } catch { MessageBox.Show("Set COL_MID_ failed"); } } @@ -1269,26 +1290,26 @@ namespace ArdupilotMega.Setup { if (MainV2.comPort.param["HSV_MAN"].ToString() == "1") { - MainV2.comPort.setParam("COL_MIN_", int.Parse(COL_MIN_.Text)); - MainV2.comPort.setParam("COL_MAX_", int.Parse(COL_MAX_.Text)); + MainV2.comPort.setParam("COL_MIN_", int.Parse(COL_MIN.Text)); + MainV2.comPort.setParam("COL_MAX_", int.Parse(COL_MAX.Text)); MainV2.comPort.setParam("HSV_MAN", 0); // randy request - last BUT_swash_manual.Text = "Manual"; - COL_MAX_.Enabled = false; - COL_MID_.Enabled = false; - COL_MIN_.Enabled = false; + COL_MAX.Enabled = false; + COL_MID.Enabled = false; + COL_MIN.Enabled = false; BUT_0collective.Enabled = false; } else { - COL_MAX_.Text = "1500"; - COL_MIN_.Text = "1500"; + COL_MAX.Text = "1500"; + COL_MIN.Text = "1500"; MainV2.comPort.setParam("HSV_MAN", 1); // randy request BUT_swash_manual.Text = "Save"; - COL_MAX_.Enabled = true; - COL_MID_.Enabled = true; - COL_MIN_.Enabled = true; + COL_MAX.Enabled = true; + COL_MID.Enabled = true; + COL_MIN.Enabled = true; BUT_0collective.Enabled = true; } } @@ -1345,10 +1366,10 @@ namespace ArdupilotMega.Setup { try { - if (int.Parse(COL_MIN_.Text) > HS3.minline) - COL_MIN_.Text = HS3.minline.ToString(); - if (int.Parse(COL_MAX_.Text) < HS3.maxline) - COL_MAX_.Text = HS3.maxline.ToString(); + if (int.Parse(COL_MIN.Text) > HS3.minline) + COL_MIN.Text = HS3.minline.ToString(); + if (int.Parse(COL_MAX.Text) < HS3.maxline) + COL_MAX.Text = HS3.maxline.ToString(); } catch { } } @@ -1595,5 +1616,23 @@ namespace ArdupilotMega.Setup TXT_inputvoltage.Enabled = true; } } + + private void H1_ENABLE_CheckedChanged(object sender, EventArgs e) + { + if (startup) + return; + try + { + if (MainV2.comPort.param["H1_ENABLE"] == null) + { + MessageBox.Show("Not Available on " + MainV2.cs.firmware.ToString()); + } + else + { + MainV2.comPort.setParam("H1_ENABLE", ((RadioButton)sender).Checked == true ? 1 : 0); + } + } + catch { MessageBox.Show("Set H1_ENABLE Failed"); } + } } } \ No newline at end of file diff --git a/Tools/ArdupilotMegaPlanner/Setup/Setup.resx b/Tools/ArdupilotMegaPlanner/Setup/Setup.resx index 63fda6166a..6bda482d71 100644 --- a/Tools/ArdupilotMegaPlanner/Setup/Setup.resx +++ b/Tools/ArdupilotMegaPlanner/Setup/Setup.resx @@ -2629,11 +2629,92 @@ will work with hexa's etc 4 + + True + + + NoControl + + + 67, 19 + + + 39, 17 + + + 137 + + + H1 + + + H1_ENABLE + + + System.Windows.Forms.RadioButton, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + groupBox5 + + + 0 + + + True + + + 6, 19 + + + 55, 17 + + + 136 + + + CCPM + + + CCPM + + + System.Windows.Forms.RadioButton, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + groupBox5 + + + 1 + + + 253, 6 + + + 120, 43 + + + 137 + + + Swash Type + + + groupBox5 + + + System.Windows.Forms.GroupBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tabHeli + + + 0 + NoControl - 479, 131 + 479, 169 69, 23 @@ -2654,13 +2735,13 @@ will work with hexa's etc tabHeli - 0 + 1 NoControl - 298, 40 + 298, 78 69, 23 @@ -2681,7 +2762,7 @@ will work with hexa's etc tabHeli - 1 + 2 True @@ -2743,59 +2824,59 @@ will work with hexa's etc 1 - + True - + NoControl - + 57, 19 - + 15, 14 - + 118 - - GYR_ENABLE_ + + GYR_ENABLE - + System.Windows.Forms.CheckBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + groupBox3 - + 2 - + 41, 35 - + 47, 20 - + 119 - + 1000 - - GYR_GAIN_ + + GYR_GAIN - + System.Windows.Forms.TextBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + groupBox3 - + 3 - 433, 271 + 433, 309 101, 63 @@ -2816,7 +2897,7 @@ will work with hexa's etc tabHeli - 2 + 3 True @@ -2825,7 +2906,7 @@ will work with hexa's etc NoControl - 532, 225 + 532, 263 27, 13 @@ -2846,7 +2927,7 @@ will work with hexa's etc tabHeli - 3 + 4 True @@ -2855,7 +2936,7 @@ will work with hexa's etc NoControl - 499, 225 + 499, 263 27, 13 @@ -2876,7 +2957,7 @@ will work with hexa's etc tabHeli - 4 + 5 True @@ -2885,7 +2966,7 @@ will work with hexa's etc NoControl - 451, 245 + 451, 283 42, 13 @@ -2906,7 +2987,7 @@ will work with hexa's etc tabHeli - 5 + 6 True @@ -3023,7 +3104,7 @@ will work with hexa's etc 3 - 433, 143 + 433, 181 169, 78 @@ -3041,7 +3122,7 @@ will work with hexa's etc tabHeli - 6 + 7 True @@ -3103,85 +3184,85 @@ will work with hexa's etc 1 - + False - + 18, 173 - + 43, 20 - + 119 - + 1500 - - COL_MIN_ + + COL_MIN - + System.Windows.Forms.TextBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + groupBox1 - + 2 - + False - + 17, 117 - + 44, 20 - + 117 - + 1500 - - COL_MID_ + + COL_MID - + System.Windows.Forms.TextBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + groupBox1 - + 3 - + False - + 18, 45 - + 43, 20 - + 115 - + 1500 - - COL_MAX_ + + COL_MAX - + System.Windows.Forms.TextBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + groupBox1 - + 4 @@ -3215,7 +3296,7 @@ will work with hexa's etc 5 - 293, 52 + 293, 90 80, 209 @@ -3233,10 +3314,10 @@ will work with hexa's etc tabHeli - 7 + 8 - 535, 241 + 535, 279 44, 20 @@ -3254,10 +3335,10 @@ will work with hexa's etc tabHeli - 8 + 9 - 122, 271 + 122, 309 44, 20 @@ -3275,10 +3356,10 @@ will work with hexa's etc tabHeli - 9 + 10 - 122, 245 + 122, 283 44, 20 @@ -3296,10 +3377,10 @@ will work with hexa's etc tabHeli - 10 + 11 - 122, 219 + 122, 257 44, 20 @@ -3317,7 +3398,7 @@ will work with hexa's etc tabHeli - 11 + 12 True @@ -3326,7 +3407,7 @@ will work with hexa's etc NoControl - 127, 206 + 127, 244 27, 13 @@ -3347,7 +3428,7 @@ will work with hexa's etc tabHeli - 12 + 13 True @@ -3356,7 +3437,7 @@ will work with hexa's etc NoControl - 98, 206 + 98, 244 27, 13 @@ -3377,7 +3458,7 @@ will work with hexa's etc tabHeli - 13 + 14 True @@ -3386,7 +3467,7 @@ will work with hexa's etc NoControl - 50, 206 + 50, 244 44, 13 @@ -3407,7 +3488,7 @@ will work with hexa's etc tabHeli - 14 + 15 True @@ -3416,7 +3497,7 @@ will work with hexa's etc NoControl - 13, 206 + 13, 244 35, 13 @@ -3437,7 +3518,7 @@ will work with hexa's etc tabHeli - 15 + 16 True @@ -3446,7 +3527,7 @@ will work with hexa's etc NoControl - 256, 345 + 256, 360 54, 13 @@ -3467,31 +3548,31 @@ will work with hexa's etc tabHeli - 16 + 17 - - 310, 342 + + 310, 357 - + 47, 20 - + 116 - + 4500 - - PIT_MAX_ + + PIT_MAX - + System.Windows.Forms.TextBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + tabHeli - - 17 + + 18 True @@ -3500,7 +3581,7 @@ will work with hexa's etc NoControl - 256, 321 + 256, 336 48, 13 @@ -3521,31 +3602,31 @@ will work with hexa's etc tabHeli - 18 + 19 - - 310, 316 + + 310, 331 - + 47, 20 - + 114 - + 4500 - - ROL_MAX_ + + ROL_MAX - + System.Windows.Forms.TextBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + tabHeli - - 19 + + 20 True @@ -3554,7 +3635,7 @@ will work with hexa's etc NoControl - 476, 23 + 476, 61 75, 13 @@ -3575,7 +3656,7 @@ will work with hexa's etc tabHeli - 20 + 21 True @@ -3584,7 +3665,7 @@ will work with hexa's etc NoControl - 232, 23 + 232, 61 72, 13 @@ -3605,7 +3686,7 @@ will work with hexa's etc tabHeli - 21 + 22 True @@ -3614,7 +3695,7 @@ will work with hexa's etc NoControl - 502, 244 + 502, 282 15, 14 @@ -3632,7 +3713,7 @@ will work with hexa's etc tabHeli - 22 + 23 True @@ -3641,7 +3722,7 @@ will work with hexa's etc NoControl - 23, 274 + 23, 312 13, 13 @@ -3662,7 +3743,7 @@ will work with hexa's etc tabHeli - 23 + 24 True @@ -3671,7 +3752,7 @@ will work with hexa's etc NoControl - 23, 248 + 23, 286 13, 13 @@ -3692,7 +3773,7 @@ will work with hexa's etc tabHeli - 24 + 25 True @@ -3701,7 +3782,7 @@ will work with hexa's etc NoControl - 23, 222 + 23, 260 13, 13 @@ -3722,80 +3803,80 @@ will work with hexa's etc tabHeli - 25 - - - 53, 271 - - - 39, 20 - - - 94 - - - 180 - - - SV3_POS_ - - - System.Windows.Forms.TextBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - tabHeli - - 26 - - 53, 245 + + 53, 309 - + 39, 20 - - 93 + + 94 - - 60 + + 180 - - SV2_POS_ + + SV3_POS - + System.Windows.Forms.TextBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + tabHeli - + 27 - - 53, 219 + + 53, 283 - + 39, 20 - - 92 + + 93 - - -60 + + 60 - - SV1_POS_ + + SV2_POS - + System.Windows.Forms.TextBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + tabHeli - + 28 + + 53, 257 + + + 39, 20 + + + 92 + + + -60 + + + SV1_POS + + + System.Windows.Forms.TextBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tabHeli + + + 29 + True @@ -3803,7 +3884,7 @@ will work with hexa's etc NoControl - 101, 274 + 101, 312 15, 14 @@ -3821,7 +3902,7 @@ will work with hexa's etc tabHeli - 29 + 30 True @@ -3830,7 +3911,7 @@ will work with hexa's etc NoControl - 101, 248 + 101, 286 15, 14 @@ -3848,7 +3929,7 @@ will work with hexa's etc tabHeli - 30 + 31 True @@ -3857,7 +3938,7 @@ will work with hexa's etc NoControl - 101, 225 + 101, 263 15, 14 @@ -3875,7 +3956,7 @@ will work with hexa's etc tabHeli - 31 + 32 True @@ -3884,7 +3965,7 @@ will work with hexa's etc NoControl - 38, 23 + 38, 61 109, 13 @@ -3905,10 +3986,10 @@ will work with hexa's etc tabHeli - 32 + 33 - 392, 50 + 392, 88 242, 42 @@ -3926,10 +4007,10 @@ will work with hexa's etc tabHeli - 33 + 34 - 235, 52 + 235, 90 42, 213 @@ -3947,7 +4028,7 @@ will work with hexa's etc tabHeli - 34 + 35 Zoom @@ -3956,7 +4037,7 @@ will work with hexa's etc Microsoft Sans Serif, 9pt - 16, 50 + 16, 88 0, 0, 0, 0 @@ -3977,7 +4058,7 @@ will work with hexa's etc tabHeli - 35 + 36 4, 22 diff --git a/Tools/ArdupilotMegaPlanner/bin/Release/ArdupilotMegaPlanner.pdb b/Tools/ArdupilotMegaPlanner/bin/Release/ArdupilotMegaPlanner.pdb index 2f372e4f1d72a1432f363f72a37cd83be899bb1b..83ab9bf5e9c3808c65f565d94b26d28beb7dc9f5 100644 GIT binary patch delta 90710 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