diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml new file mode 100644 index 00000000..03c13861 --- /dev/null +++ b/.github/workflows/main.yml @@ -0,0 +1,129 @@ +name: ci + +on: + workflow_dispatch: + push: + branches: + - "master" + tags: + - "*" + + +env: + BASE_IMAGE: crosslanguagesoccerframework/rcssserver + BASE_TAG: latest + +jobs: + docker: + runs-on: ubuntu-latest + name: Build & Push Docker + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Set up QEMU + uses: docker/setup-qemu-action@v3 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Find CMakeLists.txt version + id: cmake_version + run: | + cmake_version=$(grep -oP 'project\(.* VERSION \K[0-9]+\.[0-9]+\.[0-9]+' CMakeLists.txt) + echo "::set-output name=version::${cmake_version}" + + - name: Check if the version tag exist git then skip + id: check_tag + run: | + git tag -l | grep -q "${{ steps.cmake_version.outputs.version }}" && echo "Tag already exists" && exit 1 || echo "Tag does not exist" + continue-on-error: true + + - name: tag the version + if: steps.check_tag.outcome == 'success' + run: | + git config --global user.email "action@github.com" + git config --global user.name "GitHub Action" + git tag -a "${{ steps.cmake_version.outputs.version }}" -m "Version ${{ steps.cmake_version.outputs.version }}" + git push origin "${{ steps.cmake_version.outputs.version }}" + + - name: Login to Docker Hub + uses: docker/login-action@v3 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + + - name: Build and push RCSSServer + uses: docker/build-push-action@v5 + with: + context: . + file: ./utils/docker/Dockerfile + push: true + tags: "${{ env.BASE_IMAGE }}:latest,${{ env.BASE_IMAGE }}:ubuntu-24-${{ steps.cmake_version.outputs.version }}" + + - name: Docker Hub Description + uses: peter-evans/dockerhub-description@v4 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + repository: ${{ env.BASE_IMAGE }} + readme-filepath: utils/docker/README.md + short-description: "RoboCup Soccer Simulator Server" + + app-image: + runs-on: ubuntu-latest + name: Build AppImage + steps: + - uses: actions/checkout@v4 + + - name: Create release folder + run: | + mkdir -p ${{ github.workspace }}/artifact + + - name: Find CMakeLists.txt version + id: cmake_version + run: | + cmake_version=$(grep -oP 'project\(.* VERSION \K[0-9]+\.[0-9]+\.[0-9]+' CMakeLists.txt) + echo "::set-output name=version::${cmake_version}" + + # ------------------------------------------- Ubuntu 20.04 AppImage + - name: Prepare builder image for 20.04 + run: | + docker build -t builder-image:2004 -f ./utils/appimage/Dockerfile.builder-2004 . + + - name: Build app image on 20.04 + run: | + docker run --privileged --name builder-2004 \ + builder-image:2004 /rcssserver/utils/appimage/build_appimage.sh + docker cp builder-2004:/rcssserver-x86_64.AppImage ${{ github.workspace }}/artifact/rcssserver-x86_64-${{ steps.cmake_version.outputs.version }}.AppImage + + # ------------------------------------------- Artifact + - name: Upload Artifact + uses: actions/upload-artifact@v4 + with: + name: rcssserver-x86_64 + path: ${{ github.workspace }}/artifact/* + retention-days: 5 + + - name: List files in artifact directory + run: ls -l ${{ github.workspace }}/artifact/ + + - name: Check if there is no release with the same tag + id: check_release + run: | + result=$(curl -s -o /dev/null -w "%{http_code}" https://api.github.com/repos/${{ github.repository }}/releases/tags/${{ github.ref_name }} -u ${{ secrets.GITHUB_TOKEN }}) + echo "::set-output name=release_exists::$result" + + # ------------------------------------------- Release + - name: Create Release + id: create_release + uses: ncipollo/release-action@v1 + if: steps.check_release.outputs.release_exists == '404' + with: + artifacts: "${{ github.workspace }}/artifact/*" + token: ${{ secrets.GITHUB_TOKEN }} + tag: "${{ steps.cmake_version.outputs.version }}" + release_name: "${{ steps.cmake_version.outputs.version }}" + release_body: "RoboCup Soccer Simulator Server" + draft: false + prerelease: false diff --git a/README.md b/README.md index 0c7db2c5..3ef9acb2 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# RoboCup Soccer Simulator Server +# :soccer: RoboCup Soccer Simulator Server [![CircleCI](https://circleci.com/gh/rcsoccersim/rcssserver/tree/master.svg?style=svg)](https://circleci.com/gh/rcsoccersim/rcssserver/tree/master) ![License](https://img.shields.io/github/license/rcsoccersim/rcssserver.svg) @@ -9,7 +9,36 @@ The RoboCup Soccer Simulator Server (rcssserver) is a research and educational t For further reading, please check [the user's manual](https://rcsoccersim.readthedocs.io/). -## :soccer: Quick Start +There are three different solutions to run the RoboCup Soccer Simulator Server. +- Download the AppImage release and run (Linux, Windows WSL) +- Build from source and run (Linux, Windows WSL) +- Use Docker Image + +## :gift_heart: AppImage +#### Download AppImage +Download "rcssserver-x86_64-?.?.?.AppImage" from the (release page)[https://github.com/CLSFramework/rcssserver/releases] / latest version +or use the below command to download the latest version of AppImage: +```bash +wget $(curl -s https://api.github.com/repos/clsframework/rcssserver/releases/latest | grep -oP '"browser_download_url": "\K(.*rcssserver-x86_64-.*\.AppImage)' | head -n 1) +``` + +#### Install dependency and update permission + +then you need to update the permission of the AppImage and install fuse: +```bash +sudo apt update +sudo apt-get install fuse +chmod +x rcssserver-x86_64-*.AppImage +``` + +#### Run + +to run the AppImage: +```bash +./rcssserver-x86_64-?.?.?.AppImage +``` + +## :wrench: Build From Source rcssserver is implemented by C++14 and depends some libraries. Make sure you have the required dependencies installed on your system: diff --git a/utils/appimage/Dockerfile.builder-1804 b/utils/appimage/Dockerfile.builder-1804 new file mode 100644 index 00000000..c34733fc --- /dev/null +++ b/utils/appimage/Dockerfile.builder-1804 @@ -0,0 +1,36 @@ +FROM ubuntu:18.04 + +COPY . /rcssserver + +RUN apt-get clean && apt-get update --allow-insecure-repositories && \ + DEBIAN_FRONTEND="noninteractive" apt-get -y install \ + tzdata \ + gcc \ + g++ \ + wget \ + libfl-dev \ + flex \ + bison \ + libboost-all-dev \ + automake \ + make \ + cmake \ + iputils-ping \ + build-essential \ + libtool \ + fuse \ + libfuse-dev \ + zlib1g-dev + +RUN cd /rcssserver && \ + find . -type f -name "*.cpp" -exec sed -i 's/#include /#include /g' {} \; && \ + find . -type f -name "*.h" -exec sed -i 's/#include /#include /g' {} \; && \ + find . -type f -name "*.hpp" -exec sed -i 's/#include /#include /g' {} \; && \ + find . -type f -name "*.cpp" -exec sed -i 's/std::filesystem/std::experimental::filesystem/g' {} \; && \ + find . -type f -name "*.h" -exec sed -i 's/std::filesystem/std::experimental::filesystem/g' {} \; && \ + find . -type f -name "*.hpp" -exec sed -i 's/std::filesystem/std::experimental::filesystem/g' {} \; && \ + mkdir build && \ + cd build && \ + cmake .. && \ + make && \ + cd .. \ No newline at end of file diff --git a/utils/appimage/Dockerfile.builder-2004 b/utils/appimage/Dockerfile.builder-2004 new file mode 100644 index 00000000..91035f26 --- /dev/null +++ b/utils/appimage/Dockerfile.builder-2004 @@ -0,0 +1,30 @@ +FROM ubuntu:20.04 + +COPY . /rcssserver + +RUN apt-get clean && apt-get update --allow-insecure-repositories && \ + DEBIAN_FRONTEND="noninteractive" apt-get -y install \ + tzdata \ + gcc \ + g++ \ + wget \ + libfl-dev \ + flex \ + bison \ + libboost-all-dev \ + automake \ + make \ + cmake \ + iputils-ping \ + build-essential \ + libtool \ + fuse \ + libfuse-dev \ + zlib1g-dev + +RUN cd /rcssserver && \ + mkdir build && \ + cd build && \ + cmake .. && \ + make && \ + cd .. diff --git a/utils/appimage/Dockerfile.builder-2404 b/utils/appimage/Dockerfile.builder-2404 new file mode 100644 index 00000000..73de5c1d --- /dev/null +++ b/utils/appimage/Dockerfile.builder-2404 @@ -0,0 +1,24 @@ +FROM ubuntu:24.04 + +COPY . /rcssserver + +RUN apt-get clean && apt-get update --allow-insecure-repositories && \ + DEBIAN_FRONTEND="noninteractive" apt-get -y install \ + tzdata \ + gcc \ + g++ \ + wget \ + libfl-dev \ + flex \ + bison \ + libboost-all-dev \ + automake \ + make \ + cmake \ + iputils-ping \ + build-essential \ + libtool \ + fuse \ + libfuse-dev + +RUN cd /rcssserver && ./utils/appimage/build_code.sh \ No newline at end of file diff --git a/utils/appimage/build_appimage.sh b/utils/appimage/build_appimage.sh new file mode 100755 index 00000000..6bd2b776 --- /dev/null +++ b/utils/appimage/build_appimage.sh @@ -0,0 +1,39 @@ +#!/bin/bash +set -e + +wget -c "https://github.com/linuxdeploy/linuxdeploy/releases/download/continuous/linuxdeploy-x86_64.AppImage" -O linuxdeploy-x86_64.AppImage +chmod +x linuxdeploy-x86_64.AppImage +mkdir rcssserver-x86_64 + +SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) +BUILD_PWD="${SCRIPT_DIR}/../../build" +APP_IMAGE_DIR="${SCRIPT_DIR}" + + +# find libc and libstdc++ libz dependencies +LIBSTDCPP_PATH=$(ldd $BUILD_PWD/rcssserver | grep libstdc++ | awk '{ print $3 }') +LIBZ_PATH=$(ldd $BUILD_PWD/rcssserver | grep libz.so | awk '{ print $3 }') +LIBRCSSCLANGPARSER_PATH=$(ldd $BUILD_PWD/rcssserver | grep librcssclangparser.so | awk '{ print $3 }') +LIBRCSSCONFPARSER_PATH=$(ldd $BUILD_PWD/rcssserver | grep librcssconfparser.so | awk '{ print $3 }') +LIBRCSSGZ_PATH=$(ldd $BUILD_PWD/rcssserver | grep librcssgz.so | awk '{ print $3 }') +LIBRCSSNET_PATH=$(ldd $BUILD_PWD/rcssserver | grep librcssnet.so | awk '{ print $3 }') + +echo "LIBSTDCPP_PATH=" $LIBSTDCPP_PATH +echo "LIBZ_PATH=" $LIBZ_PATH +echo "LIBRCSSCLANGPARSER_PATH=" $LIBRCSSCLANGPARSER_PATH +echo "LIBRCSSCONFPARSER_PATH=" $LIBRCSSCONFPARSER_PATH +echo "LIBRCSSGZ_PATH=" $LIBRCSSGZ_PATH +echo "LIBRCSSNET_PATH=" $LIBRCSSNET_PATH + +./linuxdeploy-x86_64.AppImage --appdir ./rcssserver-x86_64 \ + -e $BUILD_PWD/rcssserver \ + -l $LIBRCSSCLANGPARSER_PATH \ + -l $LIBRCSSCONFPARSER_PATH \ + -l $LIBRCSSGZ_PATH \ + -l $LIBRCSSNET_PATH \ + -l $LIBSTDCPP_PATH \ + -l $LIBZ_PATH \ + -d $APP_IMAGE_DIR/rcssserver.desktop \ + -i $APP_IMAGE_DIR/rcssserver.png \ + --output appimage +echo "App Image Created." diff --git a/utils/appimage/build_code.sh b/utils/appimage/build_code.sh new file mode 100755 index 00000000..01236968 --- /dev/null +++ b/utils/appimage/build_code.sh @@ -0,0 +1,8 @@ +#!/bin/bash +set -e + +mkdir build +cd build +cmake -DCMAKE_CXX_STANDARD=17 .. +make +cd .. \ No newline at end of file diff --git a/utils/appimage/rcssserver.desktop b/utils/appimage/rcssserver.desktop new file mode 100644 index 00000000..5d011484 --- /dev/null +++ b/utils/appimage/rcssserver.desktop @@ -0,0 +1,14 @@ +[Desktop Entry] +Version=1.0 +Type=Application +Name=rcssserver +Comment=Robocup 2D Soccer Simulation Server +TryExec=rcssserver +Exec=rcssserver +Icon=rcssserver +MimeType=image/x-foo; +Categories=Development; +X-KDE-Library=librcssserver +X-KDE-FactoryName=rcssserverfactory +X-KDE-ServiceType=RcssserverService + diff --git a/utils/appimage/rcssserver.png b/utils/appimage/rcssserver.png new file mode 100644 index 00000000..2c29a896 Binary files /dev/null and b/utils/appimage/rcssserver.png differ diff --git a/utils/docker/Dockerfile b/utils/docker/Dockerfile new file mode 100644 index 00000000..62b9dd11 --- /dev/null +++ b/utils/docker/Dockerfile @@ -0,0 +1,60 @@ +#------------------------------------------------------ +# build stage +#------------------------------------------------------ + +FROM ubuntu:24.04 AS BUILD + +WORKDIR /rcssserver + +# set environment variables +ENV config_file=server.conf \ + DATE_FORMAT="%Y%m%d%H%M%S" \ + VERSION=18.1.3 + + +# install dependencies +RUN apt-get clean && apt-get update --allow-insecure-repositories && \ + DEBIAN_FRONTEND="noninteractive" apt-get -y install \ + tzdata \ + sudo \ + gcc \ + g++ \ + wget \ + flex \ + bison \ + libboost-all-dev \ + automake \ + make \ + cmake \ + iputils-ping + +# copy rcssserver source code +COPY . /rcssserver + +# make and install rcssserver +RUN cd /rcssserver/ \ + && ./bootstrap \ + && ./configure --prefix=`pwd`/server-bin \ + && make \ + && make install \ + && ldconfig + + + + +#------------------------------------------------------ +# run stage +#------------------------------------------------------ +FROM ubuntu:24.04 AS RUN + +ENV LD_LIBRARY_PATH=/app/server-bin/lib:/usr/local/lib:/usr/lib:/lib \ + PATH=/app/server-bin/bin:$PATH + +WORKDIR /app + + +COPY --from=BUILD /rcssserver/server-bin /app/server-bin + +COPY utils/docker/docker-entrypoint.sh /app/docker-entrypoint.sh + +CMD [ "bash", "/app/docker-entrypoint.sh" ] \ No newline at end of file diff --git a/utils/docker/README.md b/utils/docker/README.md new file mode 100644 index 00000000..567ad942 --- /dev/null +++ b/utils/docker/README.md @@ -0,0 +1,43 @@ +# RoboCup Soccer Simulator Server +This image contains the RoboCup Soccer Simulator Server (rcssserver) installed and ready to use. + +## Tags +- latest + +## How to use this image + +Run the following command to start the server: +```bash +docker run --name rcssserver --network host -it rcssserver:latest +``` +Now you can connect to the server using the monitor or a client. + +## How to use custom configuration files +1. You can mount a volume with your custom configuration files, like: +```bash +docker run --name rcssserver --network host -v /path/to/your/configs:/root/.rcssserver -it rcssserver:latest +``` +2. You can add your custom configuration as environment variables, like: +```bash +docker run --name rcssserver --network host -e 'synch_mode=true' -it rcssserver:latest +``` +3. You can run server with custom command line arguments, like: +```bash +docker run --name rcssserver --network host -it rcssserver:latest rcssserver server::synch_mode=true + +``` + + +**Note**: You can either use one of the above methods at a time. +It means: +* if there is a server configuration file environment variable will be ignored. +* if you use third method, the second method will be ignored. + + + +## :incoming_envelope: Contributing + +For bug reports, feature requests and latest updates, please goto +https://github.com/rcsoccersim/rcssserver and open an issue or a pull request. + +> The RoboCup Soccer Server Maintainance Group diff --git a/utils/docker/docker-entrypoint.sh b/utils/docker/docker-entrypoint.sh new file mode 100755 index 00000000..f6955e3a --- /dev/null +++ b/utils/docker/docker-entrypoint.sh @@ -0,0 +1,237 @@ +#!/bin/env bash + +SERVER_CONFIG_FOLDER='/root/.rcssserver' +LOGS_FOLDER='/root/rcssserver-logs' + +mkdir -p ${LOGS_FOLDER} + +SERVER_OPTIONS=( + 'catch_ban_cycle' '' + 'clang_advice_win' '' + 'clang_define_win' '' + 'clang_del_win' '' + 'clang_info_win' '' + 'clang_mess_delay' '' + 'clang_mess_per_cycle' '' + 'clang_meta_win' '' + 'clang_rule_win' '' + 'clang_win_size' '' + 'coach_port' '' + 'connect_wait' '' + 'drop_ball_time' '' + 'extra_half_time' '' + 'foul_cycles' '' + 'freeform_send_period' '' + 'freeform_wait_period' '' + 'game_log_compression' '' + 'game_log_version' '' + 'game_over_wait' '' + 'goalie_max_moves' '' + 'half_time' '' + 'hear_decay' '' + 'hear_inc' '' + 'hear_max' '' + 'illegal_defense_duration' '' + 'illegal_defense_number' '' + 'keepaway_start' '' + 'kick_off_wait' '' + 'max_goal_kicks' '' + 'max_monitors' '' + 'nr_extra_halfs' '' + 'nr_normal_halfs' '' + 'olcoach_port' '' + 'pen_before_setup_wait' '' + 'pen_max_extra_kicks' '' + 'pen_nr_kicks' '' + 'pen_ready_wait' '' + 'pen_setup_wait' '' + 'pen_taken_wait' '' + 'point_to_ban' '' + 'point_to_duration' '' + 'port' '' + 'recv_step' '' + 'say_coach_cnt_max' '' + 'say_coach_msg_size' '' + 'say_msg_size' '' + 'send_step' '' + 'send_vi_step' '' + 'sense_body_step' '' + 'simulator_step' '' + 'slow_down_factor' '' + 'start_goal_l' '' + 'start_goal_r' '' + 'synch_micro_sleep' '' + 'synch_offset' '' + 'synch_see_offset' '' + 'tackle_cycles' '' + 'text_log_compression' '' + 'auto_mode' '' + 'back_passes' '' + 'coach' '' + 'coach_w_referee' '' + 'forbid_kick_off_offside' '' + 'free_kick_faults' '' + 'fullstate_l' '' + 'fullstate_r' '' + 'game_log_dated' '' + 'game_log_fixed' '' + 'game_logging' '' + 'golden_goal' '' + 'keepaway' '' + 'keepaway_log_dated' '' + 'keepaway_log_fixed' '' + 'keepaway_logging' '' + 'log_times' '' + 'old_coach_hear' '' + 'pen_allow_mult_kicks' '' + 'pen_coach_moves_players' '' + 'pen_random_winner' '' + 'penalty_shoot_outs' '' + 'profile' '' + 'proper_goal_kicks' '' + 'record_messages' '' + 'send_comms' '' + 'synch_mode' '' + 'team_actuator_noise' '' + 'text_log_dated' '' + 'text_log_fixed' '' + 'text_logging' '' + 'use_offside' '' + 'verbose' '' + 'wind_none' '' + 'wind_random' '' + 'audio_cut_dist' '' + 'back_dash_rate' '' + 'ball_accel_max' '' + 'ball_decay' '' + 'ball_rand' '' + 'ball_size' '' + 'ball_speed_max' '' + 'ball_stuck_area' '' + 'ball_weight' '' + 'catch_probability' '' + 'catchable_area_l' '' + 'catchable_area_w' '' + 'ckick_margin' '' + 'control_radius' '' + 'dash_angle_step' '' + 'dash_power_rate' '' + 'effort_dec' '' + 'effort_dec_thr' '' + 'effort_inc' '' + 'effort_inc_thr' '' + 'effort_init' '' + 'effort_min' '' + 'extra_stamina' '' + 'foul_detect_probability' '' + 'foul_exponent' '' + 'goal_width' '' + 'illegal_defense_dist_x' '' + 'illegal_defense_width' '' + 'inertia_moment' '' + 'keepaway_length' '' + 'keepaway_width' '' + 'kick_power_rate' '' + 'kick_rand' '' + 'kick_rand_factor_l' '' + 'kick_rand_factor_r' '' + 'kickable_margin' '' + 'max_back_tackle_power' '' + 'max_catch_angle' '' + 'max_dash_angle' '' + 'max_dash_power' '' + 'max_tackle_power' '' + 'maxmoment' '' + 'maxneckang' '' + 'maxneckmoment' '' + 'maxpower' '' + 'min_catch_angle' '' + 'min_dash_angle' '' + 'min_dash_power' '' + 'minmoment' '' + 'minneckang' '' + 'minneckmoment' '' + 'minpower' '' + 'offside_active_area_size' '' + 'offside_kick_margin' '' + 'pen_dist_x' '' + 'pen_max_goalie_dist_x' '' + 'player_accel_max' '' + 'player_decay' '' + 'player_rand' '' + 'player_size' '' + 'player_speed_max' '' + 'player_speed_max_min' '' + 'player_weight' '' + 'prand_factor_l' '' + 'prand_factor_r' '' + 'quantize_step' '' + 'quantize_step_l' '' + 'recover_dec' '' + 'recover_dec_thr' '' + 'recover_init' '' + 'recover_min' '' + 'red_card_probability' '' + 'side_dash_rate' '' + 'slowness_on_top_for_left_team' '' + 'slowness_on_top_for_right_team' '' + 'stamina_capacity' '' + 'stamina_inc_max' '' + 'stamina_max' '' + 'stopped_ball_vel' '' + 'tackle_back_dist' '' + 'tackle_dist' '' + 'tackle_exponent' '' + 'tackle_power_rate' '' + 'tackle_rand_factor' '' + 'tackle_width' '' + 'visible_angle' '' + 'visible_distance' '' + 'wind_ang' '' + 'wind_dir' '' + 'wind_force' '' + 'wind_rand' '' + 'coach_msg_file' '' + 'fixed_teamname_l' '' + 'fixed_teamname_r' '' + 'game_log_dir' "${LOGS_FOLDER}" + 'game_log_fixed_name' '' + 'keepaway_log_dir' "${LOGS_FOLDER}" + 'keepaway_log_fixed_name' '' + 'landmark_file' '' + 'log_date_format' '' + 'team_l_start' '' + 'team_r_start' '' + 'text_log_dir' "${LOGS_FOLDER}" + 'text_log_fixed_name' '' +) + +# First Config Priority : Server Config files +# if server config does exist then run with it +if [ -f "${SERVER_CONFIG_FOLDER}/server.conf" ]; then + rcssserver + exit 0 +fi + +# Second Config Priority : Environment Variables +# if environment variables are set then run with them +# loop through the default values if they are in the environment variable change the array value +for ((i=0; i<${#SERVER_OPTIONS[@]}; i+=2)); do + if [ -n "${!SERVER_OPTIONS[i]}" ]; then + SERVER_OPTIONS[i+1]="${!SERVER_OPTIONS[i]}" + echo "ENV Loaded ${SERVER_OPTIONS[i]}=${SERVER_OPTIONS[i+1]}" + fi +done + +# run server with options +opt="" +for ((i=0; i<${#SERVER_OPTIONS[@]}; i+=2)); do + if [ -n "${SERVER_OPTIONS[i+1]}" ]; then + opt="${opt} server::${SERVER_OPTIONS[i]}=${SERVER_OPTIONS[i+1]}" + fi +done + +echo "Running server with options: ${opt}" +rcssserver ${opt} + +