avatarJohn D. Leavy

Free AI web copilot to create summaries, insights and extended knowledge, download it at here

8060

Abstract

</figure></iframe></div></div></figure><p id="b722">The latter part of the constructor and the <i>render</i>() function remain the same.</p><p id="ec84">Now comes the most important and complicated part of our code, the <i>move</i>() function. Let us focus on the code for vehicles moving towards the right, as the same conditions are checked for other directions, and the code is quite similar.</p> <figure id="98e0"> <div> <div>
            <iframe class="gist-iframe" src="/gist/mihir-m-gandhi/346436779e84a2be4141f750929083ec.js" allowfullscreen="" frameborder="0" height="undefined" width="undefined">
          </div>
        </div>
    </figure></iframe></div></div></figure><p id="7b1c">For each direction, we first check if the vehicle has crossed the intersection or not. This is important because if the vehicle has already crossed, then it can keep moving regardless of the signal being green or red, depending only on the vehicle ahead. So when the vehicle crosses the intersection, we set the value of <i>crossed</i> to 1. Now, if the vehicle goes straight i.e. it does not turn, then we add it to the <i>vehiclesNotTurned</i> list and update its <i>crossedIndex</i>, which is its index in the <i>vehiclesNotTurned</i> list. This is done because the order of the vehicles changes after the intersection as some turn and some do not, and the <i>vehicles</i> list defined earlier is not useful to prevent them from overlapping.</p><p id="339c">Next, if the vehicle is going to turn, it moves straight until the turning point which is the middle of the intersection. This movement can happen in 3 cases:</p><ol><li>If it has not reached its stop point before the intersection</li><li>If it has already crossed the intersection</li><li>If the traffic signal controlling the direction in which the vehicle is moving is Green</li></ol><p id="af07">Along with this, we need to ensure that there is no overlap with the vehicle ahead when it moves. This is decided by taking into consideration the following <b>three parameters</b>: the coordinate of the vehicle ahead, the width/height of the vehicle ahead, and the <i>movingGap</i>. Also, if the vehicle ahead has already turned, then we need not worry about overlap. Only when any of these three conditions are satisfied along with no overlap, the coordinate of the vehicle is updated by incrementing/decrementing it by the speed of the vehicle, depending on its direction of motion.</p><p id="f76b">Once the vehicle crosses its turning point, if the <i>turned</i> value is 0, it turns as it rotates while moving along both the x and y-axis. Once the <i>rotationAngle</i> is 90 degrees, the <i>turned</i> variable is set to 1, the vehicle is added to the <i>vehiclesTurned</i> list, and its <i>crossedIndex</i> is updated. Else if the <i>turned </i>value is 1, the vehicle moves only if there is a sufficient gap to the vehicle ahead, found using the <i>vehiclesTurned</i> list. This is decided based on the same three parameters mentioned above. This turning logic is coded separately for the two lanes to have more control over the simulation.</p><blockquote id="5d31"><p>This is where the originalImage is used. Rotating an image is considered a destructive transform. This means that every time it is performed, the image loses pixel data. For this reason, it is better to re-transform the original image than to keep transforming an image multiple times. Thus, we rotate the originalImage by rotationAngle and update the image by this modified image, while keeping the originalImage unchanged.</p></blockquote><p id="b6e4">Lastly, if the vehicle is not going to turn, then the first part remains the same as the turning vehicles, and they move straight until they cross the intersection. However, after crossing the intersection, they simply move if there is a sufficient gap to the vehicle ahead, found using the <i>vehiclesNotTurned</i> list. Again, this is decided based on the three parameters mentioned above.</p><p id="7aea">The entire <i>move()</i> function is given below. Note that this function is also a part of the <i>Vehicle</i> class defined above and needs to be indented accordingly.</p>
    <figure id="e166">
        <div>
          <div>
            
            <iframe class="gist-iframe" src="/gist/mihir-m-gandhi/af2f8cf07af7708a309c38f519ceb2c2.js" allowfullscreen="" frameborder="0" height="undefined" width="undefined">
          </div>
        </div>
    </figure></iframe></div></div></figure><h2 id="9a13">Creating objects of TrafficSignal class</h2><p id="a920">We need to modify the <i>initialize</i>() function so that the 4 <i>TrafficSignal</i> objects are initialized with random values between the range specified by <i>randomGreenSignalTimerRange</i> if <i>randomGreenSignalTime</i> is set to True.</p><div id="9fdf"><pre>def initialize():
<span class="hljs-keyword">min</span>Time = <span class="hljs-keyword">random</span>GreenSignalTimerRange[<span class="hljs-number">0</span>]
<span class="hljs-keyword">max</span>Time = <span class="hljs-keyword">random</span>GreenSignalTimerRange[<span class="hljs-number">1</span>]
if(<span class="hljs-keyword">random</span>GreenSignalTimer):
    ts1 = TrafficSignal(<span class="hljs-number">0</span>, <span class="hljs-keyword">default</span>Yellow, <span class="hljs-keyword">random</span>.randint(<span class="hljs-keyword">min</span>Time,<span class="hljs-keyword">max</span>Time))
    signals.append(ts1)
    ts2 = TrafficSignal(ts1.yellow+ts1.green, <span class="hljs-keyword">default</span>Yellow, <span class="hljs-keyword">random</span>.randint(<span class="hljs-keyword">min</span>Time,<span class="hljs-keyword">max</span>Time))
    signals.append(ts2)
    ts3 = TrafficSignal(<span class="hljs-keyword">default</span>Red, <span class="hljs-keyword">default</span>Yellow, <span class="hljs-keyword">random</span>.randint(<span class="hljs-keyword">min</span>Time,<span class="hljs-keyword">max</span>Time))
    signals.append(ts3)
    ts4 = TrafficSignal(<span class="hljs-keyword">default</span>Red, <span class="hljs-keyword">default</span>Yellow, <span class="hljs-keyword">random</span>.randint(<span class="hljs-keyword">min</span>Time,<span class="hljs-keyword">max</span>Time))
    signals.append(ts4)
else:
    ts1 = TrafficSignal(<span class="hljs-number">0</span>, <span class="hljs-keyword">default</span>Yellow, <span class="hljs-keyword">default</span>Green[<span class="hljs-number">0</span>])
    signals.append(ts1)
    ts2 = TrafficSignal(ts1.yellow+ts1.green, <span class="hljs-keyword">default</span>Yellow, <span class="hljs-keyword">default</span>Green[<span class="hljs-number">1</span>])
    signals.append(ts2)
    ts3 = TrafficSignal(<span class="hljs-keyword">default</span>Red, <span class="hljs-keyword">default</span>Yellow, <span class="hljs-keyword">default</span>Green[<span class="hljs-number">2</span>])
    signals.append(ts3)
    ts4 = TrafficSignal(<span class="hljs-keyword">default</span>Red, <span class="hljs-keyword">default</span>Yellow, <span class="hljs-keyword">default</span>Green[<span class="hljs-number">3</span>])
    signals.append(ts4)
repeat()</pre></div><h2 id="204c">repeat() function</h2><p id="0b4e">The same applies to the <i>repeat</i>() function as well. The only change is that if <i>randomGreenSignalTimer</i> is set to True, we generate a random number between <i>randomGreenSignalTimerRange</i>[0] and <i>randomGreenSignalTimerRange</i>[1], and set it as the green signal time.</p><div id="8e72"><pre>def repeat():
global currentGreen, currentYellow, nextGreen
while(signals[currentGreen].green&gt;<span class="hljs-number">0</span>):
    updateValues()
    time.sleep(<span class="hljs-number">1</span>)
currentYellow = <span class="hljs-number">1</span>   
for i in range(<span class="hljs-number">0</span>,<span class="hljs-number"

Options

3</span>): for vehicle in vehicles[directionNumbers[currentGreen]][i]: vehicle.stop=defaultStop[directionNumbers[currentGreen]] while(signals[currentGreen].yellow><span class="hljs-number">0</span>):
updateValues() time.sleep(<span class="hljs-number">1</span>) currentYellow = <span class="hljs-number">0</span>
minTime = randomGreenSignalTimerRange[<span class="hljs-number">0</span>] maxTime = randomGreenSignalTimerRange[<span class="hljs-number">1</span>] if(randomGreenSignalTimer): signals[currentGreen].green=random.randint(minTime, maxTime) else: signals[currentGreen].green = defaultGreen[currentGreen] signals[currentGreen].yellow = defaultYellow signals[currentGreen].red = defaultRed currentGreen = nextGreen nextGreen = (currentGreen+<span class="hljs-number">1</span>)<span class="hljs-comment">%noOfSignals</span> signals[nextGreen].red = signals[currentGreen].yellow+signals[currentGreen].green repeat()</pre></div><h2 id="1f88">generateVehicles() function</h2><p id="b24b">The <i>generateVehicles</i>() function is modified as shown below. The vehicle type is set by generating a random number from <i>allowedVehicleTypesList</i>. This list is populated in the <i>Main</i> class below. We define a new variable <i>will_turn</i>, which is initially set to 0. <i>will_turn</i> is then set to 1 with a 40% chance using random numbers. Lastly, in addition to the existing variables, this <i>will_turn</i> variable is also passed in the constructor while creating an object of the <i>Vehicle</i> class.</p><div id="8de5"><pre><span class="hljs-attribute">def</span> generateVehicles(): <span class="hljs-attribute">while</span>(True): <span class="hljs-attribute">vehicle_type</span> = random.choice(allowedVehicleTypesList) <span class="hljs-attribute">lane_number</span> = random.randint(<span class="hljs-number">1</span>,<span class="hljs-number">2</span>) <span class="hljs-attribute">will_turn</span> = <span class="hljs-number">0</span> <span class="hljs-attribute">if</span>(lane_number == <span class="hljs-number">1</span>): <span class="hljs-attribute">temp</span> = random.randint(<span class="hljs-number">0</span>,<span class="hljs-number">99</span>) <span class="hljs-attribute">if</span>(temp<<span class="hljs-number">40</span>): <span class="hljs-attribute">will_turn</span> = <span class="hljs-number">1</span> <span class="hljs-attribute">elif</span>(lane_number == <span class="hljs-number">2</span>): <span class="hljs-attribute">temp</span> = random.randint(<span class="hljs-number">0</span>,<span class="hljs-number">99</span>) <span class="hljs-attribute">if</span>(temp<<span class="hljs-number">40</span>): <span class="hljs-attribute">will_turn</span> = <span class="hljs-number">1</span> <span class="hljs-attribute">temp</span> = random.randint(<span class="hljs-number">0</span>,<span class="hljs-number">99</span>) <span class="hljs-attribute">direction_number</span> = <span class="hljs-number">0</span> <span class="hljs-attribute">dist</span> =<span class="hljs-meta"> [25,50,75,100]</span> <span class="hljs-attribute">if</span>(temp<dist[<span class="hljs-number">0</span>]): <span class="hljs-attribute">direction_number</span> = <span class="hljs-number">0</span> <span class="hljs-attribute">elif</span>(temp<dist[<span class="hljs-number">1</span>]): <span class="hljs-attribute">direction_number</span> = <span class="hljs-number">1</span> <span class="hljs-attribute">elif</span>(temp<dist[<span class="hljs-number">2</span>]): <span class="hljs-attribute">direction_number</span> = <span class="hljs-number">2</span> <span class="hljs-attribute">elif</span>(temp<dist[<span class="hljs-number">3</span>]): <span class="hljs-attribute">direction_number</span> = <span class="hljs-number">3</span> <span class="hljs-attribute">Vehicle</span>(lane_number, vehicleTypes[vehicle_type], direction_number, directionNumbers[direction_number], will_turn) <span class="hljs-attribute">time</span>.sleep(<span class="hljs-number">1</span>)</pre></div><h2 id="726d">Main class</h2><p id="81c7">There is only one small addition here. We just need to populate the <i>allowedVehicleTypesList</i> according to the <i>allowedVehicleTypes</i> dictionary. For this, the following code needs to be added right at the beginning of the Main class, as shown below. The rest of the <i>Main</i> class remains the same.</p><div id="4cc3"><pre>class Main: global allowedVehicleTypesList <span class="hljs-selector-tag">i</span> = <span class="hljs-number">0</span> <span class="hljs-keyword">for</span> vehicleType <span class="hljs-keyword">in</span> allowedVehicleTypes: <span class="hljs-built_in">if</span>(allowedVehicleTypes<span class="hljs-selector-attr">[vehicleType]</span>): allowedVehicleTypesList<span class="hljs-selector-class">.append</span>(i) <span class="hljs-selector-tag">i</span> += <span class="hljs-number">1</span></pre></div><h1 id="a2bc">Running the code</h1><p id="6e5d">Time to see the results. Fire up a cmd/terminal and run the command:</p><div id="5888"><pre>$ <span class="hljs-keyword">python</span> simulation.<span class="hljs-keyword">py</span></pre></div><figure id="01b9"><img src="https://cdn-images-1.readmedium.com/v2/resize:fit:800/1*dhRA3M5L5pH5rmUsqdLueg.png"><figcaption>Snapshot of final simulation output showing vehicles turning</figcaption></figure><figure id="004b"><img src="https://cdn-images-1.readmedium.com/v2/resize:fit:800/1*FwYlT4MUI2OLs4g5FLwhdg.png"><figcaption></figcaption></figure><figure id="320a"><img src="https://cdn-images-1.readmedium.com/v2/resize:fit:800/1*GSJwZxuK8chZmw7QlXNhug.png"><figcaption>Snapshots showing simulation with: (i) Cars only, (ii) Heavy vehicles only (Buses and Trucks)</figcaption></figure><p id="ce86"><b><i>And we are done!</i></b> We have added the three additional features — turning functionality, vehicle type controller, and random green signal timer function — to our simulation. This makes the simulation more representative of the real-life scenarios and gives us more control to customize it, thus serving as a handy tool for data analysis as well as AI or ML applications.</p><p id="7d91"><b>Source code: <a href="https://github.com/mihir-m-gandhi/Traffic-Intersection-Simulation-with-Turns"></a></b><a href="https://github.com/mihir-m-gandhi/Traffic-Intersection-Simulation-with-Turns">https://github.com/mihir-m-gandhi/Traffic-Intersection-Simulation-with-Turns</a></p><p id="fe03">This is the second part in a series of articles:</p><ul><li><a href="https://towardsdatascience.com/traffic-intersection-simulation-using-pygame-689d6bd7687a">Traffic Intersection Simulation using Pygame, Part 1</a></li><li><a href="https://towardsdatascience.com/traffic-intersection-simulation-using-pygame-part-2-9ce512fdb253">Traffic Intersection Simulation using Pygame, Part 2</a></li><li><a href="https://towardsdatascience.com/traffic-intersection-simulation-using-pygame-part-3-98159178ef30">Traffic Intersection Simulation using Pygame, Part 3</a></li></ul><p id="2ec7">This simulation was developed as part of a research project titled ‘Smart Control of Traffic Lights using Artificial Intelligence’. Check out its demonstration video <a href="https://youtu.be/OssY5pzOyo0">here</a>. This research work was presented at IEEE International Conference on Recent Advances and Innovations in Engineering (ICRAIE) 2020 and published in IEEE Xplore. Read the paper here.</p><p id="50b4"><i>Thanks for reading! I hope this article was helpful. If you have any doubts or need further clarification, feel free to reach out to me on <a href="https://www.linkedin.com/in/mihir-gandhi-0706/">LinkedIn</a>.</i></p></article></body>

The Medium Quick Reference Guide®

Table of Contents

We’re excited to announce the arrival of this new book. Click on the Amazon ad at the bottom of the page.

Image courtesy of the author.

Foreword by Dr. Mehmet Yildiz (ILLUMINATION Publications)

Introduction

1: What is Medium

2: Navigating Your Homepage

3: Getting to Know Your Homepage

4: Exploring the Profile Picture Drop-down

5: Searching for Stories from Your Homepage

6: Navigating Your Story Homepage

7: Writing/Editing Great Stories

8: Jazzing Your Stories with Images & Embeds

9: Publishing Great Stories

10: Managing Your Stories

11. Tuning Your Account Settings & Preferences

12: Getting More Email Subscribers

13: Using the Help Center to Get Answers

14: Gaining Your First 100 Followers

15: Building a Following with Publications

16: Earning Money at Medium

17: Continuing to Gain Followers

18: Boosting Your Brand with a Newsletter

Appendix A: Locate Commands Fast

Appendix B: Top 70 Most Popular Topics

Appendix C: Top 50 Publications

Appendix D: Keyboard Shortcuts

Glossary

About the Author

You might check my recent interview conducted by Dr Mehmet Yildiz, chief editor of Illumination Integrated Publications, on Medium, introducing me and my book to the writing and reading community.

Entrepreneurship
Freelancing
Freelancers
Medium
Blog
Recommended from ReadMedium