Skip to content

UAV Work from 2026 Summer Interns - #1267

Draft
ehariton wants to merge 236 commits into
OpenMDAO:mainfrom
ehariton:UAVmain
Draft

UAV Work from 2026 Summer Interns#1267
ehariton wants to merge 236 commits into
OpenMDAO:mainfrom
ehariton:UAVmain

Conversation

@ehariton

Copy link
Copy Markdown
Contributor

Summary

Incorporating a small UAV aircraft example into aviary.

Related Issues

  • Resolves #

Backwards incompatibilities

None

AI Usage

Disclose any AI usage in this PR, including models used and files affected.

Marinelli and others added 30 commits June 22, 2026 09:41
…files, and examples. Added dbf variables into variables.py and variable_metadata.py
Untracked from git (files kept on disk).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
creating dbf mass external subsystem
Cleanup of some lines of code not needed.
…26-UAV-Aviary into new_aviary_prop2_work

Mergerd mission and Premission# the commit.
Propulsion Mission and Premission Merged, still need mass subsystem. All tests run except cruise attempt, still needs debugging
Implementing an option for 'simple' vs 'medium' wing design and organizing option-focused files into a folder

cruise_phase.add_objective('distance', loc='final', ref=-1000.0, units='m')

prob.add_driver('SNOPT', use_coloring=True, max_iter=100)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I had originally commented out all the IPOPT options because I was testing with SNOPT, but these should be reverted.


prob.run_aviary_problem(run_driver=True, simulate=True)

"""Debug Print"""

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think all this debug print can be nuked.

@@ -0,0 +1,126 @@
import numpy as np

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we need these plots? Is the regular aviary output not good enough?

self.assertIn(Dynamic.Mission.VELOCITY, mission_inputs)
self.assertIn('alpha', mission_inputs)

# These commented values are not in mission inputs/outputs

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why are these values commented out? If we don't need them nuke them.

# DEBUGGING BEFORE RUNNING THE MODEL
# =========================================================

if DEBUG_MODEL:

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we should include any of this dibugging code


return x_normalized, y_normalized

def load_airfoil_if_needed(comp, Part):

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we really need this function as opposed to just saying the user must load an airfoil before calling a specific openmdao component?

comp.rho_rib = np.array([materials.get_item(m)[0] for m in rib_materials])

rib_thickness, _ = comp.options[Part.RIB_THICKNESS]
if len(rib_materials) != len(rib_thickness):

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This check can be moved into the individual compute_primals() of the functions that need to be checked.

wetted_area = span * chord
type = self.options[Aircraft.Wing.TYPE]

if type == WingType.SIMPLE:

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Inputs for simple wing vs. medium wing should be detailed to the user in docs

'fuselage', fm, promotes_inputs=['*'], promotes_outputs=['*']
)

ribs = np.array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2])

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what does this actually mean? how does this translate into a physical aircraft attributes?


#Rib definitions
ribs = np.array([0] * 15 + [1] * 5)
rib_materials = ['Balsa'] * 15 + ['Ply'] * 5

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where can the user learn about the different materaisl they can select here>?

@@ -0,0 +1,125 @@
import numpy as np

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Check with Jason if we want to keep this function around, otherwise it's not actually used by any of the other functions in the repo.

'lower': 0.1,
'upper': 2.0,
},
# Aircraft.Fuselage.WETTED_AREA: {

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If these are not design values we should probably remove them!

# TODO: reading in of data should be changed later:
from aviary.models.external_subsystems.UAV.propulsion.Parsing.PropDataReader import PropDataReader

xt, ct, cp = PropDataReader()

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why is this happening here rather than in init() ?

],
promotes_outputs=[('kv', Aircraft.Engine.Motor.KV)],
)
# commented out for now, may add back in later

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove this if not used.

@@ -0,0 +1,163 @@
import numpy as np

@ehariton ehariton Aug 20, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This file is not used anywhere. Why is it here??
If this is here to help create prop tables, then that needs to be stated somewhere and example usage given.

import os


def PropDataReader():

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This function isn't actually used in a component!


prob.build_model()

prob.add_driver('IPOPT', use_coloring=False, max_iter=15)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Flip this back to just an IPOPT test, no need for SNOPT


prob.setup()

# use to see all the constraints in the problem

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For the actual commit these notes should be removed.

def test_subsystems_in_cruise_attempt(self):
prob = CruiseExample()

# TODO: turn these back into assert_near_equal checks once the example values are confirmed.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add assert tests back in here.

return prob


# NOTE: no @use_tempdirs here. DBFMassBuilder reads its airfoil CSV via a repo-root-

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what is going on here? why do we need to be in root? sounds like this is a workaround for something that should have been fixed elsewhere.



class TestBattery(unittest.TestCase):
@use_tempdirs

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think @use_tempdirs can be moved one level down before the class and then you only need to instantiate it once for all the tests



class TestUAVMission(unittest.TestCase):
@use_tempdirs

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

move @use_temdirs down



class TestUAVPreMission(unittest.TestCase):
@use_tempdirs

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

move @use_tempdirs down



class UAVBuilder(EngineModel):
# UAVPropMission computes its own max-power chain (battery_max ... prop_max),

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

does it actually still do this? or are these comments based on old implementation?

types=float,
desc='Thickness of a single rib',
default_value=[
0.003175,

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we need some explanation of why these are arrays.

# ========================================================

av.add_meta_data(
Aircraft.Fuselage.AREAL_SKIN_DENSITY,

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need to confirm that each of these new meta data entries is actually used

types=WingType,
)

##### RC Variables #####

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what does RC mean? Why are these RC variables?

rib_materials = self.options[Aircraft.HorizontalTail.RIB_MATERIALS]
misc_mass, units = self.options[Aircraft.HorizontalTail.MISC_MASS]

load_airfoil_if_needed(self, Aircraft.HorizontalTail)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. This should be moved out of compute_primal, and into setup.
  2. This method computes self. rho_rib and self.n_area, but rho_rib is never used for any calculation, and can probably be removed.
  3. self.n_area is a static variable, and needs to be specified in get_self_statics.

'user_options': {
'num_segments': 5,
'order': 3,
'mach_optimize': False,

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Descent phase values (mach=.72, alt=34000 ft) probably still come from one of the transport aircraft.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants