Skip to content

Commit

Permalink
added an interpolated firestatusmap to the observations
Browse files Browse the repository at this point in the history
  • Loading branch information
julien meine committed Sep 26, 2024
1 parent d90dca3 commit cfb9bf1
Show file tree
Hide file tree
Showing 15 changed files with 160 additions and 42 deletions.
12 changes: 9 additions & 3 deletions src/models/firespin/firemodel_gridmap.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -443,12 +443,18 @@ std::vector<std::vector<int>> GridMap::GetExploredMap(int size, bool interpolate
return InterpolationResize(explored_map_, size, size);
}

std::vector<std::vector<int>> GridMap::GetFireMap(int size, bool interpolated) {
std::vector<std::vector<double>> GridMap::GetFireMap(int size, bool interpolated) {
if(size == 0) {
size = parameters_.GetFireMapSize();
}
if (!interpolated) {
return fire_map_;
std::vector<std::vector<double>> doubleMatrix(fire_map_.size(), std::vector<double>(fire_map_[0].size()));
for (size_t i = 0; i < fire_map_.size(); ++i) {
for (size_t j = 0; j < fire_map_[0].size(); ++j) {
doubleMatrix[i][j] = static_cast<double>(fire_map_[i][j]);
}
}
return doubleMatrix;
}
return InterpolationResize(fire_map_, size, size);
return BilinearInterpolation(fire_map_, size, size);
}
2 changes: 1 addition & 1 deletion src/models/firespin/firemodel_gridmap.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ class GridMap {
void UpdateCells();
double PercentageBurned() const;
std::vector<std::vector<int>> GetExploredMap(int size=0, bool interpolated=true);
std::vector<std::vector<int>> GetFireMap(int size=0, bool interpolated=true);
std::vector<std::vector<double>> GetFireMap(int size=0, bool interpolated=true);

double PercentageBurning() const;
double PercentageUnburnable() const;
Expand Down
2 changes: 1 addition & 1 deletion src/models/firespin/model_parameters.h
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ class FireModelParameters {
int number_of_drones_ = 1;
int view_range_ = 8;
int GetViewRange() const {return view_range_;}
int time_steps_ = 16;
int time_steps_ = 4;
int GetTimeSteps() const {return time_steps_;}
// std::pair<double, double> min_velocity_ = std::make_pair(-5.0, -5.0);
// std::pair<double, double> GetMinVelocity() const {return min_velocity_;}
Expand Down
15 changes: 7 additions & 8 deletions src/models/firespin/rendering/firemodel_imgui.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -948,22 +948,21 @@ void ImguiHandler::DrawBuffer(std::vector<float> buffer, int buffer_pos) {
draw_list->AddText(ImVec2(x + 10, graph_pos.y), IM_COL32(255, 255, 255, 255), label);
}
}

void ImguiHandler::DrawGrid(const std::vector<std::vector<int>>& grid, std::shared_ptr<FireModelRenderer> renderer, float cell_size, bool is_fire_status, bool is_exploration_map) {
template<typename T>
void ImguiHandler::DrawGrid(const std::vector<std::vector<T>>& grid, std::shared_ptr<FireModelRenderer> renderer, float cell_size, bool is_fire_status, bool is_exploration_map) {
ImVec2 cursor_pos = ImGui::GetCursorScreenPos();

// Function to map a value to a color
float max_exploration_time = parameters_.GetExplorationTime();
std::function<ImVec4(int)> value_to_color;
std::function<ImVec4(double)> value_to_color;
if (!is_fire_status) {
value_to_color = [&max_exploration_time](int value) -> ImVec4 {
value_to_color = [&max_exploration_time](double value) -> ImVec4 {
float normalized_value = std::clamp(static_cast<float>(value) / max_exploration_time, 0.0f, 0.6f);
return ImVec4(0.6f - normalized_value, 0.6f - normalized_value, 0.3f, 1.0f); // white to black
return {0.6f - normalized_value, 0.6f - normalized_value, 0.3f, 1.0f};
};
} else {
value_to_color = [&max_exploration_time](int value) -> ImVec4 {
float normalized_value = std::clamp(static_cast<float>(value), 0.0f, 1.0f);
return ImVec4(0.0f + normalized_value, 1.0f - normalized_value, 0.0f, 1.0f); // white to black
value_to_color = [](double value) -> ImVec4 {
return {0.0f + static_cast<float>(value), 1.0f - static_cast<float>(value), 0.0f, 1.0f};
};

}
Expand Down
3 changes: 2 additions & 1 deletion src/models/firespin/rendering/firemodel_imgui.h
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,8 @@ class __attribute__((visibility("default"))) ImguiHandler {


//Helper
void DrawGrid(const std::vector<std::vector<int>>& grid, std::shared_ptr<FireModelRenderer> renderer, float cell_size, bool is_fire_status = false, bool is_exploration_map = false);
template<typename T>
void DrawGrid(const std::vector<std::vector<T>>& grid, std::shared_ptr<FireModelRenderer> renderer, float cell_size, bool is_fire_status = false, bool is_exploration_map = false);
void DrawBuffer(std::vector<float> buffer, int buffer_pos);
};

Expand Down
70 changes: 70 additions & 0 deletions src/models/firespin/utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -153,4 +153,74 @@ std::vector<std::vector<int>> InterpolationResize(const std::vector<std::vector<
}

return resized_map;
}

std::vector<std::vector<int>> ResizeFire(const std::vector<std::vector<int>>& input_map, int new_width, int new_height) {
int old_width = input_map.size();
int old_height = input_map[0].size();

std::vector<std::vector<int>> resized_map(new_width, std::vector<int>(new_height, 0));

float x_ratio = static_cast<float>(old_width) / new_width;
float y_ratio = static_cast<float>(old_height) / new_height;

for (int y = 0; y < new_height; ++y) {
for (int x = 0; x < new_width; ++x) {
int x_orig = static_cast<int>(x * x_ratio);
int y_orig = static_cast<int>(y * y_ratio);

// Ensure indices are within bounds
if (x_orig >= old_width) x_orig = old_width - 1;
if (y_orig >= old_height) y_orig = old_height - 1;

resized_map[x][y] = input_map[x_orig][y_orig];
}
}

return resized_map;
}

std::vector<std::vector<double>> BilinearInterpolation(const std::vector<std::vector<int>>& input_map, int new_width, int new_height) {
int inputRows = input_map.size();
int inputCols = input_map[0].size();

std::vector<std::vector<double>> output_map(new_width, std::vector<double>(new_height, 0.0));

double x_scale = (inputCols - 1) / static_cast<double>(new_height - 1);
double y_scale = (inputRows - 1) / static_cast<double>(new_width - 1);

// Perform bilinear interpolation
for (int i = 0; i < new_width; ++i) {
for (int j = 0; j < new_height; ++j) {
double y_in = i * y_scale;
double x_in = j * x_scale;

int x0 = static_cast<int>(std::floor(x_in));
int x1 = static_cast<int>(std::ceil(x_in));
int y0 = static_cast<int>(std::floor(y_in));
int y1 = static_cast<int>(std::ceil(y_in));

x0 = std::max(0, std::min(x0, inputCols - 1));
x1 = std::max(0, std::min(x1, inputCols - 1));
y0 = std::max(0, std::min(y0, inputRows - 1));
y1 = std::max(0, std::min(y1, inputRows - 1));

double dx = x_in - x0;
double dy = y_in - y0;

double val00 = input_map[y0][x0];
double val10 = input_map[y0][x1];
double val01 = input_map[y1][x0];
double val11 = input_map[y1][x1];

// Compute the interpolated value
double value = (1 - dx) * (1 - dy) * val00
+ dx * (1 - dy) * val10
+ (1 - dx) * dy * val01
+ dx * dy * val11;

output_map[i][j] = value;
}
}
return output_map;
}
2 changes: 2 additions & 0 deletions src/models/firespin/utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ std::string CellStateToString(CellState cell_state);
std::optional<std::filesystem::path> find_project_root(const std::filesystem::path& start);
std::vector<std::vector<int>> PoolingResize(const std::vector<std::vector<int>>& input_map, int new_width, int new_height);
std::vector<std::vector<int>> InterpolationResize(const std::vector<std::vector<int>>& input_map, int new_width, int new_height);
std::vector<std::vector<int>> ResizeFire(const std::vector<std::vector<int>>& input_map, int new_width, int new_height);
std::vector<std::vector<double>> BilinearInterpolation(const std::vector<std::vector<int>>& input_map, int new_width, int new_height);

template <typename T>
class CircularBuffer {
Expand Down
9 changes: 5 additions & 4 deletions src/pysim/agent.py
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@ def get_evaluation_string(self, rewards, terminals, dones, percent_burned):
return False, console

def restructure_data(self, observations_):
all_drone_views, all_velocities, all_maps, all_positions, all_water_dispense = [], [], [], [], []
all_drone_views, all_velocities, all_maps, all_fires, all_positions, all_water_dispense = [], [], [], [], [], []

for deque in observations_:
drone_states = np.array([state for state in deque if isinstance(state, firesim.DroneState)])
Expand All @@ -181,18 +181,19 @@ def restructure_data(self, observations_):
# drone_view = np.array([state.GetDroneViewNorm() for state in drone_states])
drone_view = np.array([state.GetFireStatus() for state in drone_states])
velocities = np.array([state.GetVelocityNorm() for state in drone_states])
maps = np.array([state.GetExplorationMap() for state in drone_states])
#fire_map = np.array([state.GetFireMap() for state in drone_states])
maps = np.array([state.GetExplorationMapNorm() for state in drone_states])
fire_map = np.array([state.GetFireMap() for state in drone_states])
positions = np.array([state.GetPositionNorm() for state in drone_states])
water_dispense = np.array([state.GetWaterDispense() for state in drone_states])

all_drone_views.append(drone_view)
all_velocities.append(velocities)
all_maps.append(maps)
all_fires.append(fire_map)
all_positions.append(positions)
all_water_dispense.append(water_dispense)

return np.array(all_drone_views), np.array(all_maps), np.array(all_velocities), np.array(
all_positions), np.array(all_water_dispense)
all_positions), np.array(all_water_dispense), np.array(all_fires)


4 changes: 2 additions & 2 deletions src/pysim/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,8 @@
"agent_online": True,
"obs_collected": 0,
"num_agents": 1,
"horizon": 20000,
"batch_size": 1000,
"horizon": 12800,
"batch_size": 64,
"auto_train": False, # If True, the agent will train several episodes and then evaluate
"train_episodes": 10, # Number of total trainings containing each max_train steps
"train_episode": 0, # Current training episode
Expand Down
38 changes: 31 additions & 7 deletions src/pysim/network.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,22 @@ def __init__(self, vision_range, time_steps):
explore_out_features = 8

self.explore_flat1 = nn.Linear(in_features=features_explore, out_features=explore_out_features)

self.fire_conv1 = nn.Conv2d(in_channels=layers_dict[0]['in_channels'],
out_channels=layers_dict[0]['out_channels'],
kernel_size=layers_dict[0]['kernel_size'], stride=layers_dict[0]['stride'],
padding=layers_dict[0]['padding'])
self.fire_conv2 = nn.Conv2d(in_channels=layers_dict[1]['in_channels'],
out_channels=layers_dict[1]['out_channels'],
kernel_size=layers_dict[1]['kernel_size'], stride=layers_dict[1]['stride'],
padding=layers_dict[1]['padding'])

in_f = self.get_in_features_2d(h_in=30, w_in=30, layers_dict=layers_dict)
features_fire = in_f * layers_dict[1]['out_channels']
fire_out_features = 8

self.fire_flat1 = nn.Linear(in_features=features_fire, out_features=fire_out_features)

# initialize_hidden_weights(self.explore_flat1)

vel_out_features = 8
Expand All @@ -76,9 +92,9 @@ def __init__(self, vision_range, time_steps):

self.flatten = nn.Flatten()

input_features = explore_out_features + view_out_features + (position_out_features + vel_out_features + water_out_features) * self.time_steps
position_features = explore_out_features + (position_out_features + vel_out_features) * self.time_steps
vicinity_features = view_out_features + water_out_features * self.time_steps
input_features = fire_out_features + explore_out_features + view_out_features + (position_out_features + vel_out_features + water_out_features) * self.time_steps
# position_features = explore_out_features + (position_out_features + vel_out_features) * self.time_steps
# vicinity_features = view_out_features + water_out_features * self.time_steps
self.out_features = 16
self.pos_dense1 = nn.Linear(in_features=input_features, out_features=16)
self.pos_dense2 = nn.Linear(in_features=16, out_features=self.out_features)
Expand Down Expand Up @@ -111,7 +127,7 @@ def get_in_features_3d(self, h_in, w_in, d_in, layers_dict):
return d_in * h_in * w_in

def prepare_tensor(self, states):
drone_view, exploration_map, velocity, position, water_dispense = states
drone_view, exploration_map, velocity, position, water_dispense, fire_map = states

if len(drone_view.shape) == 5:
x, a, b, y, z = drone_view.shape
Expand All @@ -126,6 +142,9 @@ def prepare_tensor(self, states):
if isinstance(exploration_map, np.ndarray):
exploration_map = torch.tensor(exploration_map, dtype=torch.float32).to(device)

if isinstance(fire_map, np.ndarray):
fire_map = torch.tensor(fire_map, dtype=torch.float32).to(device)

if isinstance(velocity, np.ndarray):
velocity = torch.tensor(velocity, dtype=torch.float32).to(device)

Expand All @@ -137,11 +156,11 @@ def prepare_tensor(self, states):
else:
water_dispense = water_dispense.unsqueeze(2).to(device)

return drone_view, exploration_map, velocity, position, water_dispense
return drone_view, exploration_map, velocity, position, water_dispense, fire_map

def forward(self, states):
#terrain, fire_status, velocity, maps, position = self.prepare_tensor(states)
drone_view, exploration_map, velocity, position, water_dispense = self.prepare_tensor(states)
drone_view, exploration_map, velocity, position, water_dispense, fire_map = self.prepare_tensor(states)
view = F.relu(self.view_conv1(drone_view))
view = F.relu(self.view_conv2(view))
view = torch.flatten(view, start_dim=1)
Expand All @@ -152,6 +171,11 @@ def forward(self, states):
explore = torch.flatten(explore, start_dim=1)
explore = F.relu(self.explore_flat1(explore))

fire = F.relu(self.fire_conv1(fire_map))
fire = F.relu(self.fire_conv2(fire))
fire = torch.flatten(fire, start_dim=1)
fire = F.relu(self.fire_flat1(fire))

position = F.relu(self.position_dense1(position))
position = torch.flatten(position, start_dim=1)

Expand All @@ -161,7 +185,7 @@ def forward(self, states):
water = F.relu(self.water_dense1(water_dispense))
water = torch.flatten(water, start_dim=1)

concat_pos = torch.cat((explore, position, velocity, view, water), dim=1)
concat_pos = torch.cat((explore, fire, position, velocity, view, water), dim=1)
# concat_vic = torch.cat((view, water), dim=1)
pos_feature = F.relu(self.pos_dense1(concat_pos))
output_vision = torch.flatten(F.relu(self.pos_dense2(pos_feature)), start_dim=1)
Expand Down
2 changes: 1 addition & 1 deletion src/pysim/ppo.py
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,7 @@ def update(self, memory, horizon, mini_batch_size, next_obs, logger):
# batch_states = (
# states[0][index], states[1][index], states[2][index], states[3][index], states[4][index])
# batch_states = (state[i][index] for state in states)
batch_states = (states[0][index], states[1][index], states[2][index], states[3][index], states[4][index])
batch_states = (states[0][index], states[1][index], states[2][index], states[3][index], states[4][index], states[5][index])
batch_actions = actions[index]
logprobs, values, dist_entropy = self.policy.evaluate(batch_states, batch_actions)

Expand Down
2 changes: 1 addition & 1 deletion src/python_bindings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ PYBIND11_MODULE(firesim, m) {
py::class_<State, std::shared_ptr<State>>(m, "State");

py::class_<DroneState, State, std::shared_ptr<DroneState>>(m, "DroneState")
.def(py::init<std::pair<double, double>, std::pair<double, double>, std::vector<std::vector<std::vector<int>>>, std::vector<std::vector<int>>, std::vector<std::vector<int>>, std::pair<int, int>, std::pair<int, int>, int, double >())
.def(py::init<std::pair<double, double>, std::pair<double, double>, std::vector<std::vector<std::vector<int>>>, std::vector<std::vector<int>>, std::vector<std::vector<double>>, std::pair<int, int>, std::pair<int, int>, int, double >())
.def("SetVelocity", &DroneState::SetVelocity)
.def("GetVelocity", &DroneState::GetVelocity)
.def("GetDroneViewNorm", &DroneState::GetDroneViewNorm)
Expand Down
2 changes: 1 addition & 1 deletion src/reinforcementlearning/drone_agent/drone_state.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ DroneState::DroneState(std::pair<double, double> velocity_vector,
std::pair<double, double> max_speed,
std::vector<std::vector<std::vector<int>>> drone_view,
std::vector<std::vector<int>> exploration_map,
std::vector<std::vector<int>> fire_map,
std::vector<std::vector<double>> fire_map,
std::pair<double, double> map_dimensions,
std::pair<double, double> position,
int water_dispense,
Expand Down
8 changes: 4 additions & 4 deletions src/reinforcementlearning/drone_agent/drone_state.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ class DroneState : public State{
std::pair<double, double> max_speed,
std::vector<std::vector<std::vector<int>>> drone_view,
std::vector<std::vector<int>> exploration_map,
std::vector<std::vector<int>> fire_map,
std::vector<std::vector<double>> fire_map,
std::pair<double, double> map_dimensions,
std::pair<double, double> position,
int water_dispense,
Expand All @@ -39,7 +39,7 @@ class DroneState : public State{
std::vector<std::vector<int>> GetTerrain() { return drone_view_[0]; }
std::vector<std::vector<int>> GetFireStatus() { return drone_view_[1]; }
std::vector<std::vector<int>> GetExplorationMap() { return exploration_map_; }
std::vector<std::vector<int>> GetFireMap() { return fire_map_; }
std::vector<std::vector<double>> GetFireMap() { return fire_map_; }
int GetWaterDispense() { return water_dispense_; }
std::vector<std::vector<double>> GetExplorationMapNorm() const;
static std::vector<std::vector<double>> GetMapNorm();
Expand All @@ -53,7 +53,7 @@ class DroneState : public State{
std::pair<double, double> get_velocity() const { return velocity_; }
std::vector<std::vector<std::vector<int>>> get_drone_view() const { return drone_view_; }
std::vector<std::vector<int>> get_map() const { return exploration_map_; }
std::vector<std::vector<int>> get_fire_map() const { return fire_map_; }
std::vector<std::vector<double>> get_fire_map() const { return fire_map_; }
std::pair<int, int> get_position() const { return position_; }
std::pair<double, double> get_orientation_vector() const { return orientation_vector_; }
private:
Expand All @@ -66,7 +66,7 @@ class DroneState : public State{
std::pair<double, double> position_; // x, y
std::vector<std::vector<std::vector<int>>> drone_view_; // terrain, fire_status split at the first dimension
std::vector<std::vector<int>> exploration_map_;
std::vector<std::vector<int>> fire_map_;
std::vector<std::vector<double>> fire_map_;
std::pair<double, double> orientation_vector_; // x, y
double DiscretizeOutput(double netout);
};
Expand Down
Loading

0 comments on commit cfb9bf1

Please sign in to comment.