Skip to content
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

Release gil for long running functions #50

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions nocturne/cpp/src/simulation.cc
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ void Simulation::Render() {
constexpr int64_t kWinHeight = 800;

sf::ContextSettings settings;
settings.antialiasingLevel = std::min(sf::RenderTexture::getMaximumAntialiasingLevel(), 4u);
settings.antialiasingLevel =
std::min(sf::RenderTexture::getMaximumAntialiasingLevel(), 4u);
render_window_ = std::make_unique<sf::RenderWindow>(
sf::VideoMode(kWinWidth, kWinHeight), "Nocturne", sf::Style::Default,
settings);
Expand All @@ -35,7 +36,7 @@ void Simulation::Render() {

// draw scenario
render_window_->draw(*scenario_);

// draw frames per seconds on screen
sf::Time elapsed = clock_.restart();
float fps = 1.0f / elapsed.asSeconds();
Expand Down
130 changes: 111 additions & 19 deletions nocturne/pybind11/src/scenario.cc
Original file line number Diff line number Diff line change
Expand Up @@ -40,28 +40,44 @@ void DefineScenario(py::module& m) {
.def("objects", &Scenario::objects, py::return_value_policy::reference)
.def("moving_objects", &Scenario::moving_objects,
py::return_value_policy::reference)
.def("remove_object", &Scenario::RemoveObject)
.def("road_lines", &Scenario::road_lines)

.def("remove_object", &Scenario::RemoveObject,
py::call_guard<py::gil_scoped_release>())
.def("ego_state",
[](const Scenario& scenario, const Object& src) {
return utils::AsNumpyArray(scenario.EgoState(src));
NdArray<float> ret;
{
py::gil_scoped_release release;
ret = scenario.EgoState(src);
}
return utils::AsNumpyArray(std::move(ret));
})
.def(
"visible_state",
[](const Scenario& scenario, const Object& src, float view_dist,
float view_angle, float head_angle, bool padding) {
return utils::AsNumpyArrayDict(
scenario.VisibleState(src, view_dist, view_angle, head_angle, padding));
std::unordered_map<std::string, NdArray<float>> ret;
{
py::gil_scoped_release release;
ret = scenario.VisibleState(src, view_dist, view_angle,
head_angle, padding);
}
return utils::AsNumpyArrayDict(std::move(ret));
},
py::arg("object"), py::arg("view_dist") = 60,
py::arg("view_angle") = kHalfPi, py::arg("head_angle") = 0.0, py::arg("padding") = false)
py::arg("view_angle") = kHalfPi, py::arg("head_angle") = 0.0,
py::arg("padding") = false)
.def(
"flattened_visible_state",
[](const Scenario& scenario, const Object& src, float view_dist,
float view_angle, float head_angle) {
return utils::AsNumpyArray(scenario.FlattenedVisibleState(
src, view_dist, view_angle, head_angle));
NdArray<float> ret;
{
py::gil_scoped_release release;
ret = scenario.FlattenedVisibleState(src, view_dist, view_angle,
head_angle);
}
return utils::AsNumpyArray(std::move(ret));
},
py::arg("object"), py::arg("view_dist") = 60,
py::arg("view_angle") = kHalfPi, py::arg("head_angle") = 0.0)
Expand All @@ -71,6 +87,69 @@ void DefineScenario(py::module& m) {
.def("expert_action", &Scenario::ExpertAction)
.def("expert_pos_shift", &Scenario::ExpertPosShift)
.def("expert_heading_shift", &Scenario::ExpertHeadingShift)
.def(
"image",
[](Scenario& scenario, uint64_t img_height, uint64_t img_width,
bool draw_target_positions, float padding, Object* source,
uint64_t view_height, uint64_t view_width,
bool rotate_with_source) {
NdArray<unsigned char> ret;
{
py::gil_scoped_release release;
ret = scenario.Image(img_height, img_width, draw_target_positions,
padding, source, view_height, view_width,
rotate_with_source);
}
return utils::AsNumpyArray<unsigned char>(std::move(ret));
},
"Return a numpy array of dimension (img_height, img_width, 4) "
"representing an image of the scene.",
py::arg("img_height") = 1000, py::arg("img_width") = 1000,
py::arg("draw_target_positions") = true, py::arg("padding") = 50.0f,
py::arg("source") = nullptr, py::arg("view_height") = 200,
py::arg("view_width") = 200, py::arg("rotate_with_source") = true)
.def(
"feature_image",
[](Scenario& scenario, const Object& source, float view_dist,
float view_angle, float head_angle, uint64_t img_height,
uint64_t img_width, float padding, bool draw_target_position) {
NdArray<unsigned char> ret;
{
py::gil_scoped_release release;
ret = scenario.EgoVehicleFeaturesImage(
source, view_dist, view_angle, head_angle, img_height,
img_width, padding, draw_target_position);
}
return utils::AsNumpyArray<unsigned char>(std::move(ret));
},
"Return a numpy array of dimension (img_height, img_width, 4) "
"representing an image of what is returned by getVisibleState(?).",
py::arg("source"), py::arg("view_dist") = 120.0f,
py::arg("view_angle") = geometry::utils::kPi * 0.8f,
py::arg("head_angle") = 0.0f, py::arg("img_height") = 1000,
py::arg("img_width") = 1000, py::arg("padding") = 0.0f,
py::arg("draw_target_position") = true)
.def(
"cone_image",
[](Scenario& scenario, const Object& source, float view_dist,
float view_angle, float head_angle, uint64_t img_height,
uint64_t img_width, float padding, bool draw_target_position) {
NdArray<unsigned char> ret;
{
py::gil_scoped_release release;
ret = scenario.EgoVehicleConeImage(
source, view_dist, view_angle, head_angle, img_height,
img_width, padding, draw_target_position);
}
return utils::AsNumpyArray<unsigned char>(std::move(ret));
},
"Return a numpy array of dimension (img_height, img_width, 4) "
"representing a cone of what the agent sees.",
py::arg("source"), py::arg("view_dist") = 120.0f,
py::arg("view_angle") = geometry::utils::kPi * 0.8f,
py::arg("head_angle") = 0.0f, py::arg("img_height") = 1000,
py::arg("img_width") = 1000, py::arg("padding") = 0.0f,
py::arg("draw_target_position") = true)

// TODO: Deprecate the legacy interfaces below.
.def("getVehicles", &Scenario::vehicles,
Expand All @@ -89,9 +168,14 @@ void DefineScenario(py::module& m) {
bool draw_target_positions, float padding, Object* source,
uint64_t view_height, uint64_t view_width,
bool rotate_with_source) {
return utils::AsNumpyArray<unsigned char>(scenario.Image(
img_height, img_width, draw_target_positions, padding, source,
view_height, view_width, rotate_with_source));
NdArray<unsigned char> ret;
{
py::gil_scoped_release release;
ret = scenario.Image(img_height, img_width, draw_target_positions,
padding, source, view_height, view_width,
rotate_with_source);
}
return utils::AsNumpyArray<unsigned char>(std::move(ret));
},
"Return a numpy array of dimension (img_height, img_width, 4) "
"representing an image of the scene.",
Expand All @@ -104,10 +188,14 @@ void DefineScenario(py::module& m) {
[](Scenario& scenario, const Object& source, float view_dist,
float view_angle, float head_angle, uint64_t img_height,
uint64_t img_width, float padding, bool draw_target_position) {
return utils::AsNumpyArray<unsigned char>(
scenario.EgoVehicleFeaturesImage(
source, view_dist, view_angle, head_angle, img_height,
img_width, padding, draw_target_position));
NdArray<unsigned char> ret;
{
py::gil_scoped_release release;
ret = scenario.EgoVehicleFeaturesImage(
source, view_dist, view_angle, head_angle, img_height,
img_width, padding, draw_target_position);
}
return utils::AsNumpyArray<unsigned char>(std::move(ret));
},
"Return a numpy array of dimension (img_height, img_width, 4) "
"representing an image of what is returned by getVisibleState(?).",
Expand All @@ -121,10 +209,14 @@ void DefineScenario(py::module& m) {
[](Scenario& scenario, const Object& source, float view_dist,
float view_angle, float head_angle, uint64_t img_height,
uint64_t img_width, float padding, bool draw_target_position) {
return utils::AsNumpyArray<unsigned char>(
scenario.EgoVehicleConeImage(source, view_dist, view_angle,
head_angle, img_height, img_width,
padding, draw_target_position));
NdArray<unsigned char> ret;
{
py::gil_scoped_release release;
ret = scenario.EgoVehicleConeImage(
source, view_dist, view_angle, head_angle, img_height,
img_width, padding, draw_target_position);
}
return utils::AsNumpyArray<unsigned char>(std::move(ret));
},
"Return a numpy array of dimension (img_height, img_width, 4) "
"representing a cone of what the agent sees.",
Expand Down
7 changes: 4 additions & 3 deletions nocturne/pybind11/src/simulation.cc
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,12 @@ void DefineSimulation(py::module& m) {
py::arg("config") =
std::unordered_map<std::string,
std::variant<bool, int64_t, float>>())
.def("reset", &Simulation::Reset)
.def("step", &Simulation::Step)
.def("render", &Simulation::Render)
.def("reset", &Simulation::Reset,
py::call_guard<py::gil_scoped_release>())
.def("step", &Simulation::Step, py::call_guard<py::gil_scoped_release>())
.def("scenario", &Simulation::GetScenario,
py::return_value_policy::reference)
.def("render", &Simulation::Render)
.def("save_screenshot", &Simulation::SaveScreenshot)

// TODO: Deprecate the legacy methods below.
Expand Down
2 changes: 1 addition & 1 deletion tests/test_dynamics.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ def test_inverse_dynamics():
id2obj_ground_truth = {obj.id: obj for obj in objects_ground_truth}
# create a test sim that will replay actions from inverse dynamics
sim_test, objects_test = _create_sim(file_path, expert_control=False)
scenario_test = sim_test.getScenario()
scenario_test = sim_test.scenario()

# step simulation
for time in range(SIM_N_STEPS):
Expand Down
16 changes: 8 additions & 8 deletions tests/test_rl_env.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,15 +28,15 @@ def test_rl_env():
times = []
_ = env.reset()
# quick check that rendering works
_ = env.scenario.getConeImage(env.scenario.getVehicles()[0],
80.0,
120 * (np.pi / 180),
0.0,
draw_target_position=False)
_ = env.scenario.cone_image(env.scenario.vehicles()[0],
80.0,
120 * (np.pi / 180),
0.0,
draw_target_position=False)
for _ in range(90):
vehs = env.scenario.getObjectsThatMoved()
vehs = env.scenario.moving_objects()
prev_position = {
veh.getID(): [veh.position.x, veh.position.y]
veh.id: [veh.position.x, veh.position.y]
for veh in vehs
}
t = time.perf_counter()
Expand All @@ -45,7 +45,7 @@ def test_rl_env():
for veh in vehs})
times.append(time.perf_counter() - t)
for veh in vehs:
if veh in env.scenario.getObjectsThatMoved():
if veh in env.scenario.moving_objects():
new_position = [veh.position.x, veh.position.y]
assert prev_position[veh.getID(
)] != new_position, f'veh {veh.getID()} was in position \
Expand Down
Loading