Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
82 changes: 82 additions & 0 deletions .github/workflows/docker-publish.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
name: Build and Push Docker Image

on:
push:
branches:
- ibis
tags:
- 'v*.*.*'
pull_request:
branches:
- ibis
paths:
- 'data/docker/Dockerfile.simulatorcli'
- 'data/docker/simulatorcli_entrypoint.bash'
- '.github/workflows/docker-publish.yaml'
workflow_dispatch:

env:
REGISTRY: ghcr.io
IMAGE_NAME: ibis-ssl/framework-simulatorcli

jobs:
build-and-push:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
attestations: write
id-token: write

steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
submodules: recursive

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3

- name: Log in to Container Registry
if: github.event_name != 'pull_request'
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Extract metadata (tags, labels)
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
tags: |
type=raw,value=latest,enable={{is_default_branch}}
type=ref,event=branch
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
type=sha,prefix=,format=short
type=ref,event=pr

- name: Build and push Docker image
id: push
uses: docker/build-push-action@v6
with:
context: .
file: ./data/docker/Dockerfile.simulatorcli
platforms: linux/amd64
push: ${{ github.event_name != 'pull_request' }}
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha
cache-to: type=gha,mode=max
provenance: true
sbom: true

- name: Generate artifact attestation
if: github.event_name != 'pull_request'
uses: actions/attest-build-provenance@v2
with:
subject-name: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
subject-digest: ${{ steps.push.outputs.digest }}
push-to-registry: true
2 changes: 2 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,8 @@ find_package(V8 10.5.7)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
add_subdirectory(src)

install(DIRECTORY config/ DESTINATION config FILES_MATCHING PATTERN "*.txt")

if(UNIX AND NOT APPLE)
configure_file(data/pkg/ra.desktop.in ra.desktop)
configure_file(data/pkg/ra-logplayer.desktop.in ra-logplayer.desktop)
Expand Down
24 changes: 10 additions & 14 deletions data/docker/Dockerfile.simulatorcli
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,7 @@ RUN set -xe; \
apt-get install --no-install-recommends -y \
cmake make g++ libssl-dev patch \
protobuf-compiler libprotobuf-dev \
qt6-base-dev libqt6opengl6-dev \
qtbase5-dev libqt5opengl5-dev; \
qt6-base-dev libqt6opengl6-dev; \
apt-get clean -y; \
rm -rf /var/lib/apt/lists/*;

Expand All @@ -22,9 +21,9 @@ COPY . .
RUN set -xe; \
mkdir build; \
cd build; \
cmake -DCMAKE_BUILD_TYPE=RelWithDebInfo ..; \
cmake -DCMAKE_BUILD_TYPE=RelWithDebInfo -DRELATIVE_DATA_DIRS=ON ..; \
make simulator-cli -j $(nproc); \
find . -maxdepth 1 ! -name 'bin' -exec rm -r {} \; ;
cmake --install . --prefix /home/default/install;

#
# Run stage
Expand All @@ -37,25 +36,22 @@ ARG DEBIAN_FRONTEND=noninteractive
RUN set -xe; \
apt-get update; \
apt-get install --no-install-recommends -y \
qt6-base-dev libqt6opengl6-dev \
qtbase5-dev libqt5opengl5-dev \
libprotobuf-dev tini; \
libqt6core6t64 libqt6gui6t64 libqt6network6t64 libqt6opengl6t64 \
libprotobuf32t64 tini; \
apt-get clean -y; \
rm -rf /var/lib/apt/lists/*;

RUN useradd --create-home --shell /bin/bash default
USER default
WORKDIR /home/default

COPY --chown=default:default /data/docker/simulatorcli_entrypoint.bash .
ENTRYPOINT ["tini", "--", "./simulatorcli_entrypoint.bash"]

COPY --chown=default:default --from=build-stage /home/default/COPYING .
COPY --chown=default:default --from=build-stage /home/default/COPYING.GPL .
COPY --chown=default:default --from=build-stage /home/default/config config
COPY --chown=default:default --from=build-stage /home/default/build build
COPY --chown=default:default --from=build-stage /home/default/install/bin/simulator-cli bin/simulator-cli
COPY --chown=default:default --from=build-stage /home/default/install/config config

# 10300: Control - Accepts simulator configuration commands
# 10301: Blue - Accepts robot commands by the blue team
# 10302: Yellow - Accepts robot commands by the yellow team
EXPOSE 10300 10301 10302

ENTRYPOINT ["tini", "--"]
CMD ["./bin/simulator-cli"]
1 change: 0 additions & 1 deletion data/docker/Dockerfile.simulatorcli.dockerignore
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,5 @@
/strategy
/data
!/data/pkg
!/data/docker/simulatorcli_entrypoint.bash

# vim: filetype=gitignore
15 changes: 0 additions & 15 deletions data/docker/simulatorcli_entrypoint.bash

This file was deleted.

5 changes: 3 additions & 2 deletions src/amun/simulator/include/simulator/simulator.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@

// higher values break the rolling friction of the ball
const float SIMULATOR_SCALE = 10.0f;
const float SUB_TIMESTEP = 1/200.f;
const float SUB_TIMESTEP = 1/250.f;
const float COLLISION_MARGIN = 0.04f;
const unsigned FOCAL_LENGTH = 390;

Expand Down Expand Up @@ -78,6 +78,7 @@ class camun::simulator::Simulator : public QObject
void sendStatus(const Status &status);
void sendRadioResponses(const QList<robot::RadioResponse> &responses);
void sendRealData(const QByteArray& data); // sends amun::SimulatorState
void sendGroundTruth(const QByteArray& data); // sends world::SimulatorState at 125Hz, no noise
void sendSSLSimError(const QList<SSLSimError>& errors, ErrorSource source);

public slots:
Expand Down Expand Up @@ -117,7 +118,7 @@ private slots:
const Timer *m_timer;
QTimer *m_trigger;
qint64 m_time;
qint64 m_lastSentStatusTime;
unsigned int m_simulationFrameCounter;
double m_timeScaling;
bool m_enabled;
bool m_charge;
Expand Down
32 changes: 23 additions & 9 deletions src/amun/simulator/simulator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -118,15 +118,15 @@ Simulator::Simulator(const Timer *timer, const amun::SimulatorSetup &setup, bool
m_isPartial(useManualTrigger),
m_timer(timer),
m_time(0),
m_lastSentStatusTime(0),
m_simulationFrameCounter(0),
m_timeScaling(1.),
m_enabled(false),
m_charge(false),
m_visionDelay(35 * 1000 * 1000),
m_visionProcessingTime(5 * 1000 * 1000),
m_aggregator(new ErrorAggregator(this))
{
// triggers by default every 5 milliseconds if simulator is enabled
// triggers by default every 8 milliseconds if simulator is enabled
// timing may change if time is scaled
m_trigger = new QTimer(this);
m_trigger->setTimerType(Qt::PreciseTimer);
Expand Down Expand Up @@ -274,9 +274,24 @@ void Simulator::process()
m_data->dynamicsWorld->stepSimulation(timeDelta, 10, SUB_TIMESTEP);
m_time = current_time;

// only send a vision packet every third frame = 15 ms - epsilon (=half frame)
// gives a vision frequency of 66.67Hz
if (m_lastSentStatusTime + 12500000 <= m_time) {
// Emit ground truth robot positions at full simulation rate (125Hz), without noise
{
world::SimulatorState gt;
gt.set_time(m_time);
for (auto it = m_data->robotsBlue.cbegin(); it != m_data->robotsBlue.cend(); ++it) {
it.value().first->update(gt.add_blue_robots(), m_data->ball);
}
for (auto it = m_data->robotsYellow.cbegin(); it != m_data->robotsYellow.cend(); ++it) {
it.value().first->update(gt.add_yellow_robots(), m_data->ball);
}
QByteArray gtData(static_cast<int>(gt.ByteSizeLong()), 0);
gt.SerializeToArray(gtData.data(), gtData.size());
emit sendGroundTruth(gtData);
}

// send a vision packet every second simulation frame
// with the 125 Hz base loop this results in an effective vision frequency of 62.5 Hz
if ((m_simulationFrameCounter++ % 2) == 0) {
auto data = createVisionPacket();


Expand All @@ -297,8 +312,6 @@ void Simulator::process()
timer->start(timeout);
m_visionTimers.enqueue(timer);
}

m_lastSentStatusTime = m_time;
}

// send timing information
Expand Down Expand Up @@ -785,6 +798,7 @@ void Simulator::handleCommand(const Command &command)
if (sim.has_enable()) {
m_enabled = sim.enable();
m_time = m_timer->currentTime();
m_simulationFrameCounter = 0;
// update timer when simulator status is changed
setScaling(m_timeScaling);
}
Expand Down Expand Up @@ -950,8 +964,8 @@ void Simulator::setScaling(double scaling)
// clear pending vision packets
resetVisionPackets();
} else {
// scale default timing of 5 milliseconds
const int t = 5 / scaling;
// scale default timing of 8 milliseconds (125Hz)
const int t = 8 / scaling;
m_trigger->start(qMax(1, t));

// The vision packet timings are wrong after a scaling change
Expand Down
3 changes: 3 additions & 0 deletions src/simulator/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
add_executable(simulator-cli WIN32 MACOSX_BUNDLE
simulator.cpp
ssl_robocup_server.cpp
packet_sender_thread.cpp
)

target_link_libraries(simulator-cli
Expand All @@ -29,3 +30,5 @@ target_link_libraries(simulator-cli
Qt6::Widgets
amun::simulator
)

install(TARGETS simulator-cli RUNTIME DESTINATION bin)
Loading
Loading