$30
Assignment 2: Threading, Synchronisation and Data Integrity
Revision Date | Change |
01-APR-2024 | Initial Release |
27-APR-2024 | Added details for SUPER mode (starting/end location for Ackerman – and lattice details) Stated that index.dox should contain behaviour when running executable built from main.cpp |
Intent: Skills in utilising, classes, abstraction, data structures, threading, data synchronisation and documentation will be assessed.
Weight: As per subject outline
Task: Write a program in C++ using object-oriented paradigms that controls Mechatronic platforms with a number of threads. Ensure data integrity between threads and enable relating data between them via suitable data structure that enables time synchronisation and subsequently interpolation of data for task at hand. Supply appropriate autogenerated documentation utilising inline source mark-up.
Rationale: In a Mechatronics System, several platforms can be coordinated to complete a series of tasks. Decisions need to be made based correctly in near real-time. Threading and synchronisation are ways to ensure the system performs as intended, with guarantees on the responsiveness of the system to incoming task changes, processing constraints and system behaviour.
Your task is to (a) create a number of threads that can coordinate platform in reaching a series of goals (b) implement a graph, and search the graph for optimal paths, incorporating information about the platform motion into the graph (c) create a separate thread(s) to process the goals provided and ensures simultaneous execution of reaching goals (mission) between platforms.
Due: As per subject outline
This document to be read in conjunction with 2024a_a2_skeleton code available in your git repositories. The assignment uses a physics simulator called gazebo. Students are provided access to the simulator via pfms-support, they need to update to the latest version of all support files following the UPGRADE instructions on pfms-support.
Students are provided skeleton code in a2_skeleton folder that they need to use and develop from. There are two
Interface Classes MissionInterface and ControllerInterface that stipulate the functionality of the Mission or Controller/Ackerman/Quadcopter class. The Controller class is the base class for Ackerman/Quadcopter. On the level of controlling the individual platforms, we build from assignment 1, while mission has different functionality.
There are two platforms that are used to accomplish a mission, a quadcopter (drone) and Audi R8 (vehicle with
Ackerman steering), further details on platforms are in Platform Audi R8: Ackerman and Platform Drone: Quadcopter.
The task for the platforms is to go through a series of goals they are provided and therefore act as if they are patrolling a space.
There are three modes of the assignment, where mission coordinates simultaneously both platforms to accomplish following modes: BASIC / ADVANCED / SUPER mode. Students should attempt ADVANCED MODE (which unlocks D/HD for execution) ONLY if they have completed the BASIC MODE. SUPER mode is for bonus points above the 100 for this assignment. Functionally each mode is described below:
In building a complete solution you will make two libraries, are provided unit tests and have a main that demonstrated the use of the libraries.
To start the simulation, run: ros2 launch gazebo_tf a2.launch.py
An example main has been provided where it run as follows
o the execution reachGoal inside each platform should also be non-blocking
All marks for execution will be derived from unit tests, the main is an example for your own development and the behaviour of what occurs if you run the executable built from the main should be described in index.dox
The Audi R8 is a vehicle that has Ackerman Steering, for a video introduction on how to use the Ackerman steering model please see an excellent video by Jonathan Sprinkle. in essence, for control the vehicle can be approximated with a single tyre at front and back (known as bicycle model -geometric vehicle model), the wheel base T and distance between front/back wheel L. δ and the radius of turn R are related. We assume only geometry plays part and no dynamics (no drifting on track).
The steering wheel to wheel position is via a STEERING RATIO, the total number of turns (lock to lock) governs maximum steer angle. The distance between wheels is knows as wheel base (L).
Property | Values |
STEERING RATIO | 17.3 |
LOCK TO LOCK_REVS | 3.2 |
MAX STEER ANGLE | (M_PI * LOCK_TO_LOCK_REVS / STEERING_RATIO) |
TRACK WIDTH | 1.638 [m] |
WHEEL RADIUS | 0.36 [m] |
WHEELBASE | 2.65 [m] |
MAX BRAKE TORQUE | 8000.0 [Nm] |
The control of the platform is via 3 values
Property | Values |
brake | 0 to MAX BRAKE TORQUE |
steering | - MAX STEER ANGLE to + MAX STEER ANGLE |
Throttle | 0 to 1.0 |
Students can use audi library supplied via pipes which contains functionality per header file audi.h .
The quadcopter has four rotors that allow it to move in any direction, turn on spot, as well as go up/down. If the platform is not above ground, it will crash and stop running. The control of the platform is via 4 control values
Property | Values |
Turn on spot left / right | Left positive |
Move left/right | Left positive |
Move up/down | Up positive |
Move forward / backward | Forward positive |
For the drone to start moving, it first needs to lift off the ground, which requires sending a specific command to TAKEOFF as demonstrated in a1_snippets/command_uav.cpp. You do not need to do any LANDING in this assignment.
The objective is to minimise total distance travelled, and therefore the total speed is not limited. If going fast, you do need to consider time to stop (inertia exists) which might make it be more difficult to control.
All goals are on same height for this assignment. However, some rudimentary control of height Z for this assignment may be required as to not land on the group or clip car. Best to keep height at ~ 2.m (control up/down).
The mission planning simply passes the goals as supplied to the platforms (Quadcopter AND Ackerman) for execution. When calling run (which is a non-blocking call - call to run should return instantaneously) the platforms perform execution simultaneously, going through the goals in separate threads of execution.
The platforms compute the distance that needs to be travelled to reach all goals supplied (in the order provided) and have a status function that indicates if they are idle or running (IDLE – not active goals and RUNNING – travelling to goals).
If Mission status is requested, it returns the percentage of completed mission, which is percentage of distance travelled by both platforms compared to required total distance.
As we estimate total distance travelled at the beginning, often as we move we are very far from the estimate. I suggest to update your estimate as you approach goals (thereby recalibrating your estimate) and reach 100 only when you complete the mission.
The mission planning needs to determine the ordering the goals will be visited for each platform ensuring all goals are visited only once. Thereafter on run it passes the goals as supplied to the Quadcopter AND Ackerman for execution. The behaviour of platforms and mission thereafter in control (going to the goals) is the same as in BASIC mode.
A graph search (travelling salesman problem) is the best way to handle computing the ordering, and this becomes a combinatorial search committing to a certain order of visiting goals. You will need to consider the Ackerman control (the steering), keeping it constant between goals enables simpler mission planning. On completing the ordering of goals, the mission passes the goals as supplied to the platforms (Quadcopter AND Ackerman) for execution. Function std::vector<std::pair<int, int>> getPlatformGoalAssociation(); shall return the derived order and association and NEEDS to be used for testing.
For ADVANCED mode a total of 10 goals (5 were given to each platform and then combined).
The mission planning needs to Quadcopter to survey a possible path selection for Ackerman to go through a field with obstacles from bottom left corner to top right corner. It sends quadcopter to determine the locations of obstacles (cuboid of known dimensions 7x7x4.5 - WxDxH). ). Then needs to produce goals for the Ackerman to travel through maze. The obstacles are distributed as a lattice (3 rows and 5 columns), in testing it remains a lattice where the distance between rows and columns may change (between 0-5m). The starting position for Ackerman (x=-80, y=70) and end position (x=80, y=-70) whereas you can select starting position for Quadcopter (I would advise to keep it close to Ackerman).
We advise to use the laser to determine obstacles, details of how to obtain laser readings were distributed in week 08 and are part of PfmsConnector.
You will need to unit test your strategy to determine obstacles `virtual std::vector<pfms::geometry_msgs::Point> getObstacles(void) = 0;` And the strategy for goals (supply them to be tested). The Quadcopter needs to use the Laser attached to it, to determine the cuboid.
Thereafter on run it passes the goals as supplied to the Ackerman for execution. The behaviour of platforms and mission thereafter in control (going to the goals) is the same as in BASIC mode.
The testing will attempt to test the Controller Classes (Quadcopter and Ackerman) validating
Unit testing has been enabled by default, they can be disabled via set(BUILD_TESTS OFF)If your tests are succeeding you should get all green in execution of tests.
If you're attempting the SUPER section of the assignment, you will need to supply your own unit tests as discussed in Misison Planning and Control.
Criteria | % | Description / Evidence | |||||||
Use of appropriate data structures, locking mechanisms, data sorting mechanisms Total weight (%) 15
Design adheres to principles of: Inheritance from base class, common data stored and generic functionality implemented solely in base class ( duplication). Member variables/functions that should not be available f instantiation aptly protected. Suitable data containers, sorting mechanisms optimal with respect to memory footprint. Use of synchronisation mechanisms to enable efficient multithreading and safe data sharing between threads (avoiding busy waits / optimise locking). | no or | 15 | Correct use of access specifiers | ||||||
10 | Constructors and Destructors available and used correctly to initialise class | ||||||||
10 | Inheritance from base class, common data stored and generic functionality implemented solely in base class (no duplication). | ||||||||
30 | Threading implemented so function that are non-blocking return immediately (correct behaviour) and threads run inside classes as specified. | ||||||||
15 | Use of mutexes makes data secured | ||||||||
20 | Graph exploiting STL used for searching goal ordering | ||||||||
[Sections that only apply to ADVANCED MODE HIGHLIGHTED IN GREEN] | |||||||||
Proper code execution Total weight (%) 55 Platforms reach goals, controlled correctly, run concurrently (showing correct implementation of threading). Implemented correctly reporting of status for platform and mission during execution. Search for goals implemented correctly in graph search.
| 30 | Audi Reach Goals (testAudiReachGoals) | |||||||
30 | Quadcopter Goals (testQuadcopterReachGoals) | ||||||||
15 | Mission Test (testMissionReachGoals) | ||||||||
15 | Search for optimal goals ordering for Audi (testTspReachGoalsAck) | ||||||||
10 | Search for optimal goals ordering for Quadcopter (testTspReachGoalsQuad) | ||||||||
20 | Correctly determining path for Audi to travel through field and reach goal (No Unit Test Supplied) | ||||||||
10 | Reaching all goals in testMissionReachGoals (which is BASIC MODE) in under 100s receives extra points. | ||||||||
Unit tests Total weight 10%
Unit tests created that guarantee performance of underlying algorithms Students need to supply these Unit Tests.
| 50 | TSP - graph search for Quadcopter (can be part of Mission or separate library) implemented and tested separate to our test which checks passing through the goals. Implement test solely on the function that determines the order. | |||||||
50 | TSP - graph search for Ackerman (can be part of Mission or separate library) implemented and tested separate to our test which checks passing through the goals. Implement test solely on the function that determines the order. | ||||||||
40 | Implemented test for getObstacles (which is Controller) | ||||||||
Documentation Total weight (%) 10 | 100 | Documentation is produced via Doxygen, all source files contain useful comments to understand methods, members and inner workings (ie control method, search method). For HD a landing page (cover page via an index.dox) must be provided with description of submission (what is behaviour of code, how will it run, what does it use to search/ plan goal ordering) and what behaviour is expected when running the executable that is built from main.cpp. | |||||||
Modularity of software Total weight (%) 10
Appropriate use class declarations, definitions, default values and naming convention allowing for reuse. No implicit coupling between classes that disables reuse. All classes interface in ways allowing use of class in others contexts and expansion (ie controlling another controller). No “hard coded” values or assumptions. | 25 | No repeated segments of code that performs same operations | |||||||
25 | Separate threads running control of platforms and mission | ||||||||
25 | Code can handle additional ACKERMAN or QUADCOPTER | ||||||||
25 | Graph search separated into a library not within Mission to allow for reuse (and tested in this way). | ||||||||
What are biggest changes since Assignment 1 | • Your need to implement threading in Ackerman / Quadcopter to enable executing sequence of goals inside this class, setting the execution with run and monitoring progress with status (there is no reachGoal function in interface) • setGoal function now takes a vector of Points (as the platforms are now capable of pursuing goals until provided others or reaching them) |
Why do we have goals in x,y, z | For Ackerman z=0 to be on ground plane. For quadcoptrer we have a z that is fixed at 2m (so it is above the Ackerman and they do not collide. |
What is orientation reported in? | Radians, orientation is reported - π to π |
Should my main deal with threads or have functions in it. | No, your main should not have any threading. The threads should be In the classes (you need to select where (Controller, Ackerman, Quadcopter, Mission). Consider your classes to have allocated responsibility. Some classes are also needed for computation (especially if it may need to be updated or called reclusively). Look at example of Radar in Week 07 |
How do students generate Doxygen for their assignment | If you wish solely to exploit in text commenting (without adding it to cmake, which suffices for marking) then a quick way is to execute following two commands within your project folder: 1. “doxygen –g” (which will generate Doxyfile) 2. “doxygen Doxyfile”(generates the html and latex) DO NOT submit the generated document files as part of your ZIP, we can generate them from your source files. |