Source code for RCAIDE.Vehicle

# Vehicle.py
# 
# Created:  Apr 2024, M. Clarke
# Modified:  
 
# ----------------------------------------------------------------------------------------------------------------------
#  IMPORT
# ----------------------------------------------------------------------------------------------------------------------
 
from RCAIDE                    import Framework
from RCAIDE.Framework.Core     import Data, DataOrdered
from RCAIDE.Library            import Components
import numpy as np 

# ----------------------------------------------------------------------------------------------------------------------
#  Vehicle
# ----------------------------------------------------------------------------------------------------------------------  
[docs] class Vehicle(Data): """ RCAIDE Vehicle container class with database and input/output functionality. Attributes ---------- Data: Data RCAIDE data structure containing the loaded information. See defualts for more information. Notes ----- The Vehicle class serves as the top-level container for all aircraft components and systems. It provides methods for adding components to the appropriate containers and maintains the hierarchical structure of the aircraft model. The class uses a component mapping system to automatically place new components in their appropriate containers based on their type. **Definitions** 'Component Root Map' Internal mapping that associates component types with their container locations 'Energy Network Root Map' Internal mapping that associates energy network types with their container locations """ def __defaults__(self): """This sets the default values. Assumptions: None Source: None """ self.tag = 'vehicle' self.networks = Framework.Networks.Network.Container() self.fuselages = Components.Fuselages.Fuselage.Container() self.wings = Components.Wings.Wing.Container() self.nacelles = Components.Nacelles.Nacelle.Container() self.systems = Components.Powertrain.Systems.System() self.avionics = Components.Powertrain.Systems.Avionics() self.booms = Components.Booms.Boom.Container() self.mass_properties = Vehicle_Mass_Container() self.payload = Components.Payloads.Payload.Container() self.costs = Data() self.landing_gears = Components.Landing_Gear.Landing_Gear.Container() self.reference_area = 0.0 self.passengers = 0.0 self.maximum_cross_sectional_area = 0.0 self.flight_envelope = Data() self.flight_envelope.design_dynamic_pressure = None self.flight_envelope.design_mach_number = None self.flight_envelope.design_cruise_altitude = None self.flight_envelope.design_range = None self.flight_envelope.ultimate_load = 5.7 self.flight_envelope.positive_limit_load = 3.8 self.flight_envelope.negative_limit_load = -1.5 self.flight_envelope.alpha_maximum = 0.0 self.flight_envelope.category = None self.flight_envelope.FAR_part_number = None self.flight_envelope.alt_vc = 0.0 self.flight_envelope.alt_gust = 0.0 self.flight_envelope.max_ceiling = 0.0 self.flight_envelope.maximum_dynamic_pressure = 0.0 self.flight_envelope.maximum_mach_operational = 0.0 self.flight_envelope.maximum_lift_coefficient = None self.flight_envelope.minimum_lift_coefficient = None self.flight_envelope.maneuver = Data() self.flight_envelope.maneuver.load_alleviation_factor = 0.0 self.flight_envelope.maneuver.equivalent_speed = Data() self.flight_envelope.maneuver.equivalent_speed.velocity_max_gust = 0 self.flight_envelope.maneuver.equivalent_speed.velocity_max_cruise = 0 self.flight_envelope.maneuver.equivalent_speed.velocity_max_dive = 0 self.flight_envelope.maneuver.load_factor = Data() self.flight_envelope.maneuver.load_factor.velocity_max_gust = 0 self.flight_envelope.maneuver.load_factor.velocity_max_cruise = 0 self.flight_envelope.maneuver.load_factor.velocity_max_dive = 0 self.flight_envelope.gust = Data() self.flight_envelope.gust.load_alleviation_factor = 0.0 self.flight_envelope.gust.equivalent_speed = Data() self.flight_envelope.gust.equivalent_speed.velocity_max_gust = 0 self.flight_envelope.gust.equivalent_speed.velocity_max_cruise = 0 self.flight_envelope.gust.equivalent_speed.velocity_max_dive = 0 self.flight_envelope.gust.load_factor = Data() self.flight_envelope.gust.load_factor.velocity_max_gust = 0 self.flight_envelope.gust.load_factor.velocity_max_cruise = 0 self.flight_envelope.gust.load_factor.velocity_max_dive = 0 self.performance = DataOrdered() _energy_network_root_map = None
[docs] def __init__(self,*args,**kwarg): """ Sets up the component hierarchy for a vehicle Assumptions: None Source: N/A Inputs: None Outputs: None Properties Used: None """ # will set defaults super(Vehicle,self).__init__(*args,**kwarg) self._component_root_map = { Components.Fuselages.Fuselage : self['fuselages'] , Components.Wings.Wing : self['wings'] , Components.Powertrain.Systems.System : self['systems'] , Components.Powertrain.Systems.Avionics : self['avionics'] , Components.Payloads.Payload : self['payload'] , Components.Nacelles.Nacelle : self['nacelles'] , Components.Booms.Boom : self['booms'] , Components.Landing_Gear.Landing_Gear : self['landing_gears'] , Vehicle_Mass_Properties : self['mass_properties'] , } self._energy_network_root_map= { Framework.Networks.Network : self['networks'] , } self.append_component(Vehicle_Mass_Properties()) return
[docs] def find_component_root(self,component): """ find pointer to component data root. Assumptions: None Source: N/A Inputs: None Outputs: None Properties Used: None """ # find component root by type, allow subclasses for component_type, component_root in self._component_root_map.items(): if isinstance(component,component_type): break else: raise Exception("Unable to place component type %s" % component.typestring()) return component_root
[docs] def append_component(self,component): """ Adds a component to vehicle Assumptions: None Source: None """ # assert database type if not isinstance(component,Data): raise Exception('input component must be of type Data()') # find the place to store data component_root = self.find_component_root(component) # See if the component exists, if it does modify the name keys = component_root.keys() if str.lower(component.tag) in keys: string_of_keys = "".join(component_root.keys()) n_comps = string_of_keys.count(component.tag) component.tag = component.tag + str(n_comps+1) # store data component_root.append(component) return
[docs] def append_energy_network(self,energy_network): """ Adds an energy network to vehicle Assumptions: None Source: None """ # assert database type if not isinstance(energy_network,Data): raise Exception('input energy network must be of type Data()') # find the place to store data energy_network_root = self.find_energy_network_root(energy_network) # See if the energy network exists, if it does modify the name keys = energy_network_root.keys() if str.lower(energy_network.tag) in keys: string_of_keys = "".join(energy_network_root.keys()) n_comps = string_of_keys.count(energy_network.tag) energy_network.tag = energy_network.tag + str(n_comps+1) # store data energy_network_root.append(energy_network) return
[docs] def find_energy_network_root(self,energy_network): """ Find pointer to energy network data root. Assumptions: None Source: None """ # find energy network root by type, allow subclasses for energy_network_type, energy_network_root in self._energy_network_root_map.items(): if isinstance(energy_network,energy_network_type): break else: raise Exception("Unable to place energy_network type %s" % energy_network.typestring()) return energy_network_root
[docs] class Vehicle_Mass_Properties(Components.Mass_Properties): """ The vehicle's mass properties. Assumptions: None Source: None """ def __defaults__(self): """This sets the default values. Assumptions: None Source: None """ self.tag = 'mass_properties' self.operating_empty = 0.0 self.max_takeoff = 0.0 self.takeoff = 0.0 self.max_landing = 0.0 self.landing = 0.0 self.max_cargo = 0.0 self.cargo = 0.0 self.max_payload = 0.0 self.payload = 0.0 self.passenger = 0.0 self.crew = 0.0 self.max_fuel = 0.0 self.fuel = 0.0 self.max_zero_fuel = 0.0 self.center_of_gravity = [[0.0,0.0,0.0]] self.zero_fuel_center_of_gravity = np.array([[0.0,0.0,0.0]])
[docs] class Vehicle_Mass_Container(Components.Component.Container,Vehicle_Mass_Properties):
[docs] def append(self,value,key=None): """ Appends the vehicle mass, but only let's one ever exist. Keeps the newest one Assumptions: None Source: None """ self.clear() for key in value.keys(): self[key] = value[key]