Conversation
Fixed Cruise Attempt AGAIN RPM SLACK
Took Out Mission Gross Mass
…o be loaded into cruise attempt
Changing mass builder so it is actually loaded into cruise attempt
added DV's to mass builder
fixed the mass builder
…ls folder to make code more compact
Mass subsystem options update + renaming files
…nd number_of_ribs
Update fortran_to_aviary for additional GASP datasets
Some tweaks
…target_distance out of general phase info
…44.77209792], time_duration (s) [1845.81876549], Mach 0.07, Aircraft.Battery.MASS (kg) [5.], Aircraft.Engine.Motor.IDLE_CURRENT (A) [3.6], Aircraft.Engine.Motor.MASS (kg) [0.47001241]
| class Averages(om.ExplicitComponent): | ||
| # averages because Aviary objectives must be scalar. not doing this would be preferable | ||
| def initialize(self): | ||
| self.options.declare('num_nodes', types=int) | ||
|
|
||
| def setup(self): | ||
| nn = self.options['num_nodes'] | ||
|
|
||
| self.add_input('CD', shape=nn, units='unitless') | ||
| self.add_input('lifting_surface_CL', shape=nn, units='unitless') | ||
| self.add_output('avg_CD', units='unitless') | ||
| self.add_output('avg_CL', units='unitless') | ||
|
|
||
| def setup_partials(self): | ||
| nn = self.options['num_nodes'] | ||
| self.declare_partials('avg_CD', 'CD', val=np.ones(nn) / nn) | ||
| self.declare_partials('avg_CL', 'lifting_surface_CL', val=np.ones(nn) / nn) | ||
|
|
||
| def compute(self, inputs, outputs): | ||
| total_CD = inputs['CD'] | ||
| outputs['avg_CD'] = np.mean(total_CD) | ||
|
|
||
| total_CL = inputs['lifting_surface_CL'] | ||
| outputs['avg_CL'] = np.mean(total_CL) |
There was a problem hiding this comment.
This component might be unused - if it is used we need to understand why it was added
|
|
||
| add_aviary_output(self, Dynamic.Atmosphere.KINEMATIC_VISCOSITY, shape=nn, units='m**2/s') | ||
|
|
||
| add_aviary_output(self, Dynamic.Atmosphere.DYNAMIC_PRESSURE, shape=nn, units='N/m**2') |
There was a problem hiding this comment.
flight_conditions.py has a component in atmosphere that already provides dynamic viscosity
|
|
||
| add_aviary_input(self, Dynamic.Atmosphere.DYNAMIC_VISCOSITY, shape=nn, units='Pa*s') | ||
|
|
||
| add_aviary_output(self, Dynamic.Atmosphere.KINEMATIC_VISCOSITY, shape=nn, units='m**2/s') |
There was a problem hiding this comment.
We have other places in Aviary where this value is calculated as-needed, perhaps flight_conditions should output it (function of dynamic viscosity and density)
|
|
||
| add_aviary_output(self, Dynamic.Atmosphere.DYNAMIC_PRESSURE, shape=nn, units='N/m**2') | ||
|
|
||
| self.add_output('re', shape=nn, units='1/m') |
There was a problem hiding this comment.
This may be the only required output
| class LiftBalanceComp(om.ExplicitComponent): | ||
| def initialize(self): | ||
| self.options.declare('num_nodes', types=int) | ||
| add_aviary_option(self, Mission.GRAVITY, units='m/s**2') | ||
|
|
||
| def setup(self): | ||
| nn = self.options['num_nodes'] | ||
| add_aviary_input(self, Dynamic.Vehicle.LIFT, shape=nn, units='N') | ||
| add_aviary_input(self, Dynamic.Vehicle.MASS, shape=nn, units='kg') | ||
|
|
||
| # This output will be constrained to zero. | ||
| self.add_output( | ||
| 'lift_balance_residual', | ||
| val=np.zeros(nn), | ||
| units='N', | ||
| desc='Lift equilibrium residual', | ||
| ) | ||
|
|
||
| def setup_partials(self): | ||
| nn = self.options['num_nodes'] | ||
| g = self.options[Mission.GRAVITY][0] # m/s**2 | ||
| rows_cols = np.arange(nn) | ||
| self.declare_partials( | ||
| 'lift_balance_residual', Dynamic.Vehicle.LIFT, rows=rows_cols, cols=rows_cols, val=1.0 | ||
| ) | ||
| self.declare_partials( | ||
| 'lift_balance_residual', Dynamic.Vehicle.MASS, rows=rows_cols, cols=rows_cols, val=-g | ||
| ) | ||
|
|
||
| def compute(self, inputs, outputs): | ||
| L = inputs[Dynamic.Vehicle.LIFT] | ||
| m = inputs[Dynamic.Vehicle.MASS] | ||
| g = self.options[Mission.GRAVITY][0] # m/s**2 | ||
| outputs['lift_balance_residual'] = L - (m * g) |
There was a problem hiding this comment.
This seems like it should be an ODE thing, not inside the aero comp. Might be duplicating a balance which will be a huge problem for EOMs that don't want lift = weight
| AeroConditions(num_nodes=nn), | ||
| promotes_inputs=[ | ||
| Dynamic.Mission.VELOCITY, | ||
| Dynamic.Atmosphere.DENSITY, | ||
| Dynamic.Atmosphere.DYNAMIC_VISCOSITY, | ||
| ], | ||
| promotes_outputs=[ | ||
| 're', | ||
| Dynamic.Atmosphere.KINEMATIC_VISCOSITY, | ||
| Dynamic.Atmosphere.DYNAMIC_PRESSURE, | ||
| ], | ||
| ) | ||
| atmosphere_model = aviary_inputs.get_val(Settings.ATMOSPHERE_MODEL) | ||
|
|
||
| self.add_subsystem( | ||
| 'av_atmosphere', | ||
| AtmosphereComp( | ||
| num_nodes=nn, | ||
| h_def='geometric', | ||
| **{Settings.ATMOSPHERE_MODEL: atmosphere_model}, | ||
| ), | ||
| promotes_inputs=[Dynamic.Mission.ALTITUDE], | ||
| promotes_outputs=[ | ||
| Dynamic.Atmosphere.DENSITY, | ||
| Dynamic.Atmosphere.DYNAMIC_VISCOSITY, | ||
| 'temperature', | ||
| 'speed_of_sound', | ||
| ], | ||
| ) |
There was a problem hiding this comment.
These comps are out of order (and the first component is probably redundant with our existing flight condition comp)
| units='unitless', | ||
| types=str, | ||
| desc='Material density of the bulkhead', | ||
| default_value=[ |
There was a problem hiding this comment.
In general per-rib thickness might be overkill for this fidelity level. Regardless, we should have our default be all of the same value, so default_value is "Balsa".
If we don't have per-rib thickness, then we don't want multivalue=True. If we have per-rib thickness, then we can have the default be just 'Balsa' and multivalue=True, so Aviary is expecting an array like ['Balsa', 'Balsa', ... ]
| SIMPLE: | ||
| Wing is made of solid foam and two hollow spars | ||
| MEDIUM: | ||
| Wing design includes spars, sheeting, stringers, ribs, and is hollow |
There was a problem hiding this comment.
Genericize to "SOLID" and "HOLLOW"?
That way we aren't assuming DBF-style construction with foam and/or wood, so it is more obvious it can be used for other drones (metal, fiberglass, etc.)
There was a problem hiding this comment.
There aren't mass components but rather input files for a specific aircraft (basically they belong with the aircraft model alongside a csv & phase info rather than here)
Summary
Incorporating a small UAV aircraft example into aviary.
TODO:
Change the overall architecture of the UAV model to be more Aviary esque including
Breakup the propulsion system into Motor + ESC
Break out the propellar to its own separate subsystem
connect the two using the standard systems already existing in aviary
rememove the balance comp from propulsion (it's probably redundant with whats already there in core avliary)
add a separate subsystem for the battery or remove it all together
break out the OAS model into it's own separate thing so it's not mixed in with low fidility CL/CD calcs from the UAV
potentially ad reynolds number to atmospheric calculation and reorganize UAV atmosphere calcs because they are some what redundant with aviary core and potentiall output values that are unused elsewhere.
remove unused average CL/CD calculations, they are not used in other locations
have to change how the airfoil CSV is read in, this is probably for the propellar (not the wing). notes in test_cruse.py indicate: NOTE: no @use_tempdirs here. DBFMassBuilder reads its airfoil CSV via a repo-root- relative path (like the dbf_based_mass unit tests), so this must run from the repo root.need to have docs that describe mass builder, aero-builder (simple and medium)
docs need to cover why ribs are specified as ribs = np.array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2]) each array element represents one of 20 ribs along the aircraft, and the number determines which material/thickness that rib will have. So a '0' element will be 0.0016 Balsa; '1' will be 0.0016 Ply; '2' will be 0.0024 Ply.
check partials for aero_model.py and aero_OAS_examples.pymany overall tests i.e. test_cruse.py are missing asserts.
some tests create new phase infos which is probably unneeded.
Some variables are declared in UAV_variable_meta_data.py but unused in the codebase-- Aircraft.Fuselage.BULKHEAD_DENSITY
-- Aircraft.Fuselage.NUM_BULKHEADS
-- Aircraft.HorizontalTail.NUM_RIBS
-- Aircraft.HorizontalTail.RIB_DENSITY
-- Aircraft.VerticalTail.NUM_RIBS
-- Aircraft.VerticalTail.RIB_DENSITY
-- Aircraft.Wing.NUM_RIBS
-- Aircraft.Wing.RIB_DENSITY
-- Dynamic.Vehicle.Propulsion.CURRENT_MAX
-- Dynamic.Vehicle.Propulsion.RPM_MAX
-- Dynamic.Vehicle.Propulsion.PROP_POWER_MAX
Do we need an RPM_MAX assessment to keep the prop map working well
Related Issues
Backwards incompatibilities
None
AI Usage
Disclose any AI usage in this PR, including models used and files affected.