def set_initial_plan(self, name: str, traj_conf: ty.Sequence[TrajectoryConf], flight_window: ty.Tuple[float, float]): """Set up the planner for an initial plan""" tc = [ planning.Trajectory( planning.TrajectoryConfig(c.name, self.uav_models[c.uav_model], planning.Waypoint(*c.start_wp), planning.Waypoint(*c.end_wp), c.start_time, c.max_duration, planning.WindVector(*c.wind))) for c in traj_conf ] f_data = planning.make_fire_data(self._wildfire_map, self._elevation) tw = planning.TimeWindow(*flight_window) utility = planning.make_flat_utility_map(self._wildfire_map, flight_window=tw, output_layer="utility") the_plan = planning.Plan(name, tc, f_data, tw, utility.as_cpp_raster("utility")) self._current_planner = planning.Planner(the_plan, {})
def set_plan(self, name: str, trajs: ty.Sequence[TrajType], flight_window: ty.Tuple[float, float]): """Set up the planner for improving an existing plan""" tr = [ planning.Trajectory( planning.TrajectoryConfig(c[0].name, self.uav_models[c[0].uav_model], planning.Waypoint(*c[0].start_wp), planning.Waypoint(*c[0].end_wp), c[0].start_time, c[0].max_duration, planning.WindVector(*c[0].wind)), [ planning.TrajectoryManeuver(planning.Waypoint(*m[0]), m[1], m[2]) for m in c[1] ]) for c in trajs ] f_data = planning.make_fire_data(self._wildfire_map, self._elevation) tw = planning.TimeWindow(*flight_window) utility = planning.make_utility_map(self._wildfire_map, flight_window=tw, output_layer="utility") the_plan = planning.Plan(name, tr, f_data, tw, utility) self._current_planner = planning.Planner(the_plan, {})
def draw_scenario(i, scen, a): # Fetch scenario environment data with additional elevation mode for planning env = propagation.Environment( scen.area, wind_speed=scen.wind_speed, wind_dir=scen.wind_direction, world=fire_rs.geodata.environment.World( landcover_to_fuel_remap=fire_rs.geodata.environment. EVERYTHING_FUELMODEL_REMAP)) # Propagate fires in the environment propagation_end_time = scen.time_window_end + 60 * 10 _logger.debug("Propagating fire ignitions %s until %s", str(scen.ignitions), str(propagation_end_time)) prop = propagation.propagate_from_points(env, scen.ignitions, until=propagation_end_time) ignitions = prop.ignitions() # Transform altitude of UAV bases from agl (above ground level) to absolute for f in scen.flights: base_h = 0. # If flat, start at the default segment insertion h f.base_waypoint = Waypoint(f.base_waypoint.x, f.base_waypoint.y, base_h, f.base_waypoint.dir) # Define the flight window flight_window = TimeWindow(scen.time_window_start, scen.time_window_end) # Create utility map utility = make_utility_map(ignitions, flight_window, layer='ignition', output_layer='utility') utility_cpp = utility.as_cpp_raster('utility') # Make a FireData object fire_data = make_fire_data(ignitions, env.raster, elevation_map_layer='elevation') # Create an initial plan initial_plan = Plan(str(i), [f.as_cpp() for f in scen.flights], fire_data, flight_window, utility_cpp) final_plan = initial_plan # Propagation was running more time than desired in order to reduce edge effect. # Now we need to filter out-of-range ignition times. Crop range is rounded up to the next # 10-minute mark (minus 1). This makes color bar ranges and fire front contour plots nicer ignitions['ignition'][ignitions['ignition'] > \ int(scen.time_window_end / 60. + 5) * 60. - 60] = _DBL_MAX # Representation of unburned cells using max double is not suitable for display, # so those values must be converted to NaN ignitions_nan = ignitions['ignition'].copy() ignitions_nan[ignitions_nan == _DBL_MAX] = np.nan first_ignition = np.nanmin(ignitions_nan) last_ignition = np.nanmax(ignitions_nan) # Create the geodatadisplay object & extensions that are going to be used geodatadisplay = GeoDataDisplay.pyplot_figure( env.raster.combine(ignitions), frame=(0, 0)) geodatadisplay.add_extension(TrajectoryDisplayExtension, (None, ), {}) plot_plan_with_background(final_plan, geodatadisplay, (first_ignition, last_ignition), { 'colorbar': a.colorbar, 'background': a.background, 'foreground': [] }) # Save the picture filepath = os.path.join(a.output, str(i) + "." + a.format) _logger.info("Saving as figure as: %s", str(filepath)) geodatadisplay.axes.get_figure().set_size_inches(a.size) geodatadisplay.axes.get_figure().savefig(filepath, dpi=a.dpi, bbox_inches='tight') geodatadisplay.close()
seganosa_fire_env.raster.combine(fire_prop.ignitions().slice(["ignition"])), frame=(0., 0.)) gdd.draw_elevation_shade(with_colorbar=False, cmap=matplotlib.cm.terrain) gdd.draw_wind_quiver() gdd.draw_ignition_contour(with_labels=True, cmap=matplotlib.cm.plasma) gdd.draw_ignition_points(fire_start) # gdd.figure.show() gdd.figure.savefig(".".join(("demo_seganosa_propagation", "svg")), dpi=150, bbox_inches='tight') # PLANNING ## Define the initial plan ## Takie off and landing at the same location: maximum flight time 45 minutes ## Utility map depen f_data = planning.make_fire_data(fire_prop.ignitions(), seganosa_fire_env.raster) tw = planning.TimeWindow(0, np.inf) utility = planning.make_utility_map(fire_prop.ignitions(), flight_window=tw, output_layer="utility") trajectory_config = [planning.Trajectory(planning.TrajectoryConfig("Trajectory", planning.UAVModels.x8("06"), planning.Waypoint( 2801900.0 - 1500, 2298900.0 - 1500, 300.0, 0.0), planning.Waypoint( 2801900.0 - 1500, 2298900.0 - 1500, 300.0, 0.0), now, 2700.0,
def run_benchmark(scenario: Scenario, save_directory: str, instance_name: str, output_options_plot: ty.Mapping[str, ty.Any], output_options_planning: ty.Mapping[str, ty.Any], snapshots: bool, vns_name: str, output_options_data: ty.Mapping[str, ty.Any]): _logger.info("Starting benchmark instance %s", instance_name) # Fetch scenario environment data with additional elevation mode for planning env = PlanningEnvironment( scenario.area, wind_speed=scenario.wind_speed, wind_dir=scenario.wind_direction, planning_elevation_mode=output_options_planning['elevation_mode'], discrete_elevation_interval=DISCRETE_ELEVATION_INTERVAL, world=fire_rs.geodata.environment.World( landcover_to_fuel_remap=fire_rs.geodata.environment. EVERYTHING_FUELMODEL_REMAP)) # Propagate fires in the environment propagation_end_time = scenario.time_window_end + 60 * 10 _logger.debug("Propagating fire ignitions %s until %s", str(scenario.ignitions), str(propagation_end_time)) prop = propagation.propagate_from_points(env, scenario.ignitions, until=propagation_end_time) ignitions = prop.ignitions() # Transform altitude of UAV bases from agl (above ground level) to absolute for f in scenario.flights: base_h = 0. # If flat, start at the default segment insertion h if output_options_planning['elevation_mode'] != 'flat': base_h = base_h + env.raster["elevation"][env.raster.array_index( (f.base_waypoint.x, f.base_waypoint.y))] # The new WP is (old_x, old_y, old_z + elevation[old_x, old_y], old_dir) f.base_waypoint = Waypoint(f.base_waypoint.x, f.base_waypoint.y, base_h, f.base_waypoint.dir) conf = { 'min_time': scenario.time_window_start, 'max_time': scenario.time_window_end, 'save_every': 0, 'save_improvements': snapshots, 'vns': vns_configurations[vns_name] } conf['vns']['configuration_name'] = vns_name # Define the flight window flight_window = TimeWindow(scenario.time_window_start, scenario.time_window_end) # Create utility map utility = make_utility_map(ignitions, flight_window, layer='ignition', output_layer='utility') utility_cpp = utility.as_cpp_raster('utility') # Make a FireData object fire_data = make_fire_data(ignitions, env.raster, elevation_map_layer='elevation_planning') # Create an initial plan initial_plan = Plan(instance_name, [f.as_cpp() for f in scenario.flights], fire_data, flight_window, utility_cpp) # Set up a Planner object from the initial Plan pl = Planner(initial_plan, vns_configurations[vns_name]) pl.save_improvements = snapshots pl.save_every = 0 search_result = pl.compute_plan() final_plan = search_result.final_plan() # Propagation was running more time than desired in order to reduce edge effect. # Now we need to filter out-of-range ignition times. Crop range is rounded up to the next # 10-minute mark (minus 1). This makes color bar ranges and fire front contour plots nicer ignitions['ignition'][ignitions['ignition'] > \ int(scenario.time_window_end / 60. + 5) * 60. - 60] = _DBL_MAX # Representation of unburned cells using max double is not suitable for display, # so those values must be converted to NaN ignitions_nan = ignitions['ignition'].copy() ignitions_nan[ignitions_nan == _DBL_MAX] = np.nan first_ignition = np.nanmin(ignitions_nan) last_ignition = np.nanmax(ignitions_nan) # Create the geodatadisplay object & extensions that are going to be used geodatadisplay = GeoDataDisplay.pyplot_figure( env.raster.combine(ignitions), frame=(0, 0)) geodatadisplay.add_extension(TrajectoryDisplayExtension, (None, ), {}) plot_plan_with_background(final_plan, geodatadisplay, (first_ignition, last_ignition), output_options_plot) # Save the picture filepath = os.path.join( save_directory, instance_name + "." + str(output_options_plot.get('format', 'png'))) _logger.info("Saving as figure as: %s", str(filepath)) geodatadisplay.axes.get_figure().set_size_inches( *output_options_plot.get('size', (15, 10))) geodatadisplay.axes.get_figure().savefig(filepath, dpi=output_options_plot.get( 'dpi', 150), bbox_inches='tight') # Save rasters if output_options_data['save_rasters']: raster_data_dir = os.path.join(save_directory, instance_name + "_data") if not os.path.exists(raster_data_dir): os.makedirs(raster_data_dir) env.raster.write_to_file( os.path.join( raster_data_dir, ".".join(("_".join( (instance_name, "elevation_planning")), 'tif'))), 'elevation_planning') env.raster.write_to_file( os.path.join( raster_data_dir, ".".join(("_".join( (instance_name, "wind_velocity")), 'tif'))), 'wind_velocity') env.raster.write_to_file( os.path.join( raster_data_dir, ".".join(("_".join( (instance_name, "wind_angle")), 'tif'))), 'wind_angle') prop.ignitions().write_to_file(os.path.join( raster_data_dir, ".".join(("_".join( (instance_name, "ignition")), 'tif'))), 'ignition', nodata=np.inf) u_initial_map = GeoData.from_cpp_raster(initial_plan.utility_map(), "utility", projection=utility.projection) u_initial_map.write_to_file( os.path.join( raster_data_dir, ".".join(("_".join( (instance_name, "utility_initial")), 'tif'))), 'utility') u_final_map = GeoData.from_cpp_raster(final_plan.utility_map(), "utility", projection=utility.projection) u_final_map.write_to_file( os.path.join( raster_data_dir, ".".join(("_".join( (instance_name, "utility_final")), 'tif'))), 'utility') # print([o.as_tuple() for o in final_plan.observations()]) # Log planned trajectories metadata for i, t in enumerate(final_plan.trajectories()): _logger.debug("traj #{} duration: {} / {}".format( i, t.duration(), t.conf.max_flight_time)) # save metadata to file with open(os.path.join(save_directory, instance_name + ".json"), "w") as metadata_file: import json parsed = json.loads(search_result.metadata()) parsed["benchmark_id"] = instance_name parsed["date"] = datetime.datetime.now().isoformat() metadata_file.write(json.dumps(parsed, indent=4)) matplotlib.pyplot.close(geodatadisplay.axes.get_figure()) # If intermediate plans are available, save them for i, plan in enumerate(search_result.intermediate_plans): geodatadisplay = GeoDataDisplay.pyplot_figure( env.raster.combine(ignitions)) geodatadisplay.add_extension(TrajectoryDisplayExtension, (None, ), {}) plot_plan_with_background(plan, geodatadisplay, (first_ignition, last_ignition), output_options_plot) i_plan_dir = os.path.join(save_directory, instance_name) if not os.path.exists(i_plan_dir): os.makedirs(i_plan_dir) filepath = os.path.join( i_plan_dir, str(i) + "." + str(output_options_plot.get('format', 'png'))) _logger.info("Saving intermediate plan as: %s", str(filepath)) geodatadisplay.axes.get_figure().set_size_inches( *output_options_plot.get('size', (15, 10))) geodatadisplay.axes.get_figure().savefig(filepath, dpi=output_options_plot.get( 'dpi', 150), bbox_inches='tight') matplotlib.pyplot.close(geodatadisplay.axes.get_figure()) del search_result