← Back to 25T3

Assignment 2 - Epuck Tag



Changelog

Background

This assignment combines C++ programming, simulation, and robotics logic into a fun game. You’ll see your code come to life and your robots move based on what you write!

You will be using the robotics simulation software Webots (version 2025a) to write code to control robots in a virtual environment.

The game is freeze tag where you will be playing as the runners against an autonomous chaser. Write C++ code to control 3 epuck robots (runners) in the Webots simulation to make them move, communicate, and avoid being tagged.

This is an open-ended assignment for you to form your own game strategy and class design. You will have to submit your code and a rationale for your strategy in a 1-page PDF.

Try to keep your runners alive for as long as possible. The game will end when all your runners have been tagged.

Learning Outcomes

Summary

Marks

contributes 33% of your final mark

Due Date

Week 11 Friday, 11:59 PM

Late Penalty

5% per day, submissions later than 5 days not accepted without approved special consideration

Prerequisite Knowledge

Getting Started

Setting up…

Ensure you have followed this guide. You should be able to run the Webots application locally on your machine.

Retrieving the starter code

To get the assignment starter code, use the GitHub classroom link on Moodle to gain access to your assignment repository and clone the repository locally.

Examining the starter code

The starter code is a Webots project with one world and two controllers:

epuck-tag |_ controllers | |_ chaser_controller | | |_ chaser_controller.cpp | | |_ Chaser.cpp | | |_ Chaser.hpp | | |_ Makefile | | | |_ runner_controller | | |_ runner_controller.cpp | | |_ run.cpp | | |_ run.hpp | | |_ Runner.hpp | | |_ Makefile | | | |_ runner_controller_2 | |_ runner_controller_2.cpp | |_ Runner.cpp | |_ Runner.hpp | |_ Makefile | |_ worlds |_ arena.wbt

You are free to add and edit files inside the runner_controller directory. But do not edit runner_controller.cpp and anything outside of the runner_controller directory.

You will also notice there is a runner_controller_2 folder. This contains alternative starter code which has the same behaviour as the starter code in runner_controller. This alternative starter code has a Runner class which inherits the webots::Robot class. We provide this alternative starter code in case you want to closely-follow the lecture examples which uses inheritance rather than passing the robot object around. It doesn’t matter which starter code you choose. Neither will give a greater advantage or disadvantage when it comes to style or design marks.

Changes to starter code

When changes/fixes are applied to the starter code, this will be available in your GitHub repository. You must pull these changes to your local repository by running:

git pull

Simulation Environment

The simulation environment is a walled circle arena with 0.7 metre radius. It has grid flooring where each cell is 0.1 metres in width. The arena won’t have any obstacles within it.

There will be 4 epucks placed within the world. You can assume the epuck starting configuration will always be the same.

You are not allowed to modify the simulation environment or the robots within it.

Game Rules

This is a game of freeze tag between epucks. There are two types of agents:

You will play as the runners against an autonomous chaser.

There will be 1 chaser and 3 runners placed in the starting configuration. The chaser immediately begins chasing the runners once the simulation starts. All runners start in the unfrozen state and may move freely.

When the chaser gets within 0.15 metres of a runner, it emits a freeze message to that runner. Upon receiving a freeze message, the runner becomes frozen and stops moving immediately.

If an unfrozen runner comes within 0.1 metres of a frozen runner, it may help the frozen runner. Helping the frozen runner will unfreeze them and allow them to resume participating in the game.

The game ends when there are no unfrozen runners left.

This video below shows a sample game between a chaser and 3 runners (making random movements):

Chaser

⚠️

You will not be coding the chaser. The chaser is already implemented and its code provided for you to play against. To run the chaser, you need to build the chaser controller in Webots.

The chaser is the epuck marked with the black top:

The chaser’s goal is to tag all the runners in the game until there are no runners left unfrozen. Its behaviour is as follows:

  1. Identify the closest unfrozen runner as the target. If the game has just started, the runner will be runner1 instead. The chaser will not switch targets until the target is tagged. If the chaser gets close enough to another runner that is not the target, then that runner can still get tagged.
  2. Go to the target’s current position. The chaser does not rely on any devices to seek the target. It uses special privileges to always know the location of the target at all times.
  3. If the chaser is within 0.15 metres of the target, tag it. The chaser will use its emitter device to send a message to the target to indicate it being tagged.
  4. Repeat until all runners are frozen. The chaser will stop, announce the end of the game, then chaser controller will terminate/exit.

The chaser will manage the game so it will always know who should be frozen and unfrozen (even if the runners break the rules).

Warning messages

The chaser has an emitter device which will emit its own position to every runner within a 0.7 metres radius. This message is sent every 1 second and to all channels.

The format of the message is:

t:warning:x,y,h

Where:

Each part of the message is delimited by a colon (:) except for x, y, and h which are delimited by commas (,).

An example of three warning messages may look like:

1.04:warning:0.22545,0.224359,3.01162 2.048:warning:-0.317293,0.131969,2.66537 3.056:warning:-0.115643,-0.148366,0.448079

Freeze messages

The chaser will also emit a freeze message to tag runners within a 0.15 metre radius. This message is sent continuously and to all channels. The freeze message is simply:

t:freeze

Where:

An example of a freeze message may look like:

12.204:freeze

Specification

The chaser epuck will have the following parameters:

ParameterValue
Robot diameter0.071 m
Robot height0.05 m
Wheel radius0.02 m
Axle length (distance between wheels)0.052 m
Max motor speed7.536 rad/s
Warning emitter max range0.7 metres
Warning emitter channel-1 (all channels)
Freeze emitter max range0.15 metres
Freeze emitter channel-1 (all channels)

Runner

All runners will look like the following epuck - distinctly marked by the green top:

The runner has two states: frozen and unfrozen. The runner begins the game in the unfrozen state and is free to move. When the runner gets tagged, it will switch to the frozen state and immediately stops moving. These states are visualised on the epuck by whether its LED (device named “led8”) is turned on or off. The epuck on the left below has its green LED turned on. The epuck on the right has its green LED turned off.

The frozen runner can be helped out of this frozen state if there is another unfrozen runner within 0.1 metres. Helping a frozen runner will change the frozen runner’s state to unfrozen - it should have its LED turned back on and will be able to rejoin the game. You should use the runner’s emitter and receiver devices to communicate between the helper runner and frozen runner to achieve this.

The state diagram below will visualise all the states and transitions expected of the runner:

stateDiagram
    unfrozen: Unfrozen
    frozen: Frozen

    [*] --> unfrozen : start game
    unfrozen --> frozen : if tagged
    frozen --> unfrozen : if helped
    frozen --> [*] : all runners tagged

Locating the chaser

The runners do not not know where the chaser is. To survive longer, you should utilise the onboard devices to learn the chaser’s location and avoid the chaser. There are two ways you can do this:

Frozen runners are allowed to continue detecting the chaser’s position and heading.

The distance sensors of the epucks will not be able to detect other epucks due to the slight upward angle the distance sensors are pointing (rays shown as grey lines below).

Specification

The runner epuck will have the following devices attached. You can only use the devices listed in this table:

DeviceIdentifierParameterValue
Left wheel motor”left wheel motor”Max motor speed6.28 rad/s
Right wheel motor”right wheel motor”Max motor speed6.28 rad/s
Left position sensor”left wheel sensor”--
Right position sensor”right wheel sensor”--
Emitter”emitter”Max rangeINFINITY
Channel-1 (all channels)
Receiver”receiver”Max rangeINFINITY
Channel-1 (all channels)
Compass”compass”--
GPS”gps”--
Lidar”lidar”FOV360 degrees
Resolution512 rays
Min range0.01 metres
Max range0.4 metres
Distance sensors”ps0” to “ps7”TypeLaser
Min range0.1 metres
Max range0.5 metres
LEDs”led8”

You can set the emitter and receiver channels and range to other values if you wish.

The runner epuck will have the following robot parameters:

ParameterValue
Robot diameter0.071 m
Robot height0.05 m
Wheel radius0.02 m
Axle length (distance between wheels)0.052 m

Strategy

Can you outsmart the chaser? There are 3 total runners for you to control which will all have the runner controller attached. You will need to design and implement a runner strategy in the runner controller. Remember that you just need to keep at least 1 of the runners alive for as long as possible.

The simplest strategy could be to make your epucks run to the edge of the arena and move around the perimeter. A smarter strategy would be to utilise the runners’ onboard devices to learn the location of the chaser, thus avoiding it. An even smarter strategy would be to get the 3 runners to work together as a team. Feel free to experiment what works and doesn’t work!

For the strategy that you decide to implement, you must submit a rationale (1-page PDF) explaining:

You are encouraged to include diagrams to support your rationale.

See the strategy rationale rubric for more information.

Software Requirements

Supervisor

You cannot use the webots::Supervisor class.

The chaser uses the webots::Supervisor class to get special privileges to know where the runners are at all times.

New files

You are free to create new .cpp and .hpp files to organise your code. Just remember to update the Makefile so that your runner controller is compilable.

You should not create any files or write any code outside of the runner controller.

Using libraries

You may #include any standard C++ libraries that you require. You should not use any other libraries (and especially OS-specific libraries).

C++ version

This assignment should be written with modern C++ practices. The starter code and environment supplied is running C++17. You should be writing all code that is supported by this version of C++.

Class Design

We provide the bare minimum starter code for this assignment so that you are free to pursue any class design you want. You can create whatever files, classes, and functions you want. Think carefully how to design your code such that it would follow best practices e.g.

Consider this simple (and not the best) class design:

class Runner { public: void moveAwayFromChaser(); void moveToHelpRunner(); void checkFreezeMessages(); void toggleState(); private: void driveMotors(); bool mFrozen; };

This would be an example of good class design since:

Consider this other class design:

class Runner { public: void moveAwayFromChaser(); void moveToHelpRunner(); void driveMotors(); void toggle(); double distanceFormula(std::array<double, 2> a, std::array<double, 2> b); bool mFrozen; };

This would be an example of poor class design since:

See the class design rubric for marking details.

Stages

The assignment is broken into two stages so that the assignment is easier to get started with.

See the Stage 1 rubric and Stage 2 rubric for detailed marking of these stages.

Stage 1 - Rules

This stage is marked based on if your runners can follow the game rules and requirements.

Start by implementing the basic functionality that your runners will need:

Stage 2 - Survival

This stage is marked based on how effective your strategy is.

Think about how you want to play the game. Start with designing and writing down your ideas, and translating your ideas into pseudocode.

Use divide-and-conquer to break up your coding into manageable chunks e.g.

Related section: Strategy

Version Control

As part of this assignment, you will be required to use GitHub classroom. A repository has been established for all students and the starter code has been placed within this (it will NOT be released on Moodle). You will be expected to meaningfully use this version control platform as it is widely used in industry and provides a means of retrieving code in case of computer issues or getting old revisions of your work.

Testing

Use the Webots simulator to test your runners. Here are some basic scenarios that you can test:

Remember that each cell is 0.1 x 0.1 metres which you can use to eyeball distances.

If your controller isn’t working as expected or crashes, try debugging your code by printing out flags and important information e.g. GPS position.

Marking Criteria

The assignment in total is worth 33 of your course marks and is split into:

Stage 1 rubric

Stage 1 marks are awarded based on whether your runners can follow the game rules.

The marking will be done using automated tests that simulate various scenarios to check if your runners behave according to the game rules.

CriteriaMarksSubcriteriaSubmarks
Stage 17 marksUnfrozen runners freeze when tagged by chaser. Receives freeze message, stops moving immediately, and deactivates LED.3
Unfrozen runners do not freeze when not supposed to.1
Frozen runners unfreeze when helped by unfrozen runner. Activates LED and may start moving.2
Frozen runners do not unfreeze when not supposed to.1

Stage 2 rubric

Stage 2 marks are awarded using percentile-ranking based on how long your runners can survive compared to all other students’ submissions.

Your runners will be tested in 12 different games against the chaser using the same starting configuration and chaser logic provided in the starter code. Your survival time in each game will be recorded and your average survival time across all your games will be calculated.

CriteriaMarks availablePercentile rangeMarks awarded
Stage 27 marks[90.0, 100.0]7
[75.0, 90.0)6
[60.0, 75.0)5
[45.0, 60.0)4
[30.0, 45.0)3
[15.0, 30.0)2
[0, 15.0)1
Students who did not do stage 2 and no-compiles.0

Strategy rationale rubric

You must submit a 1-page PDF containing your strategy rationale. It will be marked according to the following rubric:

CriteriaMarksDescription
Strategy design and reasoning3Clearly explains the overall approach and logic behind the robot’s behavior. Justifies why this strategy was chosen, referencing game rules, robot capabilities, and anticipated challenges. Discusses key decisions and trade-offs.
Strategy implementation1Describes how the strategy was translated into code, including which devices and sensors were used, and how they support the chosen approach. Refers to specific logic, algorithms, or coordination between runners.
Reflection1Thoughtfully evaluates how well the strategy performed in practice. Identifies strengths, weaknesses, and any unexpected outcomes. Suggests concrete improvements or alternative approaches for future iterations.

Class design rubric

Your class design will be manually marked using your submitted code according to the following rubric:

CriteriaMarksDescription
Class abstraction2Classes have clear, focused responsibilities; appropriate use of inheritance; methods and properties are cohesive and relevant to the class purpose.
Class functions1Methods have single, well-defined responsibilities; appropriate use of public/private/protected access specifiers; avoid exposing internal details.
Code deduplication1Effective use of functions, helper methods, and classes to eliminate code repetition; avoids copy-paste logic.
High cohesion1Related code is grouped together in files, namespaces, or classes; each module/class/file has a clear purpose.
Low coupling1Classes and modules interact through well-defined interfaces; changes in one class do not require changes in others.

In order to be eligible to receive full marks for class design, you must have made a reasonable attempt at Stages 1 and 2. If you only attempt Stage 1, your class design mark will be capped at 2/6.

Style rubric

Please refer to the C++ Style Guide for the detailed style guide. Your code style will be manually marked using your submitted code according to the following rubric:

CriteriaMarksDescription
C++ style3Effective use of C++ features (e.g. smart pointers, STL containers, const, and type-safe casts). Code avoids outdated or unsafe practices.
Descriptive class, function, variable names2All names are clear, descriptive, and reflect their purpose. Naming style is consistent throughout the codebase.
Commenting1Comments are used to explain the intent, logic, and purpose of code, especially for non-obvious sections. Comments do not simply restate code.
Const correctness1Functions, arguments, and variables are marked const wherever possible to improve safety and clarity.
Consistent spacing and braces1Code follows a consistent indentation, bracing style, and spacing. No stray whitespace or formatting errors.
Penalties-Deductions for use of using namespace, void*, #define, or other discouraged practices.

In order to be eligible to receive full marks for style, you must have made a reasonable attempt at Stages 1 and 2. If you only attempt Stage 1, your style mark will be capped at 2/8.

Submission

The assignment is due by 11:59 pm on Friday Week 11 (28/11/2025). We will use your GitHub repository’s latest commit. Any pushes past this deadline will be considered a late submission.

Ensure you have commited and pushed all your changes before the deadline. You will need to submit your strategy rationale as a PDF titled z1234567.pdf. Submit the PDF to Moodle and committed into the root directory of your GitHub repository.

Make sure in your GitHub repository, you only have one runner_controller folder:

Compiling code

If your code does not compile, we will try to fix your compiler errors so we can give you as many marks as we can. However, submitting non-compiling code will apply a 10% penalty on your Stage 1 marks. If your code needs more than 2 error fixes, then you will receive 0 for Stage 1.

Late Penalty

UNSW has a standard late submission penalty of: 5% per day, for all assessments where a penalty applies, capped at five days (120 hours) from the assessment deadline, after which a student cannot submit an assessment.

Plagiarism

If you are unclear about the definition of plagiarism, please refer to What is plagiarism?.

You could get zero marks for the assignment if you were found:

You will be notified and allowed to justify your case before such a penalty is applied.

AI Policy

You are only permitted to use AI to the level of “planning or design assistance” for this assignment. If you are unclear about what this means, please refer to Levels of AI assistance.

You should NOT use AI to generate code or write your report for you. If you do use AI for planning or design assistance, you must clearly document this in your submitted report (excluded from the 1-page limit). You should include:

Failure to do so will be considered academic misconduct.