From aaa1254090580cae81f7410f75ac27af68888da6 Mon Sep 17 00:00:00 2001 From: pockerman Date: Wed, 1 Jan 2025 16:39:35 +0000 Subject: [PATCH 1/5] Update environments to facilitate API server (#120) --- CMakeLists.txt | 2 +- README.md | 6 +- examples/example_1/example_1.cpp | 35 ++++-- examples/example_2/example_2.cpp | 4 +- examples/example_3/example_3.cpp | 5 +- examples/example_6/example_6.cpp | 8 +- examples/example_8/example_8.cpp | 8 +- src/rlenvs/api_server/apiserver.cpp | 45 ------- src/rlenvs/api_server/apiserver.h | 45 ------- .../gymnasium/classic_control/acrobot_env.cpp | 98 ++++++--------- .../gymnasium/classic_control/acrobot_env.h | 20 +-- .../classic_control/cart_pole_env.cpp | 92 +++++--------- .../gymnasium/classic_control/cart_pole_env.h | 21 ++-- .../classic_control/mountain_car_env.cpp | 86 +++++-------- .../classic_control/mountain_car_env.h | 56 ++------- .../classic_control/pendulum_env.cpp | 88 +++++--------- .../gymnasium/classic_control/pendulum_env.h | 17 ++- .../vector/acrobot_vec_env.cpp | 105 +++++++--------- .../classic_control/vector/acrobot_vec_env.h | 14 ++- .../envs/gymnasium/gymnasium_env_base.h | 112 ++++++++--------- .../gymnasium/gymnasium_vector_env_base.h | 19 ++- .../gymnasium/toy_text/black_jack_env.cpp | 114 +++++++----------- .../envs/gymnasium/toy_text/black_jack_env.h | 18 ++- .../gymnasium/toy_text/cliff_world_env.cpp | 107 ++++++---------- .../envs/gymnasium/toy_text/cliff_world_env.h | 21 ++-- .../gymnasium/toy_text/frozen_lake_env.cpp | 114 ++++++------------ .../envs/gymnasium/toy_text/frozen_lake_env.h | 17 ++- .../envs/gymnasium/toy_text/taxi_env.cpp | 111 ++++++----------- src/rlenvs/envs/gymnasium/toy_text/taxi_env.h | 21 ++-- .../envs/gymnasium/toy_text/toy_text_base.h | 56 +++++---- src/rlenvs/rlenvscpp_version.h | 4 +- tests/CMakeLists.txt | 1 + 32 files changed, 578 insertions(+), 892 deletions(-) delete mode 100644 src/rlenvs/api_server/apiserver.cpp delete mode 100644 src/rlenvs/api_server/apiserver.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 31f86bc..9beb894 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -95,8 +95,8 @@ INCLUDE_DIRECTORIES(${Boost_INCLUDE_DIRS}) INCLUDE_DIRECTORIES(src/) FILE(GLOB SRCS src/rlenvs/*.cpp - src/rlenvs/api_server/*.cpp src/rlenvs/envs/*.cpp + src/rlenvs/envs/api_server/*.cpp src/rlenvs/envs/gymnasium/*.cpp src/rlenvs/envs/gymnasium/toy_text/*.cpp src/rlenvs/envs/gymnasium/classic_control/*.cpp diff --git a/README.md b/README.md index f25c220..16cef36 100644 --- a/README.md +++ b/README.md @@ -26,9 +26,9 @@ Currently, we provide a minimal number of wrappers for some common Gymnasium (fo There exist some wrappers for vector environments: -| Environment | REST | Example | -| :---------------- | :------: | :----: | -| AcrobotV | Yes | TODO | +| Environment | REST | Example | +| :---------------- | :------: | :----: | +| AcrobotV | Yes | example_8 | Various RL algorithms using the environments can be found at cuberl diff --git a/examples/example_1/example_1.cpp b/examples/example_1/example_1.cpp index bc04245..60503a2 100644 --- a/examples/example_1/example_1.cpp +++ b/examples/example_1/example_1.cpp @@ -3,6 +3,7 @@ #include "rlenvs/envs/gymnasium/toy_text/taxi_env.h" #include "rlenvs/envs/gymnasium/toy_text/black_jack_env.h" #include "rlenvs/envs/gymnasium/toy_text/cliff_world_env.h" +#include "rlenvs/envs/api_server/apiserver.h" #include #include @@ -13,9 +14,16 @@ namespace example_1{ const std::string SERVER_URL = "http://0.0.0.0:8001/api"; -void test_frozen_lake(){ +using rlenvscpp::envs::gymnasium::FrozenLake; +using rlenvscpp::envs::gymnasium::Taxi; +using rlenvscpp::envs::gymnasium::BlackJack; +using rlenvscpp::envs::gymnasium::CliffWorld; +using rlenvscpp::envs::RESTApiServerWrapper; - rlenvscpp::envs::gymnasium::FrozenLake<4> env(SERVER_URL); + +void test_frozen_lake(const RESTApiServerWrapper& server){ + + FrozenLake<4> env(server); std::cout<<"Environame URL: "< options; options["natural"] = true; @@ -180,9 +188,9 @@ void test_black_jack(){ } -void test_cliff_world(){ +void test_cliff_world(const RESTApiServerWrapper& server){ - rlenvscpp::envs::gymnasium::CliffWorld env(SERVER_URL); + CliffWorld env(server); std::cout<<"Environment URL: "< #include @@ -6,7 +6,7 @@ int main(){ const std::string SERVER_URL = "http://0.0.0.0:8001/api"; - rlenvscpp::ApiServerWrapper server_wrapper(SERVER_URL); + rlenvscpp::envs::RESTApiServerWrapper server_wrapper(SERVER_URL); auto has_gym = server_wrapper.has_gymnasium(); std::cout<<"Has environment server Gymnasium? "< @@ -14,11 +15,14 @@ int main(){ using namespace rlenvscpp::envs::gymnasium; using rlenvscpp::uint_t; + using rlenvscpp::envs::RESTApiServerWrapper; - const std::string url = "http://0.0.0.0:8001/api"; + const std::string SERVER_URL = "http://0.0.0.0:8001/api"; + RESTApiServerWrapper server(SERVER_URL, true); + // Acrobot vector environment - AcrobotV env(url); + AcrobotV env(server); std::cout<<"Name: "< -// SPDX-License-Identifier: Apache-2.0 - -#include "rlenvs/api_server/apiserver.h" -#include "rlenvs/extern/HTTPRequest.hpp" -#include "rlenvs/extern/nlohmann/json/json.hpp" - -#include - -namespace rlenvscpp{ - -ApiServerWrapper::ApiServerWrapper(const std::string& url) -: -url_(url) -{} - -bool -ApiServerWrapper::has_gymnasium()const{ - - const auto request_url = url_ + "/api-info/gymnasium"; - http::Request request{request_url}; - - const auto response = request.send("GET"); - return response.status.code == 200; - -} - -std::vector -ApiServerWrapper::gymnasium_envs()const{ - - const auto request_url = url_ + "/api-info/gymnasium/envs"; - http::Request request{request_url}; - - const auto response = request.send("GET"); - - if(response.status.code != 200){ - throw std::runtime_error("Environment server responded with error"); - } - - auto str_response = std::string(response.body.begin(), response.body.end()); - using json = nlohmann::json; - json j = json::parse(str_response); - return j["envs"]; -} -} diff --git a/src/rlenvs/api_server/apiserver.h b/src/rlenvs/api_server/apiserver.h deleted file mode 100644 index 350b954..0000000 --- a/src/rlenvs/api_server/apiserver.h +++ /dev/null @@ -1,45 +0,0 @@ -// SPDX-FileCopyrightText: 2024 -// SPDX-License-Identifier: Apache-2.0 - -#ifndef APISERVER_H -#define APISERVER_H - - -#include -#include - -/** - * @todo write docs - */ - - -namespace rlenvscpp{ - -class ApiServerWrapper -{ -public: - - /// - /// \brief Constructor - /// - ApiServerWrapper(const std::string& url); - - /// - /// - /// - bool has_gymnasium()const; - - /// - /// - /// - std::vector gymnasium_envs()const; - -private: - - const std::string url_; - - -}; - -} -#endif // APISERVER_H diff --git a/src/rlenvs/envs/gymnasium/classic_control/acrobot_env.cpp b/src/rlenvs/envs/gymnasium/classic_control/acrobot_env.cpp index 518c3fa..6946084 100644 --- a/src/rlenvs/envs/gymnasium/classic_control/acrobot_env.cpp +++ b/src/rlenvs/envs/gymnasium/classic_control/acrobot_env.cpp @@ -10,46 +10,44 @@ namespace envs{ namespace gymnasium{ const std::string Acrobot::name = "Acrobot"; - -Acrobot::time_step_type -Acrobot::create_time_step_from_response_(const http::Response& response)const{ - - auto str_response = std::string(response.body.begin(), response.body.end()); - using json = nlohmann::json; +const std::string Acrobot::URI = "/gymnasium/acrobot-env"; - json j = json::parse(str_response); +Acrobot::time_step_type +Acrobot::create_time_step_from_response_(const nlohmann::json& response)const{ - auto step_type = j["time_step"]["step_type"].template get(); - auto reward = j["time_step"]["reward"]; - auto discount = j["time_step"]["discount"]; - auto observation = j["time_step"]["observation"]; - auto info = j["time_step"]["info"]; + auto step_type = response["time_step"]["step_type"].template get(); + auto reward = response["time_step"]["reward"]; + auto discount = response["time_step"]["discount"]; + auto obs = response["time_step"]["observation"]; + auto info = response["time_step"]["info"]; return Acrobot::time_step_type(TimeStepEnumUtils::time_step_type_from_int(step_type), - reward, observation, discount, + reward, obs, discount, std::unordered_map()); } -Acrobot::Acrobot(const std::string& api_base_url) +Acrobot::Acrobot(const RESTApiServerWrapper& api_server) : GymnasiumEnvBase >, ContinuousVectorStateDiscreteActionEnv<6, 2, 0, real_t > - >(0, - "Acrobot", - api_base_url, - "/gymnasium/acrobot-env") -{} + >(api_server, + 0, + Acrobot::name) +{ + this -> get_api_server().register_if_not(Acrobot::name, Acrobot::URI); +} -Acrobot::Acrobot(const std::string& api_base_url, +Acrobot::Acrobot(const RESTApiServerWrapper& api_server, const uint_t cidx) : GymnasiumEnvBase >, ContinuousVectorStateDiscreteActionEnv<6, 2, 0, real_t > - >(cidx, - "Acrobot", - api_base_url, - "/gymnasium/acrobot-env") -{} + >(api_server, + cidx, + Acrobot::name) +{ + this -> get_api_server().register_if_not(Acrobot::name, Acrobot::URI); +} Acrobot::Acrobot(const Acrobot& other) : @@ -66,19 +64,9 @@ Acrobot::make(const std::string& version, return; } - const auto request_url = std::string(this->get_url()) + "/make"; - http::Request request{request_url}; - - using json = nlohmann::json; - json j; - j["version"] = version; - j["cidx"] = this -> cidx(); - - const auto response = request.send("POST", j.dump()); - - if(response.status.code != 201){ - throw std::runtime_error("Environment server failed to create Environment"); - } + auto response = this -> get_api_server().make(this -> env_name(), + this -> cidx(), + version, nlohmann::json()); this->set_version_(version); this->make_created_(); @@ -95,20 +83,10 @@ Acrobot::step(const action_type& action){ if(this->get_current_time_step_().last()){ return this->reset(42, std::unordered_map()); } - - const auto request_url = std::string(this->get_url()) + "/step"; - http::Request request{request_url}; - - using json = nlohmann::json; - json j; - j["action"] = action; - j["cidx"] = this -> cidx(); - - const auto response = request.send("POST", j.dump()); - - if(response.status.code != 202){ - throw std::runtime_error("Environment server failed to step environment"); - } + + const auto response = this -> get_api_server().step(this -> env_name(), + this -> cidx(), + action); this->get_current_time_step_() = this->create_time_step_from_response_(response); return this->get_current_time_step_(); @@ -116,14 +94,14 @@ Acrobot::step(const action_type& action){ Acrobot Acrobot::make_copy(uint_t cidx)const{ - auto api_base_url = this -> get_api_url(); - - Acrobot copy(api_base_url, cidx); - - std::unordered_map ops; - auto version = this -> version(); - copy.make(version, ops); - return copy; +// auto api_base_url = this -> get_api_url(); +// +// Acrobot copy(api_base_url, cidx); +// +// std::unordered_map ops; +// auto version = this -> version(); +// copy.make(version, ops); +// return copy; } diff --git a/src/rlenvs/envs/gymnasium/classic_control/acrobot_env.h b/src/rlenvs/envs/gymnasium/classic_control/acrobot_env.h index 3744409..b4c9b31 100644 --- a/src/rlenvs/envs/gymnasium/classic_control/acrobot_env.h +++ b/src/rlenvs/envs/gymnasium/classic_control/acrobot_env.h @@ -117,9 +117,9 @@ #include "rlenvs/rlenvs_types_v2.h" #include "rlenvs/envs/time_step.h" #include "rlenvs/envs/gymnasium/gymnasium_env_base.h" +#include "rlenvs/envs/api_server/apiserver.h" #include "rlenvs/envs/env_types.h" -#include "rlenvs/extern/HTTPRequest.hpp" - +#include "rlenvs/extern/nlohmann/json/json.hpp" #include #include @@ -145,11 +145,16 @@ class Acrobot final: public GymnasiumEnvBase >, /// static const std::string name; + /// + /// \brief The URI for accessing the environment + /// + static const std::string URI; + /// /// \brief Base class type /// typedef GymnasiumEnvBase >, - ContinuousVectorStateDiscreteActionEnv< 6, // size of state + ContinuousVectorStateDiscreteActionEnv< 6, // size of state space 2, // end of action space 0, // start of action space real_t> // type of state @@ -183,12 +188,12 @@ class Acrobot final: public GymnasiumEnvBase >, /// /// \brief Acrobot. Constructor /// - Acrobot(const std::string& api_base_url ); + Acrobot(const RESTApiServerWrapper& api_server ); /// /// \brief CartPole. Constructor /// - Acrobot(const std::string& api_base_url, + Acrobot(const RESTApiServerWrapper& api_server, const uint_t cidx); /// @@ -223,15 +228,12 @@ class Acrobot final: public GymnasiumEnvBase >, /// uint_t n_actions()const noexcept{return action_space_type::size;} - protected: - - /// /// \brief Handle the reset response from the environment server /// - virtual time_step_type create_time_step_from_response_(const http::Response& response) const override final; + virtual time_step_type create_time_step_from_response_(const nlohmann::json& response) const override final; }; diff --git a/src/rlenvs/envs/gymnasium/classic_control/cart_pole_env.cpp b/src/rlenvs/envs/gymnasium/classic_control/cart_pole_env.cpp index 351dbb1..72a4f01 100644 --- a/src/rlenvs/envs/gymnasium/classic_control/cart_pole_env.cpp +++ b/src/rlenvs/envs/gymnasium/classic_control/cart_pole_env.cpp @@ -9,50 +9,44 @@ #include #endif -#include -#include - namespace rlenvscpp{ namespace envs { namespace gymnasium{ const std::string CartPole::name = "CartPole"; - +const std::string CartPole::URI = "/gymnasium/cart-pole-env"; CartPole::time_step_type -CartPole::create_time_step_from_response_(const http::Response& response)const{ - - auto str_response = std::string(response.body.begin(), response.body.end()); - using json = nlohmann::json; - - json j = json::parse(str_response); +CartPole::create_time_step_from_response_(const nlohmann::json& response)const{ - auto step_type = j["time_step"]["step_type"].template get(); - auto reward = j["time_step"]["reward"]; - auto discount = j["time_step"]["discount"]; - auto observation = j["time_step"]["observation"]; - auto info = j["time_step"]["info"]; + auto step_type = response["time_step"]["step_type"].template get(); + auto reward = response["time_step"]["reward"]; + auto discount = response["time_step"]["discount"]; + auto obs = response["time_step"]["observation"]; + auto info = response["time_step"]["info"]; return CartPole::time_step_type(TimeStepEnumUtils::time_step_type_from_int(step_type), - reward, observation, discount, + reward, obs, discount, std::unordered_map()); } -CartPole::CartPole(const std::string& api_base_url) +CartPole::CartPole(const RESTApiServerWrapper& api_server) : GymnasiumEnvBase >, - ContinuousVectorStateDiscreteActionEnv<4, 2, 0, real_t >>(0, "CartPole", - api_base_url, - "/gymnasium/cart-pole-env") -{} + ContinuousVectorStateDiscreteActionEnv<4, 2, 0, real_t >>(api_server, 0, CartPole::name) +{ + this -> get_api_server().register_if_not(CartPole::name, CartPole::URI); +} -CartPole::CartPole(const std::string& api_base_url, +CartPole::CartPole(const RESTApiServerWrapper& api_server, const uint_t cidx) : GymnasiumEnvBase >, - ContinuousVectorStateDiscreteActionEnv<4, 2, 0, real_t >>(cidx, "CartPole", - api_base_url, - "/gymnasium/cart-pole-env") -{} + ContinuousVectorStateDiscreteActionEnv<4, 2, 0, real_t >>(api_server, + cidx, + CartPole::name) +{ + this -> get_api_server().register_if_not(CartPole::name, CartPole::URI); +} CartPole::CartPole(const CartPole& other) : @@ -68,20 +62,10 @@ CartPole::make(const std::string& version, return; } - const auto request_url = std::string(this->get_url()) + "/make"; - http::Request request{request_url}; - using json = nlohmann::json; - json j; - j["version"] = version; - j["cidx"] = this -> cidx(); - - auto body = j.dump(); - const auto response = request.send("POST", body); - - if(response.status.code != 201){ - throw std::runtime_error("Environment server failed to create Environment"); - } + auto response = this -> get_api_server().make(this -> env_name(), + this -> cidx(), + version, nlohmann::json()); this->set_version_(version); this->make_created_(); @@ -99,19 +83,9 @@ CartPole::step(const action_type& action){ return this->reset(42, std::unordered_map()); } - const auto request_url = std::string(this->get_url()) + "/step"; - http::Request request{request_url}; - - using json = nlohmann::json; - json j; - j["cidx"] = this -> cidx();; - j["action"] = action; - - const auto response = request.send("POST", j.dump()); - - if(response.status.code != 202){ - throw std::runtime_error("Environment server failed to step environment"); - } + const auto response = this -> get_api_server().step(this -> env_name(), + this -> cidx(), + action); this->get_current_time_step_() = this->create_time_step_from_response_(response); return this->get_current_time_step_(); @@ -119,13 +93,13 @@ CartPole::step(const action_type& action){ CartPole CartPole::make_copy(uint_t cidx)const{ - auto api_base_url = this -> get_api_url(); - - CartPole copy(api_base_url, cidx); - std::unordered_map ops; - auto version = this -> version(); - copy.make(version, ops); - return copy; +// auto api_base_url = this -> get_api_url(); +// +// CartPole copy(api_base_url, cidx); +// std::unordered_map ops; +// auto version = this -> version(); +// copy.make(version, ops); +// return copy; } diff --git a/src/rlenvs/envs/gymnasium/classic_control/cart_pole_env.h b/src/rlenvs/envs/gymnasium/classic_control/cart_pole_env.h index e5196ef..7b9fd17 100644 --- a/src/rlenvs/envs/gymnasium/classic_control/cart_pole_env.h +++ b/src/rlenvs/envs/gymnasium/classic_control/cart_pole_env.h @@ -42,14 +42,14 @@ #include "rlenvs/envs/time_step.h" #include "rlenvs/envs/gymnasium/gymnasium_env_base.h" #include "rlenvs/envs/env_types.h" -#include "rlenvs/extern/HTTPRequest.hpp" - +#include "rlenvs/envs/api_server/apiserver.h" +#include "rlenvs/extern/nlohmann/json/json.hpp" #include #include #include #include -#include + namespace rlenvscpp{ @@ -77,6 +77,11 @@ class CartPole final: public GymnasiumEnvBase >, /// static const std::string name; + /// + /// \brief The URI for accessing the environment + /// + static const std::string URI; + /// /// \brief Base class type /// @@ -117,12 +122,12 @@ class CartPole final: public GymnasiumEnvBase >, /// /// \brief CartPole. Constructor /// - CartPole(const std::string& api_base_url ); + CartPole(const RESTApiServerWrapper& api_server ); /// /// \brief CartPole. Constructor /// - CartPole(const std::string& api_base_url, + CartPole(const RESTApiServerWrapper& api_server, const uint_t cidx); /// @@ -164,14 +169,10 @@ class CartPole final: public GymnasiumEnvBase >, /// /// \brief Handle the reset response from the environment server /// - virtual time_step_type create_time_step_from_response_(const http::Response& response) const override final; + virtual time_step_type create_time_step_from_response_(const nlohmann::json& response) const override final; }; -//inline -//CartPole::~CartPole() -//{} - } } diff --git a/src/rlenvs/envs/gymnasium/classic_control/mountain_car_env.cpp b/src/rlenvs/envs/gymnasium/classic_control/mountain_car_env.cpp index dd56972..392dcc9 100644 --- a/src/rlenvs/envs/gymnasium/classic_control/mountain_car_env.cpp +++ b/src/rlenvs/envs/gymnasium/classic_control/mountain_car_env.cpp @@ -20,46 +20,41 @@ namespace gymnasium{ const std::string MountainCar::name = "MountainCar"; - +const std::string MountainCar::URI = "/gymnasium/mountain-car-env"; MountainCar::time_step_type -MountainCar::create_time_step_from_response_(const http::Response& response)const{ - - auto str_response = std::string(response.body.begin(), response.body.end()); - using json = nlohmann::json; +MountainCar::create_time_step_from_response_(const nlohmann::json& response)const{ - json j = json::parse(str_response); - - auto step_type = j["time_step"]["step_type"].template get(); - auto reward = j["time_step"]["reward"]; - auto discount = j["time_step"]["discount"]; - auto observation = j["time_step"]["observation"]; - auto info = j["time_step"]["info"]; + auto step_type = response["time_step"]["step_type"].template get(); + auto reward = response["time_step"]["reward"]; + auto discount = response["time_step"]["discount"]; + auto obs = response["time_step"]["observation"]; + auto info = response["time_step"]["info"]; return MountainCar::time_step_type(TimeStepEnumUtils::time_step_type_from_int(step_type), - reward, observation, discount, + reward, obs, discount, std::unordered_map()); } -MountainCar::MountainCar(const std::string& api_base_url) +MountainCar::MountainCar(const RESTApiServerWrapper& api_server ) : GymnasiumEnvBase>, ContinuousVectorStateDiscreteActionEnv<3, 2, 0, real_t > - >(0, "MountainCar", - api_base_url, - "/gymnasium/mountain-car-env") -{} + >(api_server, 0, MountainCar::name) +{ + this -> get_api_server().register_if_not(MountainCar::name, MountainCar::URI); +} -MountainCar::MountainCar(const std::string& api_base_url, +MountainCar::MountainCar(const RESTApiServerWrapper& api_server , const uint_t cidx) : GymnasiumEnvBase>, ContinuousVectorStateDiscreteActionEnv<3, 2, 0, real_t > - >(cidx, "MountainCar", - api_base_url, - "/gymnasium/mountain-car-env") -{} + >(api_server, cidx, MountainCar::name) +{ + this -> get_api_server().register_if_not(MountainCar::name, MountainCar::URI); +} MountainCar::MountainCar(const MountainCar& other) : @@ -76,19 +71,12 @@ MountainCar::make(const std::string& version, return; } - const auto request_url = std::string(this->get_url()) + "/make"; - http::Request request{request_url}; + auto response = this -> get_api_server().make(this -> env_name(), + this -> cidx(), + version, nlohmann::json()); - using json = nlohmann::json; - json j; - j["version"] = version; - j["cidx"] = this -> cidx(); - - const auto response = request.send("POST", j.dump()); - - if(response.status.code != 201){ - throw std::runtime_error("Environment server failed to create Environment"); - } + this->set_version_(version); + this->make_created_(); this->set_version_(version); this->make_created_(); @@ -106,18 +94,10 @@ MountainCar::step(const action_type& action){ return this->reset(42, std::unordered_map()); } - const auto request_url = std::string(this->get_url()) + "/step"; - http::Request request{request_url}; - - using json = nlohmann::json; - json j; - j["action"] = action; - j["cidx"] = this -> cidx(); - const auto response = request.send("POST", j.dump()); + const auto response = this -> get_api_server().step(this -> env_name(), + this -> cidx(), + action); - if(response.status.code != 202){ - throw std::runtime_error("Environment server failed to step environment"); - } this->get_current_time_step_() = this->create_time_step_from_response_(response); return this->get_current_time_step_(); @@ -126,13 +106,13 @@ MountainCar::step(const action_type& action){ MountainCar MountainCar::make_copy(uint_t cidx)const{ - auto api_base_url = this -> get_api_url(); - MountainCar copy(api_base_url, cidx); - - std::unordered_map ops; - auto version = this -> version(); - copy.make(version, ops); - return copy; +// auto api_base_url = this -> get_api_url(); +// MountainCar copy(api_base_url, cidx); +// +// std::unordered_map ops; +// auto version = this -> version(); +// copy.make(version, ops); +// return copy; } } diff --git a/src/rlenvs/envs/gymnasium/classic_control/mountain_car_env.h b/src/rlenvs/envs/gymnasium/classic_control/mountain_car_env.h index 0888207..2fd6695 100644 --- a/src/rlenvs/envs/gymnasium/classic_control/mountain_car_env.h +++ b/src/rlenvs/envs/gymnasium/classic_control/mountain_car_env.h @@ -6,7 +6,8 @@ #include "rlenvs/envs/gymnasium/gymnasium_env_base.h" #include "rlenvs/envs/time_step.h" #include "rlenvs/envs/env_types.h" - +#include "rlenvs/envs/api_server/apiserver.h" +#include "rlenvs/extern/nlohmann/json/json.hpp" #include #include @@ -18,48 +19,6 @@ namespace rlenvscpp{ namespace envs{ namespace gymnasium{ - /* -BETTER_ENUM(MountainCarActionsEnum, int, ACCELERATE_LEFT=0, - DO_NOT_ACCELERATE=1, - ACCELERATE_RIGHT=2, - INVALID_ACTION=3); - -/// -/// \brief The MountainCarData struct. Wrapper for the environment data -/// -struct MountainCarData -{ - /// - /// \brief action_space_t. The type of the action space - /// - typedef DiscreteSpace<3> action_space_type; - - /// - /// \brief action_t - /// - typedef action_space_type::item_t action_type; - - /// - /// \brief state_space_t - /// - typedef ContinuousSpace<3> state_space_type; - - /// - /// \brief state_t - /// - typedef state_space_type::item_t state_type; - - - - /// - /// \brief time_step_t. The type of the time step - /// - typedef TimeStep time_step_type; - - -}; -*/ - /// /// \brief The MountainCar class /// @@ -74,6 +33,11 @@ class MountainCar final: public GymnasiumEnvBase>, /// \brief name /// static const std::string name; + + /// + /// \brief The URI for accessing the environment + /// + static const std::string URI; /// /// \brief Base class type @@ -116,13 +80,13 @@ class MountainCar final: public GymnasiumEnvBase>, /// \param gym_namespace The boost::python open-ai gym namespace /// \param do_create If true it calls make /// - MountainCar(const std::string& api_base_url); + MountainCar(const RESTApiServerWrapper& api_server ); /// /// \brief Constructor. Protected so that applications /// cannot explicitly instantiate copies /// - MountainCar(const std::string& api_base_url, + MountainCar(const RESTApiServerWrapper& api_server , const uint_t cidx); /// @@ -164,7 +128,7 @@ class MountainCar final: public GymnasiumEnvBase>, /// /// \brief Handle the reset response from the environment server /// - virtual time_step_type create_time_step_from_response_(const http::Response& response) const override final; + virtual time_step_type create_time_step_from_response_(const nlohmann::json& response) const override final; diff --git a/src/rlenvs/envs/gymnasium/classic_control/pendulum_env.cpp b/src/rlenvs/envs/gymnasium/classic_control/pendulum_env.cpp index c93a40e..a46f5da 100644 --- a/src/rlenvs/envs/gymnasium/classic_control/pendulum_env.cpp +++ b/src/rlenvs/envs/gymnasium/classic_control/pendulum_env.cpp @@ -12,39 +12,35 @@ namespace gymnasium{ // static data const std::string Pendulum::name = "Pendulum"; +const std::string Pendulum::URI = "/gymnasium/pendulum-env"; Pendulum::time_step_type -Pendulum::create_time_step_from_response_(const http::Response& response)const{ +Pendulum::create_time_step_from_response_(const nlohmann::json& response)const{ - auto str_response = std::string(response.body.begin(), response.body.end()); - using json = nlohmann::json; - - json j = json::parse(str_response); - - auto step_type = j["time_step"]["step_type"].template get(); - auto reward = j["time_step"]["reward"]; - auto discount = j["time_step"]["discount"]; - auto observation = j["time_step"]["observation"]; - auto info = j["time_step"]["info"]; + auto step_type = response["time_step"]["step_type"].template get(); + auto reward = response["time_step"]["reward"]; + auto discount = response["time_step"]["discount"]; + auto obs = response["time_step"]["observation"]; + auto info = response["time_step"]["info"]; return Pendulum::time_step_type(TimeStepEnumUtils::time_step_type_from_int(step_type), - reward, observation, discount, + reward, obs, discount, std::unordered_map()); } -Pendulum::Pendulum(const std::string& api_base_url) +Pendulum::Pendulum(const RESTApiServerWrapper& api_server) : GymnasiumEnvBase>, ContinuousVectorStateContinuousScalarBoundedActionEnv<3, 1, RealRange<-2.0, 2.0>, 0, real_t> - >(0, "Pendulum", - api_base_url, - "/gymnasium/pendulum-env") -{} + >(api_server, 0, Pendulum::name) +{ + this -> get_api_server().register_if_not(Pendulum::name,Pendulum::URI); +} -Pendulum::Pendulum(const std::string& api_base_url, +Pendulum::Pendulum(const RESTApiServerWrapper& api_server, const uint_t cidx) : GymnasiumEnvBase>, @@ -52,10 +48,12 @@ GymnasiumEnvBase>, 1, RealRange<-2.0, 2.0>, 0, real_t> - >(cidx, "Pendulum", - api_base_url, - "/gymnasium/pendulum-env") -{} + >(api_server, + cidx, + Pendulum::name) +{ + this -> get_api_server().register_if_not(Pendulum::name,Pendulum::URI); +} Pendulum::Pendulum(const Pendulum& other) : @@ -74,20 +72,10 @@ Pendulum::make(const std::string& version, if(this->is_created()){ return; } - - const auto request_url = std::string(this->get_url()) + "/make"; - http::Request request{request_url}; - - using json = nlohmann::json; - json j; - j["version"] = version; - j["cidx"] = this -> cidx(); - const auto response = request.send("POST", j.dump()); - - if(response.status.code != 201){ - throw std::runtime_error("Environment server failed to create Environment"); - } + auto response = this -> get_api_server().make(this -> env_name(), + this -> cidx(), + version, nlohmann::json()); this->set_version_(version); this->make_created_(); @@ -105,19 +93,9 @@ Pendulum::step(const action_type& action){ return this->reset(42, std::unordered_map()); } - const auto request_url = std::string(this->get_url()) + "/step"; - http::Request request{request_url}; - - using json = nlohmann::json; - json j; - j["cidx"] = this -> cidx();; - j["action"] = action; - - const auto response = request.send("POST", j.dump()); - - if(response.status.code != 202){ - throw std::runtime_error("Environment server failed to step environment"); - } + auto response = this -> get_api_server().step(this -> env_name(), + this -> cidx(), + action); this->get_current_time_step_() = this->create_time_step_from_response_(response); return this->get_current_time_step_(); @@ -126,13 +104,13 @@ Pendulum::step(const action_type& action){ Pendulum Pendulum::make_copy(uint_t cidx)const{ - auto api_base_url = this -> get_api_url(); - - Pendulum copy(api_base_url, cidx); - std::unordered_map ops; - auto version = this -> version(); - copy.make(version, ops); - return copy; +// auto api_base_url = this -> get_api_url(); +// +// Pendulum copy(api_base_url, cidx); +// std::unordered_map ops; +// auto version = this -> version(); +// copy.make(version, ops); +// return copy; } } diff --git a/src/rlenvs/envs/gymnasium/classic_control/pendulum_env.h b/src/rlenvs/envs/gymnasium/classic_control/pendulum_env.h index 5601f9c..49ec1cf 100644 --- a/src/rlenvs/envs/gymnasium/classic_control/pendulum_env.h +++ b/src/rlenvs/envs/gymnasium/classic_control/pendulum_env.h @@ -81,6 +81,8 @@ #include "rlenvs/rlenvs_types_v2.h" #include "rlenvs/envs/time_step.h" #include "rlenvs/envs/gymnasium/gymnasium_env_base.h" +#include "rlenvs/envs/api_server/apiserver.h" +#include "rlenvs/extern/nlohmann/json/json.hpp" #include "rlenvs/envs/env_types.h" #include @@ -110,6 +112,11 @@ class Pendulum final: public GymnasiumEnvBase>, /// static const std::string name; + /// + /// \brief The URI for accessing the environment + /// + static const std::string URI; + /// /// \brief Base class type @@ -149,13 +156,13 @@ class Pendulum final: public GymnasiumEnvBase>, /// /// \brief Pendulum. Constructor /// - Pendulum(const std::string& api_base_url ); + Pendulum(const RESTApiServerWrapper& api_server ); /// /// \brief Constructor /// - Pendulum(const std::string& api_base_url, - const uint_t cidx); + Pendulum(const RESTApiServerWrapper& api_server, + const uint_t cidx); /// /// \brief copy ctor @@ -193,12 +200,10 @@ class Pendulum final: public GymnasiumEnvBase>, protected: - - /// /// \brief Handle the reset response from the environment server /// - virtual time_step_type create_time_step_from_response_(const http::Response& response) const override final; + virtual time_step_type create_time_step_from_response_(const nlohmann::json& response) const override final; }; diff --git a/src/rlenvs/envs/gymnasium/classic_control/vector/acrobot_vec_env.cpp b/src/rlenvs/envs/gymnasium/classic_control/vector/acrobot_vec_env.cpp index 08233ab..f03a27b 100644 --- a/src/rlenvs/envs/gymnasium/classic_control/vector/acrobot_vec_env.cpp +++ b/src/rlenvs/envs/gymnasium/classic_control/vector/acrobot_vec_env.cpp @@ -10,24 +10,19 @@ namespace envs{ namespace gymnasium{ -const std::string AcrobotV::name = "Acrobot"; +const std::string AcrobotV::name = "AcrobotV"; +const std::string AcrobotV::URI = "/gymnasium/acrobot-env/v"; AcrobotV::time_step_type -AcrobotV::create_time_step_from_response_(const http::Response& response)const{ - - auto str_response = std::string(response.body.begin(), response.body.end()); - using json = nlohmann::json; - - // parse the response - json j = json::parse(str_response); - - auto step_types = j["time_step"]["step_types"].template get >(); - auto time_step_types = TimeStepEnumUtils::time_step_type_from_int(step_types); - auto reward_response = j["time_step"]["rewards"]; - auto discount_response = j["time_step"]["discounts"]; - auto observation = j["time_step"]["observations"]; - auto info = j["time_step"]["infos"]; +AcrobotV::create_time_step_from_response_(const nlohmann::json& response)const{ + + auto step_types = response["time_step"]["step_types"].template get >(); + auto time_step_types = TimeStepEnumUtils::time_step_type_from_int(step_types); + auto reward_response = response["time_step"]["rewards"]; + auto discount_response = response["time_step"]["discounts"]; + auto observation = response["time_step"]["observations"]; + auto info = response["time_step"]["infos"]; return AcrobotV::time_step_type(time_step_types, reward_response, observation, @@ -36,21 +31,22 @@ AcrobotV::create_time_step_from_response_(const http::Response& response)const{ } -AcrobotV::AcrobotV(const std::string& api_base_url) +AcrobotV::AcrobotV(const RESTApiServerWrapper& api_server ) : -GymnasiumVecEnvBase, detail_::AcrobotVEnv>(0, "Acrobot", - api_base_url, - "/gymnasium/acrobot-env/v") -{} +GymnasiumVecEnvBase, + detail_::AcrobotVEnv>(api_server, 0, AcrobotV::name) +{ + this -> get_api_server().register_if_not(AcrobotV::name,AcrobotV::URI); +} -AcrobotV::AcrobotV(const std::string& api_base_url, const uint_t cidx) +AcrobotV::AcrobotV(const RESTApiServerWrapper& api_server , const uint_t cidx) : GymnasiumVecEnvBase, - detail_::AcrobotVEnv>(cidx, - "Acrobot", - api_base_url, - "/gymnasium/acrobot-env/v") -{} + detail_::AcrobotVEnv>(api_server, cidx, + AcrobotV::name) +{ + this -> get_api_server().register_if_not(AcrobotV::name,AcrobotV::URI); +} AcrobotV::AcrobotV(const AcrobotV& other) @@ -70,21 +66,12 @@ AcrobotV::make(const std::string& version, this->GymnasiumVecEnvBase, detail_::AcrobotVEnv>::make(version, options); - - const auto request_url = std::string(this->get_url()) + "/make"; - http::Request request{request_url}; - - using json = nlohmann::json; - json j; - j["version"] = version; - j["num_envs"] = this->get_n_envs(); - - auto body = j.dump(); - const auto response = request.send("POST", body); - - if(response.status.code != 201){ - throw std::runtime_error("Environment server failed to create Environment"); - } + + nlohmann::json ops; + ops["num_envs"] = this->get_n_envs(); + auto response = this -> get_api_server().make(this -> env_name(), + this -> cidx(), + version, ops); this->set_version_(version); this->make_created_(); @@ -102,20 +89,10 @@ AcrobotV::step(const action_type& action){ if(this->get_reset_if_any_done() && this->get_current_time_step_().last()){ return this->reset(42, std::unordered_map()); } - - const auto request_url = std::string(this->get_url()) + "/step"; - http::Request request{request_url}; - - using json = nlohmann::json; - json j; - j["actions"] = action; - j["cidx"] = this -> cidx(); - - const auto response = request.send("POST", j.dump()); - - if(response.status.code != 202){ - throw std::runtime_error("Environment server failed to step environment"); - } + + auto response = this -> get_api_server().step(this -> env_name(), + this -> cidx(), + action); this->get_current_time_step_() = this->create_time_step_from_response_(response); return this->get_current_time_step_(); @@ -124,15 +101,15 @@ AcrobotV::step(const action_type& action){ AcrobotV AcrobotV::make_copy(uint_t cidx)const{ - auto api_base_url = this -> get_api_url(); - - AcrobotV copy(api_base_url, cidx); - - std::unordered_map ops; - ops["num_envs"] = this -> get_n_envs(); - auto version = this -> version(); - copy.make(version, ops); - return copy; +// auto api_base_url = this -> get_api_url(); +// +// AcrobotV copy(api_base_url, cidx); +// +// std::unordered_map ops; +// ops["num_envs"] = this -> get_n_envs(); +// auto version = this -> version(); +// copy.make(version, ops); +// return copy; } } diff --git a/src/rlenvs/envs/gymnasium/classic_control/vector/acrobot_vec_env.h b/src/rlenvs/envs/gymnasium/classic_control/vector/acrobot_vec_env.h index baf76b5..ad776bc 100644 --- a/src/rlenvs/envs/gymnasium/classic_control/vector/acrobot_vec_env.h +++ b/src/rlenvs/envs/gymnasium/classic_control/vector/acrobot_vec_env.h @@ -13,7 +13,8 @@ #include "rlenvs/envs/vector_time_step.h" #include "rlenvs/envs/space_type.h" #include "rlenvs/envs/gymnasium/gymnasium_vector_env_base.h" -#include "rlenvs/extern/HTTPRequest.hpp" +#include "rlenvs/envs/api_server/apiserver.h" +#include "rlenvs/extern/nlohmann/json/json.hpp" #include @@ -73,6 +74,11 @@ class AcrobotV final: public GymnasiumVecEnvBase @@ -28,8 +27,7 @@ namespace envs{ namespace gymnasium { template -class GymnasiumEnvBase: public EnvBase, - public with_rest_api_mixin{ +class GymnasiumEnvBase: public EnvBase{ public: @@ -77,7 +75,7 @@ class GymnasiumEnvBase: public EnvBase, /// /// \brief /// - virtual bool is_alive()const override; + virtual bool is_alive()const; /// /// \brief close the environment @@ -89,6 +87,16 @@ class GymnasiumEnvBase: public EnvBase, /// virtual time_step_type reset(uint_t seed, const std::unordered_map& options)override; + + /// + /// \brief Returns read reference to the underlying API server wrapper + /// + const RESTApiServerWrapper& get_api_server()const{return api_server_;} + + /// + /// \brief Returns the full path on the server for this environment + /// + std::string get_url()const; protected: @@ -96,31 +104,42 @@ class GymnasiumEnvBase: public EnvBase, /// /// \brief Constructor /// - GymnasiumEnvBase(const uint_t cidx, - const std::string& name, - const std::string& api_url, - const std::string& resource_path); + GymnasiumEnvBase(const RESTApiServerWrapper& api_server, + const uint_t cidx, + const std::string& name); /// /// \brief Copy constructor /// GymnasiumEnvBase(const GymnasiumEnvBase&); + + + /// + /// \brief Pointer to the api server that handles the requests + /// + RESTApiServerWrapper api_server_; + + + /// + /// \brief read reference to the api server instance + /// + RESTApiServerWrapper& get_api_server(){return api_server_;} /// /// \brief build the time step from the server response /// - virtual time_step_type create_time_step_from_response_(const http::Response& response)const=0; + virtual time_step_type create_time_step_from_response_(const nlohmann::json& response)const=0; }; template GymnasiumEnvBase::GymnasiumEnvBase(const uint_t cidx, const std::string& name, - const std::string& api_url, - const std::string& resource_path) + SpaceType>::GymnasiumEnvBase(const RESTApiServerWrapper& api_server, + const uint_t cidx, + const std::string& name) : EnvBase(cidx, name), -with_rest_api_mixin(api_url, resource_path) +api_server_(api_server) {} template @@ -128,33 +147,26 @@ GymnasiumEnvBase::GymnasiumEnvBase(const GymnasiumEnvBase& other) : EnvBase(other), -with_rest_api_mixin(other) +api_server_(other.api_server_) {} template GymnasiumEnvBase::~GymnasiumEnvBase(){ - close(); + + try{ + close(); + } + catch(...){ + + } } template bool GymnasiumEnvBase::is_alive()const{ - - - auto url_ = this->get_url(); - auto copy_idx_str = std::to_string(this -> cidx()); - - http::Request request{url_ + "/is-alive?cidx="+copy_idx_str}; - const auto response = request.send("GET"); - const auto str_response = std::string(response.body.begin(), response.body.end()); - - using json = nlohmann::json; - - // parse the response - json j = json::parse(str_response); - return j["result"]; - + auto response = this -> api_server_.is_alive(this->env_name(), this -> cidx()); + return response["result"]; } template @@ -163,12 +175,9 @@ GymnasiumEnvBase::close(){ if(!this->is_created()){ return; - } - - auto url = this -> get_url(); + } - http::Request request{url + "/close?cidx="+std::to_string(this -> cidx())}; - const auto response = request.send("POST"); + auto response = this -> api_server_.close(this->env_name(), this -> cidx()); this -> invalidate_is_created_flag_(); } @@ -185,28 +194,19 @@ GymnasiumEnvBase::reset(uint_t seed, return time_step_type(); } - auto copy_idx = this -> cidx(); - - auto url = this -> get_url(); - const auto request_url = url + "/reset"; - http::Request request{request_url}; - - - using json = nlohmann::json; - json j; - j["seed"] = seed; - j["cidx"] = copy_idx; - - auto body = j.dump(); - const auto response = request.send("POST", body); - - if(response.status.code != 202){ - throw std::runtime_error("Environment server failed to reset environment"); - } - - this -> get_current_time_step_() = this->create_time_step_from_response_(response); + auto response = this -> api_server_.reset(this->env_name(), + this -> cidx(), seed, + nlohmann::json()); + + this -> get_current_time_step_() = this->create_time_step_from_response_(response); return this -> get_current_time_step_(); +} + +template +std::string +GymnasiumEnvBase::get_url()const{ + return api_server_.get_env_url(this -> env_name()); } diff --git a/src/rlenvs/envs/gymnasium/gymnasium_vector_env_base.h b/src/rlenvs/envs/gymnasium/gymnasium_vector_env_base.h index 45835df..477c4c5 100644 --- a/src/rlenvs/envs/gymnasium/gymnasium_vector_env_base.h +++ b/src/rlenvs/envs/gymnasium/gymnasium_vector_env_base.h @@ -13,7 +13,8 @@ #include "rlenvs/envs/gymnasium/gymnasium_env_base.h" #include "rlenvs/rlenvs_types_v2.h" #include "rlenvs/envs/env_types.h" - +#include "rlenvs/envs/api_server/apiserver.h" +#include "rlenvs/extern/nlohmann/json/json.hpp" #ifdef RLENVSCPP_DEBUG #include @@ -88,10 +89,9 @@ class GymnasiumVecEnvBase: public GymnasiumEnvBase -GymnasiumVecEnvBase::GymnasiumVecEnvBase(const uint_t cidx, - const std::string& name, - const std::string& api_url, - const std::string& resource_path) +GymnasiumVecEnvBase::GymnasiumVecEnvBase(const RESTApiServerWrapper& api_server, + const uint_t cidx, + const std::string& name) : -GymnasiumEnvBase(cidx, name, api_url, resource_path) +GymnasiumEnvBase(api_server, cidx, name) {} diff --git a/src/rlenvs/envs/gymnasium/toy_text/black_jack_env.cpp b/src/rlenvs/envs/gymnasium/toy_text/black_jack_env.cpp index 52cc4de..f31a36d 100644 --- a/src/rlenvs/envs/gymnasium/toy_text/black_jack_env.cpp +++ b/src/rlenvs/envs/gymnasium/toy_text/black_jack_env.cpp @@ -16,48 +16,45 @@ namespace envs{ namespace gymnasium{ const std::string BlackJack::name = "BlackJack"; +const std::string BlackJack::URI = "/gymnasium/black-jack-env"; BlackJack::dynamics_t -BlackJack::build_dynamics_from_response_(const http::Response& response)const{ +BlackJack::build_dynamics_from_response_(const nlohmann::json& /*response*/)const{ throw std::logic_error("Environment BlackJack does not have dynamics"); } BlackJack::time_step_type -BlackJack::create_time_step_from_response_(const http::Response& response)const{ +BlackJack::create_time_step_from_response_(const nlohmann::json& response)const{ - auto str_response = std::string(response.body.begin(), response.body.end()); - using json = nlohmann::json; - - json j = json::parse(str_response); - - auto step_type = TimeStepEnumUtils::time_step_type_from_int(j["time_step"]["step_type"].template get()); - auto reward = j["time_step"]["reward"]; - auto discount = j["time_step"]["discount"]; - auto observation = j["time_step"]["observation"]; - auto info = j["time_step"]["info"]; + auto step_type = TimeStepEnumUtils::time_step_type_from_int(response["time_step"]["step_type"].template get()); + auto reward = response["time_step"]["reward"]; + auto discount = response["time_step"]["discount"]; + auto observation = response["time_step"]["observation"]; + auto info = response["time_step"]["info"]; std::vector > state(1, observation); - return BlackJack::time_step_type( - //step_type, reward, - //state, discount - //std::unordered_map() + return BlackJack::time_step_type(step_type, + reward, + observation, + discount, + std::unordered_map() ); } -BlackJack::BlackJack(const std::string& api_base_url) +BlackJack::BlackJack(const RESTApiServerWrapper& api_server) : -ToyTextEnvBase, 48, 2>(0, "BlackJack", - api_base_url, - "/gymnasium/black-jack-env") -{} +ToyTextEnvBase, 48, 2>(api_server, 0, BlackJack::name) +{ + this ->get_api_server().register_if_not(BlackJack::name, BlackJack::URI); +} -BlackJack::BlackJack(const std::string& api_base_url, +BlackJack::BlackJack(const RESTApiServerWrapper& api_server, const uint_t cidx) : -ToyTextEnvBase, 48, 2>(cidx, "BlackJack", - api_base_url, - "/gymnasium/black-jack-env") -{} +ToyTextEnvBase, 48, 2>(api_server, cidx, BlackJack::name) +{ + this ->get_api_server().register_if_not(BlackJack::name, BlackJack::URI); +} BlackJack::BlackJack(const BlackJack& other) : @@ -83,23 +80,14 @@ BlackJack::make(const std::string& version, if( sab_itr != options.end()){ is_sab_ = std::any_cast(sab_itr->second); } - - const auto request_url = std::string(this->get_url()) + "/make"; - http::Request request{request_url}; - - using json = nlohmann::json; - json j; - j["version"] = version; - j["natural"] = is_natural_; - j["sab"] = is_sab_; - j["cidx"] = this -> cidx(); - - auto body = j.dump(); - const auto response = request.send("POST", body); - - if(response.status.code != 201){ - throw std::runtime_error("Environment server failed to create Environment"); - } + + nlohmann::json ops; + ops["natural"] = is_natural_; + ops["sab"] = is_sab_; + auto response = this -> get_api_server().make(this -> env_name(), + this -> cidx(), + version, + ops); this->set_version_(version); this->make_created_(); @@ -116,20 +104,10 @@ BlackJack::step(const action_type& action){ if(this->get_current_time_step_().last()){ return this->reset(42, std::unordered_map()); } - - const std::string request_url = std::string(this->get_url()) + "/step"; - - http::Request request{request_url}; - - using json = nlohmann::json; - json j; - j["cidx"] = this -> cidx(); - j["action"] = action; - const auto response = request.send("POST", j.dump()); - - if(response.status.code != 202){ - throw std::runtime_error("Environment server failed to step environment"); - } + + auto response = this -> get_api_server().step(this -> env_name(), + this -> cidx(), + action); this->get_current_time_step_() = this->create_time_step_from_response_(response); return this->get_current_time_step_(); @@ -139,17 +117,17 @@ BlackJack::step(const action_type& action){ BlackJack BlackJack::make_copy(uint_t cidx)const{ - auto api_base_url = this -> get_api_url(); - - BlackJack copy(api_base_url, cidx); - - std::unordered_map ops; - ops["natural"] = this->is_natural(); - ops["sab"] = this->is_sab(); - - auto version = this -> version(); - copy.make(version, ops); - return copy; +// auto api_base_url = this -> get_api_url(); +// +// BlackJack copy(api_base_url, cidx); +// +// std::unordered_map ops; +// ops["natural"] = this->is_natural(); +// ops["sab"] = this->is_sab(); +// +// auto version = this -> version(); +// copy.make(version, ops); +// return copy; } diff --git a/src/rlenvs/envs/gymnasium/toy_text/black_jack_env.h b/src/rlenvs/envs/gymnasium/toy_text/black_jack_env.h index b310920..4e7713b 100644 --- a/src/rlenvs/envs/gymnasium/toy_text/black_jack_env.h +++ b/src/rlenvs/envs/gymnasium/toy_text/black_jack_env.h @@ -8,15 +8,16 @@ #include "rlenvs/rlenvs_types_v2.h" #include "rlenvs/envs/time_step.h" -#include "rlenvs/extern/HTTPRequest.hpp" +#include "rlenvs/envs/api_server/apiserver.h" #include "rlenvs/envs/gymnasium/toy_text/toy_text_base.h" +#include "rlenvs/extern/nlohmann/json/json.hpp" #include #include #include #include #include -#include + namespace rlenvscpp{ namespace envs{ @@ -35,6 +36,11 @@ class BlackJack final: public ToyTextEnvBase, 48, 2> /// \brief name /// static const std::string name; + + /// + /// \brief The URI for accessing the environment + /// + static const std::string URI; /// /// \brief The base type @@ -70,12 +76,12 @@ class BlackJack final: public ToyTextEnvBase, 48, 2> /// /// \brief BlackJack. Constructor. /// - BlackJack(const std::string& api_base_url); + BlackJack(const RESTApiServerWrapper& api_server); /// /// \brief Constructor /// - BlackJack(const std::string& api_base_url, + BlackJack(const RESTApiServerWrapper& api_server, const uint_t cidx); /// @@ -125,12 +131,12 @@ class BlackJack final: public ToyTextEnvBase, 48, 2> /// /// \brief build the dynamics from response /// - virtual dynamics_t build_dynamics_from_response_(const http::Response& response)const override final; + virtual dynamics_t build_dynamics_from_response_(const nlohmann::json&)const override final; /// /// \brief Handle the reset response from the environment server /// - virtual time_step_type create_time_step_from_response_(const http::Response& response) const override final; + virtual time_step_type create_time_step_from_response_(const nlohmann::json&) const override final; diff --git a/src/rlenvs/envs/gymnasium/toy_text/cliff_world_env.cpp b/src/rlenvs/envs/gymnasium/toy_text/cliff_world_env.cpp index dddde8f..cda6808 100644 --- a/src/rlenvs/envs/gymnasium/toy_text/cliff_world_env.cpp +++ b/src/rlenvs/envs/gymnasium/toy_text/cliff_world_env.cpp @@ -17,32 +17,16 @@ namespace envs { namespace gymnasium{ const std::string CliffWorld::name = "CliffWalking"; - - -CliffWorld::dynamics_t -CliffWorld::build_dynamics_from_response_(const http::Response& response)const{ - - auto str_response = std::string(response.body.begin(), response.body.end()); - using json = nlohmann::json; - json j = json::parse(str_response); - - auto dynamics = j["dynamics"]; - return dynamics; -} +const std::string CliffWorld::URI = "/gymnasium/cliff-walking-env"; CliffWorld::time_step_type -CliffWorld::create_time_step_from_response_(const http::Response& response)const{ - - auto str_response = std::string(response.body.begin(), response.body.end()); - using json = nlohmann::json; +CliffWorld::create_time_step_from_response_(const nlohmann::json& response)const{ - json j = json::parse(str_response); - - auto step_type = j["time_step"]["step_type"].template get(); - auto reward = j["time_step"]["reward"]; - auto discount = j["time_step"]["discount"]; - auto observation = j["time_step"]["observation"]; - auto info = j["time_step"]["info"]; + auto step_type = response["time_step"]["step_type"].template get(); + auto reward = response["time_step"]["reward"]; + auto discount = response["time_step"]["discount"]; + auto observation = response["time_step"]["observation"]; + auto info = response["time_step"]["info"]; std::unordered_map info_; info_["prob"] = std::any(static_cast(info["prob"])); @@ -55,23 +39,22 @@ CliffWorld::create_time_step_from_response_(const http::Response& response)const } -CliffWorld::CliffWorld(const std::string& api_base_url) +CliffWorld::CliffWorld(const RESTApiServerWrapper& api_server) : -ToyTextEnvBase, 37, 4>(0, - "CliffWalking", - api_base_url, - "/gymnasium/cliff-walking-env"), +ToyTextEnvBase, 37, 4>(api_server, 0, CliffWorld::name), max_episode_steps_(200) -{} +{ + this ->get_api_server().register_if_not(CliffWorld::name,CliffWorld::URI); +} -CliffWorld::CliffWorld(const std::string& api_base_url, +CliffWorld::CliffWorld(const RESTApiServerWrapper& api_server, const uint_t cidx) : -ToyTextEnvBase, 37, 4>(cidx, "CliffWalking", - api_base_url, - "/gymnasium/cliff-walking-env"), +ToyTextEnvBase, 37, 4>(api_server, cidx, CliffWorld::name), max_episode_steps_(200) -{} +{ + this ->get_api_server().register_if_not(CliffWorld::name,CliffWorld::URI); +} CliffWorld::CliffWorld(const CliffWorld& other) : @@ -91,23 +74,14 @@ CliffWorld::make(const std::string& version, if( max_episode_steps_itr != options.end()){ max_episode_steps_ = std::any_cast(max_episode_steps_itr->second); } - - const auto request_url = std::string(this->get_url()) + "/make"; - http::Request request{request_url}; - - using json = nlohmann::json; - json j; - j["version"] = version; - j["max_episode_steps"] = max_episode_steps_; - j["cidx"] = this -> cidx(); - auto body = j.dump(); - - const auto response = request.send("POST", body); - - if(response.status.code != 201){ - throw std::runtime_error("Environment server failed to create Environment"); - } - + + nlohmann::json ops; + ops["max_episode_steps"] = max_episode_steps_; + auto response = this -> get_api_server().make(this->env_name(), + this->cidx(), + version, + ops); + this->set_version_(version); this->make_created_(); @@ -123,21 +97,10 @@ CliffWorld::step(const action_type& action){ if(this->get_current_time_step_().last()){ return this->reset(42, std::unordered_map()); } - - const auto request_url = std::string(this->get_url()) + "/step"; - http::Request request{request_url}; - - auto copy_idx = this -> cidx(); - - using json = nlohmann::json; - json j; - j["cidx"] = copy_idx; - j["action"] = action; - const auto response = request.send("POST", j.dump()); - - if(response.status.code != 202){ - throw std::runtime_error("Environment server failed to step environment"); - } + + auto response = this -> get_api_server().step(this->env_name(), + this->cidx(), + action); this->get_current_time_step_() = this->create_time_step_from_response_(response); return this->get_current_time_step_(); @@ -147,12 +110,12 @@ CliffWorld::step(const action_type& action){ CliffWorld CliffWorld::make_copy(uint_t cidx)const{ - auto api_base_url = this -> get_api_url(); - CliffWorld copy(api_base_url,cidx); - std::unordered_map ops; - auto version = this -> version(); - copy.make(version, ops); - return copy; +// auto api_base_url = this -> get_api_url(); +// CliffWorld copy(api_base_url,cidx); +// std::unordered_map ops; +// auto version = this -> version(); +// copy.make(version, ops); +// return copy; } } diff --git a/src/rlenvs/envs/gymnasium/toy_text/cliff_world_env.h b/src/rlenvs/envs/gymnasium/toy_text/cliff_world_env.h index 0d5f096..a56f517 100644 --- a/src/rlenvs/envs/gymnasium/toy_text/cliff_world_env.h +++ b/src/rlenvs/envs/gymnasium/toy_text/cliff_world_env.h @@ -37,15 +37,17 @@ #include "rlenvs/rlenvs_types_v2.h" #include "rlenvs/envs/time_step.h" -#include "rlenvs/extern/HTTPRequest.hpp" +//#include "rlenvs/extern/HTTPRequest.hpp" #include "rlenvs/envs/gymnasium/toy_text/toy_text_base.h" -#include "rlenvs/envs/space_type.h" +#include "rlenvs/envs/api_server/apiserver.h" +#include "rlenvs/extern/nlohmann/json/json.hpp" +//#include "rlenvs/envs/space_type.h" #include #include #include #include -#include + namespace rlenvscpp{ namespace envs { @@ -63,6 +65,11 @@ class CliffWorld final: public ToyTextEnvBase, 37, 4> /// \brief name /// static const std::string name; + + /// + /// \brief The URI for accessing the environment + /// + static const std::string URI; /// /// \brief dynamics_t @@ -103,12 +110,12 @@ class CliffWorld final: public ToyTextEnvBase, 37, 4> /// /// \brief CliffWorld /// - CliffWorld(const std::string& api_base_url); + CliffWorld(const RESTApiServerWrapper& api_server); /// /// \brief Constructor /// - CliffWorld(const std::string& api_base_url, + CliffWorld(const RESTApiServerWrapper& api_server, const uint_t cidx); /// @@ -152,12 +159,12 @@ class CliffWorld final: public ToyTextEnvBase, 37, 4> /// /// \brief build the dynamics from response /// - virtual dynamics_t build_dynamics_from_response_(const http::Response& response)const override final; + //virtual dynamics_t build_dynamics_from_response_(const nlohmann::json& response)const override final; /// /// \brief Handle the reset response from the environment server /// - virtual time_step_type create_time_step_from_response_(const http::Response& response) const override final; + virtual time_step_type create_time_step_from_response_(const nlohmann::json& response) const override final; }; } diff --git a/src/rlenvs/envs/gymnasium/toy_text/frozen_lake_env.cpp b/src/rlenvs/envs/gymnasium/toy_text/frozen_lake_env.cpp index 32fb589..b2fd171 100644 --- a/src/rlenvs/envs/gymnasium/toy_text/frozen_lake_env.cpp +++ b/src/rlenvs/envs/gymnasium/toy_text/frozen_lake_env.cpp @@ -19,23 +19,30 @@ template const std::string FrozenLake::name = "FrozenLake"; template -FrozenLake::FrozenLake(const std::string& api_base_url) +const std::string FrozenLake::URI = "/gymnasium/frozen-lake-env"; + +template +FrozenLake::FrozenLake(const RESTApiServerWrapper& api_server) : ToyTextEnvBase, frozenlake_state_size::size, - 4>(0, "FrozenLake", api_base_url,"/gymnasium/frozen-lake-env"), + 4>(api_server, 0, FrozenLake::name), is_slippery_(true) -{} +{ + this -> get_api_server().register_if_not(FrozenLake::name,FrozenLake::URI); +} template -FrozenLake::FrozenLake(const std::string& api_base_url, +FrozenLake::FrozenLake(const RESTApiServerWrapper& api_server, const uint_t cidx, bool slippery) : ToyTextEnvBase, frozenlake_state_size::size, - 4>(cidx, "FrozenLake", api_base_url, "/gymnasium/frozen-lake-env"), + 4>(api_server, cidx, FrozenLake::name), is_slippery_(slippery) -{} +{ + this -> get_api_server().register_if_not(FrozenLake::name,FrozenLake::URI); +} template FrozenLake::FrozenLake(const FrozenLake& other) @@ -46,33 +53,16 @@ ToyTextEnvBase, is_slippery_(other.is_slippery_) {} -template -typename FrozenLake::dynamics_t -FrozenLake::build_dynamics_from_response_(const http::Response& response)const{ - - auto str_response = std::string(response.body.begin(), response.body.end()); - using json = nlohmann::json; - json j = json::parse(str_response); - - auto dynamics = j["dynamics"]; - return dynamics; -} - template typename FrozenLake::time_step_type -FrozenLake::create_time_step_from_response_(const http::Response& response)const{ - - auto str_response = std::string(response.body.begin(), response.body.end()); - using json = nlohmann::json; +FrozenLake::create_time_step_from_response_(const nlohmann::json& response)const{ - json j = json::parse(str_response); - - auto step_type = j["time_step"]["step_type"].template get(); + auto step_type = response["time_step"]["step_type"].template get(); auto step_type_val = TimeStepEnumUtils::time_step_type_from_int(step_type); - auto reward = j["time_step"]["reward"]; - auto discount = j["time_step"]["discount"]; - auto observation = j["time_step"]["observation"]; - auto info = j["time_step"]["info"]; + auto reward = response["time_step"]["reward"]; + auto discount = response["time_step"]["discount"]; + auto observation = response["time_step"]["observation"]; + auto info = response["time_step"]["info"]; auto time_step = FrozenLake::time_step_type(step_type_val, reward, observation, discount, @@ -97,24 +87,13 @@ FrozenLake::make(const std::string& version, is_slippery_ = std::any_cast(slip_itr->second); } - auto copy_idx = this -> cidx(); - const auto request_url = std::string(this->get_url()) + "/make"; - http::Request request{request_url}; - - using json = nlohmann::json; - json j; - j["version"] = version; - j["map_name"] = map_type(); - j["is_slippery"] = is_slippery_; - j["cidx"] = copy_idx; - - auto body = j.dump(); - const auto response = request.send("POST", body); - - if(response.status.code != 201){ - throw std::runtime_error("Environment server failed to create Environment"); - } - + nlohmann::json ops; + ops["map_name"] = map_type(); + ops["is_slippery"] = is_slippery_; + auto response = this -> get_api_server().make(this -> env_name(), + this -> cidx(), + version, ops); + this->set_version_(version); this->make_created_(); } @@ -130,23 +109,10 @@ FrozenLake::step(const action_type& action){ if(this->get_current_time_step_().last()){ return this->reset(42, std::unordered_map()); } - - const auto request_url = std::string(this->get_url()) + "/step"; - http::Request request{request_url}; - - auto copy_idx = this -> cidx(); - - using json = nlohmann::json; - json j; - j["cidx"] = copy_idx; - j["action"] = action; - auto body = j.dump(); - - const auto response = request.send("POST", body); - - if(response.status.code != 202){ - throw std::runtime_error("Environment server failed to step environment"); - } + + auto response = this -> get_api_server().step(this -> env_name(), + this -> cidx(), + action); this->get_current_time_step_() = this->create_time_step_from_response_(response); return this->get_current_time_step_(); @@ -157,16 +123,16 @@ template FrozenLake FrozenLake::make_copy(uint_t cidx)const{ - auto api_base_url = this -> get_api_url(); - auto slippery = this -> is_slippery(); - FrozenLake copy(api_base_url, - cidx,slippery); - - std::unordered_map ops; - ops["is_slippery"] = this -> is_slippery(); - auto version = this -> version(); - copy.make(version, ops); - return copy; +// auto api_base_url = this -> get_api_url(); +// auto slippery = this -> is_slippery(); +// FrozenLake copy(api_base_url, +// cidx,slippery); +// +// std::unordered_map ops; +// ops["is_slippery"] = this -> is_slippery(); +// auto version = this -> version(); +// copy.make(version, ops); +// return copy; } diff --git a/src/rlenvs/envs/gymnasium/toy_text/frozen_lake_env.h b/src/rlenvs/envs/gymnasium/toy_text/frozen_lake_env.h index e854804..b35c151 100644 --- a/src/rlenvs/envs/gymnasium/toy_text/frozen_lake_env.h +++ b/src/rlenvs/envs/gymnasium/toy_text/frozen_lake_env.h @@ -57,15 +57,15 @@ #include "rlenvs/rlenvs_types_v2.h" #include "rlenvs/envs/time_step.h" -#include "rlenvs/extern/HTTPRequest.hpp" #include "rlenvs/envs/gymnasium/toy_text/toy_text_base.h" +#include "rlenvs/envs/api_server/apiserver.h" +#include "rlenvs/extern/nlohmann/json/json.hpp" #include #include #include #include #include -#include namespace rlenvscpp{ namespace envs{ @@ -111,6 +111,11 @@ class FrozenLake final: public ToyTextEnvBase, /// \brief name /// static const std::string name; + + /// + /// \brief The URI for accessing the environment + /// + static const std::string URI; /// /// \brief dynamics_t @@ -154,12 +159,12 @@ class FrozenLake final: public ToyTextEnvBase, /// /// \brief Constructor. /// - FrozenLake(const std::string& api_base_url); + FrozenLake(const RESTApiServerWrapper& api_server); /// /// \brief Constructor /// - FrozenLake(const std::string& api_base_url, + FrozenLake(const RESTApiServerWrapper& api_server, const uint_t cidx, bool slippery); /// @@ -211,12 +216,12 @@ class FrozenLake final: public ToyTextEnvBase, /// /// \brief build the dynamics from response /// - virtual dynamics_t build_dynamics_from_response_(const http::Response& response)const override final; + //virtual dynamics_t build_dynamics_from_response_(const nlohmann::json& response)const override final; /// /// \brief Handle the reset response from the environment server /// - virtual time_step_type create_time_step_from_response_(const http::Response& response) const override final; + virtual time_step_type create_time_step_from_response_(const nlohmann::json& response) const override final; private: diff --git a/src/rlenvs/envs/gymnasium/toy_text/taxi_env.cpp b/src/rlenvs/envs/gymnasium/toy_text/taxi_env.cpp index a34aabc..ae17fa7 100644 --- a/src/rlenvs/envs/gymnasium/toy_text/taxi_env.cpp +++ b/src/rlenvs/envs/gymnasium/toy_text/taxi_env.cpp @@ -16,54 +16,38 @@ namespace envs{ namespace gymnasium{ const std::string Taxi::name = "Taxi"; +const std::string Taxi::URI = "/gymnasium/taxi-env"; - -Taxi::Taxi(const std::string& api_base_url) +Taxi::Taxi(const RESTApiServerWrapper& api_server) : - ToyTextEnvBase, 500, 6>(0, - "Taxi", - api_base_url, - "/gymnasium/taxi-env") -{} + ToyTextEnvBase, 500, 6>(api_server, 0, Taxi::name) +{ + + this ->get_api_server().register_if_not(Taxi::name,Taxi::URI); +} -Taxi::Taxi(const std::string& api_base_url, +Taxi::Taxi(const RESTApiServerWrapper& api_server, const uint_t cidx) : -ToyTextEnvBase, 500, 6>(cidx, - "Taxi", - api_base_url, - "/gymnasium/taxi-env") -{} +ToyTextEnvBase, 500, 6>(api_server, cidx,Taxi::name) +{ + this ->get_api_server().register_if_not(Taxi::name,Taxi::URI); +} Taxi::Taxi(const Taxi& other) : ToyTextEnvBase, 500, 6>(other) {} -Taxi::dynamics_t -Taxi::build_dynamics_from_response_(const http::Response& response)const{ - - auto str_response = std::string(response.body.begin(), response.body.end()); - using json = nlohmann::json; - json j = json::parse(str_response); - - auto dynamics = j["dynamics"]; - return dynamics; -} Taxi::time_step_type -Taxi::create_time_step_from_response_(const http::Response& response)const{ - - auto str_response = std::string(response.body.begin(), response.body.end()); - using json = nlohmann::json; +Taxi::create_time_step_from_response_(const nlohmann::json& response)const{ - json j = json::parse(str_response); - - auto step_type = j["time_step"]["step_type"].template get(); - auto reward = j["time_step"]["reward"]; - auto discount = j["time_step"]["discount"]; - auto observation = j["time_step"]["observation"]; - auto info = j["time_step"]["info"]; + auto step_type = response["time_step"]["step_type"].template get(); + auto reward = response["time_step"]["reward"]; + auto discount = response["time_step"]["discount"]; + auto observation = response["time_step"]["observation"]; + auto info = response["time_step"]["info"]; return Taxi::time_step_type(TimeStepEnumUtils::time_step_type_from_int(step_type), reward, observation, discount, std::unordered_map()); @@ -76,24 +60,11 @@ Taxi::make(const std::string& version, if(this->is_created()){ return; } - - const auto request_url = std::string(this->get_url()) + "/make"; - - http::Request request{request_url}; - - auto copy_idx = this -> cidx(); - - using json = nlohmann::json; - json j; - j["version"] = version; - j["cidx"] = copy_idx; - auto body = j.dump(); - const auto response = request.send("POST", body); - - if(response.status.code != 201){ - throw std::runtime_error("Environment server failed to create Environment"); - } + this -> get_api_server().make(this->env_name(), + this->cidx(), + version, + nlohmann::json()); this->set_version_(version); this->make_created_(); @@ -110,22 +81,10 @@ Taxi::step(const action_type& action){ if(this->get_current_time_step_().last()){ return this->reset(42, std::unordered_map()); } - - const auto request_url = std::string(this->get_url()) + "/step"; - http::Request request{request_url}; - - auto copy_idx = this -> cidx(); - - using json = nlohmann::json; - json j; - j["cidx"] = copy_idx; - j["action"] = action; - - const auto response = request.send("POST", j.dump()); - - if(response.status.code != 202){ - throw std::runtime_error("Environment server failed to step environment"); - } + + auto response = this -> get_api_server().step(this->env_name(), + this->cidx(), + action); this->get_current_time_step_() = this->create_time_step_from_response_(response); return this->get_current_time_step_(); @@ -134,15 +93,15 @@ Taxi::step(const action_type& action){ Taxi Taxi::make_copy(uint_t cidx)const{ - auto api_base_url = this -> get_api_url(); - - Taxi copy(api_base_url, cidx); - - std::unordered_map ops; - auto version = this -> version(); - - copy.make(version, ops); - return copy; +// auto api_base_url = this -> get_api_url(); +// +// Taxi copy(api_base_url, cidx); +// +// std::unordered_map ops; +// auto version = this -> version(); +// +// copy.make(version, ops); +// return copy; } diff --git a/src/rlenvs/envs/gymnasium/toy_text/taxi_env.h b/src/rlenvs/envs/gymnasium/toy_text/taxi_env.h index 8820404..182ed80 100644 --- a/src/rlenvs/envs/gymnasium/toy_text/taxi_env.h +++ b/src/rlenvs/envs/gymnasium/toy_text/taxi_env.h @@ -5,16 +5,12 @@ #include "rlenvs/rlenvs_types_v2.h" #include "rlenvs/envs/gymnasium/toy_text/toy_text_base.h" #include "rlenvs/envs/time_step.h" -//#include "rlenvs/envs/space_type.h" -#include "rlenvs/extern/HTTPRequest.hpp" +#include "rlenvs/envs/api_server/apiserver.h" +#include "rlenvs/extern/nlohmann/json/json.hpp" - -#include #include #include #include -#include - namespace rlenvscpp{ namespace envs { @@ -32,6 +28,11 @@ class Taxi final: public ToyTextEnvBase, 500, 6> /// static const std::string name; + /// + /// \brief The URI for accessing the environment + /// + static const std::string URI; + /// /// \brief The base type /// @@ -66,12 +67,12 @@ class Taxi final: public ToyTextEnvBase, 500, 6> /// /// \brief Taxi /// - Taxi(const std::string& api_base_url); + Taxi(const RESTApiServerWrapper& api_server); /// /// \brief Constructor /// - Taxi(const std::string& api_base_url, + Taxi(const RESTApiServerWrapper& api_server, const uint_t cidx); /// @@ -110,12 +111,12 @@ class Taxi final: public ToyTextEnvBase, 500, 6> /// /// \brief build the dynamics from response /// - virtual dynamics_t build_dynamics_from_response_(const http::Response& response)const override final; + //virtual dynamics_t build_dynamics_from_response_(const nlohmann::json& response)const override final; /// /// \brief Handle the reset response from the environment server /// - virtual time_step_type create_time_step_from_response_(const http::Response& response) const override final; + virtual time_step_type create_time_step_from_response_(const nlohmann::json& response) const override final; diff --git a/src/rlenvs/envs/gymnasium/toy_text/toy_text_base.h b/src/rlenvs/envs/gymnasium/toy_text/toy_text_base.h index 34a2456..821ad48 100644 --- a/src/rlenvs/envs/gymnasium/toy_text/toy_text_base.h +++ b/src/rlenvs/envs/gymnasium/toy_text/toy_text_base.h @@ -1,10 +1,11 @@ #ifndef TOY_TEXT_BASE_ENV_H #define TOY_TEXT_BASE_ENV_H +#include "rlenvs/envs/gymnasium/gymnasium_env_base.h" #include "rlenvs/rlenvs_types_v2.h" -#include "rlenvs/extern/HTTPRequest.hpp" +#include "rlenvs/extern/nlohmann/json/json.hpp" #include "rlenvs/rlenvscpp_config.h" -#include "rlenvs/envs/gymnasium/gymnasium_env_base.h" +#include "rlenvs/envs/api_server/apiserver.h" #include "rlenvs/envs/env_types.h" #include @@ -12,7 +13,6 @@ #include #include #include -#include #ifdef RLENVSCPP_DEBUG #include @@ -88,8 +88,7 @@ class ToyTextEnvBase: public GymnasiumEnvBase -ToyTextEnvBase::ToyTextEnvBase(const uint_t cidx, - const std::string& name, - const std::string& api_url, - const std::string& resource_path) +ToyTextEnvBase::ToyTextEnvBase(const RESTApiServerWrapper& api_server, + const uint_t cidx, + const std::string& name) : GymnasiumEnvBase>(cidx, name, api_url, resource_path) + ScalarDiscreteEnv>(api_server, + cidx, + name) {} template -ToyTextEnvBase::ToyTextEnvBase(const ToyTextEnvBase& other) +ToyTextEnvBase::ToyTextEnvBase(const ToyTextEnvBase& other) : GymnasiumEnvBase>(other) @@ -142,18 +144,20 @@ ToyTextEnvBase::p(uint_t sidx, uint_t aidx) assert(this->is_created() && "Environment has not been created"); #endif - const std::string url(this->get_url()); - const auto request_url = url + "/dynamics?cidx="+std::to_string(this -> cidx()) - +"&stateId="+std::to_string(sidx) - +"&actionId="+std::to_string(aidx); - http::Request request{request_url}; - const auto response = request.send("GET"); + auto response = this -> get_api_server().dynamics(this->env_name(), + this->cidx(), + sidx, aidx); + return build_dynamics_from_response_(response); +} - if(response.status.code != 200){ - throw std::runtime_error("Environment server failed to return environment dynamics"); - } - return build_dynamics_from_response_(response); +template +typename ToyTextEnvBase::dynamics_t +ToyTextEnvBase::build_dynamics_from_response_(const nlohmann::json& response)const{ + auto dynamics = response["dynamics"]; + return dynamics; } diff --git a/src/rlenvs/rlenvscpp_version.h b/src/rlenvs/rlenvscpp_version.h index 3b5375c..c3c6f49 100755 --- a/src/rlenvs/rlenvscpp_version.h +++ b/src/rlenvs/rlenvscpp_version.h @@ -2,7 +2,7 @@ #define GYMFCPP_VERSION_H #define RLENVSCPP_VERSION_MAJOR 1 -#define RLENVSCPP_VERSION_MINOR 4 +#define RLENVSCPP_VERSION_MINOR 5 #define RLENVSCPP_VERSION_PATCH 0 -#define RLENVSCPP_VERSION "1.4.0" +#define RLENVSCPP_VERSION "1.5.0" #endif diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 112fb78..94fb542 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -56,4 +56,5 @@ ADD_SUBDIRECTORY(test_acrobot) #ADD_SUBDIRECTORY(test_vector_env_wrapper) #ADD_SUBDIRECTORY(test_vector_time_step) ADD_SUBDIRECTORY(test_generic_line) +ADD_SUBDIRECTORY(test_rest_api_server_wrapper) From 16b727d59576e43058b05012613de5e3fb22a21a Mon Sep 17 00:00:00 2001 From: pockerman Date: Wed, 1 Jan 2025 16:40:11 +0000 Subject: [PATCH 2/5] Refactor API server (#120) --- src/rlenvs/envs/api_server/apiserver.cpp | 257 +++++++++++++++++++++++ src/rlenvs/envs/api_server/apiserver.h | 203 ++++++++++++++++++ 2 files changed, 460 insertions(+) create mode 100644 src/rlenvs/envs/api_server/apiserver.cpp create mode 100644 src/rlenvs/envs/api_server/apiserver.h diff --git a/src/rlenvs/envs/api_server/apiserver.cpp b/src/rlenvs/envs/api_server/apiserver.cpp new file mode 100644 index 0000000..3feabc1 --- /dev/null +++ b/src/rlenvs/envs/api_server/apiserver.cpp @@ -0,0 +1,257 @@ +#include "rlenvs/envs/api_server/apiserver.h" +#include "rlenvs/rlenvs_consts.h" +#include "rlenvs/extern/HTTPRequest.hpp" +#include "rlenvs/extern/nlohmann/json/json.hpp" + +#include +#include + +namespace rlenvscpp{ +namespace envs{ + +RESTApiServerWrapper::RESTApiServerWrapper(const std::string& url, const bool initialize) +: +url_(url), +is_init_(false), +envs_() +{ + if(initialize){ + init_(); + } +} + +void +RESTApiServerWrapper::init_(){ + + envs_["FrozenLake"] = "/gymnasium/frozen-lake-env"; + envs_["Taxi"] = "/gymnasium/taxi-env"; + envs_["CliffWalking"] = "/gymnasium/cliff-walking-env"; + envs_["BlackJack"] = "/gymnasium/black-jack-env"; + envs_["MountainCar"] = "/gymnasium/mountain-car-env"; + envs_["CartPole"] = "/gymnasium/cart-pole-env"; + envs_["Acrobot"] = "/gymnasium/acrobot-env"; + envs_["Pendulum"] = "/gymnasium/pendulum-env"; + envs_["AcrobotV"] = "/gymnasium/acrobot-env/v"; + +} + +void +RESTApiServerWrapper::register_new(const std::string& name, const std::string& uri){ + + auto env_itr = envs_.find(name); + + if(env_itr == envs_.end()){ + envs_[name] = uri; + return; + } + + throw std::logic_error("Environment: " + name + " already exists"); + +} + +void +RESTApiServerWrapper::register_if_not(const std::string& name, + const std::string& uri){ + + try{ + register_new(name, uri); + } + catch(const std::logic_error& e){ + + } + +} + +std::string +RESTApiServerWrapper::get_uri(const std::string& name)const noexcept{ + + auto env_itr = envs_.find(name); + + if(env_itr == envs_.end()){ + return rlenvscpp::consts::INVALID_STR; + } + + return env_itr -> second; +} + +std::string +RESTApiServerWrapper::get_env_url(const std::string& name)const noexcept{ + + auto uri_ = get_uri(name); + + if(uri_ == rlenvscpp::consts::INVALID_STR){ + return rlenvscpp::consts::INVALID_STR; + } + + return get_url() + uri_; +} + +nlohmann::json +RESTApiServerWrapper::is_alive(const std::string& env_name, + const uint_t cidx)const{ + + // find the source + auto url_ = get_env_url(env_name); + + if(url_ == rlenvscpp::consts::INVALID_STR){ + throw std::logic_error("Environment: " + env_name + " is not registered"); + } + + + auto copy_idx_str = std::to_string(cidx); + + http::Request request{url_ + "/is-alive?cidx="+copy_idx_str}; + const auto response = request.send("GET"); + + auto str_response = std::string(response.body.begin(), response.body.end()); + nlohmann::json j = nlohmann::json::parse(str_response); + return j; + +} + +nlohmann::json +RESTApiServerWrapper::close(const std::string& env_name, + const uint_t cidx)const{ + + // find the source + auto url_ = get_env_url(env_name); + + if(url_ == rlenvscpp::consts::INVALID_STR){ + throw std::logic_error("Environment: " + env_name + " is not registered"); + } + + http::Request request{url_ + "/close?cidx="+std::to_string(cidx)}; + const auto response = request.send("POST"); + + if(response.status.code != 201){ + throw std::runtime_error("Could not close environment " + env_name); + } + + auto str_response = std::string(response.body.begin(), response.body.end()); + nlohmann::json j = nlohmann::json::parse(str_response); + return j; +} + +nlohmann::json +RESTApiServerWrapper::reset(const std::string& env_name, + const uint_t cidx, + const uint_t seed, + const nlohmann::json& options)const{ + + + // find the source + auto url_ = get_env_url(env_name); + + if(url_ == rlenvscpp::consts::INVALID_STR){ + throw std::logic_error("Environment: " + env_name + " is not registered"); + } + + const auto request_url = url_ + "/reset"; + http::Request request{request_url}; + + nlohmann::json request_body; + request_body["seed"] = seed; + request_body["cidx"] = cidx; + request_body["options"] = options; + + const auto response = request.send("POST", request_body.dump()); + + if(response.status.code != 202){ + throw std::runtime_error("Environment server failed to reset environment"); + } + + auto str_response = std::string(response.body.begin(), response.body.end()); + nlohmann::json j = nlohmann::json::parse(str_response); + return j; + +} + + +nlohmann::json +RESTApiServerWrapper::make(const std::string& env_name, + const uint_t cidx, + const std::string& version, + const nlohmann::json& options)const{ + + // find the source + auto url_ = get_env_url(env_name); + + if(url_ == rlenvscpp::consts::INVALID_STR){ + throw std::logic_error("Environment: " + env_name + " is not registered"); + } + + const auto request_url = url_ + "/make"; + http::Request request{request_url}; + + nlohmann::json request_body; + request_body["version"] = version; + request_body["cidx"] = cidx; + request_body["options"] = options; + + const auto response = request.send("POST", request_body.dump()); + + if(response.status.code != 201){ + throw std::runtime_error("Environment server failed to create Environment"); + } + + auto str_response = std::string(response.body.begin(), response.body.end()); + nlohmann::json j = nlohmann::json::parse(str_response); + return j; + +} + +nlohmann::json +RESTApiServerWrapper::dynamics(const std::string& env_name, + const uint_t cidx, + const uint_t sidx, + const uint_t aidx)const{ + + // find the source + auto url_ = get_env_url(env_name); + + if(url_ == rlenvscpp::consts::INVALID_STR){ + throw std::logic_error("Environment: " + env_name + " is not registered"); + } + + const auto request_url = url_ + "/dynamics?cidx="+std::to_string(cidx) + +"&stateId="+std::to_string(sidx) + +"&actionId="+std::to_string(aidx); + http::Request request{request_url}; + const auto response = request.send("GET"); + + auto str_response = std::string(response.body.begin(), response.body.end()); + nlohmann::json j = nlohmann::json::parse(str_response); + return j; +} + +bool +RESTApiServerWrapper::has_gymnasium()const{ + + const auto request_url = url_ + "/api-info/gymnasium"; + http::Request request{request_url}; + + const auto response = request.send("GET"); + return response.status.code == 200; + +} + +std::vector +RESTApiServerWrapper::gymnasium_envs()const{ + + const auto request_url = url_ + "/api-info/gymnasium/envs"; + http::Request request{request_url}; + + const auto response = request.send("GET"); + + if(response.status.code != 200){ + throw std::runtime_error("Environment server responded with error"); + } + + auto str_response = std::string(response.body.begin(), response.body.end()); + using json = nlohmann::json; + json j = json::parse(str_response); + return j["envs"]; +} + +} +} diff --git a/src/rlenvs/envs/api_server/apiserver.h b/src/rlenvs/envs/api_server/apiserver.h new file mode 100644 index 0000000..a3d8c6c --- /dev/null +++ b/src/rlenvs/envs/api_server/apiserver.h @@ -0,0 +1,203 @@ + + +#ifndef APISERVER_H +#define APISERVER_H + +#include "rlenvs/rlenvs_types_v2.h" +#include "rlenvs/rlenvs_consts.h" +#include "rlenvs/extern/nlohmann/json/json.hpp" +#include "rlenvs/extern/HTTPRequest.hpp" +#include +#include +#include +#include + +/// +/// todo write docs +/// +/// +/// +namespace rlenvscpp{ +namespace envs{ + +/// +/// \brief Utility class to facilitate +/// HTTP requests between the environments REST API +/// and C++ drivers +/// +class RESTApiServerWrapper +{ +public: + + /// + /// \brief Constructor + /// + explicit RESTApiServerWrapper(const std::string& url="http://0.0.0.0:8001/api", + const bool initialize=true); + + /// + /// \brief Returns true if the server is initialised + /// + bool is_inisialised()const noexcept{return is_init_;} + + /// + /// \brief Returns the remote url + /// + std::string get_url()const noexcept{return url_;} + + /// + /// \brief Return the url for the environment + /// with the given name + /// + std::string get_env_url(const std::string& name)const noexcept; + + /// + /// \brief Returns the URI of the environment + /// with the given name Returns INVALID_STR + /// if the environment is not registered + /// + std::string get_uri(const std::string& name)const noexcept; + + /// + /// \brief Register a new environment. Throws + /// std::logic_error if the environment name already exists + /// + void register_new(const std::string& name, const std::string& uri); + + /// + /// \brief Same as register_new but swallows the thrown exception + /// + void register_if_not(const std::string& name, const std::string& uri); + + + /// + /// \brief Queries the remote server if the environment with the + /// given cidx is alive + /// Throws std::logic_error is the environment is not registered + /// + nlohmann::json is_alive(const std::string& env_name, + const uint_t cidx)const; + + /// + /// \brief Close the environment with the given name. + /// Throws std::logic_error is the environment is not registered + /// Throws std::runtime_error if the server response is not 201 + /// + nlohmann::json close(const std::string& env_name, + const uint_t cidx)const; + + /// + /// \brief Step in the environment with the given name + /// and the given copy index executing action. + /// ActionType has to be JSON serializable + /// Throws std::logic_error is the environment is not registered + /// Throws std::runtime_error if the server response is not 201 + /// + template + nlohmann::json step(const std::string& env_name, + const uint_t cidx, + const ActionType& action)const; + + /// + /// \brief Reset the the environment with the given name + /// and the given copy index executing action. + /// Throws std::logic_error is the environment is not registered + /// Throws std::runtime_error if the server response is not 202 + /// + nlohmann::json reset(const std::string& env_name, + const uint_t cidx, + const uint_t seed, + const nlohmann::json& options)const; + + /// + /// \brief Make the the environment with the given name + /// and the given copy index executing action. + /// Throws std::logic_error is the environment is not registered + /// Throws std::runtime_error if the server response is not 202 + /// + nlohmann::json make(const std::string& env_name, + const uint_t cidx, + const std::string& version, + const nlohmann::json& options)const; + + + /// + /// \brief Get the dynamics of the environment. If the environment + /// does not expose such an endpoint it returns 404 + /// + nlohmann::json dynamics(const std::string& env_name, + const uint_t cidx, + const uint_t sidx, + const uint_t aidx)const; + + /// + /// + /// + bool has_gymnasium()const; + + /// + /// + /// + std::vector gymnasium_envs()const; + +private: + + /// + /// \brief The source url of the remote server + /// + const std::string url_; + + /// + /// \brief Flag indicating if the underlying + /// environments have been initialised + /// + bool is_init_{false}; + + /// + /// \brief Map that holds the environment names and their + /// respective URI on the remote server + /// + std::unordered_map envs_; + + /// + /// \brief Initialzes the available environments + /// + void init_(); +}; + +template +nlohmann::json +RESTApiServerWrapper::step(const std::string& env_name, const uint_t cidx, + const ActionType& action)const{ + + + // find the source + auto url_ = get_env_url(env_name); + + if(url_ == rlenvscpp::consts::INVALID_STR){ + throw std::logic_error("Environment: " + env_name + " is not registered"); + } + + const auto request_url = url_ + "/step"; + http::Request request{request_url}; + + nlohmann::json body; + body["cidx"] = cidx; + body["action"] = action; + + const auto response = request.send("POST", body.dump()); + + if(response.status.code != 202){ + throw std::runtime_error("Environment server failed to step environment"); + } + + auto str_response = std::string(response.body.begin(), response.body.end()); + nlohmann::json j = nlohmann::json::parse(str_response); + return j; + +} + + +} +} +#endif // APISERVER_H From 4d0da6a0227f61dbdd112e4524a06cfedc78f2eb Mon Sep 17 00:00:00 2001 From: pockerman Date: Wed, 1 Jan 2025 16:41:10 +0000 Subject: [PATCH 3/5] Add unit tests for rest api server (#120) --- .../CMakeLists.txt | 12 +++++ .../test_rest_api_server_wrapper.cpp | 49 +++++++++++++++++++ 2 files changed, 61 insertions(+) create mode 100644 tests/test_rest_api_server_wrapper/CMakeLists.txt create mode 100644 tests/test_rest_api_server_wrapper/test_rest_api_server_wrapper.cpp diff --git a/tests/test_rest_api_server_wrapper/CMakeLists.txt b/tests/test_rest_api_server_wrapper/CMakeLists.txt new file mode 100644 index 0000000..a71de1f --- /dev/null +++ b/tests/test_rest_api_server_wrapper/CMakeLists.txt @@ -0,0 +1,12 @@ +CMAKE_MINIMUM_REQUIRED(VERSION 3.6) + +SET(EXECUTABLE test_rest_api_server_wrapper) +SET(SOURCE ${EXECUTABLE}.cpp) + +ADD_EXECUTABLE(${EXECUTABLE} ${SOURCE}) + +TARGET_LINK_LIBRARIES(${EXECUTABLE} rlenvscpplib) +TARGET_LINK_LIBRARIES(${EXECUTABLE} gtest) +TARGET_LINK_LIBRARIES(${EXECUTABLE} gtest_main) # so that tests dont need to have a main +TARGET_LINK_LIBRARIES(${EXECUTABLE} pthread) + diff --git a/tests/test_rest_api_server_wrapper/test_rest_api_server_wrapper.cpp b/tests/test_rest_api_server_wrapper/test_rest_api_server_wrapper.cpp new file mode 100644 index 0000000..7365ba4 --- /dev/null +++ b/tests/test_rest_api_server_wrapper/test_rest_api_server_wrapper.cpp @@ -0,0 +1,49 @@ +#include "rlenvs/envs/api_server/apiserver.h" +#include "rlenvs/rlenvs_types_v2.h" + +#include +#include +#include +#include + +namespace{ + +using namespace rlenvscpp; +using rlenvscpp::envs::RESTApiServerWrapper; +const std::string SERVER_URL = "http://0.0.0.0:8001/api"; + +} + +TEST(TestRESTApiServerWrapper, Constructor) { + + RESTApiServerWrapper api_server(SERVER_URL); + ASSERT_EQ(api_server.get_url(), SERVER_URL); +} + + +TEST(TestRESTApiServerWrapper, register_new) { + + RESTApiServerWrapper api_server(SERVER_URL); + + api_server.register_new("Dummy", "/dummy-env-uri"); + ASSERT_EQ(api_server.get_uri("Dummy"), "/dummy-env-uri"); +} + +TEST(TestRESTApiServerWrapper, register_new_throws) { + + RESTApiServerWrapper api_server(SERVER_URL); + + const std::string name("Dummy"); + api_server.register_new(name, "/dummy-env-uri"); + + try { + api_server.register_new(name, "/another/dummy-env-uri"); + } + catch(const std::logic_error& err) { + EXPECT_EQ(err.what(), std::string("Environment: " + name + " already exists")); + } + catch(...) { + FAIL() << "Expected std::std::logic_error"; + } + +} From 40b6c828a91fec1130cd5b7dec0cdfaa9e709bb6 Mon Sep 17 00:00:00 2001 From: pockerman Date: Wed, 1 Jan 2025 16:52:41 +0000 Subject: [PATCH 4/5] Add make_copy function (#120) --- README.md | 4 ++-- src/rlenvs/envs/api_server/apiserver.h | 8 ++++++++ .../gymnasium/classic_control/acrobot_env.cpp | 15 +++++++------- .../classic_control/cart_pole_env.cpp | 14 ++++++------- .../classic_control/mountain_car_env.cpp | 13 ++++++------ .../classic_control/pendulum_env.cpp | 12 +++++------ .../vector/acrobot_vec_env.cpp | 17 ++++++++-------- .../gymnasium/toy_text/black_jack_env.cpp | 20 +++++++++---------- .../gymnasium/toy_text/cliff_world_env.cpp | 11 +++++----- .../gymnasium/toy_text/frozen_lake_env.cpp | 19 +++++++++--------- .../envs/gymnasium/toy_text/taxi_env.cpp | 14 +++++-------- 11 files changed, 71 insertions(+), 76 deletions(-) diff --git a/README.md b/README.md index 16cef36..acd5573 100644 --- a/README.md +++ b/README.md @@ -12,8 +12,8 @@ Currently, we provide a minimal number of wrappers for some common Gymnasium (fo | FrozenLake 8x8 map | Yes | TODO | | Blackjack | Yes | example_1 | | CliffWalking | Yes | example_1 | -| CartPole | Yes | TODO | -| MountainCar | Yes | TODO | +| CartPole | Yes | TODO | +| MountainCar | Yes | TODO | | Taxi | Yes | example_1 | | Pendulum | Yes | example_6 | | Acrobot | Yes | TODO | diff --git a/src/rlenvs/envs/api_server/apiserver.h b/src/rlenvs/envs/api_server/apiserver.h index a3d8c6c..2b27747 100644 --- a/src/rlenvs/envs/api_server/apiserver.h +++ b/src/rlenvs/envs/api_server/apiserver.h @@ -129,6 +129,14 @@ class RESTApiServerWrapper const uint_t cidx, const uint_t sidx, const uint_t aidx)const; + + /// + /// \brief Make the cidx copy of the environment + /// + nlohmann::json copy(const std::string& env_name, + const uint_t cidx, + const std::string& version, + const nlohmann::json& options)const{return make(env_name, cidx, version, options);} /// /// diff --git a/src/rlenvs/envs/gymnasium/classic_control/acrobot_env.cpp b/src/rlenvs/envs/gymnasium/classic_control/acrobot_env.cpp index 6946084..3848954 100644 --- a/src/rlenvs/envs/gymnasium/classic_control/acrobot_env.cpp +++ b/src/rlenvs/envs/gymnasium/classic_control/acrobot_env.cpp @@ -94,14 +94,13 @@ Acrobot::step(const action_type& action){ Acrobot Acrobot::make_copy(uint_t cidx)const{ -// auto api_base_url = this -> get_api_url(); -// -// Acrobot copy(api_base_url, cidx); -// -// std::unordered_map ops; -// auto version = this -> version(); -// copy.make(version, ops); -// return copy; + + Acrobot copy(this->get_api_server(), cidx); + + std::unordered_map ops; + auto version = this -> version(); + copy.make(version, ops); + return copy; } diff --git a/src/rlenvs/envs/gymnasium/classic_control/cart_pole_env.cpp b/src/rlenvs/envs/gymnasium/classic_control/cart_pole_env.cpp index 72a4f01..9d2d2bd 100644 --- a/src/rlenvs/envs/gymnasium/classic_control/cart_pole_env.cpp +++ b/src/rlenvs/envs/gymnasium/classic_control/cart_pole_env.cpp @@ -93,13 +93,13 @@ CartPole::step(const action_type& action){ CartPole CartPole::make_copy(uint_t cidx)const{ -// auto api_base_url = this -> get_api_url(); -// -// CartPole copy(api_base_url, cidx); -// std::unordered_map ops; -// auto version = this -> version(); -// copy.make(version, ops); -// return copy; + + + CartPole copy(this -> get_api_server(), cidx); + std::unordered_map ops; + auto version = this -> version(); + copy.make(version, ops); + return copy; } diff --git a/src/rlenvs/envs/gymnasium/classic_control/mountain_car_env.cpp b/src/rlenvs/envs/gymnasium/classic_control/mountain_car_env.cpp index 392dcc9..80230aa 100644 --- a/src/rlenvs/envs/gymnasium/classic_control/mountain_car_env.cpp +++ b/src/rlenvs/envs/gymnasium/classic_control/mountain_car_env.cpp @@ -106,13 +106,12 @@ MountainCar::step(const action_type& action){ MountainCar MountainCar::make_copy(uint_t cidx)const{ -// auto api_base_url = this -> get_api_url(); -// MountainCar copy(api_base_url, cidx); -// -// std::unordered_map ops; -// auto version = this -> version(); -// copy.make(version, ops); -// return copy; + + MountainCar copy(this -> get_api_server(), cidx); + std::unordered_map ops; + auto version = this -> version(); + copy.make(version, ops); + return copy; } } diff --git a/src/rlenvs/envs/gymnasium/classic_control/pendulum_env.cpp b/src/rlenvs/envs/gymnasium/classic_control/pendulum_env.cpp index a46f5da..7651b36 100644 --- a/src/rlenvs/envs/gymnasium/classic_control/pendulum_env.cpp +++ b/src/rlenvs/envs/gymnasium/classic_control/pendulum_env.cpp @@ -104,13 +104,11 @@ Pendulum::step(const action_type& action){ Pendulum Pendulum::make_copy(uint_t cidx)const{ -// auto api_base_url = this -> get_api_url(); -// -// Pendulum copy(api_base_url, cidx); -// std::unordered_map ops; -// auto version = this -> version(); -// copy.make(version, ops); -// return copy; + Pendulum copy(this -> get_api_server(), cidx); + std::unordered_map ops; + auto version = this -> version(); + copy.make(version, ops); + return copy; } } diff --git a/src/rlenvs/envs/gymnasium/classic_control/vector/acrobot_vec_env.cpp b/src/rlenvs/envs/gymnasium/classic_control/vector/acrobot_vec_env.cpp index f03a27b..cf60957 100644 --- a/src/rlenvs/envs/gymnasium/classic_control/vector/acrobot_vec_env.cpp +++ b/src/rlenvs/envs/gymnasium/classic_control/vector/acrobot_vec_env.cpp @@ -101,15 +101,14 @@ AcrobotV::step(const action_type& action){ AcrobotV AcrobotV::make_copy(uint_t cidx)const{ -// auto api_base_url = this -> get_api_url(); -// -// AcrobotV copy(api_base_url, cidx); -// -// std::unordered_map ops; -// ops["num_envs"] = this -> get_n_envs(); -// auto version = this -> version(); -// copy.make(version, ops); -// return copy; + + AcrobotV copy(this->get_api_server(), cidx); + + std::unordered_map ops; + ops["num_envs"] = this -> get_n_envs(); + auto version = this -> version(); + copy.make(version, ops); + return copy; } } diff --git a/src/rlenvs/envs/gymnasium/toy_text/black_jack_env.cpp b/src/rlenvs/envs/gymnasium/toy_text/black_jack_env.cpp index f31a36d..4394078 100644 --- a/src/rlenvs/envs/gymnasium/toy_text/black_jack_env.cpp +++ b/src/rlenvs/envs/gymnasium/toy_text/black_jack_env.cpp @@ -117,17 +117,15 @@ BlackJack::step(const action_type& action){ BlackJack BlackJack::make_copy(uint_t cidx)const{ -// auto api_base_url = this -> get_api_url(); -// -// BlackJack copy(api_base_url, cidx); -// -// std::unordered_map ops; -// ops["natural"] = this->is_natural(); -// ops["sab"] = this->is_sab(); -// -// auto version = this -> version(); -// copy.make(version, ops); -// return copy; + BlackJack copy(this -> get_api_server(), cidx); + + std::unordered_map ops; + ops["natural"] = this->is_natural(); + ops["sab"] = this->is_sab(); + + auto version = this -> version(); + copy.make(version, ops); + return copy; } diff --git a/src/rlenvs/envs/gymnasium/toy_text/cliff_world_env.cpp b/src/rlenvs/envs/gymnasium/toy_text/cliff_world_env.cpp index cda6808..e281c19 100644 --- a/src/rlenvs/envs/gymnasium/toy_text/cliff_world_env.cpp +++ b/src/rlenvs/envs/gymnasium/toy_text/cliff_world_env.cpp @@ -110,12 +110,11 @@ CliffWorld::step(const action_type& action){ CliffWorld CliffWorld::make_copy(uint_t cidx)const{ -// auto api_base_url = this -> get_api_url(); -// CliffWorld copy(api_base_url,cidx); -// std::unordered_map ops; -// auto version = this -> version(); -// copy.make(version, ops); -// return copy; + CliffWorld copy(this -> get_api_server(),cidx); + std::unordered_map ops; + auto version = this -> version(); + copy.make(version, ops); + return copy; } } diff --git a/src/rlenvs/envs/gymnasium/toy_text/frozen_lake_env.cpp b/src/rlenvs/envs/gymnasium/toy_text/frozen_lake_env.cpp index b2fd171..e3be039 100644 --- a/src/rlenvs/envs/gymnasium/toy_text/frozen_lake_env.cpp +++ b/src/rlenvs/envs/gymnasium/toy_text/frozen_lake_env.cpp @@ -123,16 +123,15 @@ template FrozenLake FrozenLake::make_copy(uint_t cidx)const{ -// auto api_base_url = this -> get_api_url(); -// auto slippery = this -> is_slippery(); -// FrozenLake copy(api_base_url, -// cidx,slippery); -// -// std::unordered_map ops; -// ops["is_slippery"] = this -> is_slippery(); -// auto version = this -> version(); -// copy.make(version, ops); -// return copy; + auto slippery = this -> is_slippery(); + FrozenLake copy(this -> get_api_server(), + cidx, slippery); + + std::unordered_map ops; + ops["is_slippery"] = this -> is_slippery(); + auto version = this -> version(); + copy.make(version, ops); + return copy; } diff --git a/src/rlenvs/envs/gymnasium/toy_text/taxi_env.cpp b/src/rlenvs/envs/gymnasium/toy_text/taxi_env.cpp index ae17fa7..583b629 100644 --- a/src/rlenvs/envs/gymnasium/toy_text/taxi_env.cpp +++ b/src/rlenvs/envs/gymnasium/toy_text/taxi_env.cpp @@ -93,15 +93,11 @@ Taxi::step(const action_type& action){ Taxi Taxi::make_copy(uint_t cidx)const{ -// auto api_base_url = this -> get_api_url(); -// -// Taxi copy(api_base_url, cidx); -// -// std::unordered_map ops; -// auto version = this -> version(); -// -// copy.make(version, ops); -// return copy; + Taxi copy(this -> get_api_server(), cidx); + std::unordered_map ops; + auto version = this -> version(); + copy.make(version, ops); + return copy; } From 7e8705dda11a5ca30171bc160539f68925b2028c Mon Sep 17 00:00:00 2001 From: pockerman Date: Wed, 1 Jan 2025 17:21:24 +0000 Subject: [PATCH 5/5] Update FastAPI API (#120) --- .../gdrl/gym_walk_env/gym_walk_env_api.py | 15 +- .../classic_control/acrobot_env_api.py | 2 +- .../classic_control/cart_pole_env_api.py | 8 +- .../classic_control/mountain_car_env_api.py | 3 +- .../classic_control/pendulum_env_api.py | 5 +- .../classic_control/v/acrobot_v_env_api.py | 9 +- .../toy_text/black_jack_env_api.py | 5 +- .../toy_text/frozenlake_env_api.py | 14 +- .../gymnasium_envs/toy_text/taxi_env_api.py | 5 +- src/rlenvs/envs/api_server/apiserver.cpp | 1 + src/rlenvs/envs/gdrl/gym_walk.h | 158 ++++++------------ 11 files changed, 93 insertions(+), 132 deletions(-) diff --git a/rest_api/gdrl/gym_walk_env/gym_walk_env_api.py b/rest_api/gdrl/gym_walk_env/gym_walk_env_api.py index e0cfdc3..1c01256 100644 --- a/rest_api/gdrl/gym_walk_env/gym_walk_env_api.py +++ b/rest_api/gdrl/gym_walk_env/gym_walk_env_api.py @@ -59,11 +59,20 @@ async def close(cidx: int) -> JSONResponse: @gym_walk_env_router.post("/make") async def make(version: str = Body(default="v1"), cidx: int = Body(...), - n_states: int = Body(default=7, ge=2), - p_stay: float = Body(default=0.0, ge=0.0, le=1.0), - p_backward: float = Body(default=0.5, le=1.0, ge=0.0)) -> JSONResponse: + options: dict[str, Any] = Body(default={"n_states": 7, + "p_stay": 0.0, + "p_backward": 0.5}), + ) -> JSONResponse: global envs + # n_states: int = Body(default=7, ge=2), + # p_stay: float = Body(default=0.0, ge=0.0, le=1.0), + # p_backward: float = Body(default=0.5, le=1.0, ge=0.0) + + n_states = options.get("n_states", 7) + p_stay = options.get("p_stay", 0.0) + p_backward = options.get("p_backward", 0.5) + if cidx in envs: env = envs[cidx] diff --git a/rest_api/gymnasium_envs/classic_control/acrobot_env_api.py b/rest_api/gymnasium_envs/classic_control/acrobot_env_api.py index b1e3505..4f7a6fa 100644 --- a/rest_api/gymnasium_envs/classic_control/acrobot_env_api.py +++ b/rest_api/gymnasium_envs/classic_control/acrobot_env_api.py @@ -66,7 +66,7 @@ async def close(cidx: int) -> JSONResponse: @acrobot_router.post("/make") async def make(version: str = Body(default="v1"), cidx: int = Body(...), - max_episode_steps: int = Body(default=500)) -> JSONResponse: + options: dict[str, Any] = Body(default={})) -> JSONResponse: global envs env_type = f"{ENV_NAME}-{version}" if cidx in envs: diff --git a/rest_api/gymnasium_envs/classic_control/cart_pole_env_api.py b/rest_api/gymnasium_envs/classic_control/cart_pole_env_api.py index fa83110..de8e9fe 100644 --- a/rest_api/gymnasium_envs/classic_control/cart_pole_env_api.py +++ b/rest_api/gymnasium_envs/classic_control/cart_pole_env_api.py @@ -61,9 +61,7 @@ async def close(cidx: int) -> JSONResponse: @cart_pole_router.post("/make") async def make(version: str = Body(default="v1"), cidx: int = Body(...), - natural: bool = Body(default=False), - sab: bool = Body(default=False), - max_episode_steps: int = Body(default=500)) -> JSONResponse: + options: dict[str, Any] = Body(default={})) -> JSONResponse: global envs env_type = f"{ENV_NAME}-{version}" if cidx in envs: @@ -73,7 +71,7 @@ async def make(version: str = Body(default="v1"), envs[cidx].close() try: - env = gym.make(env_type, natural, sab) + env = gym.make(env_type,) envs[cidx] = env except Exception as e: logger.error('An exception was raised') @@ -82,7 +80,7 @@ async def make(version: str = Body(default="v1"), detail=str(e)) else: try: - env = gym.make(env_type, natural, sab) + env = gym.make(env_type) envs[cidx] = env except Exception as e: logger.error('An exception was raised') diff --git a/rest_api/gymnasium_envs/classic_control/mountain_car_env_api.py b/rest_api/gymnasium_envs/classic_control/mountain_car_env_api.py index a6259d4..173d93a 100644 --- a/rest_api/gymnasium_envs/classic_control/mountain_car_env_api.py +++ b/rest_api/gymnasium_envs/classic_control/mountain_car_env_api.py @@ -63,10 +63,11 @@ async def close(cidx: int) -> JSONResponse: @mountain_car_router.post("/make") async def make(version: str = Body(default="v0"), cidx: int = Body(...), - max_episode_steps: int = Body(default=200) + options: dict[str, Any] = Body(default={"max_episode_steps": 200}) ) -> JSONResponse: global envs env_type = f"{ENV_NAME}-{version}" + max_episode_steps = options.get("max_episode_steps", 200) if cidx in envs: env = envs[cidx] diff --git a/rest_api/gymnasium_envs/classic_control/pendulum_env_api.py b/rest_api/gymnasium_envs/classic_control/pendulum_env_api.py index 8938053..102592d 100644 --- a/rest_api/gymnasium_envs/classic_control/pendulum_env_api.py +++ b/rest_api/gymnasium_envs/classic_control/pendulum_env_api.py @@ -70,10 +70,11 @@ async def close(cidx: int) -> JSONResponse: @pendulum_router.post("/make") async def make(version: str = Body(default="v1"), cidx: int = Body(...), - g: float = Body(default=10.0), - max_episode_steps: int = Body(default=200)) -> JSONResponse: + options: dict[str, Any] = Body(default={"g": 10.0, "max_episode_steps": 200})) -> JSONResponse: global envs env_type = f"{ENV_NAME}-{version}" + g = options.get("g", 10.0) + max_episode_steps = options.get("max_episode_steps", 200) if cidx in envs: env = envs[cidx] diff --git a/rest_api/gymnasium_envs/classic_control/v/acrobot_v_env_api.py b/rest_api/gymnasium_envs/classic_control/v/acrobot_v_env_api.py index 9aa7159..efb2411 100644 --- a/rest_api/gymnasium_envs/classic_control/v/acrobot_v_env_api.py +++ b/rest_api/gymnasium_envs/classic_control/v/acrobot_v_env_api.py @@ -86,14 +86,13 @@ async def close(cidx: int) -> JSONResponse: @acrobot_v_router.post("/make") async def make(version: str = Body(default="v1"), cidx: int = Body(...), - num_envs: int = Body(default=2), - max_episode_steps: int = Body(default=500)) -> JSONResponse: + options: dict[str, Any] = Body(default={"num_envs": 2})) -> JSONResponse: global env global NUM_COPIES global envs env_type = f"{ENV_NAME}-{version}" - + num_envs = options.get("num_envs", 2) if cidx in envs: env = envs[cidx] @@ -164,11 +163,11 @@ async def reset(seed: int = Body(default=42), cidx: int = Body(...), @acrobot_v_router.post("/step") -async def step(actions: dict[str, list[int]] = Body(title='actions'), cidx: int = Body(...)) -> JSONResponse: +async def step(action: dict[str, list[int]] = Body(title='actions'), cidx: int = Body(...)) -> JSONResponse: global NUM_COPIES - actions = actions['actions'] + actions = action['actions'] if len(actions) != NUM_COPIES: raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=f"actions length should be {NUM_COPIES} ") diff --git a/rest_api/gymnasium_envs/toy_text/black_jack_env_api.py b/rest_api/gymnasium_envs/toy_text/black_jack_env_api.py index 5de417a..b41332e 100644 --- a/rest_api/gymnasium_envs/toy_text/black_jack_env_api.py +++ b/rest_api/gymnasium_envs/toy_text/black_jack_env_api.py @@ -57,10 +57,11 @@ async def close(cidx: int) -> JSONResponse: @black_jack_router.post("/make") async def make(version: str = Body(default="v1"), cidx: int = Body(...), - natural: bool = Body(default=False), - sab: bool = Body(default=False)): + options: dict[str, Any] = Body(default={"natural": False, "sab": False})) -> JSONResponse: global envs + natural = options.get("natural", False) + sab = options.get("sab", False) if cidx in envs: env = envs[cidx] diff --git a/rest_api/gymnasium_envs/toy_text/frozenlake_env_api.py b/rest_api/gymnasium_envs/toy_text/frozenlake_env_api.py index 381fc6f..80bd360 100644 --- a/rest_api/gymnasium_envs/toy_text/frozenlake_env_api.py +++ b/rest_api/gymnasium_envs/toy_text/frozenlake_env_api.py @@ -53,11 +53,17 @@ async def close(cidx: int) -> JSONResponse: @frozenlake_router.post("/make") async def make(version: str = Body(default='v1'), cidx: int = Body(...), - map_name: str = Body(default="4x4"), - is_slippery: bool = Body(default=True), max_episode_steps: int = Body(default=500)) -> JSONResponse: + options: dict[str, Any] = Body(default={"map_name": "4x4", + "is_slippery": True, + "max_episode_steps": 500}) + ) -> JSONResponse: global envs + map_name = options.get("map_name", "4x4") + is_slippery = options.get("is_slippery", True) + max_episode_steps = options.get("max_episode_steps", 500) + env_tag = f"FrozenLake-{version}" if cidx in envs: env = envs[cidx] @@ -65,7 +71,7 @@ async def make(version: str = Body(default='v1'), env.close() try: - env = gym.make(f"FrozenLake-{version}", + env = gym.make(id=env_tag, map_name=map_name, is_slippery=is_slippery, max_episode_steps=max_episode_steps) envs[cidx] = env @@ -74,7 +80,7 @@ async def make(version: str = Body(default='v1'), detail=str(e)) else: try: - env = gym.make(f"FrozenLake-{version}", + env = gym.make(id=env_tag, map_name=map_name, is_slippery=is_slippery, max_episode_steps=max_episode_steps) envs[cidx] = env diff --git a/rest_api/gymnasium_envs/toy_text/taxi_env_api.py b/rest_api/gymnasium_envs/toy_text/taxi_env_api.py index d10a152..f46f308 100644 --- a/rest_api/gymnasium_envs/toy_text/taxi_env_api.py +++ b/rest_api/gymnasium_envs/toy_text/taxi_env_api.py @@ -53,10 +53,13 @@ async def close(cidx: int) -> JSONResponse: @taxi_router.post("/make") async def make(version: str = Body(default="v3"), cidx: int = Body(...), - max_episode_steps: int = Body(default=500)) -> JSONResponse: + options: dict[str, Any] = Body(default={"max_episode_steps": 500}) + ) -> JSONResponse: global envs env_type = f"{ENV_NAME}-{version}" + max_episode_steps = options.get("max_episode_steps", 500) + if cidx in envs: env = envs[cidx] diff --git a/src/rlenvs/envs/api_server/apiserver.cpp b/src/rlenvs/envs/api_server/apiserver.cpp index 3feabc1..c51c0fc 100644 --- a/src/rlenvs/envs/api_server/apiserver.cpp +++ b/src/rlenvs/envs/api_server/apiserver.cpp @@ -32,6 +32,7 @@ RESTApiServerWrapper::init_(){ envs_["Acrobot"] = "/gymnasium/acrobot-env"; envs_["Pendulum"] = "/gymnasium/pendulum-env"; envs_["AcrobotV"] = "/gymnasium/acrobot-env/v"; + envs_["GymWalk"]= "/gdrl/gym-walk-env"; } diff --git a/src/rlenvs/envs/gdrl/gym_walk.h b/src/rlenvs/envs/gdrl/gym_walk.h index 20bc93a..6386726 100644 --- a/src/rlenvs/envs/gdrl/gym_walk.h +++ b/src/rlenvs/envs/gdrl/gym_walk.h @@ -14,8 +14,6 @@ #include "rlenvs/envs/time_step.h" #include "rlenvs/envs/env_types.h" #include "rlenvs/envs/env_base.h" -#include "rlenvs/envs/with_rest_api_mixin.h" -#include "rlenvs/extern/HTTPRequest.hpp" #include "rlenvs/extern/nlohmann/json/json.hpp" #include @@ -41,8 +39,7 @@ namespace gdrl{ template class GymWalk final: public EnvBase, ScalarDiscreteEnv - >, - public with_rest_api_mixin> + > { public: @@ -51,6 +48,11 @@ class GymWalk final: public EnvBase, /// static const std::string name; + /// + /// \brief The URI for accessing the environment + /// + static const std::string URI; + typedef EnvBase, ScalarDiscreteEnv > base_type; @@ -89,12 +91,12 @@ class GymWalk final: public EnvBase, /// /// \brief Constructor /// - GymWalk(const std::string& api_base_url); + GymWalk(const RESTApiServerWrapper& api_server); /// /// \brief Constructor /// - GymWalk(const std::string& api_base_url, + GymWalk(const RESTApiServerWrapper& api_server, const uint_t cidx); /// @@ -157,36 +159,44 @@ class GymWalk final: public EnvBase, /// /// \brief build the dynamics from response /// - dynamics_t build_dynamics_from_response_(const http::Response& response)const; + dynamics_t build_dynamics_from_response_(const nlohmann::json& response)const; /// /// \brief Handle the reset response from the environment server /// - time_step_type create_time_step_from_response_(const http::Response& response) const; + time_step_type create_time_step_from_response_(const nlohmann::json& response) const; + + + RESTApiServerWrapper api_server_; }; template const std::string GymWalk::name = "GymWalk"; +const std::string GymWalk::URI = "/gdrl/gym-walk-env"; template -GymWalk::GymWalk(const std::string& api_base_url) +GymWalk::GymWalk(const RESTApiServerWrapper& api_server) : EnvBase, ScalarDiscreteEnv - >(0, "GymWalk"), -with_rest_api_mixin>(api_base_url, "/gdrl/gym-walk-env") -{} + >(0, GymWalk::name), +api_server_(api_server_) +{ + api_server_.register_if_not(GymWalk::name, GymWalk::URI); +} template -GymWalk::GymWalk(const std::string& api_base_url, - const uint_t cidx) +GymWalk::GymWalk(const RESTApiServerWrapper& api_server, + const uint_t cidx) : EnvBase, ScalarDiscreteEnv >(cidx, "GymWalk"), -with_rest_api_mixin>(api_base_url, "/gdrl/gym-walk-env") -{} +api_server_(api_server) +{ + api_server_.register_if_not(GymWalk::name, GymWalk::URI); +} template @@ -195,35 +205,25 @@ GymWalk::GymWalk(const GymWalk& other) EnvBase, ScalarDiscreteEnv >(other), -with_rest_api_mixin>(other) +api_server_(other.api_server_) {} template typename GymWalk::dynamics_t -GymWalk::build_dynamics_from_response_(const http::Response& response)const{ - - auto str_response = std::string(response.body.begin(), response.body.end()); - using json = nlohmann::json; - json j = json::parse(str_response); - - auto dynamics = j["dynamics"]; +GymWalk::build_dynamics_from_response_(const nlohmann::json& response)const{ + auto dynamics = response["dynamics"]; return dynamics; } template typename GymWalk::time_step_type -GymWalk::create_time_step_from_response_(const http::Response& response)const{ - - auto str_response = std::string(response.body.begin(), response.body.end()); - using json = nlohmann::json; +GymWalk::create_time_step_from_response_(const nlohmann::json& response)const{ - json j = json::parse(str_response); - - auto step_type = j["time_step"]["step_type"]; - auto reward = j["time_step"]["reward"]; - auto discount = j["time_step"]["discount"]; - auto observation = j["time_step"]["observation"]; - auto info = j["time_step"]["info"]; + auto step_type = response["time_step"]["step_type"]; + auto reward = response["time_step"]["reward"]; + auto discount = response["time_step"]["discount"]; + auto observation = response["time_step"]["observation"]; + auto info = response["time_step"]["info"]; return GymWalk::time_step_type(time_step_type_from_int(step_type), reward, observation, discount, std::unordered_map()); @@ -238,20 +238,10 @@ GymWalk::make(const std::string& version, return; } - const auto request_url = std::string(this->get_url()) + "/make"; - http::Request request{request_url}; - - using json = nlohmann::json; - json j; - j["version"] = version; - j["cidx"] = this -> cidx(); - auto body = j.dump(); - - const auto response = request.send("POST", body); - - if(response.status.code != 201){ - throw std::runtime_error("Environment server failed to create Environment"); - } + auto response = api_server_.make(this->env_name(), + this->cidx(), + version, + ops); this->set_version_(version); this->make_created_(); @@ -269,20 +259,9 @@ GymWalk::step(const action_type& action){ return this->reset(42, std::unordered_map()); } - const auto request_url = std::string(this->get_url()) + "/step"; - http::Request request{request_url}; - - auto copy_idx = this -> cidx(); - - using json = nlohmann::json; - json j; - j["cidx"] = copy_idx; - j["action"] = action; - const auto response = request.send("POST", j.dump()); - - if(response.status.code != 202){ - throw std::runtime_error("Environment server failed to step environment"); - } + const auto response = api_server_.step(this -> env_name(), + this -> cidx(), + action); this->get_current_time_step_() = this->create_time_step_from_response_(response); return this->get_current_time_step_(); @@ -291,20 +270,8 @@ GymWalk::step(const action_type& action){ template bool GymWalk::is_alive()const{ - - - auto url_ = this->get_url(); - auto copy_idx_str = std::to_string(this -> cidx()); - - http::Request request{url_ + "/is-alive?cidx="+copy_idx_str}; - const auto response = request.send("GET"); - const auto str_response = std::string(response.body.begin(), response.body.end()); - - using json = nlohmann::json; - - // parse the response - json j = json::parse(str_response); - return j["result"]; + auto response = this -> api_server_.is_alive(this->env_name(), this -> cidx()); + return response["result"]; } @@ -312,21 +279,12 @@ template bool GymWalk::close(){ - if(!this->is_created()){ + if(!this->is_created()){ return; } - auto copy_idx = this -> cidx(); - using json = nlohmann::json; - json j; - j["cidx"] = copy_idx; - - auto url = this -> get_url(); - - http::Request request{url + "/close"}; - const auto response = request.send("POST"); + auto response = this -> api_server_.close(this->env_name(), this -> cidx()); this -> invalidate_is_created_flag_(); - } template @@ -341,24 +299,9 @@ GymWalk::reset(uint_t seed, return time_step_type(); } - auto copy_idx = this -> cidx(); - - auto url = this -> get_url(); - const auto request_url = url + "/reset"; - http::Request request{request_url}; - - - using json = nlohmann::json; - json j; - j["seed"] = seed; - j["cidx"] = copy_idx; - - auto body = j.dump(); - const auto response = request.send("POST", body); - - if(response.status.code != 202){ - throw std::runtime_error("Environment server failed to reset environment"); - } + auto response = this -> api_server_.reset(this->env_name(), + this -> cidx(), seed, + nlohmann::json()); this->create_time_step_from_response_(response); return this -> get_current_time_step_(); @@ -368,8 +311,7 @@ template GymWalk GymWalk::make_copy(uint_t cidx)const{ - auto api_base_url = this -> get_api_url(); - GymWalk copy(api_base_url,cidx); + GymWalk copy(api_server_ ,cidx); std::unordered_map ops; auto version = this -> version(); copy.make(version, ops);