diff --git a/README.md b/README.md index 4775e16..0f1ad3e 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,20 @@ -# fgscenery-tools -Tools for creating, managing and editing FlightGear scenery +# fgtools +Tools for creating, managing and editing FlightGear scenery, aircraft, … + +## Installation +To run these scripts you need Python 3, Python 2 won't work. Recommended version is 3.8 as I only have that installed so couldn't test with any other versions - earlier 3.x versions should work, but no guarantee ! + +### Linux +Download / `git clone` this repo and put it in a place of your choice, say `/home/user/fgtools`. With `git clone`, you would use this command: +```sh +/home/user$ git clone https://github.com/TheFGFSEagle/fgtools +``` +Before you run the scripts you have to make sure that the folder containing this repository on your local disk (here `/home/user`) is inside your `PYTHONPATH` environment variable, or you must run the scripts from inside the `fgtools` folder. To add the folder to your `PYTHONPATH`, use this command: +```sh +export PYTHONPATH="${PYTHONPATH}:/home/user" +``` +Note: this is lost when you close the terminal / console, so you have to run this command every time you open a new console and run the scripts from it. To make the change persistent, add the command to the end of the `.profile` file in your home folder. + +### Windows +_I don't have Windows so cannot provide any instructions - contributions by Windows users welcome !_ + diff --git a/__init__.py b/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/aircraft/javaprop2jsbcpct.py b/aircraft/javaprop2jsbcpct.py index 65371f5..3cef063 100755 --- a/aircraft/javaprop2jsbcpct.py +++ b/aircraft/javaprop2jsbcpct.py @@ -3,24 +3,51 @@ import argparse import os +from fgtools.utils.interpolator import Interpolator + def parse_data_files(input_files, blade_angles): blade_angles = list(map(float, blade_angles)) data = {} for file, angle in zip(input_files, blade_angles): + data[angle] = { + "Cp": Interpolator(), + "Ct": Interpolator() + } with open(file) as f: content = f.readlines() content = list(map(lambda s: s.strip().split("\t"), content))[2:] - data[angle] = {} for line in content: - data[angle][float(line[0])] = {"Ct": float(line[2]), "Cp": float(line[3])} + av, cp, ct = float(line[0]), float(line[2]), float(line[3]) + data[angle]["Cp"].add_value(av, cp) + data[angle]["Ct"].add_value(av, ct) return data +def make_tables(data, maximum, indentation="\t", resolution=0.05): + Cp = Ct = indentation * 4 + (indentation * 2).join(map(str, data)) + "\n" + av = 0 + while av <= maximum: + av = round(av, 6) + Cp += indentation * 2 + indentation + str(av) + indentation + Ct += indentation * 2 + indentation + str(av) + indentation + cps = [] + cts = [] + for angle in data: + cps.append("%.6f" % round(data[angle]["Cp"].interpolate(av, sort=False), 6)) + cts.append("%.6f" % round(data[angle]["Ct"].interpolate(av, sort=False), 6)) + + Cp += indentation.join(cps) + "\n" + Ct += indentation.join(cts) + "\n" + av += resolution + return {"Cp":Cp, "Ct": Ct} + + + if __name__ == "__main__": - argp = argparse.ArgumentParser(description="javaprop2jsbcpct.py - converts JavaProp propeller data into Cp and Ct tables for a JSBsim propelller") + argp = argparse.ArgumentParser(description="javaprop2jsbcpct.py - converts JavaProp propeller data into Cp and Ct tables for a JSBsim propeller") argp.add_argument( "-i", "--input-file", @@ -38,6 +65,13 @@ if __name__ == "__main__": dest="blade_angles" ) + argp.add_argument( + "-m", "--max", + help="Maximum advance ratio to output data for", + required=True, + type=float + ) + argp.add_argument( "--interactive", action="store_true", @@ -50,6 +84,13 @@ if __name__ == "__main__": default="\t" ) + argp.add_argument( + "-r", "--resolution", + help="Advance ratio resolution to generate (default: 0.05)", + type=float, + default=0.05 + ) + args = argp.parse_args() for path in args.input_files: @@ -60,8 +101,22 @@ if __name__ == "__main__": if len(args.blade_angles) < len(args.input_files): print("Error: less blade angles than input files") elif len(args.blade_angles) > len(args.input_files): - args.blade_angles, rest = args.blade_angles[:len(args.input_files)] + args.blade_angles, rest = args.blade_angles[:len(args.input_files) + 1] print(f"Warning: skipping {len(rest)} blade angles because no corresponding data file was specified") data = parse_data_files(args.input_files, args.blade_angles) + output = make_tables(data, args.max, args.indentation, args.resolution) + + + print(args.indentation + "