-
Notifications
You must be signed in to change notification settings - Fork 69
[ENVIRONMENT] Wildfire Environment to simulate Wildfires for OpenEnv (FastAPI, RL-compatible) #108
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
|
Hi @shankerram3! Thank you for your pull request and welcome to our community. Action RequiredIn order to merge any pull request (code, docs, etc.), we require contributors to sign our Contributor License Agreement, and we don't seem to have one on file for you. ProcessIn order for us to review and merge your suggested changes, please sign at https://code.facebook.com/cla. If you are contributing on behalf of someone else (eg your employer), the individual CLA may not be sufficient and your employer may need to sign the corporate CLA. Once the CLA is signed, our tooling will perform checks and validations. Afterwards, the pull request will be tagged with If you have received this in error or have any questions, please contact us at [email protected]. Thanks! |
|
Thank you for signing our Contributor License Agreement. We can now accept your code for this (and any) Meta Open Source project. Thanks! |
Updated README with sample rendering code for wildfree simulation.
Added sections on wildfire simulation motivation, research goals, and citations to the README.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This PR introduces a new wildfire simulation environment to the OpenEnv framework. The environment models fire spread dynamics influenced by wind, humidity, and limited resources (water and firebreaks), enabling RL agents to learn fire containment strategies.
Key Changes
- Implements
WildfireEnvironmentwith physics-based fire spread mechanics including wind direction effects, humidity suppression, and multi-tick burn lifetime - Adds Docker containerization support with build scripts and Dockerfile for deployment
- Provides client-side API with visualization utilities for rendering the grid state
Reviewed Changes
Copilot reviewed 14 out of 14 changed files in this pull request and generated 9 comments.
Show a summary per file
| File | Description |
|---|---|
src/envs/wildfire_env/server/wildfire_environment.py |
Core server implementation with fire spread logic, reward shaping, and action handling |
src/envs/wildfire_env/models.py |
Data models for actions, observations, and state |
src/envs/wildfire_env/client.py |
HTTP client implementation with grid rendering utility |
src/envs/wildfire_env/server/app.py |
FastAPI application entry point |
src/envs/wildfire_env/server/Dockerfile |
Docker container configuration |
src/envs/wildfire_env/server/build_docker.sh |
Docker build script |
src/envs/wildfire_env/README.md |
Comprehensive documentation with usage examples |
src/envs/wildfire_env/__init__.py |
Package initialization and exports |
src/envs/wildfire_env/server/__init__.py |
Server package initialization |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| # --- Required abstract property implementation --- | ||
| @property | ||
| def state(self) -> WildfireState: | ||
| """Return the current environment state.""" | ||
| return self._state |
Copilot
AI
Oct 31, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Inconsistent indentation detected. Lines 364-368 have mixed indentation levels. Line 364 has excessive leading whitespace, line 367 has only 1 space of indentation instead of the expected 8 spaces for a method body. Standardize to use consistent 4-space indentation throughout.
| # --- Required abstract property implementation --- | |
| @property | |
| def state(self) -> WildfireState: | |
| """Return the current environment state.""" | |
| return self._state | |
| # --- Required abstract property implementation --- | |
| @property | |
| def state(self) -> WildfireState: | |
| """Return the current environment state.""" | |
| return self._state |
| burned_count: int # total ash (0) cells (cumulative) | ||
| reward_hint: float = 0.0 | ||
| remaining_water: int = 0 | ||
| remaining_breaks: int = 0# optional shaping info |
Copilot
AI
Oct 31, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The comment '# optional shaping info' on line 28 is misplaced. It should be on line 26 or 27, or removed entirely since it doesn't accurately describe the resource fields on lines 27-28. The comment appears to be a leftover from line 26's reward_hint field.
| remaining_breaks: int = 0# optional shaping info | |
| remaining_breaks: int = 0 |
| rows = [] | ||
| for y in range(h): | ||
| rows.append("".join(legend.get(g[y*w+x], "?") for x in range(w))) | ||
| meta = f"step={obs.step} wind={obs.wind_dir} hum={obs.humidity:.2f} burning={obs.burning_count} burned= {obs.burned_count}" |
Copilot
AI
Oct 31, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Excessive whitespace after 'burned=' creates inconsistent spacing in the output string. Replace the multiple spaces with a single space for consistent formatting.
| meta = f"step={obs.step} wind={obs.wind_dir} hum={obs.humidity:.2f} burning={obs.burning_count} burned= {obs.burned_count}" | |
| meta = f"step={obs.step} wind={obs.wind_dir} hum={obs.humidity:.2f} burning={obs.burning_count} burned= {obs.burned_count}" |
| ) | ||
|
|
||
| def _parse_state(self, payload: dict) -> WildfireState: | ||
| return WildfireState(**payload) |
Copilot
AI
Oct 31, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missing blank lines before function definition. PEP 8 requires two blank lines before top-level function definitions. Add a blank line between line 18 and line 19.
| return WildfireState(**payload) | |
| return WildfireState(**payload) |
| ``` | ||
|
|
||
| --- | ||
| ## Sample rendering to see wildfree simulation |
Copilot
AI
Oct 31, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Corrected spelling of 'wildfree' to 'wildfire'.
| ## Sample rendering to see wildfree simulation | |
| ## Sample rendering to see wildfire simulation |
| @@ -0,0 +1,321 @@ | |||
| import os | |||
| import random, uuid | |||
| from typing import List | |||
Copilot
AI
Oct 31, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Import of 'List' is not used.
| from typing import List |
| from dataclasses import replace | ||
|
|
Copilot
AI
Oct 31, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Import of 'replace' is not used.
| from dataclasses import replace |
|
|
||
| import os | ||
| import random, uuid | ||
| from typing import List |
Copilot
AI
Oct 31, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Import of 'List' is not used.
| from typing import List |
| import os | ||
| import random, uuid | ||
| from typing import List | ||
| from dataclasses import replace |
Copilot
AI
Oct 31, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Import of 'replace' is not used.
| from dataclasses import replace |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wowwww this is soo cool!!! Thank you for the contribution :)
I can see a few small things that we should change, but otherwise we are almost ready to land.
Also, could you add an example? examples/wildfire.py would be awesome...
| @@ -0,0 +1,10 @@ | |||
| # server/app.py | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wait, what does this directory do? .ipynb_checkpoints doesn't look like a directory that you wanna check in! :D
|
|
||
| from IPython.display import clear_output, display | ||
| import matplotlib.colors as mcolors | ||
| sys.path.append("/workspace/OpenEnv/src") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hardcoded path
| from ..models import WildfireAction, WildfireObservation | ||
| from .wildfire_environment import WildfireEnvironment | ||
|
|
||
| W = int(os.getenv("WILDFIRE_W", "16")) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The naming is inconsistent, because in wildfire_environment.py you actually use WILDFIRE_WIDTH. Same thing for height
| from envs.wildfire_env.server.wildfire_environment import WildfireEnvironment | ||
|
|
||
|
|
||
| client = WildfireEnv("http://localhost:8020") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's use port 8000 for these examples
| time.sleep(0.3) | ||
|
|
||
|
|
||
| res = client.step(WildfireAction(action="WAIT")) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The actual action is lowercase "wait" though
| import numpy as np | ||
| import time, sys | ||
|
|
||
| from IPython.display import clear_output, display |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is jupyter specific but won't work in standalone Python
| remaining_breaks: int = 0# optional shaping info | ||
|
|
||
| @dataclass | ||
| class WildfireState(State): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should add burn_timers here. They currently get added dynamically upon reset which breaks type safety
| ) | ||
|
|
||
| # per-cell burn timers (persist across steps) | ||
| self._state.burn_timers = [0] * (self.w * self.h) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See my comment in models.py
No description provided.