Ejemplo n.º 1
0
 def __init__(self):
     
     """ DEBUG """
     self.DEBUG = False
     
     if self.DEBUG: print '*** Mission Initialization ***'
     #  initialize a ntr for the mission
     from spaceobjects import NTR
     import solarsystem_objects_parameters as ss
     
     #  initializae an ntr spacecraft
     self.ntr = NTR()
     if self.DEBUG: print self.ntr.mass
     #  set the equations of motion of the ntr to 'S2B'
     #+ for shooting methods
     self.ntr.eom = 'S2B'
     
     #  initialize global parameters
     #  set the generic global decision vector for the mission
     #+ and call the global optimizer setup
     #  the entries of global_decision_vector correspond with
     #  [0]: mission type
     #  [1]: launch vehicle
     #  [2]: payload fairing
     self.set_global_decisions([1, 0, 0])
     
     #  initialize local parameters
     #  set the ntr to have initial conditions of a
     #+ generic 'NSO' Nuclear Safe Orbit
     self.nso_altitude = 1200.0
     self.ntr.set_sma(ss.earth['Radius'] + self.nso_altitude)
     #  set the thrust level of the ntr core
     self.ntr.core.thrust = 25000.0
     self.ntr.core.set_thrust_derived_properties()
     if self.DEBUG: print self.ntr.mass
     #  set a generic local decision vector for the mission
     self.local_decision_vector = [self.nso_altitude, self.ntr.core.thrust]
     
     #  set a generic target for the mission
     self.set_target()
     
     #  initialize a dictionary for storing relevant history information
     self.history = {}
     self.history['burnmass'] = []
Ejemplo n.º 2
0
class Mission:
    'Mission class documentation string'

    #  initialization method
    def __init__(self):
        
        """ DEBUG """
        self.DEBUG = False
        
        if self.DEBUG: print '*** Mission Initialization ***'
        #  initialize a ntr for the mission
        from spaceobjects import NTR
        import solarsystem_objects_parameters as ss
        
        #  initializae an ntr spacecraft
        self.ntr = NTR()
        if self.DEBUG: print self.ntr.mass
        #  set the equations of motion of the ntr to 'S2B'
        #+ for shooting methods
        self.ntr.eom = 'S2B'
        
        #  initialize global parameters
        #  set the generic global decision vector for the mission
        #+ and call the global optimizer setup
        #  the entries of global_decision_vector correspond with
        #  [0]: mission type
        #  [1]: launch vehicle
        #  [2]: payload fairing
        self.set_global_decisions([1, 0, 0])
        
        #  initialize local parameters
        #  set the ntr to have initial conditions of a
        #+ generic 'NSO' Nuclear Safe Orbit
        self.nso_altitude = 1200.0
        self.ntr.set_sma(ss.earth['Radius'] + self.nso_altitude)
        #  set the thrust level of the ntr core
        self.ntr.core.thrust = 25000.0
        self.ntr.core.set_thrust_derived_properties()
        if self.DEBUG: print self.ntr.mass
        #  set a generic local decision vector for the mission
        self.local_decision_vector = [self.nso_altitude, self.ntr.core.thrust]
        
        #  set a generic target for the mission
        self.set_target()
        
        #  initialize a dictionary for storing relevant history information
        self.history = {}
        self.history['burnmass'] = []
    
    
    
    #  method for setting the payload
    def set_payload(self, name, mass, height, radius):
        #  set attributes for the payload
        self.payload_name   = name
        self.payload_mass   = mass
        self.payload_height = height
        self.payload_radius = radius
        #  add the payload mass to the spacecraft
        self.ntr.add_payload_mass(self.payload_mass)



    #  method for setting the specified target
    def set_target(self):
        #  initialize a mission target
        from spaceobjects import SpaceCraft
        self.target = SpaceCraft()
        self.target.set_sma(42000.0)
        self.target.set_i(0.0, 'Degrees')
        self.target.set_f(180.0, 'Degrees')


       
    #  method for setting global optimization variables
    def set_global_decisions(self,
                             global_decision_vector = None,
                             mission_type = None,          # (integer)   [0, 4]
                             launch_vehicle = None,        # (integer)   [0, 15]
                             payload_fairing = None):      # (integer)   [0, 3]
        #  set the global decision vector if given as an argument
        if global_decision_vector != None:
            self.global_decision_vector = global_decision_vector
        #  set the global decision vector elements
        if mission_type    == None:
            mission_type    = self.global_decision_vector[0]
        if launch_vehicle  == None:
            launch_vehicle  = self.global_decision_vector[1]
        if payload_fairing == None:
            payload_fairing = self.global_decision_vector[2]
        #  convert mission type identifier to string
        if   mission_type == 0: self.mission_type = 'gto payload release, ' \
                                                    'gto tank release'
        elif mission_type == 1: self.mission_type = 'gto payload release, ' \
                                                    'nso tank release'
        elif mission_type == 2: self.mission_type = 'geo payload release, ' \
                                                    'geo tank release'
        elif mission_type == 3: self.mission_type = 'geo payload release, ' \
                                                    'gto tank release'
        elif mission_type == 4: self.mission_type = 'geo payload release, ' \
                                                    'nso tank release'
        #  convert launch vehicle integer identifier to string
        if   launch_vehicle ==  0: self.launch_vehicle = 'AtlasV501'
        elif launch_vehicle ==  1: self.launch_vehicle = 'AtlasV511'
        elif launch_vehicle ==  2: self.launch_vehicle = 'AtlasV521'
        elif launch_vehicle ==  3: self.launch_vehicle = 'AtlasV531'
        elif launch_vehicle ==  4: self.launch_vehicle = 'AtlasV541'
        elif launch_vehicle ==  5: self.launch_vehicle = 'AtlasV701'
        elif launch_vehicle ==  6: self.launch_vehicle = 'AtlasV711'
        elif launch_vehicle ==  7: self.launch_vehicle = 'AtlasV721'
        elif launch_vehicle ==  8: self.launch_vehicle = 'AtlasV731'
        elif launch_vehicle ==  9: self.launch_vehicle = 'DeltaIVM42E'
        elif launch_vehicle == 10: self.launch_vehicle = 'DeltaIVM52E'
        elif launch_vehicle == 11: self.launch_vehicle = 'DeltaIVM54E'
        elif launch_vehicle == 12: self.launch_vehicle = 'Falcon9'
        elif launch_vehicle == 13: self.launch_vehicle = 'ArianeVECA'
        elif launch_vehicle == 14: self.launch_vehicle = 'ProtonM'
        elif launch_vehicle == 15: self.launch_vehicle = 'DeltaIVH'
        #  set the payload fairing type
        #  some launch vehicles only have 1 choice for payload fairings,
        #+ others have up to 4
        self.payload_fairing = payload_fairing
        pass
    
    
    
    #  method for setting local optimization variables
    def set_local_decisions(self,
                            local_decision_vector = None,
                            nso_altitude = None,
                            core_thrust  = None,
                            permanent_tank_fuel = None,
                            mission_tank_fuel = None,
                            mission_tank_radius = None):
        #  set the local decision vector if given as an argument
        if local_decision_vector != None:
            self.local_decision_vector = local_decision_vector
        
        #  import statement
        import solarsystem_objects_parameters as ss
        #  set the nso altitude
        if nso_altitude == None: self.nso_altitude = self.local_decision_vector[0]
        else: self.nso_altitude = nso_altitude
        #  set sma
        self.ntr.set_sma(ss.earth['Radius'] + self.nso_altitude)
        
        #  set the core thrust and derived parameters
        if core_thrust == None: self.ntr.core.thrust = self.local_decision_vector[1]
        else: self.ntr.core.thrust = core_thrust
        #  update relevant ntr attributes
        self.ntr.core.set_thrust_derived_properties()

        #  add the permanent tank
        self.ntr.add_tank()
        if permanent_tank_fuel == None:
            self.ntr.tank[0].add_fuel(self.local_decision_vector[2])
            self.ntr.tank[0].tank_size(-1, 5, geometry = 'spherical')
        else:
            self.ntr.tank[0].add_fuel(permanent_tank_fuel)
            self.ntr.tank[0].tank_size(-1, 5, geometry = 'spherical')

        #  add the mission tank
        self.ntr.add_tank()
        if permanent_tank_fuel == None:
            self.ntr.tank[1].add_fuel(self.local_decision_vector[3])
            self.ntr.tank[1].tank_size(self.local_decision_vector[4], 5)
        else:
            self.ntr.tank[1].add_fuel(mission_tank_fuel)
            self.ntr.tank[1].tank_size(mission_tank_radius, 5)





    #  method call for global optimization
    def global_optimization(self, decision_vector = None):
        #  setup the global parameters if a decision vector is given
        if decision_vector != None:
            self.set_global_decisions(decision_vector)
        #  call the local optimizer
        self.local_optimization()



    #  method call for local optimization
    def local_optimization(self):
        """ Inner-Loop Optimization Call Here """
        #  import scipy.optimize module
        from scipy.optimize import minimize
        from scipy.optimize import fmin_l_bfgs_b
        from numpy import array
        #  the decision_vector that scipy.optimize OR equivalent can modify
        #  nso_alititude:   (real)      [400, 2000]     (km)    ic: 1200
        #  core_thrust:     (real)      [5000, 25000]   (lbf)   ic: 25000
        #  perm_tank_fuel:  (real)      [100, 600]      (kg)    ic: 400
        #  payl_tank_fuel:  (real)      [400, 5000]     (kg)    ic: 1000
        #  payl_tank_rad:   (real)      [LV Dependent]  (m)     ic: 1.5
        
        #  notes:
        #  for now, permanent tank assumed to be of type 'spherical'
        #+ and payload tank assumed to be of type 'cylindrical'
        #+ final version of code can move the decision of tank type to the
        #+ outer loop level where a GA or Brute force method would trade each.
        #+ a if-loop would need to be added within this method to setup the
        #+ correct decision vector length based on which tank types have been
        #+ chosen.
        
        #  perform inner-loop optimization
        """ For whatever reason, the minimize() interface is not
            working appropriately : 2014_06_22
            , so using direct call to fmin_l_bfgs_b with
            maxfun = 5. maxfun = 3 was sufficient for transfer
            test problem """
        #    profit = minimize(mission.optimize,
        #                      ((nso_altitude),),
        #                      bounds = bnds, method = 'L-BFGS-B',
        #                      options = {'disp': False, 'maxiter': 6})
        self.bnds = ((400.0, 2000.0), (5000.0, 25000.0),
                     (100.0, 600.0), (400.0, 5000.0), (0.5, 2.0))
        self.initial_guess = array([self.nso_altitude, self.ntr.core.thrust,
                                    400.0, 1000.0, 1.5])
        opt_result = fmin_l_bfgs_b(self._evaluate,
                                   self.initial_guess,
                                   bounds = self.bnds,
                                   approx_grad = True,
                                   epsilon = 100,
                                   maxfun = 5)
        #  store the decision vector and obj. func.
        self.local_decision_vector = opt_result[0]
        self.objfunc = opt_result[1]
        #  return inner-loop optimization result to
        #+ the global optimization routine
        if self.DEBUG: print opt_result
        if self.DEBUG: print opt_result[0]
        if self.DEBUG: print opt_result[1]
        #    return profit
        #    return mission


    
    #  evaluate the mission (this is the "internal" call)
    def _evaluate(self, decision_vector):
        #  import statements
        import solarsystem_objects_parameters as ss
        from numpy.linalg import norm
        from numpy   import array
        from copy    import copy, deepcopy
        from revenue import calculate_revenue
        from cost    import calculate_cost
        from time    import sleep
        
        #  make a copy of the actual mission and its ntr to optimize on
        mission_copy = deepcopy(self)
        mission_copy.set_local_decisions(decision_vector)
        #  debug print statements
        if self.DEBUG: print ('\n ---- Starting a New Iteration ---- \n')
        if self.DEBUG: print ('--- Memory Locations ---')
        if self.DEBUG: print ('  mission level  ')
        if self.DEBUG: print mission_copy
        if self.DEBUG: print self
        if self.DEBUG: print ''
        if self.DEBUG: print ('  1 sub level  ')
        if self.DEBUG: print mission_copy.ntr
        if self.DEBUG: print self.ntr
        if self.DEBUG: print ''
        if self.DEBUG: print ('  1 obj sub level 1 attribute level  ')
        if self.DEBUG: print hex(id(mission_copy.ntr.mass))
        if self.DEBUG: print hex(id(self.ntr.mass))
        if self.DEBUG: print ''
        if self.DEBUG: print ('  2 obj sub levels  ')
        if self.DEBUG: print mission_copy.ntr.core
        if self.DEBUG: print self.ntr.core
        if self.DEBUG: print ''
        if self.DEBUG: print ('  2 obj ')
        if self.DEBUG: print ('-----------------------')
        if self.DEBUG: print mission_copy.ntr.mass
        if self.DEBUG: print ('self.nso_altitude is: %f ' %self.nso_altitude)
        if self.DEBUG: print ('copy.nso_altitude is: %f ' %mission_copy.nso_altitude)
        if self.DEBUG: print ('nso_altitude: %.12f ' %decision_vector[0])
        if self.DEBUG: print ('self.ntr.sma %f ' %self.ntr.sma)
        if self.DEBUG: print ('copy.ntr.sma %f ' %mission_copy.ntr.sma)
        if self.DEBUG: print ('mission_copy parameters')
        if self.DEBUG: print ('core thrust is: %f ' %mission_copy.ntr.core.thrust)
        if self.DEBUG: print ('core mass   is: %f ' %mission_copy.ntr.core.mass)
        if self.DEBUG: print ('ntr mass    is: %f ' %mission_copy.ntr.mass)
        if self.DEBUG: print ('self parameters')
        if self.DEBUG: print ('core thrust is: %f ' %self.ntr.core.thrust)
        if self.DEBUG: print ('core mass   is: %f ' %self.ntr.core.mass)
        if self.DEBUG: print ('ntr mass    is: %f ' %self.ntr.mass)
        if self.DEBUG: print 'sleep.....'
        if self.DEBUG: sleep(5.0)
        
        #  execute the mission
        mission_copy.execute()
        
        #  calculate if feasible/infeasible
        pass
        
        #  call the revenue function, which calculates the
        #+ revenue generated by the mission
        calculate_revenue(mission_copy)
        #  call the cost function, which calculates the cost
        #+ of the mission
        calculate_cost(mission_copy)
        #  add a 'profit' attribute to the mission
        mission_copy.profit = mission_copy.revenue - mission_copy.cost
        #  return the mission profit to the inner-loop solver
#        return mission_copy.profit
        if self.DEBUG: print ('Delta-V: %8.5f ' %(norm(array(mission_copy.ntr.dv1)))) #+ norm(array(self.ntr.dv2))
        
        return norm(array(mission_copy.ntr.dv1)) # + norm(array(mission_copy.ntr.dv2))



    #  method for evaluating a decision vector
    def evaluate(self,
                 global_decision_vector = None,
                 local_decision_vector  = None):
        #  import statements
        from revenue import calculate_revenue
        from cost import calculate_cost
        #  setting global decision vector
        if global_decision_vector == None: self.set_global_decisions()
        else: self.set_global_decisions(global_decision_vector)
        #  setting local decision vector
        if local_decision_vector == None: self.set_local_decisions()
        else: self.set_local_decisions(local_decision_vector)
        #  execute the mission
        self.execute()
        #  call the revenue function, which calculates the
        #+ revenue generated by the mission
        calculate_revenue(self)
        #  call the cost function, which calculates the cost
        #+ of the mission
        calculate_cost(self)
        #  add a 'profit' attribute to the mission
        self.profit = self.revenue - self.cost



    #  execute the specified mission
    def execute(self):
        #  import rocket equation for computing fuel usage
        from auxiliary    import tsiolkovsky
        from numpy.linalg import norm
        #  reset the r and v history
        self.ntr.r_history = []
        self.ntr.v_history = []
        #  select and perform mission type
        if self.mission_type == 'gto payload release, gto tank release':
            pass
        elif self.mission_type == 'gto payload release, nso tank release':
            # ----------------
            #    NSO -> GTO
            # ----------------
            self.ntr.transfer(self.target.r, self.target.v,
                              Minimize_Energy = True)
            #  based on the transfer calculation, compute the fuel burn
            fuel_used = self.ntr.mass - tsiolkovsky(norm(self.ntr.dv1),
                                                    self.ntr.nozzle.Isp,
                                                    self.ntr.mass)
            if self.DEBUG: print ('ntr Isp: %f ' %self.ntr.nozzle.Isp)
            if self.DEBUG: print ('Fuel Available at Start: %8.5f ' %self.ntr.fuel)
            if self.DEBUG: print ('Fuel Used: %8.5f' %fuel_used)
            if self.DEBUG: print ('Fuel Remaining: %8.5f ' %(self.ntr.fuel - fuel_used))
            #  store the burn history (i.e. fuel consumed at impulses)
            self.history['burnmass'].append(fuel_used)
            #  remove whatever fuel is left in mission tank and then
            #+ subtract the rest from permanent tank
            if self.ntr.tank[1].fuel >= fuel_used:
                self.ntr.tank[1].remove_fuel(fuel_used)
            else:
                self.ntr.tank[0].remove_fuel(fuel_used - self.ntr.tank[1].fuel)
                self.ntr.tank[1].remove_fuel(self.ntr.tank[1].fuel)
            if self.DEBUG: print ('CHECK -> Fuel Remaining: %f ' %self.ntr.fuel)
            # -------------------
            #    GTO Insertion
            # -------------------
            fuel_used = self.ntr.mass - tsiolkovsky(norm(self.ntr.dv2),
                                                    self.ntr.nozzle.Isp,
                                                    self.ntr.mass)
            if self.DEBUG: print ('ntr Isp: %f ' %self.ntr.nozzle.Isp)
            if self.DEBUG: print ('Fuel Available at Start: %8.5f ' %self.ntr.fuel)
            if self.DEBUG: print ('Fuel Used: %8.5f' %fuel_used)
            if self.DEBUG: print ('Fuel Remaining: %8.5f ' %(self.ntr.fuel - fuel_used))
            #  store the burn history (i.e. fuel consumed at impulses)
            self.history['burnmass'].append(fuel_used)
            #  remove whatever fuel is left in mission tank and then
            #+ subtract the rest from permanent tank
            if self.ntr.tank[1].fuel >= fuel_used:
                self.ntr.tank[1].remove_fuel(fuel_used)
            else:
                self.ntr.tank[0].remove_fuel(fuel_used - self.ntr.tank[1].fuel)
                self.ntr.tank[1].remove_fuel(self.ntr.tank[1].fuel)
            #  dropoff the payload in GTO
            self.ntr.remove_payload_mass(self.payload_mass)
            if self.DEBUG: print ('CHECK -> Fuel Remaining: %f ' %self.ntr.fuel)
            # ----------------
            #    GTO -> NSO
            # ----------------
            fuel_used = self.ntr.mass - tsiolkovsky(norm(self.ntr.dv2),
                                                    self.ntr.nozzle.Isp,
                                                    self.ntr.mass)
            if self.DEBUG: print ('ntr Isp: %f ' %self.ntr.nozzle.Isp)
            if self.DEBUG: print ('Fuel Available at Start: %8.5f ' %self.ntr.fuel)
            if self.DEBUG: print ('Fuel Used: %8.5f' %fuel_used)
            if self.DEBUG: print ('Fuel Remaining: %8.5f ' %(self.ntr.fuel - fuel_used))
            #  store the burn history (i.e. fuel consumed at impulses)
            self.history['burnmass'].append(fuel_used)
            #  remove whatever fuel is left in mission tank and then
            #+ subtract the rest from permanent tank
            if self.ntr.tank[1].fuel >= fuel_used:
                self.ntr.tank[1].remove_fuel(fuel_used)
            else:
                self.ntr.tank[0].remove_fuel(fuel_used - self.ntr.tank[1].fuel)
                self.ntr.tank[1].remove_fuel(self.ntr.tank[1].fuel)
            if self.DEBUG: print ('CHECK -> Fuel Remaining: %f ' %self.ntr.fuel)
            # -------------------
            #    NSO Insertion
            # -------------------
            fuel_used = self.ntr.mass - tsiolkovsky(norm(self.ntr.dv1),
                                                    self.ntr.nozzle.Isp,
                                                    self.ntr.mass)
            if self.DEBUG: print ('ntr Isp: %f ' %self.ntr.nozzle.Isp)
            if self.DEBUG: print ('Fuel Available at Start: %8.5f ' %self.ntr.fuel)
            if self.DEBUG: print ('Fuel Used: %8.5f' %fuel_used)
            if self.DEBUG: print ('Fuel Remaining: %8.5f ' %(self.ntr.fuel - fuel_used))
            #  store the burn history (i.e. fuel consumed at impulses)
            self.history['burnmass'].append(fuel_used)
            #  remove whatever fuel is left in mission tank and then
            #+ subtract the rest from permanent tank
            if self.ntr.tank[1].fuel >= fuel_used:
                self.ntr.tank[1].remove_fuel(fuel_used)
            else:
                self.ntr.tank[0].remove_fuel(fuel_used - self.ntr.tank[1].fuel)
                self.ntr.tank[1].remove_fuel(self.ntr.tank[1].fuel)
            if self.DEBUG: print ('CHECK -> Fuel Remaining: %f ' %self.ntr.fuel)
            #  transfer any additional fuel from the mission tank to the permanent
            #+ tank if there is extra
            if self.ntr.tank[1].fuel > 0:
                fuel_that_can_be_added = self.ntr.tank[0].fuel_capacity - \
                                         self.ntr.tank[0].fuel
                if self.ntr.tank[1].fuel > fuel_that_can_be_added:
                    self.ntr.tank[0].add_fuel(fuel_that_can_be_added)
                    self.ntr.tank[1].remove_fuel(fuel_that_can_be_added)
                else:
                    self.ntr.tank[0].add_fuel(self.ntr.tank[1].fuel)
                    self.ntr.tank[1].remove_fuel(self.ntr.tank[1].fuel)

            #  dropoff the payload specific tank in NSO
            self.ntr.remove_tank(1)
    

        #  flow NSO -> GTO trajectory and save state information
        elif self.mission_type == 'geo payload release, geo tank release':
            pass
        elif self.mission_type == 'geo payload release, gto tank release':
            pass
        elif self.mission_type == 'geo payload release, nso tank release':
            pass