Example #1
0
class Placement:
    def __init__(self, pid, fp):
        self.pid = pid
        self.fp = FlightPlan(fp)

    def compareTo(self, other):
        return (self.pid > other.pid) - (self.pid < other.pid)

    def setFp(self, fp):
        if fp == None:
            raise AssertionError("FlightPlan can't be None!")
        self.fp = FlightPlan(fp)

    def getPid(self):
        return self.pid

    def getFp(self):
        return self.fp

    def addFlight(self, f):
        return self.fp.addFlight(f)

    def size(self):
        return self.fp.size()

    def get(self, index):
        return self.fp.get(index)
Example #2
0
 def partitionToPlacements(self, allFlights):
     pHash = dict()
     for f in allFlights:
         if f.getPlacementToken() in pHash.keys():
             p = pHash[f.getPlacementToken()]
             p.addFlight(f)
         else:
             nfp = FlightPlan([])
             pHash.update({
                 f.getPlacementToken():
                 Placement.Placement(f.getPlacementToken(), nfp)
             })
             nfp.addFlight(f)
     return list(pHash.values())
Example #3
0
    def test_case1(cls):
        fuel = 35000
        oxidizer = 85000
        flight_plan = FlightPlan()

        flight_plan.add_step(1, velocity=0.25)
        flight_plan.add_step(10, velocity=0.25, velocity_variance=0.01)
        flight_plan.add_step(150, velocity=-0.25)
        flight_plan.add_step(280, velocity=-0.1)
        flight_plan.add_step(290, velocity=-0.1, velocity_variance=0.01)
        flight_plan.add_step(420, velocity=-0.1)
        flight_plan.add_step(445,
                             velocity=0.0,
                             height=0.0,
                             velocity_variance=0.0,
                             height_variance=0.0)

        return flight_plan, fuel, oxidizer
Example #4
0
    def test_case1(cls):
        fuel = 35000
        flight_plan = FlightPlan()

        flight_plan.add_step(1, velocity=0.25)
        flight_plan.add_step(10, velocity=0.25, velocity_variance=0.01)
        flight_plan.add_step(100, velocity=0.5, height=25, height_variance=5.0)
        flight_plan.add_step(110, velocity=0.5, velocity_variance=0.01)
        flight_plan.add_step(150, velocity=-0.5)
        flight_plan.add_step(180, height=50, height_variance=5.0)
        flight_plan.add_step(355, velocity=-0.1)
        flight_plan.add_step(360, velocity=-0.1, velocity_variance=0.01)
        flight_plan.add_step(380, velocity=-0.1)
        flight_plan.add_step(400,
                             velocity=0.0,
                             height=0.0,
                             velocity_variance=0.0,
                             height_variance=0.0)

        return flight_plan, fuel
Example #5
0
 def __init__(self, pid, fp):
     self.pid = pid
     self.fp = FlightPlan(fp)
Example #6
0
 def setFp(self, fp):
     if fp == None:
         raise AssertionError("FlightPlan can't be None!")
     self.fp = FlightPlan(fp)
Example #7
0
    def launch_rocket(
        self,
        flight_plan: FlightPlan,
        fuel: int,
        oxidizer: int,
        bipropellant_pid_solution: Callable,
        optional_data: Optional[Dict] = None
    ) -> Tuple[float, float, float, str]:
        """
        Launch rocket to attempt to fly optimal flight path

        Args:
            flight_plan: Flight plan of rocket
            fuel: Fuel load in kg
            oxidizer: Oxidizer load in kg
            bipropellant_pid_solution: Rocket PID function to control launch
            optional_data: Optional params to be passed to the pd solution

        Returns:
              Final grade, Output of launch
        """
        output = ''

        # fuel load in kg
        init_fuel = 35000
        # oxidizer load in kg
        init_oxidizer = 85000
        # initial velocity level (height = 0 at base) in km/2
        init_velocity = 0
        # initial engine position (shutoff = 0, max thrust = 1) in percent
        # kerosene RG-1 consumption in kg/s
        fuel_consumption = 480
        # oxidizer consumption in kg/s
        oxidizer_consumption = 480
        oxidizer_fuel_ratio = 2.77

        # status indicator for landing
        landed = 0
        # status indicator for fuel tank
        fuel_empty = False
        oxidizer_empty = False
        # status indicator for successful landing
        good_landing = 0

        delta_t = self.time_final // (self.total_steps - 1)
        time = np.linspace(0, self.time_final, self.total_steps)

        throttle_set = np.zeros(self.total_steps)
        velocity_log = np.zeros(self.total_steps)
        optimal_velocity_log = np.zeros(self.total_steps)
        height = np.zeros(self.total_steps)
        fuel_level = np.zeros(self.total_steps)
        oxidizer_level = np.zeros(self.total_steps)

        # Initialize data
        data = {'ErrorP': 0, 'ErrorI': 0, 'ErrorD': 0}

        if optional_data:
            data.update(optional_data)

        # Rocket Altitude ODE solver
        for time_step in range(len(time) - 1):
            if landed > 0:
                break

            (optimal_velocity, is_velocity_mandatory, desired_height,
             is_height_mandatory) = flight_plan.get_current_values(time_step)

            fuel_throttle, oxidizer_throttle, data = bipropellant_pid_solution(
                delta_t, velocity_log[time_step], optimal_velocity, data)
            fuel_throttle = effective_fuel_throttle = max(
                0, min(1, fuel_throttle))
            oxidizer_throttle = effective_oxidizer_throttle = max(
                0, min(1, oxidizer_throttle))

            # Check for oxidizer : fuel ratio
            if fuel_throttle != 0:

                current_oxidizer_fuel_ratio = oxidizer_consumption * oxidizer_throttle / (
                    fuel_consumption * fuel_throttle)
                # oxidizer is less, so use fuel according to oxidizer
                if current_oxidizer_fuel_ratio < oxidizer_fuel_ratio - 0.1:
                    effective_fuel_throttle = max(
                        0.0, min(1.0, current_oxidizer_fuel_ratio))

                # oxidizer is more, so use oxidizer according to fuel
                elif current_oxidizer_fuel_ratio > oxidizer_fuel_ratio + 0.1:
                    effective_oxidizer_throttle = (oxidizer_fuel_ratio *
                                                   fuel_consumption *
                                                   fuel_throttle /
                                                   oxidizer_consumption)

            else:
                effective_oxidizer_throttle = 0
                effective_fuel_throttle = 0

            # simulate air density drop with altitude
            self.rho = 1225000000 * np.exp(-height[time_step] / 1000)

            # shutoff engines if fuel empty
            if fuel_empty:
                output += 'The bi-propellant rocket ran out of fuel!\n'
                effective_fuel_throttle = 0
                effective_oxidizer_throttle = 0

            if oxidizer_empty:
                output += 'The bi-propellant rocket ran out of oxidizer!\n'
                effective_fuel_throttle = 0
                effective_oxidizer_throttle = 0

            # ODE solver to simulate rocket velocity change
            rocket_velocity = odeint(self.rocket,
                                     init_velocity,
                                     [time[time_step], time[time_step + 1]],
                                     args=(time_step, effective_fuel_throttle,
                                           effective_oxidizer_throttle,
                                           init_fuel, init_oxidizer))

            # update velocity with ODE value
            init_velocity = rocket_velocity[1][0]
            # log current velocity
            velocity_log[time_step + 1] = init_velocity
            # log throttle
            throttle_set[time_step + 1] = fuel_throttle
            # reduce fuel per consumption rate
            init_fuel = init_fuel - fuel_consumption * fuel_throttle
            init_oxidizer = init_oxidizer - oxidizer_consumption * oxidizer_throttle

            # log optimal velocity
            optimal_velocity_log[time_step + 1] = optimal_velocity

            # Altitude and Fuel Checks
            if height[time_step] < 0 and abs(init_velocity) > 0.11:
                height[time_step + 1] = 0
                landed = time_step
                output += 'The bi-propellant rocket CRASHED!\n'
            elif height[time_step] < 0 and abs(
                    init_velocity) <= 0.11 and time_step > 10:
                height[time_step + 1] = 0
                landed = time_step
                good_landing = True
                output += 'The bi-propellant rocket landed safely!\n'
            elif height[time_step] >= 0:
                height[time_step +
                       1] = height[time_step] + init_velocity * delta_t

            if fuel_empty:
                fuel_level[time_step + 1] = 0
            if oxidizer_empty:
                oxidizer_level[time_step + 1] = 0
            elif init_fuel < 0:
                fuel_level[time_step + 1] = 0
                fuel_empty = True
            elif init_oxidizer < 0:
                oxidizer_level[time_step + 1] = 0
                oxidizer_empty = True
            else:
                oxidizer_level[time_step + 1] = init_oxidizer
                fuel_level[time_step + 1] = init_fuel

        # Plotting for testing purposes
        if SHOW_GRAPH:
            try:
                graph = flight_graph("Bipropellant rocket launch", 800, 600, 6)

                sub_data_0 = [{
                    'x': time,
                    'y': optimal_velocity_log,
                    'color': "#008888",
                    'label': "Optimum  velocity"
                }, {
                    'x': time,
                    'y': velocity_log,
                    'color': "#0000ff",
                    'label': "Current velocity"
                }]
                graph.add_plot("Velocity (km/s)", sub_data_0)

                sub_data_1 = [{
                    'x': (0, self.time_final),
                    'y': (1, 1),
                    'color': "#880088",
                    'label': "Maximum thrust"
                }, {
                    'x': time,
                    'y': throttle_set,
                    'color': "#ff0000",
                    'label': "Current throttle"
                }]
                graph.add_plot("Throttle (%)", sub_data_1)

                sub_data_2 = [{
                    'x': time,
                    'y': height,
                    'color': "#008800",
                    'label': "Current height"
                }]
                graph.add_plot("Height (km)", sub_data_2)

                sub_data_3 = [{
                    'x': time,
                    'y': fuel_level,
                    'color': "#888800",
                    'label': "Current fuel"
                }]
                graph.add_plot("Fuel (kg)", sub_data_3)

                sub_data_4 = [{
                    'x': time,
                    'y': oxidizer_level,
                    'color': "#888800",
                    'label': "Current oxidizer"
                }]
                graph.add_plot("Oxidizer (kg)", sub_data_4)

                sub_data_5 = [{
                    'x': time,
                    'y': self.thrust,
                    'color': "#0000ff",
                    'label': "Thrust"
                }, {
                    'x': time,
                    'y': self.gravity,
                    'color': "#008800",
                    'label': "Gravity"
                }, {
                    'x': time,
                    'y': self.drag,
                    'color': "#ff0000",
                    'label': "Drag"
                }]
                graph.add_plot("Force (N)", sub_data_5)

                graph.done()

            except Exception as exp:
                import traceback
                output += 'Error with plotting results:' + str(exp)
                output += traceback.format_exc()
                output += '\n'

        # Score for following optimal course
        scored_time_steps = 0
        scored_height_steps = 0

        student_velocity_score = 0
        student_height_score = 0

        total_time = flight_plan.get_plan_length()

        for time_step in range(0, total_time + 1):
            (expected_velocity, allowed_velocity_variance, expected_height,
             allowed_height_variance
             ) = flight_plan.get_current_values(time_step)

            if allowed_velocity_variance is not None:
                scored_time_steps += 1

                lower_velocity = expected_velocity - allowed_velocity_variance
                upper_velocity = expected_velocity + allowed_velocity_variance

                if lower_velocity <= velocity_log[time_step] <= upper_velocity:
                    student_velocity_score += 1
                else:
                    print(
                        f'Velocity not met at time step: {time_step} ::: ' +
                        f'{lower_velocity} <= {velocity_log[time_step]} <= {upper_velocity}'
                    )

            if allowed_height_variance is not None:
                scored_height_steps += 1

                lower_height = expected_height - allowed_height_variance
                upper_height = expected_height + allowed_height_variance

                if lower_height <= height[time_step] <= upper_height:
                    student_height_score += 1
                else:
                    print(
                        f'Height not met at time step: {time_step} ::: ' +
                        f'{lower_height} <= {height[time_step]} <= {upper_height}'
                    )

        student_score = student_velocity_score + student_height_score
        expected_score = scored_time_steps + scored_height_steps
        flight_score = student_score / expected_score * BIPROP_FLIGHT_SCORE

        # Score for making a successful landing
        if good_landing:
            landing_score = BIPROP_LAND_SCORE
        else:
            landing_score = 0

        rocket_score = min(flight_score + landing_score,
                           BIPROP_FLIGHT_SCORE + BIPROP_LAND_SCORE)

        return rocket_score, landing_score, flight_score, output