CPPND: Program a Concurrent Traffic Simulation
This is the project for the fourth course in the Udacity C++ Nanodegree Program: Concurrency.
Throughout the Concurrency course, you have been developing a traffic simulation in which vehicles are moving along streets and are crossing intersections. However, with increasing traffic in the city, traffic lights are needed for road safety. Each intersection will therefore be equipped with a traffic light. In this project, you will build a suitable and thread-safe communication protocol between vehicles and intersections to complete the simulation. Use your knowledge of concurrent programming (such as mutexes, locks and message queues) to implement the traffic lights and integrate them properly in the code base.
Dependencies for Running Locally
- cmake >= 2.8
- All OSes: click here for installation instructions
- make >= 4.1 (Linux, Mac), 3.81 (Windows)
- Linux: make is installed by default on most Linux distros
- Mac: install Xcode command line tools to get make
- Windows: Click here for installation instructions
- OpenCV >= 4.1
- The OpenCV 4.1.0 source code can be found here
- gcc/g++ >= 5.4
- Linux: gcc / g++ is installed by default on most Linux distros
- Mac: same deal as make - install Xcode command line tools
- Windows: recommend using MinGW
Basic Build Instructions
- Clone this repo.
- Make a build directory in the top level directory:
mkdir build && cd build
cmake .. && make
- Run it:
When the project is built initially, all traffic lights will be green. When you are finished with the project, your traffic simulation should run with red lights controlling traffic, just as in the .gif file above. See the classroom instruction and code comments for more details on each of these parts.
- Task FP.1 : Define a class
TrafficLightwhich is a child class of
TrafficObject. The class shall have the public methods
void simulate()as well as
TrafficLightPhase getCurrentPhase(), where
TrafficLightPhaseis an enum that can be either
green. Also, add the private method
void cycleThroughPhases(). Furthermore, there shall be the private member
_currentPhasewhich can take
greenas its value.
- Task FP.2 : Implement the function with an infinite loop that measures the time between two loop cycles and toggles the current phase of the traffic light between red and green and sends an update method to the message queue using move semantics. The cycle duration should be a random value between 4 and 6 seconds. Also, the while-loop should use
std::this_thread::sleep_for to wait 1ms between two cycles. Finally, the private method
cycleThroughPhasesshould be started in a thread when the public method
simulateis called. To do this, use the thread queue in the base class.
- Task FP.3 : Define a class
MessageQueuewhich has the public methods send and receive. Send should take an rvalue reference of type TrafficLightPhase whereas receive should return this type. Also, the class should define an
_queue, which stores objects of type
TrafficLightPhase. Finally, there should be an
std::condition_variableas well as an
std::mutexas private members.
- Task FP.4 : Implement the method
Send, which should use the mechanisms
std::lock_guard<std::mutex>as well as
_condition.notify_one()to add a new message to the queue and afterwards send a notification. Also, in class
TrafficLight, create a private member of type
MessageQueuefor messages of type
TrafficLightPhaseand use it within the infinite loop to push each new
TrafficLightPhaseinto it by calling send in conjunction with move semantics.
- Task FP.5 : The method receive should use
_condition.wait()to wait for and receive new messages and pull them from the queue using move semantics. The received object should then be returned by the receive function. Then, add the implementation of the method
waitForGreen, in which an infinite while-loop runs and repeatedly calls the
receivefunction on the message queue. Once it receives
TrafficLightPhase::green, the method returns.
- Task FP.6 : In class Intersection, add a private member
TrafficLight. In method
Intersection::simulate(), start the simulation of
_trafficLight. Then, in method
Intersection::addVehicleToQueue, use the methods
TrafficLight::waitForGreento block the execution until the traffic light turns green.