commit 23b8abf455ac040615597e9fb96294011cdbe5a0 Author: fly Date: Sun Jun 25 17:49:06 2023 +0200 Initial Commit Signed-off-by: fly diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c010749 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +# vim swap files +*.swp +*.swo diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..2d1a019 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,52 @@ +# Change Log + +All notable changes to this project will be documented in this file. +This project adheres to [Semantic Versioning](http://semver.org/). Release +canidates are not covered by this file. + + + +## v2.0.2 +### Changed +* File structure: Nasal files now under "Nasal/Autopush" directory. + +## v2.0.1 +### Changed +* Satellite view: accessible from dialog; always switch to when entering route +* Settings of the view used for satellite view are now restored after use +### Fixed +* Satelite view due to upcoming removal of `Model View` + +## v2.0 +### Major Changes +* Moved the autopush property sub tree from `/sim/model/pushback/` to `/sim/model/autopush`. See issue #19 +Make sure you update all references to the properties. +* Moved the configuration out of the -set.xml. See issue #18 +### Added +* Top down view for entering the route +* Option to display wing tip path. +* Check for too tight turns +* Auto push resuming +* Pitch offset to properly calculate the force for aircraft with high parking pitch +* Added documentation on how to implement steering, chocks control and availability. See the last step of installation instruction. +* Push and Pull support +### Changed +* Coefficients adjusted for smoother performance +* Dialog sliders improved for better control +### Fixed +* Missed points make the driver turn around and try to catch it again. +* The integration was taking input change instead of the input, which resulted in strange behaviour. +* Fixed derivative part of PID not working +* Stopping too early at last point + +## v1.0 +Initial release. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..8822ea7 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,45 @@ +# CONTRIBUTING +Contribution rules for the autopush project. +## General +By contributing you agree that your work will be published under the GPL2. + +Where possible, text width should not exceed 70 characters. + +## Code style +### XML +For `.xml` files the following rules apply. +* While there is no preference for indent style or code formatting, it must be consistent within each file. +* No whitespace-only lines and trailing whitespace allowed. +* Whitespace between tags and their data is forbidden, for example `` 10.0 `` is not acceptable. +* If a tag has children, it has to be on it's own line. + +Example: +```xml + + 3 + 100 + + +``` + +### Nasal +For `.nas` files the following rules apply. +* While there is no preference for indent style or code formatting, it must be consistent within each file. +* No whitespace-only lines and trailing whitespace allowed. +* For names use camelCase or snake_case. +* Prefix "private" vars and functions with a `_`. +* Use coments for blocks of codes and only when something is not clear (eg. starting iterating from 3). + +Example: +```js +# This function does something non obvious. +var function = func() { + if (a == b) { + var a = geo.Coord.new(); + } else { + var b = 0; + } +} +``` +## Git +Please add a descriptive commit message to **every** commit. diff --git a/LICENSE.TXT b/LICENSE.TXT new file mode 100644 index 0000000..d159169 --- /dev/null +++ b/LICENSE.TXT @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program 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 2 of the License, or + (at your option) any later version. + + This program 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, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. diff --git a/README.TXT b/README.TXT new file mode 100644 index 0000000..45ed159 --- /dev/null +++ b/README.TXT @@ -0,0 +1,260 @@ +AUTOMATIC PUSHBACK FOR FLIGHTGEAR +https://gitea.merspieler.tk/fly/autopush + +Version 2.0.1 + +Copyright (c) 2018 Autopush authors: + Joshua Davidson http://github.com/Octal450 + Merspieler http://gitlab.com/merspieler +Some of the code (c) FlightGear +Distribute under the terms of GPLv2. + + +This project aims to develop a generic pushback for JSBSim and YASim +aircraft, with the following characteristics. + +1. Do the pushback procedure automatically. +2. Scale to different aircraft with minimum changes to their logic. +3. Use no computer resources in flight. + + +INSTALLATION + +Minimum FlightGear version: 2018.0 + +NOTE: these steps cover the minimal testing setup. To get the most +realism out of Autopush, you will have to add logic aircraft-side as +described in the last step. + +1. Copy everything from from "YourAircraftDir" into your aircraft, + while keeping the directory structure: + +Models/Autopush cursor models and the animation for + FGDATA pushbacks. +Nasal/Autopush Autopush logic +gui/dialogs/autopush.xml GUI dialog +autopush-config.xml.template Configuration of autopush + +2. Set up the pushback logic. + +Add the following line under of your set.xml + + + +Rename autopush-config.xml.template to autopush-config.xml and edit +the file as described below. + +Alternatively, you can copy the contents of +autopush-config.xml.template to under of your +set.xml and make these modifications there. + +Change the aliases to point to the following data: + +steer-cmd-norm nose wheel steering command norm +yaw nose wheel steering output norm or angle (see below) +chocks chocks command bool (or leave it until step 7) +available pushback availability bool (or leave it until step 7) + +Replace the MULTIPLIER in yaw-mult with: + +max steering angle if yaw is norm +1.0 if yaw is degrees +57.3 if yaw is radians + +Replace PITCH with the pushback's pitch relative to aircraft. If your +aircraft's ground pitch varies greatly, you can make an alias to +property with calculated relative pitch. + +Replace MIN_RADIUS with the minimum allowed turning radius in m of the +center of the aircraft during pushback procedure. + +NOTE: on some aircraft the turning radius is different for taxi and +pushback. Please check the aircraft's literature. + +Replace STOP_DIST with the stopping distance in m from pushback speed. + +Add under of your set.xml: + + + Nasal/Autopush/autopush.nas + + + Nasal/Autopush/driver.nas + + + Nasal/Autopush/dynarr.nas + + + Nasal/Autopush/route.nas + + +Add under of your set.xml: + + /sim/model/autopush/route/show + /sim/model/autopush/route/show-wingtip + +3. Connect the force to FDM. + + 3.a. JSBSim: + + 3.a.1. Add the following under of your JSBSim + XML. + + + + FRONT-X + FRONT-Y + FRONT-Z + + + 1.0 + 0.0 + 0.0 + + + +Replace FRONT-X, FRONT-Y, FRONT-Z with coordinates of your front +bogey. + + 3.a.2. Add the following under of + your set.xml. + + + + + + + + + 3.b. YASim. Add the following under of your YASim xml. + + + + + + + + + + + +Replace FRONT-X, FRONT-Y, FRONT-Z with coordinates of your front +bogey. + +4. Add the pushback model to your Model XML: + + + Pushback + MODEL + + FRONT-X + FRONT-Y + FRONT-Z + + + +Replace FRONT-X, FRONT-Y, FRONT-Z with coordinates of your front +bogey. Replace MODEL with one of the following file names: + +Autopush/Goldhofert.xml for Goldhofer towbarless pushback + +Edit the "SETTINGS" part in the beginning of respective file to match +your setup. + +5. Add gui/dialogs/autopush.xml to your aircraft's menu (see + FlightGear documentation for editing the menu). + +6. If you have a bug tracker, please add a note, that autopush related + bugs should be reported here: + +To merspieler on the forum + +7. Launch the simulator and try Autopush. After making sure it works, + complete the support by implementing some logic in your aircraft + and connecting the rest of the interface. + +CAUTION. +1. Make sure to HAVE A BACK-UP COPY of your work. +2. If anything is not clear in the instruction below, do not guess -- + contact the authors. + + 7.1. When pushback is connected ("/sim/model/autopush/connected"), + nose wheel steering must actuate at different speed, depending + on its rollspeed. The exact dependency is different per aircraft + and used pushback visual, and for most aircraft the only way to + find it is trial and error until it "looks right": + - the input must be taken from pushback steering command norm + (set by autopush-config.xml, default: + "/controls/flight/rudder"); + - the output must be written to pushback orientation in degrees, + radians or norm (set by autopush-config.xml, default: + "/gear/gear[0]/steering-norm"). + + 7.2. Set or alias (in autopush-config.xml) the availability property + "/sim/model/autopush/available". It must be false if e.g. the + aircraft is moving too fast, the front wheel is not touching + the ground, the aircraft is damaged or is outside of an airport + etc. + + 7.3. Make Autopush remove wheel chocks by setting the alias in + autopush-config.xml to the chocks property. (default: + "/controls/gear/wheel-chocks"). + + 7.4. Optionally, Autopush may be made visible in multiplayer by + duplicating the properties used in its model.xml into some + unused MP properties. See the list in + +https://sourceforge.net/p/flightgear/flightgear/ci/next/tree/src/MultiPlayer/multiplaymgr.cxx + + around line 215, and then using those properties in the + "SETTINGS" part of Autopush model.xml. + + After making these changes check the Autopush model.xml's settings + and make sure they match the setup. Launch the simulator and try + Autopush. + + +TUNING + +There should normally be no need to change the coefficients, because +the inertia of different aircraft is already taken into account. But +the gear setup may differ enough to require some tuning. + +If these settings are changed during simulation, they take effect +after disconnecting and reconnecting the pushback. + +Pushback (/sim/model/autopush): + +Coefficient Unit Description + +K_p ((km/h)/s)/(km/h) Proportional coefficient of PID. + Defines the start/stop throttle + and immediate response to speed + difference deltaV = V_set - V. + +F_p (km/h)/s Proportional clipping. + +K_i ((km/h)/s)/((km/h)*s) Integral coefficient of PID. + Defines how fast the steady + throttle is ramped during the + push. + +F_i (km/h)/s Integral clipping. + +K_d -((km/h)/s)/((km/h)/s) Differential coefficient of PID. + Stabilizes the approaching of + steady throttle. + +F_d (km/h)/s Differential clipping. + +Pushback driver (/sim/model/autopush/driver): + +Coefficient Unit Description + +F_V km/h Max towing speed in auto mode. +K_psi 1/deg Amount of steering per heading correction. +F_psi 1/deg Max steering per heading correction. +K_deltapsi -1/(deg/s) Amount of steering compensation per heading + derivative. +F_psi 1/(deg/s) Max amount of steering compensation per + heading derivative. diff --git a/YourAircraftDir/Models/Autopush/Goldhofert.xml b/YourAircraftDir/Models/Autopush/Goldhofert.xml new file mode 100644 index 0000000..84bd872 --- /dev/null +++ b/YourAircraftDir/Models/Autopush/Goldhofert.xml @@ -0,0 +1,151 @@ + + + + + + + + + + + + + + + + + + + + + +]> + + + + + + + Models/Airport/Pushback/Goldhofert.ac + + + + + Models/Airport/Pushback/Goldhofert-warning-light.xml + + -2.908 + 0.260 + 1.326 + 0 + + + + + Models/Airport/Pushback/Goldhofert-warning-light.xml + + -1.781 + 0.260 + 1.326 + 90 + + + + + spin + wheelfl + wheelfr + &ROLLSPEED-PROP; + -16.3 +
+ -2.8976 + 0 + 0.5809 +
+ + 0 + 1 + 0 + +
+ + + spin + wheelrl + wheelrr + &ROLLSPEED-PROP; + -16.3 +
+ 2.0501 + 0 + 0.5735 +
+ + 0 + 1 + 0 + +
+ + + select + + &CONNECTED-PROP; + + + + + rotate + &YAW-PROP; + &YAW-MULT; +
+ 0 + 0 + 0 +
+ + 0 + 0 + -1 + +
+ + + translate + &COMPRESSION-PROP; + 0.3048 + + 0 + 0 + 1 + + + + + rotate + &PITCH-PROP; + &PITCH-FACTOR; + &PITCH-OFFSET; +
+ 0 + 0 + 0 +
+ + 0 + 1 + 0 + +
+
diff --git a/YourAircraftDir/Models/Autopush/cursor.ac b/YourAircraftDir/Models/Autopush/cursor.ac new file mode 100644 index 0000000..0b32067 --- /dev/null +++ b/YourAircraftDir/Models/Autopush/cursor.ac @@ -0,0 +1,589 @@ +AC3Db +MATERIAL "autopush cursor" rgb 0.0000 0.0000 0.0000 amb 0.0000 0.0000 0.0000 emis 1.000 0.173 0.545 spec 0.0000 0.0000 0.0000 shi 50 trans 0.0000 +OBJECT world +name "Blender_exporter_v2.26__cursor.ac" +kids 1 +OBJECT poly +name "Circle" +data 11 +Circle.mesh +crease 40.0 +numvert 128 +0 0.2 -0.75 +0 0.2 -1 +-0.09802 0.2 -0.99518 +-0.19509 0.2 -0.98079 +-0.29028 0.2 -0.95694 +-0.38268 0.2 -0.92388 +-0.4714 0.2 -0.88192 +-0.55557 0.2 -0.83147 +-0.63439 0.2 -0.77301 +-0.70711 0.2 -0.70711 +-0.77301 0.2 -0.63439 +-0.83147 0.2 -0.55557 +-0.88192 0.2 -0.4714 +-0.92388 0.2 -0.38268 +-0.95694 0.2 -0.29028 +-0.98079 0.2 -0.19509 +-0.99518 0.2 -0.09802 +-1 0.2 0 +-0.99518 0.2 0.09802 +-0.98079 0.2 0.19509 +-0.95694 0.2 0.29028 +-0.92388 0.2 0.38268 +-0.88192 0.2 0.4714 +-0.83147 0.2 0.55557 +-0.77301 0.2 0.63439 +-0.70711 0.2 0.70711 +-0.63439 0.2 0.77301 +-0.55557 0.2 0.83147 +-0.4714 0.2 0.88192 +-0.38268 0.2 0.92388 +-0.29028 0.2 0.95694 +-0.19509 0.2 0.98079 +-0.09802 0.2 0.99518 +0 0.2 1 +0.09802 0.2 0.99518 +0.19509 0.2 0.98079 +0.29029 0.2 0.95694 +0.38268 0.2 0.92388 +0.4714 0.2 0.88192 +0.55557 0.2 0.83147 +0.63439 0.2 0.77301 +0.70711 0.2 0.70711 +0.77301 0.2 0.63439 +0.83147 0.2 0.55557 +0.88192 0.2 0.4714 +0.92388 0.2 0.38268 +0.95694 0.2 0.29028 +0.98079 0.2 0.19509 +0.99518 0.2 0.09802 +1 0.2 0 +0.99518 0.2 -0.09802 +0.98079 0.2 -0.19509 +0.95694 0.2 -0.29028 +0.92388 0.2 -0.38268 +0.88192 0.2 -0.4714 +0.83147 0.2 -0.55557 +0.77301 0.2 -0.63439 +0.70711 0.2 -0.70711 +0.6344 0.2 -0.77301 +0.55557 0.2 -0.83147 +0.4714 0.2 -0.88192 +0.38269 0.2 -0.92388 +0.29029 0.2 -0.95694 +0.19509 0.2 -0.98078 +0.09802 0.2 -0.99518 +-0.07351 0.2 -0.74639 +-0.14632 0.2 -0.73559 +-0.21771 0.2 -0.71771 +-0.28701 0.2 -0.69291 +-0.35355 0.2 -0.66144 +-0.41668 0.2 -0.6236 +-0.47579 0.2 -0.57976 +-0.53033 0.2 -0.53033 +-0.57976 0.2 -0.47579 +-0.6236 0.2 -0.41668 +-0.66144 0.2 -0.35355 +-0.69291 0.2 -0.28701 +-0.71771 0.2 -0.21771 +-0.73559 0.2 -0.14632 +-0.74639 0.2 -0.07351 +-0.75 0.2 0 +-0.74639 0.2 0.07351 +-0.73559 0.2 0.14632 +-0.71771 0.2 0.21771 +-0.69291 0.2 0.28701 +-0.66144 0.2 0.35355 +-0.6236 0.2 0.41668 +-0.57976 0.2 0.4758 +-0.53033 0.2 0.53033 +-0.47579 0.2 0.57976 +-0.41668 0.2 0.6236 +-0.35355 0.2 0.66144 +-0.28701 0.2 0.69291 +-0.21771 0.2 0.71771 +-0.14632 0.2 0.73559 +-0.07351 0.2 0.74639 +0 0.2 0.75 +0.07351 0.2 0.74639 +0.14632 0.2 0.73559 +0.21771 0.2 0.71771 +0.28701 0.2 0.69291 +0.35355 0.2 0.66144 +0.41668 0.2 0.6236 +0.4758 0.2 0.57976 +0.53033 0.2 0.53033 +0.57976 0.2 0.47579 +0.6236 0.2 0.41668 +0.66144 0.2 0.35355 +0.69291 0.2 0.28701 +0.71771 0.2 0.21771 +0.73559 0.2 0.14632 +0.74639 0.2 0.07351 +0.75 0.2 0 +0.74639 0.2 -0.07351 +0.73559 0.2 -0.14632 +0.71771 0.2 -0.21771 +0.69291 0.2 -0.28701 +0.66144 0.2 -0.35355 +0.6236 0.2 -0.41668 +0.57976 0.2 -0.47579 +0.53033 0.2 -0.53033 +0.4758 0.2 -0.57976 +0.41668 0.2 -0.6236 +0.35355 0.2 -0.66144 +0.28701 0.2 -0.69291 +0.21772 0.2 -0.7177 +0.14632 0.2 -0.73559 +0.07352 0.2 -0.74639 +numsurf 64 +SURF 0X10 +mat 0 +refs 4 +25 0.080806 0.323223 +88 0.091854 0.367417 +87 0.088765 0.381051 +24 0.076687 0.341402 +SURF 0X10 +mat 0 +refs 4 +12 0.06988 0.617849 +75 0.08366 0.588387 +74 0.086025 0.604169 +11 0.073033 0.638893 +SURF 0X10 +mat 0 +refs 4 +51 0.186299 0.548772 +114 0.170974 0.536579 +113 0.171649 0.518378 +50 0.187199 0.524504 +SURF 0X10 +mat 0 +refs 4 +64 0.131126 0.748796 +127 0.129595 0.686597 +126 0.134145 0.683897 +63 0.137193 0.745196 +SURF 0X10 +mat 0 +refs 4 +11 0.073033 0.638893 +74 0.086025 0.604169 +73 0.088765 0.618949 +10 0.076687 0.658598 +SURF 0X10 +mat 0 +refs 4 +24 0.076687 0.341402 +87 0.088765 0.381051 +86 0.086025 0.39583 +23 0.073033 0.361107 +SURF 0X10 +mat 0 +refs 4 +37 0.148918 0.26903 +100 0.142938 0.326773 +99 0.138607 0.320574 +36 0.143143 0.260765 +SURF 0X10 +mat 0 +refs 4 +50 0.187199 0.524504 +113 0.171649 0.518378 +112 0.171875 0.5 +49 0.1875 0.5 +SURF 0X10 +mat 0 +refs 4 +63 0.137193 0.745196 +126 0.134145 0.683897 +125 0.138607 0.679426 +62 0.143143 0.739235 +SURF 0X10 +mat 0 +refs 4 +10 0.076687 0.658598 +73 0.088765 0.618949 +72 0.091854 0.632583 +9 0.080806 0.676777 +SURF 0X10 +mat 0 +refs 4 +23 0.073033 0.361107 +86 0.086025 0.39583 +85 0.08366 0.411613 +22 0.06988 0.382151 +SURF 0X10 +mat 0 +refs 4 +36 0.143143 0.260765 +99 0.138607 0.320574 +98 0.134145 0.316103 +35 0.137193 0.254804 +SURF 0X10 +mat 0 +refs 4 +49 0.1875 0.5 +112 0.171875 0.5 +111 0.171649 0.481622 +48 0.187199 0.475496 +SURF 0X10 +mat 0 +refs 4 +62 0.143143 0.739235 +125 0.138607 0.679426 +124 0.142938 0.673227 +61 0.148918 0.73097 +SURF 0X10 +mat 0 +refs 4 +9 0.080806 0.676777 +72 0.091854 0.632583 +71 0.095263 0.644939 +8 0.08535 0.693253 +SURF 0X10 +mat 0 +refs 4 +22 0.06988 0.382151 +85 0.08366 0.411613 +84 0.081693 0.428247 +21 0.067258 0.404329 +SURF 0X10 +mat 0 +refs 4 +35 0.137193 0.254804 +98 0.134145 0.316103 +97 0.129595 0.313403 +34 0.131126 0.251204 +SURF 0X10 +mat 0 +refs 4 +48 0.187199 0.475496 +111 0.171649 0.481622 +110 0.170974 0.463421 +47 0.186299 0.451227 +SURF 0X10 +mat 0 +refs 4 +61 0.148918 0.73097 +124 0.142938 0.673227 +123 0.147097 0.66536 +60 0.154463 0.72048 +SURF 0X10 +mat 0 +refs 4 +8 0.08535 0.693253 +71 0.095263 0.644939 +70 0.098958 0.6559 +7 0.090277 0.707867 +SURF 0X10 +mat 0 +refs 4 +21 0.067258 0.404329 +84 0.081693 0.428247 +83 0.080143 0.445572 +20 0.065191 0.427429 +SURF 0X10 +mat 0 +refs 4 +34 0.131126 0.251204 +97 0.129595 0.313403 +96 0.125 0.3125 +33 0.125 0.25 +SURF 0X10 +mat 0 +refs 4 +47 0.186299 0.451227 +110 0.170974 0.463421 +109 0.169857 0.445572 +46 0.184809 0.427429 +SURF 0X10 +mat 0 +refs 4 +60 0.154463 0.72048 +123 0.147097 0.66536 +122 0.151043 0.6559 +59 0.159723 0.707867 +SURF 0X10 +mat 0 +refs 4 +7 0.090277 0.707867 +70 0.098958 0.6559 +69 0.102903 0.66536 +6 0.095538 0.72048 +SURF 0X10 +mat 0 +refs 4 +20 0.065191 0.427429 +83 0.080143 0.445572 +82 0.079026 0.46342 +19 0.063701 0.451227 +SURF 0X10 +mat 0 +refs 4 +33 0.125 0.25 +96 0.125 0.3125 +95 0.120406 0.313403 +32 0.118874 0.251204 +SURF 0X10 +mat 0 +refs 4 +46 0.184809 0.427429 +109 0.169857 0.445572 +108 0.168307 0.428247 +45 0.182743 0.404329 +SURF 0X10 +mat 0 +refs 4 +59 0.159723 0.707867 +122 0.151043 0.6559 +121 0.154737 0.644939 +58 0.16465 0.693252 +SURF 0X10 +mat 0 +refs 4 +6 0.095538 0.72048 +69 0.102903 0.66536 +68 0.107062 0.673227 +5 0.101082 0.73097 +SURF 0X10 +mat 0 +refs 4 +19 0.063701 0.451227 +82 0.079026 0.46342 +81 0.078351 0.481622 +18 0.062801 0.475496 +SURF 0X10 +mat 0 +refs 4 +32 0.118874 0.251204 +95 0.120406 0.313403 +94 0.115855 0.316103 +31 0.112807 0.254804 +SURF 0X10 +mat 0 +refs 4 +45 0.182743 0.404329 +108 0.168307 0.428247 +107 0.16634 0.411613 +44 0.18012 0.382151 +SURF 0X10 +mat 0 +refs 4 +58 0.16465 0.693252 +121 0.154737 0.644939 +120 0.158146 0.632582 +57 0.169194 0.676776 +SURF 0X10 +mat 0 +refs 4 +5 0.101082 0.73097 +68 0.107062 0.673227 +67 0.111393 0.679426 +4 0.106857 0.739235 +SURF 0X10 +mat 0 +refs 4 +18 0.062801 0.475496 +81 0.078351 0.481622 +80 0.078125 0.5 +17 0.0625 0.5 +SURF 0X10 +mat 0 +refs 4 +31 0.112807 0.254804 +94 0.115855 0.316103 +93 0.111393 0.320574 +30 0.106857 0.260765 +SURF 0X10 +mat 0 +refs 4 +44 0.18012 0.382151 +107 0.16634 0.411613 +106 0.163975 0.395831 +43 0.176967 0.361108 +SURF 0X10 +mat 0 +refs 4 +57 0.169194 0.676776 +120 0.158146 0.632582 +119 0.161235 0.618949 +56 0.173313 0.658598 +SURF 0X10 +mat 0 +refs 4 +4 0.106857 0.739235 +67 0.111393 0.679426 +66 0.115855 0.683897 +3 0.112807 0.745196 +SURF 0X10 +mat 0 +refs 4 +17 0.0625 0.5 +80 0.078125 0.5 +79 0.078351 0.518378 +16 0.062801 0.524504 +SURF 0X10 +mat 0 +refs 4 +30 0.106857 0.260765 +93 0.111393 0.320574 +92 0.107062 0.326772 +29 0.101082 0.26903 +SURF 0X10 +mat 0 +refs 4 +43 0.176967 0.361108 +106 0.163975 0.395831 +105 0.161235 0.381051 +42 0.173313 0.341402 +SURF 0X10 +mat 0 +refs 4 +56 0.173313 0.658598 +119 0.161235 0.618949 +118 0.163975 0.604169 +55 0.176967 0.638892 +SURF 0X10 +mat 0 +refs 4 +3 0.112807 0.745196 +66 0.115855 0.683897 +65 0.120406 0.686597 +2 0.118874 0.748796 +SURF 0X10 +mat 0 +refs 4 +16 0.062801 0.524504 +79 0.078351 0.518378 +78 0.079026 0.536579 +15 0.063701 0.548773 +SURF 0X10 +mat 0 +refs 4 +29 0.101082 0.26903 +92 0.107062 0.326772 +91 0.102903 0.33464 +28 0.095538 0.27952 +SURF 0X10 +mat 0 +refs 4 +42 0.173313 0.341402 +105 0.161235 0.381051 +104 0.158146 0.367418 +41 0.169194 0.323223 +SURF 0X10 +mat 0 +refs 4 +55 0.176967 0.638892 +118 0.163975 0.604169 +117 0.16634 0.588387 +54 0.18012 0.617849 +SURF 0X10 +mat 0 +refs 4 +15 0.063701 0.548773 +78 0.079026 0.536579 +77 0.080143 0.554428 +14 0.065191 0.572571 +SURF 0X10 +mat 0 +refs 4 +28 0.095538 0.27952 +91 0.102903 0.33464 +90 0.098958 0.344099 +27 0.090277 0.292132 +SURF 0X10 +mat 0 +refs 4 +41 0.169194 0.323223 +104 0.158146 0.367418 +103 0.154737 0.355061 +40 0.16465 0.306747 +SURF 0X10 +mat 0 +refs 4 +54 0.18012 0.617849 +117 0.16634 0.588387 +116 0.168307 0.571753 +53 0.182743 0.595671 +SURF 0X10 +mat 0 +refs 4 +0 0.125 0.6875 +1 0.125 0.75 +2 0.118874 0.748796 +65 0.120406 0.686597 +SURF 0X10 +mat 0 +refs 4 +14 0.065191 0.572571 +77 0.080143 0.554428 +76 0.081693 0.571753 +13 0.067258 0.595671 +SURF 0X10 +mat 0 +refs 4 +27 0.090277 0.292132 +90 0.098958 0.344099 +89 0.095263 0.35506 +26 0.08535 0.306747 +SURF 0X10 +mat 0 +refs 4 +40 0.16465 0.306747 +103 0.154737 0.355061 +102 0.151042 0.344099 +39 0.159723 0.292133 +SURF 0X10 +mat 0 +refs 4 +53 0.182743 0.595671 +116 0.168307 0.571753 +115 0.169857 0.554428 +52 0.184809 0.572571 +SURF 0X10 +mat 0 +refs 4 +13 0.067258 0.595671 +76 0.081693 0.571753 +75 0.08366 0.588387 +12 0.06988 0.617849 +SURF 0X10 +mat 0 +refs 4 +26 0.08535 0.306747 +89 0.095263 0.35506 +88 0.091854 0.367417 +25 0.080806 0.323223 +SURF 0X10 +mat 0 +refs 4 +39 0.159723 0.292133 +102 0.151042 0.344099 +101 0.147097 0.33464 +38 0.154462 0.27952 +SURF 0X10 +mat 0 +refs 4 +52 0.184809 0.572571 +115 0.169857 0.554428 +114 0.170974 0.536579 +51 0.186299 0.548772 +SURF 0X10 +mat 0 +refs 4 +1 0.125 0.75 +0 0.125 0.6875 +127 0.129595 0.686597 +64 0.131126 0.748796 +SURF 0X10 +mat 0 +refs 4 +38 0.154462 0.27952 +101 0.147097 0.33464 +100 0.142938 0.326773 +37 0.148918 0.26903 +kids 0 diff --git a/YourAircraftDir/Models/Autopush/cursor.xml b/YourAircraftDir/Models/Autopush/cursor.xml new file mode 100644 index 0000000..ee73009 --- /dev/null +++ b/YourAircraftDir/Models/Autopush/cursor.xml @@ -0,0 +1,45 @@ + + + + + cursor.ac + + + false + + + + scale + /sim/model/autopush/stopping-distance-m + 0.0 + 1.0 + + + + material + + /sim/model/autopush/route/invalid + + + 1.0 + 0.0 + 0.0 + + + 1.0 + 0.0 + 0.0 + + + + diff --git a/YourAircraftDir/Models/Autopush/cursor_reverse.ac b/YourAircraftDir/Models/Autopush/cursor_reverse.ac new file mode 100644 index 0000000..938b7fc --- /dev/null +++ b/YourAircraftDir/Models/Autopush/cursor_reverse.ac @@ -0,0 +1,133 @@ +AC3Db +MATERIAL "autopush cursor" rgb 0.0000 0.0000 0.0000 amb 0.0000 0.0000 0.0000 emis 1.000 0.173 0.545 spec 0.0000 0.0000 0.0000 shi 50 trans 0.0000 +OBJECT world +name "Blender_exporter_v2.26__cursor_reverse.ac" +kids 1 +OBJECT poly +name "Circle" +data 11 +Circle.mesh +crease 40.0 +numvert 36 +-0.86603 0.2 0.15 +-0.64952 0.2 0.15 +-0.64952 0.2 -0.375 +-0.86603 0.2 -0.15 +-0.64952 0.2 -0.15 +-0.86603 0.2 -0.5 +-0.56292 0.2 -0.675 +-0.45466 0.2 -0.4875 +-0 0.2 -0.75 +-0 0.2 -1 +-0.30311 0.2 -0.825 +-0.19486 0.2 -0.6375 +0.30311 0.2 -0.825 +0.19486 0.2 -0.6375 +0.64952 0.2 -0.375 +0.86603 0.2 -0.5 +0.56292 0.2 -0.675 +0.45466 0.2 -0.4875 +0.86603 0.2 -0.15 +0.64952 0.2 -0.15 +0.86603 0.2 0.5 +0.86603 0.2 0.15 +0.64952 0.2 0.15 +0.64952 0.2 0.375 +0.56292 0.2 0.675 +0.45466 0.2 0.4875 +0.30311 0.2 0.825 +0.19486 0.2 0.6375 +-0 0.2 0.75 +-0 0.2 1 +-0.30311 0.2 0.825 +-0.19486 0.2 0.6375 +-0.64952 0.2 0.375 +-0.86603 0.2 0.5 +-0.56292 0.2 0.675 +-0.45466 0.2 0.4875 +numsurf 12 +SURF 0X10 +mat 0 +refs 4 +2 0.078125 0.40625 +5 0.0625 0.375 +3 0.0625 0.5 +4 0.078125 0.5 +SURF 0X10 +mat 0 +refs 4 +32 0.078125 0.40625 +1 0.078125 0.5 +0 0.0625 0.5 +33 0.0625 0.375 +SURF 0X10 +mat 0 +refs 4 +8 0.078125 0.40625 +9 0.0625 0.375 +10 0.0625 0.5 +11 0.078125 0.5 +SURF 0X10 +mat 0 +refs 4 +2 0.078125 0.40625 +7 0.078125 0.5 +6 0.0625 0.5 +5 0.0625 0.375 +SURF 0X10 +mat 0 +refs 4 +14 0.078125 0.40625 +15 0.0625 0.375 +16 0.0625 0.5 +17 0.078125 0.5 +SURF 0X10 +mat 0 +refs 4 +8 0.078125 0.40625 +13 0.078125 0.5 +12 0.0625 0.5 +9 0.0625 0.375 +SURF 0X10 +mat 0 +refs 4 +23 0.078125 0.40625 +20 0.0625 0.375 +21 0.0625 0.5 +22 0.078125 0.5 +SURF 0X10 +mat 0 +refs 4 +14 0.078125 0.40625 +19 0.078125 0.5 +18 0.0625 0.5 +15 0.0625 0.375 +SURF 0X10 +mat 0 +refs 4 +28 0.078125 0.40625 +29 0.0625 0.375 +26 0.0625 0.5 +27 0.078125 0.5 +SURF 0X10 +mat 0 +refs 4 +23 0.078125 0.40625 +25 0.078125 0.5 +24 0.0625 0.5 +20 0.0625 0.375 +SURF 0X10 +mat 0 +refs 4 +32 0.078125 0.40625 +33 0.0625 0.375 +34 0.0625 0.5 +35 0.078125 0.5 +SURF 0X10 +mat 0 +refs 4 +28 0.078125 0.40625 +31 0.078125 0.5 +30 0.0625 0.5 +29 0.0625 0.375 +kids 0 diff --git a/YourAircraftDir/Models/Autopush/cursor_reverse.xml b/YourAircraftDir/Models/Autopush/cursor_reverse.xml new file mode 100644 index 0000000..f81fe76 --- /dev/null +++ b/YourAircraftDir/Models/Autopush/cursor_reverse.xml @@ -0,0 +1,45 @@ + + + + + cursor_reverse.ac + + + false + + + + scale + /sim/model/autopush/stopping-distance-m + 0.0 + 1.0 + + + + material + + /sim/model/autopush/route/invalid + + + 1.0 + 0.0 + 0.0 + + + 1.0 + 0.0 + 0.0 + + + + diff --git a/YourAircraftDir/Models/Autopush/cursor_sharp.ac b/YourAircraftDir/Models/Autopush/cursor_sharp.ac new file mode 100644 index 0000000..e899295 --- /dev/null +++ b/YourAircraftDir/Models/Autopush/cursor_sharp.ac @@ -0,0 +1,67 @@ +AC3Db +MATERIAL "autopush cursor" rgb 0.0000 0.0000 0.0000 amb 0.0000 0.0000 0.0000 emis 1.000 0.173 0.545 spec 0.0000 0.0000 0.0000 shi 50 trans 0.0000 +OBJECT world +name "Blender_exporter_v2.26__cursor_sharp.ac" +kids 1 +OBJECT poly +name "Circle" +data 11 +Circle.mesh +crease 40.0 +numvert 12 +0 0.2 -0.75 +0 0.2 -1 +0.64952 0.2 -0.375 +0.86603 0.2 -0.5 +0.64952 0.2 0.375 +0.86603 0.2 0.5 +0 0.2 0.75 +0 0.2 1 +-0.64952 0.2 0.375 +-0.86603 0.2 0.5 +-0.64952 0.2 -0.375 +-0.86603 0.2 -0.5 +numsurf 6 +SURF 0X10 +mat 0 +refs 4 +0 0.125 0.6875 +2 0.171875 0.59375 +3 0.1875 0.625 +1 0.125 0.75 +SURF 0X10 +mat 0 +refs 4 +2 0.171875 0.59375 +4 0.171875 0.40625 +5 0.1875 0.375 +3 0.1875 0.625 +SURF 0X10 +mat 0 +refs 4 +4 0.171875 0.40625 +6 0.125 0.3125 +7 0.125 0.25 +5 0.1875 0.375 +SURF 0X10 +mat 0 +refs 4 +6 0.125 0.3125 +8 0.078125 0.40625 +9 0.0625 0.375 +7 0.125 0.25 +SURF 0X10 +mat 0 +refs 4 +8 0.078125 0.40625 +10 0.078125 0.59375 +11 0.0625 0.625 +9 0.0625 0.375 +SURF 0X10 +mat 0 +refs 4 +10 0.078125 0.59375 +0 0.125 0.6875 +1 0.125 0.75 +11 0.0625 0.625 +kids 0 diff --git a/YourAircraftDir/Models/Autopush/cursor_sharp.xml b/YourAircraftDir/Models/Autopush/cursor_sharp.xml new file mode 100644 index 0000000..c804033 --- /dev/null +++ b/YourAircraftDir/Models/Autopush/cursor_sharp.xml @@ -0,0 +1,45 @@ + + + + + cursor_sharp.ac + + + false + + + + scale + /sim/model/autopush/stopping-distance-m + 0.0 + 1.0 + + + + material + + /sim/model/autopush/route/invalid + + + 1.0 + 0.0 + 0.0 + + + 1.0 + 0.0 + 0.0 + + + + diff --git a/YourAircraftDir/Models/Autopush/waypoint.ac b/YourAircraftDir/Models/Autopush/waypoint.ac new file mode 100644 index 0000000..e6c3ff9 --- /dev/null +++ b/YourAircraftDir/Models/Autopush/waypoint.ac @@ -0,0 +1,276 @@ +AC3Db +MATERIAL "autopush cursor" rgb 0.0000 0.0000 0.0000 amb 0.0000 0.0000 0.0000 emis 1.000 0.173 0.545 spec 0.0000 0.0000 0.0000 shi 50 trans 0.0000 +OBJECT world +name "Blender_exporter_v2.26__waypoint.ac" +kids 3 +OBJECT poly +name "Waypoint" +data 11 +Circle.mesh +crease 40.0 +numvert 33 +0.03902 0.2 -0.19616 +0.07654 0.2 -0.18478 +0.11111 0.2 -0.16629 +0.14142 0.2 -0.14142 +0.16629 0.2 -0.11111 +0.18478 0.2 -0.07654 +0.19616 0.2 -0.03902 +0.2 0.2 0 +0.19616 0.2 0.03902 +0.18478 0.2 0.07654 +0.16629 0.2 0.11111 +0.14142 0.2 0.14142 +0.11111 0.2 0.16629 +0.07654 0.2 0.18478 +0.03902 0.2 0.19616 +0 0.2 0.2 +-0.03902 0.2 0.19616 +-0.07654 0.2 0.18478 +-0.11111 0.2 0.16629 +-0.14142 0.2 0.14142 +-0.16629 0.2 0.11111 +-0.18478 0.2 0.07654 +-0.19616 0.2 0.03902 +-0.2 0.2 0 +-0.19616 0.2 -0.03902 +-0.18478 0.2 -0.07654 +-0.16629 0.2 -0.11111 +-0.14142 0.2 -0.14142 +-0.11111 0.2 -0.16629 +-0.07654 0.2 -0.18478 +-0.03902 0.2 -0.19616 +0 0.2 -0.2 +0 0.2 0 +numsurf 32 +SURF 0X0 +mat 0 +refs 3 +32 0.125 0.5 +18 0.090277 0.292133 +17 0.101082 0.26903 +SURF 0X0 +mat 0 +refs 3 +32 0.125 0.5 +31 0.125 0.75 +30 0.112807 0.745197 +SURF 0X0 +mat 0 +refs 3 +32 0.125 0.5 +4 0.176967 0.638893 +3 0.169194 0.676777 +SURF 0X0 +mat 0 +refs 3 +32 0.125 0.5 +17 0.101082 0.26903 +16 0.112807 0.254804 +SURF 0X0 +mat 0 +refs 3 +32 0.125 0.5 +30 0.112807 0.745197 +29 0.101082 0.73097 +SURF 0X0 +mat 0 +refs 3 +32 0.125 0.5 +3 0.169194 0.676777 +2 0.159723 0.707868 +SURF 0X0 +mat 0 +refs 3 +32 0.125 0.5 +16 0.112807 0.254804 +15 0.125 0.25 +SURF 0X0 +mat 0 +refs 3 +32 0.125 0.5 +29 0.101082 0.73097 +28 0.090277 0.707868 +SURF 0X0 +mat 0 +refs 3 +32 0.125 0.5 +2 0.159723 0.707868 +1 0.148918 0.73097 +SURF 0X0 +mat 0 +refs 3 +32 0.125 0.5 +15 0.125 0.25 +14 0.137193 0.254804 +SURF 0X0 +mat 0 +refs 3 +32 0.125 0.5 +28 0.090277 0.707868 +27 0.080806 0.676777 +SURF 0X0 +mat 0 +refs 3 +32 0.125 0.5 +1 0.148918 0.73097 +0 0.137193 0.745197 +SURF 0X0 +mat 0 +refs 3 +32 0.125 0.5 +14 0.137193 0.254804 +13 0.148918 0.26903 +SURF 0X0 +mat 0 +refs 3 +32 0.125 0.5 +27 0.080806 0.676777 +26 0.073033 0.638893 +SURF 0X0 +mat 0 +refs 3 +32 0.125 0.5 +0 0.137193 0.745197 +31 0.125 0.75 +SURF 0X0 +mat 0 +refs 3 +32 0.125 0.5 +13 0.148918 0.26903 +12 0.159723 0.292133 +SURF 0X0 +mat 0 +refs 3 +32 0.125 0.5 +26 0.073033 0.638893 +25 0.067258 0.595671 +SURF 0X0 +mat 0 +refs 3 +32 0.125 0.5 +12 0.159723 0.292133 +11 0.169194 0.323224 +SURF 0X0 +mat 0 +refs 3 +32 0.125 0.5 +25 0.067258 0.595671 +24 0.063701 0.548773 +SURF 0X0 +mat 0 +refs 3 +32 0.125 0.5 +11 0.169194 0.323224 +10 0.176967 0.361108 +SURF 0X0 +mat 0 +refs 3 +32 0.125 0.5 +24 0.063701 0.548773 +23 0.0625 0.5 +SURF 0X0 +mat 0 +refs 3 +32 0.125 0.5 +10 0.176967 0.361108 +9 0.182743 0.404329 +SURF 0X0 +mat 0 +refs 3 +32 0.125 0.5 +23 0.0625 0.5 +22 0.063701 0.451228 +SURF 0X0 +mat 0 +refs 3 +32 0.125 0.5 +9 0.182743 0.404329 +8 0.186299 0.451228 +SURF 0X0 +mat 0 +refs 3 +32 0.125 0.5 +22 0.063701 0.451228 +21 0.067258 0.404329 +SURF 0X0 +mat 0 +refs 3 +32 0.125 0.5 +8 0.186299 0.451228 +7 0.1875 0.5 +SURF 0X0 +mat 0 +refs 3 +32 0.125 0.5 +21 0.067258 0.404329 +20 0.073033 0.361108 +SURF 0X0 +mat 0 +refs 3 +32 0.125 0.5 +7 0.1875 0.5 +6 0.186299 0.548773 +SURF 0X0 +mat 0 +refs 3 +32 0.125 0.5 +20 0.073033 0.361108 +19 0.080806 0.323223 +SURF 0X0 +mat 0 +refs 3 +32 0.125 0.5 +6 0.186299 0.548773 +5 0.182742 0.595671 +SURF 0X0 +mat 0 +refs 3 +32 0.125 0.5 +19 0.080806 0.323223 +18 0.090277 0.292133 +SURF 0X0 +mat 0 +refs 3 +32 0.125 0.5 +5 0.182742 0.595671 +4 0.176967 0.638893 +kids 0 +OBJECT poly +name "WingtipL" +data 15 +Circle.mesh.001 +crease 40.0 +numvert 4 +-0.1 0.2 -0.1 +-0.1 0.2 0.1 +0.1 0.2 -0.1 +0.1 0.2 0.1 +numsurf 1 +SURF 0X0 +mat 0 +refs 4 +0 0 0 +1 0 0 +3 0 0 +2 0 0 +kids 0 +OBJECT poly +name "WingtipR" +data 15 +Circle.mesh.007 +crease 40.0 +numvert 4 +-0.1 0.2 -0.1 +-0.1 0.2 0.1 +0.1 0.2 -0.1 +0.1 0.2 0.1 +numsurf 1 +SURF 0X0 +mat 0 +refs 4 +0 0 0 +1 0 0 +3 0 0 +2 0 0 +kids 0 diff --git a/YourAircraftDir/Models/Autopush/waypoint.xml b/YourAircraftDir/Models/Autopush/waypoint.xml new file mode 100644 index 0000000..a359210 --- /dev/null +++ b/YourAircraftDir/Models/Autopush/waypoint.xml @@ -0,0 +1,86 @@ + + + + + waypoint.ac + + + false + + + + select + WingtipL + WingtipR + + /sim/model/autopush/route/show-wingtip + + + + + translate + WingtipL + /sim/model/autopush/route/wingspan-m + 0.5 + + 0 + 1 + 0 + + 0.0 + 1.0 + + + + translate + WingtipR + /sim/model/autopush/route/wingspan-m + -0.5 + + 0 + 1 + 0 + + 0.0 + 1.0 + + + + scale + + Waypoint + WingtipL + WingtipR + /sim/model/autopush/stopping-distance-m + 0.0 + 1.0 + + + + material + + /sim/model/autopush/route/invalid + + + 1.0 + 0.0 + 0.0 + + + 1.0 + 0.0 + 0.0 + + + + diff --git a/YourAircraftDir/Nasal/Autopush/autopush.nas b/YourAircraftDir/Nasal/Autopush/autopush.nas new file mode 100644 index 0000000..a942420 --- /dev/null +++ b/YourAircraftDir/Nasal/Autopush/autopush.nas @@ -0,0 +1,141 @@ +# AUTOPUSH +# Basic pushback logic class. +# +# Copyright (c) 2018 Autopush authors: +# Joshua Davidson http://github.com/Octal450 +# Merspieler http://gitlab.com/merspieler +# Distribute under the terms of GPLv2. + + +var _K_p = nil; +var _F_p = nil; +var _K_i = nil; +var _F_i = nil; +var _K_d = nil; +var _F_d = nil; +var _F = nil; +var _int = nil; +var _V = nil; +var _T_f = nil; +var _K_yaw = nil; +var _yasim = 0; +var _time = nil; +# (ft / s^2) / ((km / h) / s) +var _unitconv = M2FT / 3.6; +var _debug = nil; + +var _loop = func() { + if (!getprop("/sim/model/autopush/available")) { + _stop(); + return; + } + var force = 0.0; + var x = 0.0; + var y = 0.0; + var z = 0.0; + # Rollspeed is only adequate if the wheel is touching the ground. + if (getprop("/gear/gear[0]/wow")) { + var V = getprop("/gear/gear[0]/rollspeed-ms") * 3.6; + var deltaV = getprop("/sim/model/autopush/target-speed-km_h") - V; + var minus_dV = _V - V; + var time = getprop("/sim/time/elapsed-sec"); + var prop = math.min(math.max(_K_p * deltaV, -_F_p), _F_p); + var dt = time - _time; + var deriv = 0.0; + # XXX Sanitising dt. Smaller chance of freakout on lag spike. + if(dt > 0.0) { + if(dt < 0.05) { + _int = math.min(math.max(_int + _K_i * deltaV * dt, -_F_i), _F_i); + } + if(dt > 0.002) { + deriv = math.min(math.max(_K_d * minus_dV / dt, -_F_d), _F_d); + } + } + var accel = prop + _int + deriv; + if (_debug > 2) { + print("pushback prop " ~ prop ~ ", _int " ~ _int ~ ", deriv " ~ deriv); + } + _V = V; + _time = time; + if (!_yasim) { + force = accel * getprop("/fdm/jsbsim/inertia/weight-lbs") * _unitconv; + } else { + force = accel * getprop("/fdm/yasim/gross-weight-lbs") * _unitconv; + } + var pitch = getprop("/sim/model/autopush/pitch-deg") * D2R; + z = math.sin(pitch); + var pz = math.cos(pitch); + var yaw = getprop("/sim/model/autopush/yaw") * _K_yaw; + x = math.cos(yaw) * pz; + y = math.sin(yaw) * pz; + setprop("/sim/model/autopush/force-x", x); + setprop("/sim/model/autopush/force-y", y); + # JSBSim force's z is down. + setprop("/sim/model/autopush/force-z", -z); + } + setprop("/sim/model/autopush/force-lbf", force); + if (_yasim) { + # The force is divided by YASim thrust="100000.0" setting. + setprop("/sim/model/autopush/force-x-yasim", x * force * 0.00001); + # YASim force's y is to the left. + setprop("/sim/model/autopush/force-y-yasim", -y * force * 0.00001); + setprop("/sim/model/autopush/force-z-yasim", z * force * 0.00001); + } +} + +var _timer = maketimer(0.0167, func{_loop()}); +_timer.simulatedTime = 1; + +var _start = func() { + # Else overwritten by dialog. + settimer(func() { + setprop("/sim/model/autopush/target-speed-km_h", 0.0) + }, 0.1, 1); + _K_p = getprop("/sim/model/autopush/K_p"); + _F_p = getprop("/sim/model/autopush/F_p"); + _K_i = getprop("/sim/model/autopush/K_i"); + _F_i = getprop("/sim/model/autopush/F_i"); + _K_d = getprop("/sim/model/autopush/K_d"); + _F_d = getprop("/sim/model/autopush/F_d"); + _F = getprop("/sim/model/autopush/F"); + _T_f = getprop("/sim/model/autopush/T_f"); + _K_yaw = getprop("/sim/model/autopush/yaw-mult") * D2R; + _yasim = (getprop("/sim/flight-model") == "yasim"); + _debug = getprop("/sim/model/autopush/debug") or 0; + _int = 0.0; + _V = 0.0; + _time = getprop("/sim/time/elapsed-sec"); + setprop("/sim/model/autopush/connected", 1); + if (!_timer.isRunning) { + if (getprop("/sim/model/autopush/chocks")) { + setprop("/sim/model/autopush/chocks", 0); + screen.log.write("(pushback): Pushback connected, chocks removed. Please release brakes."); + } else { + screen.log.write("(pushback): Pushback connected, please release brakes."); + } + } + _timer.start(); +} + +var _stop = func() { + if (_timer.isRunning) { + screen.log.write("(pushback): Pushback and bypass pin removed."); + } + _timer.stop(); + setprop("/sim/model/autopush/force-lbf", 0.0); + if (_yasim) { + setprop("/sim/model/autopush/force-x-yasim", 0.0); + setprop("/sim/model/autopush/force-y-yasim", 0.0); + } + setprop("/sim/model/autopush/connected", 0); + setprop("/sim/model/autopush/enabled", 0); +} + +setlistener("/sim/model/autopush/enabled", func(p) { + var enabled = p.getValue(); + if ((enabled) and getprop("/sim/model/autopush/available")) { + _start(); + } else { + _stop(); + } +}, 1, 0); diff --git a/YourAircraftDir/Nasal/Autopush/driver.nas b/YourAircraftDir/Nasal/Autopush/driver.nas new file mode 100644 index 0000000..59ed98d --- /dev/null +++ b/YourAircraftDir/Nasal/Autopush/driver.nas @@ -0,0 +1,155 @@ +# AUTOPUSH +# Pushback driver class. +# +# Command the pushback to tow/push the aircraft. +# +# Copyright (c) 2018 Autopush authors: +# Joshua Davidson http://github.com/Octal450 +# Merspieler http://gitlab.com/merspieler +# Distribute under the terms of GPLv2. + + +var _K_V = nil; +var _F_V = nil; +var _R_turn_min = nil; +var _D_stop = nil; +var _K_psi = nil; +var _F_psi = nil; +var _K_psidot = nil; +var _F_psidot = nil; +var _debug = nil; +var _psi = nil; +var _time = nil; + +var _route = nil; +var _route_reverse = nil; +var _push = nil; +var _sign = nil; + +var _to_wp = 0; +var _is_last_wp = 0; +var _is_reverse_wp = 0; + + +var _advance_wp = func(flip_sign = 0) { + _to_wp += 1; + _is_last_wp = (_to_wp == (size(_route) - 1)); + _is_reverse_wp = (_route_reverse[_to_wp]); + if (flip_sign) { + _sign *= -1; + _push = !_push; + } + if (_debug == 1) { + print("autopush_driver to_wp " ~ _to_wp); + } +} + +var _loop = func() { + if (!getprop("/sim/model/autopush/connected")) { + stop(); + return; + } + var (A, D) = courseAndDistance(_route[_to_wp]); + D *= NM2M; + var (psi_leg, D_leg) = courseAndDistance(_route[_to_wp - 1], _route[_to_wp]); + var deltapsi = geo.normdeg180(A - psi_leg); + var psi = getprop("/orientation/heading-deg") + _push * 180.0; + var deltaA = math.min(math.max(_K_psi * geo.normdeg180(A - psi), -_F_psi), _F_psi); + var time = getprop("/sim/time/elapsed-sec"); + var dt = time - _time; + var minus_psidot = (dt > 0.002) * math.min(math.max(_K_psidot * (_psi - psi) / dt, -_F_psidot), _F_psidot); + _psi = psi; + _time = time; + # TODO Either use _K_V and total remaining distance or turn radius to calculate speed. + # TODO Make slider input override speed. + var V = _F_V; + if (_is_reverse_wp or _is_last_wp) { + if ((D < _D_stop) or (abs(deltapsi) > 90.0)) { + if (_is_last_wp) { + _done(); + return; + } + if (_is_reverse_wp) { + _advance_wp(1); + } + } + } else { + if ((D < _R_turn_min) or (abs(deltapsi) > 90.0)) { + _advance_wp(); + } + } + var steering = math.min(math.max(_sign * (deltaA + minus_psidot), -1.0), 1.0); + if (_debug > 1) { + print("autopush_driver to_wp " ~ _to_wp ~ ", A " ~ geo.normdeg(A) ~ ", deltaA " ~ deltaA ~ ", minus_psidot " ~ minus_psidot); + } + setprop("/sim/model/autopush/target-speed-km_h", _sign * V); + setprop("/sim/model/autopush/steer-cmd-norm", steering); +} + +var _timer = maketimer(0.051, func{_loop()}); +_timer.simulatedTime = 1; + +var _done = func() { + stop(); + autopush_route.clear(); + screen.log.write("(pushback): Pushback complete, please set parking brake."); +} + +var start = func() { + if (_timer.isRunning) { + gui.popupTip("Already moving"); + return; + } + if (!getprop("/sim/model/autopush/connected")) { + gui.popupTip("Pushback not connected"); + return; + } + _route = autopush_route.route(); + _route_reverse = autopush_route.route_reverse(); + if ((_route == nil) or size(_route) < 2) { + gui.popupTip("Pushback route empty or invalid"); + return; + } else { + autopush_route.done(); + } + _K_V = getprop("/sim/model/autopush/driver/K_V"); + _F_V = getprop("/sim/model/autopush/driver/F_V"); + _R_turn_min = getprop("/sim/model/autopush/min-turn-radius-m"); + _D_stop = getprop("/sim/model/autopush/stopping-distance-m"); + _K_psi = getprop("/sim/model/autopush/driver/K_psi"); + _F_psi = getprop("/sim/model/autopush/driver/F_psi"); + _K_psidot = getprop("/sim/model/autopush/driver/K_psidot"); + _F_psidot = getprop("/sim/model/autopush/driver/F_psidot"); + _debug = getprop("/sim/model/autopush/debug") or 0; + if (!_to_wp) { + var (psi_park, D_park) = courseAndDistance(_route[0], _route[1]); + _push = (abs(geo.normdeg180(getprop("/orientation/heading-deg") - psi_park)) > 90.0); + _sign = 1.0 - 2.0 * _push; + _advance_wp(); + _psi = 0.0; + } + _time = getprop("/sim/time/elapsed-sec"); + _timer.start(); + var endsign = _sign; + for (ii = _to_wp; ii < size(_route_reverse); ii += 1) { + if (_route_reverse[ii]) { + endsign = -endsign; + } + } + var (psi_twy, D_twy) = courseAndDistance(_route[size(_route) - 2], _route[size(_route) - 1]); + if (endsign < 0.0) { + screen.log.write("(pushback): Push back facing " ~ math.round(geo.normdeg(psi_twy + 180.0 - magvar()), 1.0) ~ "."); + } else { + screen.log.write("(pushback): Tow facing " ~ math.round(geo.normdeg(psi_twy - magvar()), 1.0) ~ "."); + } +} + +var pause = func() { + _timer.stop(); + setprop("/sim/model/autopush/target-speed-km_h", 0.0); +} + +var stop = func() { + pause(); + _to_wp = 0; +} diff --git a/YourAircraftDir/Nasal/Autopush/dynarr.nas b/YourAircraftDir/Nasal/Autopush/dynarr.nas new file mode 100644 index 0000000..663e881 --- /dev/null +++ b/YourAircraftDir/Nasal/Autopush/dynarr.nas @@ -0,0 +1,60 @@ +# Class for dynamic arrays +# +# Copyright (c) 2018 dynamic arrays authors: +# Merspieler http://gitlab.com/merspieler +# Distribute under the terms of GPLv2. + +## Useage +# to create a new object: var = dynarr.new(); +# to add elements: .add(); +# you can access the full stored array as: .arr +# to get only the used area of the array: var = .get_spliced() + +var dynarr = +{ + new: func(size = 8) + { + var this = {parents:[dynarr]}; + this.maxsize = size; + this.size = 0; + this.arr = setsize([], size); + + return this; + }, + + # add a new element to the array + add: func(obj) + { + # case there's no space left + if (me.size + 1 >= me.maxsize) + { + # double array size + me.maxsize *= 2; + me.arr = setsize(me.arr, me.maxsize); + } + + # add object and increase used counter + me.arr[me.size] = obj; + me.size += 1; + }, + + # delete an element from the array + del: func(id) + { + me.size -= 1; + for(ii = id; ii < me.size - 1; ii += 1){ + me.arr[ii] = me.arr[ii + 1]; + } + }, + + # returns only the filled part of the array or nil if array is empty + get_sliced: func() + { + if (me.size == 0) + { + return nil; + } + + return me.arr[0:me.size - 1]; + } +}; diff --git a/YourAircraftDir/Nasal/Autopush/route.nas b/YourAircraftDir/Nasal/Autopush/route.nas new file mode 100644 index 0000000..eab2292 --- /dev/null +++ b/YourAircraftDir/Nasal/Autopush/route.nas @@ -0,0 +1,432 @@ +# AUTOPUSH +# Visual entry of pushback route. +# +# Copyright (c) 2018 Autopush authors: +# Joshua Davidson http://github.com/Octal450 +# Merspieler http://gitlab.com/merspieler +# Distribute under the terms of GPLv2. + + +var _listener = nil; +var _view_listener = nil; +var _user_points = dynarr.dynarr.new(4); +var _user_point_modes = dynarr.dynarr.new(4); # Modes: 0 = Bezier node, 1 = Bezier end/start node, 2 = Reverse +var _route = []; +var _route_hdg = []; +var _route_reverse = []; +var _top_view_index = nil; +var _top_view_heading_offset_deg = 180.0; +var _reset_view_index = nil; +var _view_z_offset = nil; +var _view_pitch_offset_deg = nil; +var _view_heading_offset_deg = nil; +var _user_point_models = []; +var _waypoint_models = []; +var _N = 0; +var _show = 0; +var _R_turn_min = 0; +var _invalid = 0; + +# Make top-down view point north in old FG. +var __fg_version = num(string.replace(getprop("/sim/version/flightgear"),".","")); +if (__fg_version < 201920) { + _top_view_heading_offset_deg = 94.5; +} + + +var _add = func(pos) { + if (_N) { + var (A, S) = courseAndDistance(_user_points.arr[_N - 1], pos); + S *= NM2M; + if (S < _R_turn_min) { + gui.popupTip("Too close to the previous point,\ntry again"); + return; + }else if (S > 10000.0) { + gui.popupTip("Too far from the previous point,\ntry again"); + return; + } + } + _user_points.add(geo.Coord.new(pos)); + + if (_user_point_modes.maxsize == 1 and _user_point_modes.size == 1) { + _user_point_modes.arr[0] = 0; + } else { + _user_point_modes.add(0); + } + setsize(_user_point_models, _N + 1); + _user_point_models[_N] = geo.put_model("Models/Autopush/cursor.xml", pos, 0.0); + _N += 1; + if (_N == 1) { + gui.popupTip("Click waypoints, press \"Done\" to finish"); + } else { + _calculate_route(); + _place_waypoint_models(); + } +} + +var delete_last = func() { + if (_listener == nil) { + return; + } + if (_N > 1) { + _N -= 1; + _user_points.del(_N); + _user_point_modes.del(_N); + _user_point_models[_N].remove(); + _user_point_models[_N] = nil; + setsize(_user_point_models, _N); + _calculate_route(); + _place_waypoint_models(); + } +} + +var _stop = func(fail = 0) { + if (_listener != nil) { + removelistener(_listener); + _listener = nil; + if (!fail) { + settimer(func() { + _finalize_top_view(); + gui.popupTip("Done"); + }, 1.0, 1); + } else { + _finalize_top_view(); + } + } +} + +var _place_user_point_models = func() { + _clear_user_point_models(); + setsize(_user_point_models, _N); + var user_points = _user_points.get_sliced(); + for (var ii = 0; ii < _N; ii += 1) { + var model = "Models/Autopush/cursor.xml"; + if (_user_point_modes.arr[ii] == 1) { + model = "Models/Autopush/cursor_sharp.xml"; + } else if (_user_point_modes.arr[ii] == 2) { + model = "Models/Autopush/cursor_reverse.xml"; + } + _user_point_models[ii] = geo.put_model(model, user_points[ii], 0.0); + } +} + +var _clear_user_point_models = func() { + for (var ii = 0; ii < size(_user_point_models); ii += 1) { + if (_user_point_models[ii] != nil) { + _user_point_models[ii].remove(); + _user_point_models[ii] = nil; + } + } + setsize(_user_point_models, 0); +} + +var _place_waypoint_models = func() { + _clear_waypoint_models(); + setsize(_waypoint_models, size(_route)); + for (var ii = 0; ii < size(_route); ii += 1) { + _waypoint_models[ii] = geo.put_model("Models/Autopush/waypoint.xml", _route[ii], _route_hdg[ii]); + } +} + +var _clear_waypoint_models = func() { + for (var ii = 0; ii < size(_waypoint_models); ii += 1) { + if (_waypoint_models[ii] != nil) { + _waypoint_models[ii].remove(); + _waypoint_models[ii] = nil; + } + } + setsize(_waypoint_models, 0); +} + +var top_view = func() { + if (_view_listener != nil) { + return; + } + _top_view_index = view.indexof("Chase View Without Yaw"); + _reset_view_index = getprop("/sim/current-view/view-number"); + setprop("/sim/current-view/view-number", _top_view_index); + _view_pitch_offset_deg = getprop("/sim/current-view/pitch-offset-deg"); + _view_heading_offset_deg = getprop("/sim/current-view/heading-offset-deg"); + _view_z_offset = getprop("/sim/current-view/z-offset-m"); + setprop("/sim/current-view/z-offset-m", -500.0); + setprop("/sim/current-view/heading-offset-deg", _top_view_heading_offset_deg); + setprop("/sim/current-view/pitch-offset-deg", 90.0); + _view_listener = setlistener("/sim/current-view/name", func { + _finalize_top_view(); + }, 0, 0); +} + +var _finalize_top_view = func() { + if (_view_listener == nil) { + return; + } + removelistener(_view_listener); + _view_listener = nil; + # Go back to the view to restore settings, in case user has switched away. + setprop("/sim/current-view/view-number", _top_view_index); + setprop("/sim/current-view/z-offset-m", _view_z_offset); + setprop("/sim/current-view/heading-offset-deg", _view_heading_offset_deg); + setprop("/sim/current-view/pitch-offset-deg", _view_pitch_offset_deg); + setprop("/sim/current-view/view-number", _reset_view_index); + if (!_show) { + _clear_user_point_models(); + _clear_waypoint_models(); + } +} + +var _calculate_route = func() { + _route = []; + _route_reverse = []; + var user_points = _user_points.get_sliced(); + var route = dynarr.dynarr.new(); + # add the first point cause it will be fix at this pos + route.add(geo.Coord.new(user_points[0])); + n = size(user_points); + var base = 0; + # Detect points where push/pull direction is reversed. + for (var i = 0; i < n; i += 1) { + if (i and (i < n - 1)) { + if((_user_point_modes.arr[i] == 1) or (_user_point_modes.arr[i] == 2)) { + var newmode = 1; + var deltaA = abs(geo.normdeg180(user_points[i - 1].course_to(user_points[i]) - user_points[i].course_to(user_points[i + 1]))); + if (deltaA > 91.0) { + newmode = 2; + } + if(newmode != _user_point_modes.arr[i]){ + _set_userpoint_mode(i, newmode); + } + } + } else { + # Clear reverse for first and last points. + if(_user_point_modes.arr[i] == 2) { + if(_user_point_modes.arr[i] != 1){ + _set_userpoint_mode(i, 1); + } + } + } + } + for (var i = 0; i < n; i += 1) { + if (_user_point_modes.arr[i] or (i == n - 1)) { + if (i - base > 0) { + var bezier = _calculate_bezier(user_points[base:i]); + if (bezier != nil) { + var m = size(bezier); + for (var j = 0; j < m; j += 1) { + route.add(geo.Coord.new(bezier[j])); + } + } + } + base = i; + route.add(geo.Coord.new(user_points[i])); + if (_user_point_modes.arr[i] == 2) { + var route_size = size(route.get_sliced()); + setsize(_route_reverse, route_size); + _route_reverse[route_size - 1] = 1; + } + } + } + var PNumber = size(user_points); + _route = route.get_sliced(); + setsize(_route_reverse, size(_route)); + _check_turn_radius(); + _calculate_hdg(); +} + +var _calculate_bezier = func(user_points) { + var route = dynarr.dynarr.new(); + + var PNumber = size(user_points); + + if (PNumber > 1) { + var pointList = []; + setsize(pointList, PNumber); + for (var i = 0; i < PNumber; i += 1) { + pointList[i] = []; + setsize(pointList[i], PNumber); + } + + pointList[0] = user_points; + + var len = 0; + for (var i = 0; i < PNumber - 1; i += 1) { + len += user_points[i].distance_to(user_points[i + 1]); + } + + if (len < _R_turn_min) { + route.add(geo.Coord.new(user_points[PNumber - 1])) + } else { + var step = _R_turn_min / len; + + for (var i = step; i < 1 - step; i+= step) { + # start iterating from 1 cause we don't need to iterate over Pn + for (var j = 1; j < PNumber; j += 1) { + for (var k = 0; k < PNumber - j; k += 1) { + pointList[j][k] = geo.Coord.new(pointList[j - 1][k]); + var dist = pointList[j - 1][k].distance_to(pointList[j - 1][k + 1]); + var course = pointList[j - 1][k].course_to(pointList[j - 1][k + 1]); + pointList[j][k].apply_course_distance(course, dist * i); + } + } + pointList[PNumber - 1][0].set_alt(geo.elevation(pointList[PNumber - 1][0].lat(),pointList[PNumber - 1][0].lon())); + route.add(geo.Coord.new(pointList[PNumber - 1][0])); + } + } + } + + return route.get_sliced(); +} + +var _calculate_hdg = func() { + _route_hdg = []; + var route_hdg = dynarr.dynarr.new(); + var ilast = size(_route) - 1; + for (i = 0; i < ilast; i += 1) { + var hdg = _route[i].course_to(_route[i + 1]); + route_hdg.add(hdg); + } + # Last heading would be undefined, so just repeat the one before the last. + route_hdg.add(route_hdg.get_sliced()[ilast - 1]); + _route_hdg = route_hdg.get_sliced(); +} + +# Checks each waypoint's turn radius and marks the route invalid if +# it is smaller than the aircraft's turn radius. +var _check_turn_radius = func() { + # A waypoint's turn radius is the radius of a circle circumscribed around the waypoint, previous and next waypoints. + # Formula source: https://math.stackexchange.com/questions/947882/radius-of-circumscribed-circle-of-triangle-as-function-of-the-sides + + var len = size(_route); + _invalid = 0; + + # We can't calculate the radius for the first and last point + for (i = 1; i < len - 2; i += 1) { + # Disable check for push and pull points + if (_route_reverse[i] != 1) { + var a = _route[i].distance_to(_route[i + 1]); + var b = _route[i].distance_to(_route[i - 1]); + var c = _route[i - 1].distance_to(_route[i + 1]); + + + var margin = _R_turn_min / 5000; + + # Stright line check with marging to prevent floating point error + if (a + b + margin >= c and a + b - margin <= c) { + var r = - 1; + } else { + var r = (a * b * c) / math.sqrt( + 2 * a * a * b * b + + 2 * a * a * c * c + + 2 * b * b * c * c + - a * a * a * a + - b * b * b * b + - c * c * c * c + ); + } + + if ((r < _R_turn_min) and (r != -1)) { + _invalid = 1; + } + } + } + + setprop("/sim/model/autopush/route/invalid", _invalid); +} + +setlistener("/sim/model/autopush/route/show", func(p) { + var show = p.getValue(); + if (_listener == nil) { + if (show) { + _place_user_point_models(); + _place_waypoint_models(); + } else { + _clear_user_point_models(); + _clear_waypoint_models(); + } + } + _show = show; +}, 1, 0); + + +var enter = func() { + clear(); + top_view(); + _R_turn_min = getprop("/sim/model/autopush/min-turn-radius-m"); + var wp = geo.aircraft_position(); + var H = geo.elevation(wp.lat(), wp.lon()); + if (H != nil) { + wp.set_alt(H); + } + _add(wp); + _listener = setlistener("/sim/signals/click", func { + _add(geo.click_position()); + }); + # This property can be overridden manually, if needed. + var wingspan = getprop("/sim/model/autopush/route/wingspan-m"); + if ((wingspan == nil) or (wingspan == 0.0)) { + # JSBSim + wingspan = getprop("/fdm/jsbsim/metrics/bw-ft"); + if (wingspan != nil) { + wingspan *= FT2M; + } else { + # YAsim + wingspan = getprop("/fdm/yasim/model/wings/wing/wing-span"); + } + setprop("/sim/model/autopush/route/wingspan-m", wingspan); + } +} + +var _set_userpoint_mode = func(id, mode) { + if (_user_point_modes.arr[id] != mode) { + _user_point_modes.arr[id] = mode; + } + if (_user_point_models[id] != nil) { + _user_point_models[id].remove(); + var model = "Models/Autopush/cursor.xml"; + if (_user_point_modes.arr[id] == 1) { + model = "Models/Autopush/cursor_sharp.xml"; + } else if (_user_point_modes.arr[id] == 2) { + model = "Models/Autopush/cursor_reverse.xml"; + } + _user_point_models[id] = geo.put_model(model, _user_points.get_sliced()[id], 0.0); + } +} + +var toggle_sharp = func() { + if (_listener == nil) { + return; + } + id = _N - 1; + if (_user_point_modes.arr[id]) { + _set_userpoint_mode(id, 0); + } else { + _set_userpoint_mode(id, 1); + } +} + +var done = func() { + _stop(0); +} + +var clear = func() { + autopush_driver.stop(); + _stop(1); + _clear_user_point_models(); + _clear_waypoint_models(); + _N = 0; + _user_points = dynarr.dynarr.new(4); + _user_point_modes = dynarr.dynarr.new(1); +} + +var route = func() { + if (_invalid or (_N < 2)) { + return nil; + } + return _route; +} + +var route_reverse = func() { + if (_invalid or (_N < 2)) { + return nil; + } + return _route_reverse; +} diff --git a/YourAircraftDir/autopush-config.xml.template b/YourAircraftDir/autopush-config.xml.template new file mode 100644 index 0000000..f34540c --- /dev/null +++ b/YourAircraftDir/autopush-config.xml.template @@ -0,0 +1,30 @@ + + + + MULTIPLIER + PITCH + MIN_RADIUS + STOP_DIST + + 1 + + false + 0.0 + 0.5 + 0.15 + 0.25 + 0.1 + 0.0 + 0.0 + + 8.0 + 0.03 + 1.0 + 0.03 + 1.0 + + + + + 0 + diff --git a/YourAircraftDir/gui/dialogs/autopush.xml b/YourAircraftDir/gui/dialogs/autopush.xml new file mode 100644 index 0000000..a069126 --- /dev/null +++ b/YourAircraftDir/gui/dialogs/autopush.xml @@ -0,0 +1,360 @@ + + + + + + + autopush + vbox + + + + hbox + + + + + + + true + + + + + + + + + + + true + vbox + center + top + + + left + + /sim/model/autopush/enabled + true + + dialog-apply + + + + + table + + + 0 + 0 + + left + + + + + + 0 + 2 + -1.0 + 1.0 + /sim/model/autopush/steer-cmd-norm + 0.1 + true + + dialog-apply + + + + + + + + + 1 + 0 + + left + + + + + + 1 + 2 + -25 + 25 + /sim/model/autopush/target-speed-km_h + 1.0 + true + + dialog-apply + + + + + + + + + 1 + 5 + 16 + /sim/model/autopush/target-speed-km_h + %3.0f + true + right + + + + 1 + 6 + + left + + + + + + + + table + + + 0 + 0 + + left + + + + + + + + + + 1 + 0 + + left + + + + + + + + 1 + 3 + left + + /sim/model/autopush/route/show + true + + dialog-apply + + + + + 2 + 0 + + left + + + + + + + + 2 + 3 + left + + true + /sim/model/autopush/route/show-wingtip + + dialog-apply + + + + + + + +