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
- Compile:
cmake .. && make
- Run it:
./traffic_simulation
.
Project Tasks
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
TrafficLight
which is a child class ofTrafficObject
. The class shall have the public methodsvoid waitForGreen()
andvoid simulate()
as well asTrafficLightPhase getCurrentPhase()
, whereTrafficLightPhase
is an enum that can be eitherred
orgreen
. Also, add the private methodvoid cycleThroughPhases()
. Furthermore, there shall be the private member_currentPhase
which can takered
orgreen
as 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 methodcycleThroughPhases
should be started in a thread when the public methodsimulate
is called. To do this, use the thread queue in the base class. - Task FP.3 : Define a class
MessageQueue
which 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 anstd::dequeue
called_queue
, which stores objects of typeTrafficLightPhase
. Finally, there should be anstd::condition_variable
as well as anstd::mutex
as private members. - Task FP.4 : Implement the method
Send
, which should use the mechanismsstd::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 classTrafficLight
, create a private member of typeMessageQueue
for messages of typeTrafficLightPhase
and use it within the infinite loop to push each newTrafficLightPhase
into it by calling send in conjunction with move semantics. - Task FP.5 : The method receive should use
std::unique_lock<std::mutex>
and_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 methodwaitForGreen
, in which an infinite while-loop runs and repeatedly calls thereceive
function on the message queue. Once it receivesTrafficLightPhase::green
, the method returns. - Task FP.6 : In class Intersection, add a private member
_trafficLight
of typeTrafficLight
. In methodIntersection::simulate()
, start the simulation of_trafficLight
. Then, in methodIntersection::addVehicleToQueue
, use the methodsTrafficLight::getCurrentPhase
andTrafficLight::waitForGreen
to block the execution until the traffic light turns green.