STAR
Cal STAR — firmware, DAQ server, and engine design
Loading...
Searching...
No Matches
cli.py
Go to the documentation of this file.
1"""
2Command-line interface for csv_to_eng.
3"""
4
5from __future__ import annotations
6
7import argparse
8import sys
9from pathlib import Path
10
11from .core import convert
12
13
14def main(argv: list[str] | None = None) -> int:
15 """
16 Main CLI entrypoint.
17
18 Args:
19 argv: Command line arguments (defaults to sys.argv[1:])
20
21 Returns:
22 Exit code (0 for success, non-zero for error)
23 """
24 parser = argparse.ArgumentParser(
25 prog="csv_to_eng",
26 description="Convert CSV thrust curve data to RASP .eng engine file format.",
27 formatter_class=argparse.RawDescriptionHelpFormatter,
28 epilog="""
29Examples:
30 # Basic conversion:
31 python -m csv_to_eng --input curve.csv --output motor.eng
32
33 # With metadata overrides:
34 python -m csv_to_eng --input curve.csv --output motor.eng \\
35 --name "K1000" --diameter-mm 54 --length-mm 326 \\
36 --manufacturer "Acme Rocketry"
37
38 # Specify units explicitly:
39 python -m csv_to_eng --input curve.csv --output motor.eng \\
40 --thrust-units lbf --time-units ms
41 """,
42 )
43
44 # Required arguments
45 parser.add_argument(
46 "-i", "--input",
47 required=True,
48 type=Path,
49 metavar="CSV",
50 help="Input CSV file containing thrust curve data",
51 )
52 parser.add_argument(
53 "-o", "--output",
54 required=True,
55 type=Path,
56 metavar="ENG",
57 help="Output .eng file path",
58 )
59
60 # Metadata overrides
61 metadata_group = parser.add_argument_group("Metadata Overrides")
62 metadata_group.add_argument(
63 "--name",
64 type=str,
65 metavar="NAME",
66 help="Engine name (e.g., 'K1000')",
67 )
68 metadata_group.add_argument(
69 "--diameter-mm",
70 type=float,
71 metavar="MM",
72 help="Engine diameter in millimeters",
73 )
74 metadata_group.add_argument(
75 "--length-mm",
76 type=float,
77 metavar="MM",
78 help="Engine length in millimeters",
79 )
80 metadata_group.add_argument(
81 "--prop-mass-kg",
82 type=float,
83 metavar="KG",
84 help="Propellant mass in kilograms",
85 )
86 metadata_group.add_argument(
87 "--total-mass-kg",
88 type=float,
89 metavar="KG",
90 help="Total loaded mass in kilograms",
91 )
92 metadata_group.add_argument(
93 "--manufacturer",
94 type=str,
95 metavar="MFR",
96 help="Manufacturer name",
97 )
98 metadata_group.add_argument(
99 "--delays",
100 type=str,
101 metavar="DELAYS",
102 help="Delay charges (e.g., '6-10-14' or 'P' for plugged)",
103 )
104
105 # Unit specifications
106 units_group = parser.add_argument_group("Unit Specifications")
107 units_group.add_argument(
108 "--thrust-units",
109 type=str,
110 choices=["N", "lbf"],
111 metavar="{N,lbf}",
112 help="Thrust units in input CSV (default: auto-detect, fallback N)",
113 )
114 units_group.add_argument(
115 "--time-units",
116 type=str,
117 choices=["s", "ms"],
118 metavar="{s,ms}",
119 help="Time units in input CSV (default: auto-detect, fallback s)",
120 )
121
122 # Format options
123 format_group = parser.add_argument_group("Format Options")
124 format_group.add_argument(
125 "--format",
126 type=str,
127 choices=["rasp"],
128 default="rasp",
129 metavar="{rasp}",
130 help="Output format (default: rasp)",
131 )
132 format_group.add_argument(
133 "--time-decimals",
134 type=int,
135 default=3,
136 metavar="N",
137 help="Decimal places for time values (default: 3)",
138 )
139 format_group.add_argument(
140 "--thrust-decimals",
141 type=int,
142 default=1,
143 metavar="N",
144 help="Decimal places for thrust values (default: 1)",
145 )
146 format_group.add_argument(
147 "--header-mode",
148 type=str,
149 choices=["auto", "none", "row0_json"],
150 default="auto",
151 metavar="{auto,none,row0_json}",
152 help="Header detection mode (default: auto)",
153 )
154
155 args = parser.parse_args(argv)
156
157 # Validate input file exists
158 if not args.input.exists():
159 print(f"Error: Input file not found: {args.input}", file=sys.stderr)
160 return 1
161
162 # Perform conversion
163 try:
164 convert(
165 csv_path=args.input,
166 eng_path=args.output,
167 name=args.name,
168 diameter_mm=args.diameter_mm,
169 length_mm=args.length_mm,
170 delays=args.delays,
171 prop_mass_kg=args.prop_mass_kg,
172 total_mass_kg=args.total_mass_kg,
173 manufacturer=args.manufacturer,
174 time_units=args.time_units,
175 thrust_units=args.thrust_units,
176 time_decimals=args.time_decimals,
177 thrust_decimals=args.thrust_decimals,
178 )
179
180 print(f"Successfully converted: {args.input} -> {args.output}")
181 return 0
182
183 except FileNotFoundError as e:
184 print(f"Error: {e}", file=sys.stderr)
185 return 1
186 except ValueError as e:
187 print(f"Error: Invalid data - {e}", file=sys.stderr)
188 return 1
189 except Exception as e:
190 print(f"Error: Unexpected error - {e}", file=sys.stderr)
191 return 1
192
193
194if __name__ == "__main__":
195 sys.exit(main())
json_pointer< string_t > convert() const &
Definition json.hpp:14640
int main()