From e840b342990b02aa6f182d29dadc4081f37113f7 Mon Sep 17 00:00:00 2001 From: aelhabashy <96305832+aelhabashy@users.noreply.github.com> Date: Fri, 22 Nov 2024 12:24:06 +0100 Subject: [PATCH] initial pipline implementation (not working) --- .gitconfig | 81 ++++++++ .gitignore | 6 + roboteam_ai/CMakeLists.txt | 8 + .../roboteam_ai/stp/plays/offensive/Attack.h | 16 +- roboteam_ai/src/RL/sentActionCommand.py | 11 +- .../src/stp/plays/offensive/Attack.cpp | 182 +++++++----------- 6 files changed, 189 insertions(+), 115 deletions(-) create mode 100644 .gitconfig diff --git a/.gitconfig b/.gitconfig new file mode 100644 index 000000000..5d44d4de5 --- /dev/null +++ b/.gitconfig @@ -0,0 +1,81 @@ +[safe] + directory = /home/roboteamtwente + directory = /home/roboteamtwente/build/_deps/tracy-src + directory = /home/roboteamtwente + directory = /home/roboteamtwente/build/_deps/tracy-src + directory = /home/roboteamtwente + directory = /home/roboteamtwente/build/_deps/tracy-src + directory = /home/roboteamtwente + directory = /home/roboteamtwente/build/_deps/tracy-src + directory = /home/roboteamtwente + directory = /home/roboteamtwente/build/_deps/tracy-src + directory = /home/roboteamtwente + directory = /home/roboteamtwente/build/_deps/tracy-src + directory = /home/roboteamtwente + directory = /home/roboteamtwente/build/_deps/tracy-src + directory = /home/roboteamtwente + directory = /home/roboteamtwente/build/_deps/tracy-src + directory = /home/roboteamtwente + directory = /home/roboteamtwente/build/_deps/tracy-src + directory = /home/roboteamtwente + directory = /home/roboteamtwente/build/_deps/tracy-src + directory = /home/roboteamtwente + directory = /home/roboteamtwente/build/_deps/tracy-src + directory = /home/roboteamtwente + directory = /home/roboteamtwente/build/_deps/tracy-src + directory = /home/roboteamtwente + directory = /home/roboteamtwente/build/_deps/tracy-src + directory = /home/roboteamtwente + directory = /home/roboteamtwente/build/_deps/tracy-src + directory = /home/roboteamtwente + directory = /home/roboteamtwente/build/_deps/tracy-src + directory = /home/roboteamtwente + directory = /home/roboteamtwente/build/_deps/tracy-src + directory = /home/roboteamtwente + directory = /home/roboteamtwente/build/_deps/tracy-src + directory = /home/roboteamtwente + directory = /home/roboteamtwente/build/_deps/tracy-src + directory = /home/roboteamtwente + directory = /home/roboteamtwente/build/_deps/tracy-src + directory = /home/roboteamtwente + directory = /home/roboteamtwente/build/_deps/tracy-src + directory = /home/roboteamtwente + directory = /home/roboteamtwente/build/_deps/tracy-src + directory = /home/roboteamtwente + directory = /home/roboteamtwente/build/_deps/tracy-src + directory = /home/roboteamtwente + directory = /home/roboteamtwente/build/_deps/tracy-src + directory = /home/roboteamtwente + directory = /home/roboteamtwente/build/_deps/tracy-src + directory = /home/roboteamtwente + directory = /home/roboteamtwente/build/_deps/tracy-src + directory = /home/roboteamtwente + directory = /home/roboteamtwente/build/_deps/tracy-src + directory = /home/roboteamtwente + directory = /home/roboteamtwente/build/_deps/tracy-src + directory = /home/roboteamtwente + directory = /home/roboteamtwente/build/_deps/tracy-src + directory = /home/roboteamtwente + directory = /home/roboteamtwente/build/_deps/tracy-src + directory = /home/roboteamtwente + directory = /home/roboteamtwente/build/_deps/tracy-src + directory = /home/roboteamtwente + directory = /home/roboteamtwente/build/_deps/tracy-src + directory = /home/roboteamtwente + directory = /home/roboteamtwente/build/_deps/tracy-src + directory = /home/roboteamtwente + directory = /home/roboteamtwente/build/_deps/tracy-src + directory = /home/roboteamtwente + directory = /home/roboteamtwente/build/_deps/tracy-src + directory = /home/roboteamtwente + directory = /home/roboteamtwente/build/_deps/tracy-src + directory = /home/roboteamtwente + directory = /home/roboteamtwente/build/_deps/tracy-src + directory = /home/roboteamtwente + directory = /home/roboteamtwente/build/_deps/tracy-src + directory = /home/roboteamtwente + directory = /home/roboteamtwente/build/_deps/tracy-src + directory = /home/roboteamtwente + directory = /home/roboteamtwente/build/_deps/tracy-src + directory = /home/roboteamtwente + directory = /home/roboteamtwente/build/_deps/tracy-src diff --git a/.gitignore b/.gitignore index 43e946d93..d7ce1f68d 100644 --- a/.gitignore +++ b/.gitignore @@ -37,3 +37,9 @@ ENV/ env.bak/ venv.bak/ __pycache__/ +tigers_sumatra +docker/runner/ssl-game-controller-config/20* +roboteam_ai/src/RL/src/ppo_* +roboteam_ai/src/RL/src/best_model_PPO.zip +roboteam_ai/src/RL/src/tmp/eval_monitor.monitor.csv +roboteam_ai/src/RL/src/tmp/monitor.monitor.csv diff --git a/roboteam_ai/CMakeLists.txt b/roboteam_ai/CMakeLists.txt index 8971c13e0..a15e18f0d 100644 --- a/roboteam_ai/CMakeLists.txt +++ b/roboteam_ai/CMakeLists.txt @@ -300,3 +300,11 @@ gtest_discover_tests(roboteam_ai_tests) # PRIVATE roboteam_utils # PRIVATE testHelpers # ) +# Add the protobuf generated source files +set(PROTO_SRCS + ${CMAKE_SOURCE_DIR}/roboteam_networking/proto/ActionCommand.pb.cc +) +target_sources(roboteam_ai PRIVATE ${PROTO_SRCS}) +find_package(Protobuf REQUIRED) + +target_link_libraries(roboteam_ai PRIVATE protobuf::libprotobuf) diff --git a/roboteam_ai/include/roboteam_ai/stp/plays/offensive/Attack.h b/roboteam_ai/include/roboteam_ai/stp/plays/offensive/Attack.h index c91907651..7616a88e6 100644 --- a/roboteam_ai/include/roboteam_ai/stp/plays/offensive/Attack.h +++ b/roboteam_ai/include/roboteam_ai/stp/plays/offensive/Attack.h @@ -2,11 +2,12 @@ #define RTT_ATTACK_H #include "stp/Play.hpp" +#include // For std::vector namespace rtt::ai::stp::play { /** - * @brief The attack play is executed when there is a chance to shoot at the enemey goal + * @brief The attack play is executed when there is a chance to shoot at the enemy goal */ class Attack : public Play { public: @@ -15,6 +16,14 @@ class Attack : public Play { */ Attack(); + ~Attack() override; + + + /** + * @brief Receives action commands dynamically to modify roles + */ + void receiveActionCommand(); + /** * @brief Calculates the score of this play to determine which play is best in this situation * @param field The current Field @@ -34,7 +43,7 @@ class Attack : public Play { void calculateInfoForRoles() noexcept override; /** - * @brief Check if play should end. True when stri role is finished. + * @brief Check if play should end. True when striker role is finished. */ bool shouldEndPlay() noexcept override; @@ -43,6 +52,9 @@ class Attack : public Play { * @return The name of the play as string */ const char* getName() const override; + + private: + std::vector> roles; // Updated to std::vector }; } // namespace rtt::ai::stp::play diff --git a/roboteam_ai/src/RL/sentActionCommand.py b/roboteam_ai/src/RL/sentActionCommand.py index 368d5f8f8..c37d11981 100644 --- a/roboteam_ai/src/RL/sentActionCommand.py +++ b/roboteam_ai/src/RL/sentActionCommand.py @@ -8,7 +8,8 @@ roboteam_path = os.path.abspath(os.path.join(current_dir, "..", "..", "..")) # Add to sys.path -sys.path.append(roboteam_path) +sys.path.append(roboteam_path) +pipe_path = os.path.join(os.path.dirname(__file__), "action_pipe") # Import the generated protobuf classes from roboteam_networking.proto import ActionCommand_pb2 @@ -18,16 +19,20 @@ def send_action_command(num_attacker, num_defender, num_waller): socket = context.socket(zmq.PUSH) # Use PUSH socket type socket.bind("tcp://*:5555") # Send data over this port. - + action_command = ActionCommand_pb2.ActionCommand() action_command.numDefender = num_defender action_command.numAttacker = num_attacker action_command.numWaller = num_waller message = action_command.SerializeToString() - socket.send(message) + # socket.send(message) print(f"Sent: numDefender={num_defender}, numAttacker={num_attacker}, numWaller={num_waller}") + with open(pipe_path, "wb") as fifo: + fifo.write(message) + print(f"Sent: numDefender={num_defender}, numAttacker={num_attacker}, numWaller={num_waller}") + if __name__ == "__main__": # Example usage diff --git a/roboteam_ai/src/stp/plays/offensive/Attack.cpp b/roboteam_ai/src/stp/plays/offensive/Attack.cpp index 7ed760fad..4fd04b50c 100644 --- a/roboteam_ai/src/stp/plays/offensive/Attack.cpp +++ b/roboteam_ai/src/stp/plays/offensive/Attack.cpp @@ -1,102 +1,92 @@ #include #include -#include "stp/plays/offensive/Attack.h" -#include +#include +#include +#include +#include +#include +#include +#include "stp/plays/offensive/Attack.h" #include "stp/computations/GoalComputations.h" #include "stp/computations/PositionScoring.h" #include "stp/roles/Keeper.h" #include "stp/roles/active/Striker.h" #include "stp/roles/passive/Defender.h" #include "stp/roles/passive/Formation.h" +#include "../../../roboteam_networking/proto/ActionCommand.pb.h" namespace rtt::ai::stp::play { -void Attack::receiveActionCommand() { - zmq::context_t context(1); // Create a context - zmq::socket_t socket(context, ZMQ_PULL); // Create a PULL socket - socket.bind("tcp://*:5555"); // Bind to the same port as the sender - - while (true) { - zmq::message_t message; // Create a message to receive - socket.recv(&message); // Receive the message - - // Parse the protobuf message - ActionCommand action_command; - action_command.ParseFromArray(message.data(), message.size()); // Deserialize - - int num_attacker = action_command.numAttacker(); - int num_defender = action_command.numDefender(); - int num_waller = action_command.numWaller(); - - // Clear existing roles (if any) - roles.clear(); - - // Create Striker roles - for (int i = 0; i < num_attacker; ++i) { - std::string name = "striker_" + std::to_string(i); - roles.push_back(std::make_unique(name)); - } - - // Create Defender roles - for (int i = 0; i < num_defender; ++i) { - std::string name = "defender_" + std::to_string(i); - roles.push_back(std::make_unique(name)); - } - - // Create Waller roles - for (int i = 0; i < num_waller; ++i) { - std::string name = "waller_" + std::to_string(i); - roles.push_back(std::make_unique(name)); // Assuming Waller is also a Defender - } - - // Print the received values for debugging - std::cout << "Received: numDefender=" << num_defender - << ", numAttacker=" << num_attacker - << ", numWaller=" << num_waller << std::endl; - - // Optionally, print created roles - for (const auto& role : roles) { - std::cout << "Created role: " << role->getName() << std::endl; // Assuming getName() method exists - } - } -} - - - Attack::Attack() : Play() { - // Evaluations that have to be true in order for this play to be considered valid. startPlayEvaluation.clear(); startPlayEvaluation.emplace_back(GlobalEvaluation::NormalPlayGameState); startPlayEvaluation.emplace_back(GlobalEvaluation::WeWillHaveBall); startPlayEvaluation.emplace_back(GlobalEvaluation::BallNotInOurDefenseAreaAndStill); - // Evaluations that have to be true to allow the play to continue, otherwise the play will change. Plays can also end using the shouldEndPlay(). keepPlayEvaluation.clear(); keepPlayEvaluation.emplace_back(GlobalEvaluation::NormalPlayGameState); keepPlayEvaluation.emplace_back(GlobalEvaluation::WeWillHaveBall); keepPlayEvaluation.emplace_back(GlobalEvaluation::BallNotInOurDefenseAreaAndStill); - // Role creation, the names should be unique. The names are used in the stpInfos-map. - roles = std::array, rtt::ai::constants::MAX_ROBOT_COUNT>{ - // Roles is we play 6v6 - std::make_unique("keeper"), - std::make_unique("striker"), - std::make_unique("defender_0"), - std::make_unique("attacker_0"), - std::make_unique("defender_1"), - std::make_unique("defender_2"), - // Additional roles if we play 11v11 - std::make_unique("waller_0"), - std::make_unique("waller_1"), - std::make_unique("attacker_1"), - std::make_unique("defender_3"), - std::make_unique("attacker_2"), - }; + roles.push_back(std::make_unique("keeper")); + roles.push_back(std::make_unique("striker")); + roles.push_back(std::make_unique("defender_0")); + roles.push_back(std::make_unique("attacker_0")); + roles.push_back(std::make_unique("defender_1")); + roles.push_back(std::make_unique("defender_2")); +} + +Attack::~Attack() = default; + +void Attack::receiveActionCommand() { + const char* fifo_path = "/tmp/action_pipe"; + mkfifo(fifo_path, 0666); // Create the FIFO + + while (true) { + int fifo_fd = open(fifo_path, O_RDONLY); + if (fifo_fd == -1) { + perror("Error opening FIFO"); + return; + } + + char buffer[1024]; + ssize_t bytes_read = read(fifo_fd, buffer, sizeof(buffer)); + close(fifo_fd); + + if (bytes_read > 0) { + ActionCommand action_command; + if (action_command.ParseFromArray(buffer, bytes_read)) { + int num_attacker = action_command.numattacker(); + int num_defender = action_command.numdefender(); + int num_waller = action_command.numwaller(); + + roles.clear(); // Clear existing roles + + for (int i = 0; i < num_attacker; ++i) { + roles.push_back(std::make_unique("striker_" + std::to_string(i))); + } + for (int i = 0; i < num_defender; ++i) { + roles.push_back(std::make_unique("defender_" + std::to_string(i))); + } + for (int i = 0; i < num_waller; ++i) { + roles.push_back(std::make_unique("waller_" + std::to_string(i))); + } + + std::cout << "Received: numDefender=" << num_defender + << ", numAttacker=" << num_attacker + << ", numWaller=" << num_waller << std::endl; + } else { + std::cerr << "Failed to parse protobuf message" << std::endl; + } + } + } } uint8_t Attack::score(const rtt::Field& field) noexcept { - // Score the position of the ball based on the odds of scoring - return PositionScoring::scorePosition(world->getWorld()->getBall().value()->position, gen::GoalShot, field, world).score * (rand() % (2) + 1); + return PositionScoring::scorePosition( + world->getWorld()->getBall().value()->position, gen::GoalShot, field, world) + .score * + (rand() % 2 + 1); } Dealer::FlagMap Attack::decideRoleFlags() const noexcept { @@ -121,25 +111,20 @@ Dealer::FlagMap Attack::decideRoleFlags() const noexcept { } void Attack::calculateInfoForRoles() noexcept { - PositionComputations::calculateInfoForDefendersAndWallers(stpInfos, roles, field, world, true); - PositionComputations::calculateInfoForAttackers(stpInfos, roles, field, world); - - // Striker - auto goalTarget = computations::GoalComputations::calculateGoalTarget(world, field); - goalTarget.y = std::clamp(goalTarget.y, field.rightGoalArea.bottom() + 0.2, field.rightGoalArea.top() - 0.2); - stpInfos["striker"].setPositionToShootAt(goalTarget); - stpInfos["striker"].setKickOrChip(KickType::KICK); - stpInfos["striker"].setShotPower(ShotPower::MAX); - PositionComputations::recalculateInfoForNonPassers(stpInfos, field, world, goalTarget); + std::array, constants::MAX_ROBOT_COUNT> roles_array{}; + std::move(roles.begin(), roles.end(), roles_array.begin()); + + PositionComputations::calculateInfoForDefendersAndWallers(stpInfos, roles_array, field, world, true); + PositionComputations::calculateInfoForAttackers(stpInfos, roles_array, field, world); } bool Attack::shouldEndPlay() noexcept { - // If the striker has finished, the play finished successfully - if (std::any_of(roles.begin(), roles.end(), [](const auto& role) { return role != nullptr && role->getName() == "striker" && role->finished(); })) { + if (std::any_of(roles.begin(), roles.end(), [](const auto& role) { + return role != nullptr && role->getName() == "striker" && role->finished(); + })) { return true; } - // Find id of robot with name striker auto strikerId = stpInfos.at("striker"); if (strikerId.getRobot() && strikerId.getRobot().value()) { auto strikerRobotId = strikerId.getRobot().value()->getId(); @@ -154,26 +139,3 @@ bool Attack::shouldEndPlay() noexcept { const char* Attack::getName() const { return "Attack"; } } // namespace rtt::ai::stp::play - - - - - - -int main() { - // Create an instance of the Attack class - rtt::ai::stp::play::Attack attack; - - // Start receiving action commands in a separate thread - std::thread receiver_thread(&rtt::ai::stp::play::Attack::receiveActionCommand, &attack); - receiver_thread.detach(); // Detach the thread to allow it to run independently - - // Allow some time for receiving messages - std::cout << "Receiving messages. Press Enter to exit..." << std::endl; - - // Wait for user input to exit - std::cin.get(); // This will block until you press Enter - - return 0; -} -