You can acquire the necessary programming skills by doing a simpler project first: simulate a spring-mass system according to physics. Once you have reached that milestone, it will be easier for you to conceptualize a larger system.
Your program is a loop. At each time step ("tick of time"), say t
, your program must calculate the parameters (position, velocity, acceleration, driver's decision) of each car for the next time step, say t + 1
.
- You will have an array of cars, say
carCurrentStates[carNumber]
.
- You may need to create a duplicate array,
carNextStates[carNumber]
.
- At each time step, use the information from
carCurrentStates[carNumber]
to compute new information for carNextStates[carNumber]
. When all calculations for the time step is done, copy the information from carNextStates[carNumber]
back to carCurrentStates[carNumber]
.
- The duplicate array
carNextStates[carNumber]
can be reused (overwritten) in the next time step.
You will need to synchronize these calculations.
Whether you use threads or not, you will have to use some kinds of synchronization techniques. Synchronization techniques for threads are also known as barriers.
Thread schedulers do not magically cause your threads to run in a synchronized way. They don't magically give equal share of time to each of your threads. If you do not use any synchronization techniques, some of your threads will get more execution time than others; they will lose sync.
If more than one threads need to update (write to) a certain program variable, that need to be serialized. Serialization means that one thread can complete a "read-modify-write" sequence before another thread can start its own "read-modify-write" sequence. If access to program variables aren't serialized, each thread's written result will clobber the earlier result, or that a thread may perform calculations based on a stale result that has since been clobbered.
Once you know how to implement the calculations in a synchronized way, and update the program's states correctly, you may find that you can implement the project either with or without threads.
As to simulating driver's behavior, each driver will accelerate or decelerate according to:
- What is my speed? (Low/medium/high)
- What is the speed of adjacent lanes?
- How far is the car in front of me?
- Is the space between me and the car in front: increasing (accelerating faster than me), same (same velocity/same acceleration), or decreasing?
- Am I planning to change lane? If so, I need to match the speed of that other lane.
- Do I have any other reason to slow down? If I am going to exit from a highway, or if there's a traffic light, or if there's a sharp curve, then I need to slow down.
- Do I need to make a complete stop at a certain point? If I'm reaching my destination, or if the traffic light is red, then I'm not allowed to overshoot. I have to brake as hard as I can if that is necessary.