{"id":541,"date":"2019-03-21T16:32:59","date_gmt":"2019-03-21T16:32:59","guid":{"rendered":"https:\/\/tutorials.retopall.com\/?p=541"},"modified":"2019-03-30T19:44:10","modified_gmt":"2019-03-30T19:44:10","slug":"self-driving-cars-3d-simulation","status":"publish","type":"post","link":"https:\/\/tutorials.retopall.com\/index.php\/2019\/03\/21\/self-driving-cars-3d-simulation\/","title":{"rendered":"Self Driving Cars 3D Simulation"},"content":{"rendered":"\n<p>In this post you will learn how I have created this Self Driving Simulation with interesting features and innovative ideas that will help you to create your own <a href=\"https:\/\/tutorials.retopall.com\/index.php\/2019\/03\/01\/autonomous-driving-simulation\/\">autonomous car.<\/a><\/p>\n\n\n\n<figure class=\"wp-block-embed-youtube wp-block-embed is-type-video is-provider-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio\"><div class=\"wp-block-embed__wrapper\">\n<iframe loading=\"lazy\" width=\"860\" height=\"484\" src=\"https:\/\/www.youtube.com\/embed\/lZW97USRtdU?feature=oembed\" frameborder=\"0\" allow=\"accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen><\/iframe>\n<\/div><\/figure>\n\n\n\n<p>Apart from the effects of the simulation, this autonomous simulation has a lot of complex algorithms and neural networks behind it.<\/p>\n\n\n\n<p>It&#8217;s developed in C# and Unity 3D and has some keys ideas to make this work. You can also learn some of the basic ideas and create a simple Self Driving Simulation in 3D <a href=\"https:\/\/tutorials.retopall.com\/index.php\/2019\/03\/01\/autonomous-driving-simulation\/\">here<\/a>.<\/p>\n\n\n\n<p>This are the most important key ideas for creating the project:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>Track System <br><\/li><li>Car Sensors  <\/li><li>Neural Network <\/li><li>Output movements (acceleration and rotation)<\/li><li>Training: back-propagation and genetic algorithm<\/li><li>Car DNA and JSON importer<\/li><li>Environment and camera<\/li><\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">TRACK SYSTEM<\/h2>\n\n\n\n<p>The track of the demo is made in Blender with bezier curves. In Unity 3D is a mesh that has a collider component.<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter is-resized\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/tutorials.retopall.com\/wp-content\/uploads\/2019\/03\/Track3-1024x350.png\" alt=\"\" class=\"wp-image-564\" width=\"685\" height=\"234\" srcset=\"https:\/\/tutorials.retopall.com\/wp-content\/uploads\/2019\/03\/Track3-1024x350.png 1024w, https:\/\/tutorials.retopall.com\/wp-content\/uploads\/2019\/03\/Track3-300x103.png 300w, https:\/\/tutorials.retopall.com\/wp-content\/uploads\/2019\/03\/Track3-768x263.png 768w, https:\/\/tutorials.retopall.com\/wp-content\/uploads\/2019\/03\/Track3.png 1568w\" sizes=\"auto, (max-width: 685px) 100vw, 685px\" \/><\/figure><\/div>\n\n\n\n<p>When the track is imported from Unity, some track points are added in game. These points will be in charge of localizing each car. They will be in the entire track.<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter is-resized\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/tutorials.retopall.com\/wp-content\/uploads\/2019\/03\/TrackSystem.png\" alt=\"\" class=\"wp-image-552\" width=\"356\" height=\"259\" srcset=\"https:\/\/tutorials.retopall.com\/wp-content\/uploads\/2019\/03\/TrackSystem.png 540w, https:\/\/tutorials.retopall.com\/wp-content\/uploads\/2019\/03\/TrackSystem-300x218.png 300w\" sizes=\"auto, (max-width: 356px) 100vw, 356px\" \/><\/figure><\/div>\n\n\n\n<p>Now we will understand how a car is tracked:<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">TRILATERATION<\/h4>\n\n\n\n<p>The track systems is similar to a GPS localization and will help to create navigation systems as a new feature of the application.<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>We take the initial trackpoint where the car has been spawned. In this case denoted with the colour purple. With the next two points we will be able to trilaterate the position and calculate the point where the three points are with the same distance (center of a circunference).<\/li><li>This centers will be calculated at the start of the simulation with  the track points. <\/li><\/ul>\n\n\n\n<pre class=\"wp-block-code\"><code>float v1 = x1 * x1 + y1 * y1;\nfloat v2 = x2 * x2 + y2 * y2;\nfloat v3 = x3 * x3 + y3 * y3;\n        \n\nfloat a = x1 * (y2 - y3) - y1 * (x2 - x3) + x2 * y3 - x3 * y2; ;\nfloat b = v1 * (y3 - y2) + v2 * (y1 - y3) + v3 * (y2 - y1);\nfloat c = v1 * (x2 - x3) + v2 * (x3 - x1) + v3 * (x1 - x2);\n\n\n\nfloat xCenter= -b\/(2f*a);\nfloat yCenter = -c \/ (2f    * a);<\/code><\/pre>\n\n\n\n<p>Where x and y are the positions of the track points selected.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">INTERSECTION<\/h4>\n\n\n\n<p>When all the center points have been calculated, on each update of the simulation we will calculate the intersection point of the line that joins the car and the center with the line of the current track point and the next point.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>  public Vector2 intersection(float x1, float y1, float x2, float y2, float x3, float y3, float x4, float y4)\n    {\n        float pxN = (x1 * y2 - y1 * x2) * (x3 - x4) - (x1 - x2) * (x3 * y4 - y3 * x4);\n        float pyN = (x1 * y2 - y1 * x2) * (y3 - y4) - (y1 - y2) * (x3 * y4 - y3 * x4);\n        float pD = (x1-x2)*(y3-y4)-(y1-y2)*(x3-x4);\n        return new Vector2(pxN \/ pD, pyN \/ pD);\n    }<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"mce_39\">DISTANCE TRAVELLED<\/h4>\n\n\n\n<p>With the intersection calculated, the initial  and current track point, we will calculate the distance.<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter is-resized\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/tutorials.retopall.com\/wp-content\/uploads\/2019\/03\/Track2.png\" alt=\"\" class=\"wp-image-563\" width=\"375\" height=\"272\" srcset=\"https:\/\/tutorials.retopall.com\/wp-content\/uploads\/2019\/03\/Track2.png 540w, https:\/\/tutorials.retopall.com\/wp-content\/uploads\/2019\/03\/Track2-300x218.png 300w\" sizes=\"auto, (max-width: 375px) 100vw, 375px\" \/><\/figure><\/div>\n\n\n\n<p>The distance in the image will be the red path.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"mce_63\">SENSORS<\/h2>\n\n\n\n<p>Each car will have some back and front sensors that will be the equivalent of the real LiDAR sensors. Each sensor will raycast the distance to the first object that could be a track or another car.<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter is-resized\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/tutorials.retopall.com\/wp-content\/uploads\/2019\/03\/Sensors-e1553182670318-1024x481.png\" alt=\"\" class=\"wp-image-565\" width=\"423\" height=\"199\" srcset=\"https:\/\/tutorials.retopall.com\/wp-content\/uploads\/2019\/03\/Sensors-e1553182670318-1024x481.png 1024w, https:\/\/tutorials.retopall.com\/wp-content\/uploads\/2019\/03\/Sensors-e1553182670318-300x141.png 300w, https:\/\/tutorials.retopall.com\/wp-content\/uploads\/2019\/03\/Sensors-e1553182670318-768x361.png 768w, https:\/\/tutorials.retopall.com\/wp-content\/uploads\/2019\/03\/Sensors-e1553182670318.png 1154w\" sizes=\"auto, (max-width: 423px) 100vw, 423px\" \/><\/figure><\/div>\n\n\n\n<p>The output of the sensor will be the max distance of it divided by the collision point distance from the car. The output will be a value from [0-1]. If the sensor haven&#8217;t detected any object it will return 1.<\/p>\n\n\n\n<p>This are the car sensors parameters in the editor:<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter is-resized\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/tutorials.retopall.com\/wp-content\/uploads\/2019\/03\/Screenshot-36.png\" alt=\"\" class=\"wp-image-572\" width=\"436\" height=\"422\" srcset=\"https:\/\/tutorials.retopall.com\/wp-content\/uploads\/2019\/03\/Screenshot-36.png 512w, https:\/\/tutorials.retopall.com\/wp-content\/uploads\/2019\/03\/Screenshot-36-300x291.png 300w\" sizes=\"auto, (max-width: 436px) 100vw, 436px\" \/><\/figure><\/div>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"mce_64\">NEURAL NETWORK<\/h2>\n\n\n\n<p>Each car will have a <a href=\"https:\/\/tutorials.retopall.com\/index.php\/2019\/03\/01\/feed-forward-neural-network\/\">Feed-Forward Neural Network<\/a>. This network will have a lot of parameters to edit such as the architecture or the initialization range.<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter is-resized\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/tutorials.retopall.com\/wp-content\/uploads\/2019\/03\/nn-918x1024.jpg\" alt=\"\" class=\"wp-image-574\" width=\"397\" height=\"443\" srcset=\"https:\/\/tutorials.retopall.com\/wp-content\/uploads\/2019\/03\/nn-918x1024.jpg 918w, https:\/\/tutorials.retopall.com\/wp-content\/uploads\/2019\/03\/nn-269x300.jpg 269w, https:\/\/tutorials.retopall.com\/wp-content\/uploads\/2019\/03\/nn-768x857.jpg 768w, https:\/\/tutorials.retopall.com\/wp-content\/uploads\/2019\/03\/nn.jpg 1811w\" sizes=\"auto, (max-width: 397px) 100vw, 397px\" \/><\/figure><\/div>\n\n\n\n<p>This architecture is similar to the neural network of a car. It will have as input the sensor data. Each sensor will have one neuron value if it only detects the track. However if the simulation also detect car collisions, the input data of a sensor will be two for each. The output will be always 2 because of the acceleration and rotation of each car. The hidden layers will vary and will be able to be customized by the user.<\/p>\n\n\n\n<p>The architecture of the hidden layers can be edited:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>[Header(\"Architecture Network\")]\npublic int[] hiddenArchitecture;<\/code><\/pre>\n\n\n\n<p>Also the activation function can be selected from the sigmoid to the hyperbolic tanh and RELU:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>[Header(\"Activation\")]\npublic Activation activationFunction = Activation.Sigmoid;<\/code><\/pre>\n\n\n\n<p>The values of the weights, bias, neurons and error will be stored in different array:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>  \/\/Arrays\n    private List&lt;float[]> neurons;\n    private List&lt;float[,]> weights;\n    private List&lt;float[]> bias;\n    private List&lt;float[]> deltas;\n    private List&lt;float[,]> gradient;\n    private List&lt;float[,]>previousVariation;\n   \n<\/code><\/pre>\n\n\n\n<p>\n\nThe Neural Network class will have the feed-forward update method that will be charge of calculating the outputs with the input data and the weights values.\n\n<\/p>\n\n\n\n<p>This is the feed-forward algorithm implemented in code:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>for (int i = 0; i &lt; neurons[0].Length; i++)\n        {\n\n            neurons[0][i] = inputs[i];\n        }\n        for (int i = 0; i &lt; getLayers() - 1; i++)\n        {\n            float[,] weightsLayer = weights[i];\n            float[] layerNeurons = neurons[i];\n            float[] layerNextNeurons = neurons[i + 1];\n            for (int j = 0; j &lt; layerNextNeurons.Length; j++)\n            {\n                float sum = 0;\n                for (int k = 0; k &lt; layerNeurons.Length; k++)\n                {\n                    sum += (weightsLayer[k, j] * layerNeurons[k]+bias[i][k]);\n                }\n                layerNextNeurons[j] = applyActivationFunction(sum);\n            }\n        }<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"mce_74\">CAR MOVEMENT<\/h2>\n\n\n\n<p>Each car depending on the outputs will accelerate and deccelerate and also steer. Each car will be able to move in every direction and with different speeds. Also cars will have a rigid body to trigger the collisions with other objects ingame.<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter is-resized\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/tutorials.retopall.com\/wp-content\/uploads\/2019\/03\/Rotation.png\" alt=\"\" class=\"wp-image-578\" width=\"230\" height=\"277\" srcset=\"https:\/\/tutorials.retopall.com\/wp-content\/uploads\/2019\/03\/Rotation.png 663w, https:\/\/tutorials.retopall.com\/wp-content\/uploads\/2019\/03\/Rotation-249x300.png 249w\" sizes=\"auto, (max-width: 230px) 100vw, 230px\" \/><\/figure><\/div>\n\n\n\n<p>Depending on the values from [0-1] of the output layer we will need to manipulate them to get right and left rotations and also have gradual speeds. The simulation also helps the cars to have a speed limit.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/Rotation\n            float rotation = outputs[0] * 2 - 1;\n          \n            transform.Rotate(new Vector3(0, (netConstantRotation * rotation)*Time.deltaTime, 0));\n\n            \/\/Acceleration\n            if (applyAcceleration)\n            {\n                float accelerate = outputs[1] * 2 - 1;\n                if ((speed) >= maxSpeed)\n                {\n                    if (accelerate >= 0)\n                    {\n                        accelerate = 0;\n                    }\n                }\n                else if ((speed) &lt;= minSpeed)\n                {\n                    if (accelerate &lt;= 0)\n                    {\n                        accelerate = 0;\n                    }\n                }\n                acceleration += netConstantAcceleration * accelerate;\n\n            }<\/code><\/pre>\n\n\n\n<p>Each car will have two different modes. The autonomous mode where the movements will be predicted by the neural network or the manual mode. In this mode the car will be steered by the WASD control of the keyboard. This will help the car to learn of the movements of the car. We will be seeing this in the Supervised Learning.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">LEARNING ALGORITHMS<\/h2>\n\n\n\n<h4 class=\"wp-block-heading\">ARTIFICIAL INTELLIGENCE<\/h4>\n\n\n\n<p>This is the most important part. When the neural network is initialized it will be completely random and  the weights will need to be modified to get nice movements of the car and prevent the car from colliding.<\/p>\n\n\n\n<p>There are different of <a href=\"https:\/\/tutorials.retopall.com\/index.php\/2019\/02\/17\/neural-networks\/\">artificial intelligence learning algorithms<\/a>. In this simulation the Supervised Learning and the Reinforcment Learning are implemented.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">REINFORCEMENT LEARNING &#8211; GENETIC ALGORITHM<\/h4>\n\n\n\n<p>One strategy for the car to learn  is to use the Evolution Law of Darwin. You can get a deep explanation of this in this <a href=\"https:\/\/tutorials.retopall.com\/index.php\/2019\/03\/01\/genetic-algorithm\/\">post of Genetic Algorithm.<\/a> The overall idea is to get better individuals with different methods. The weights in this type or learning are called DNAs. This DNA will have all the important information of the car (the neural network learnable parameters). <\/p>\n\n\n\n<p>In this image you can see the steps of the Genetic Algorithms to create new child cars from the parents (best cars):<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter is-resized\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/tutorials.retopall.com\/wp-content\/uploads\/2019\/03\/GeneticAlgorithm-1-1024x374.png\" alt=\"\" class=\"wp-image-358\" width=\"443\" height=\"161\" srcset=\"https:\/\/tutorials.retopall.com\/wp-content\/uploads\/2019\/03\/GeneticAlgorithm-1-1024x374.png 1024w, https:\/\/tutorials.retopall.com\/wp-content\/uploads\/2019\/03\/GeneticAlgorithm-1-300x109.png 300w, https:\/\/tutorials.retopall.com\/wp-content\/uploads\/2019\/03\/GeneticAlgorithm-1-768x280.png 768w, https:\/\/tutorials.retopall.com\/wp-content\/uploads\/2019\/03\/GeneticAlgorithm-1.png 1403w\" sizes=\"auto, (max-width: 443px) 100vw, 443px\" \/><\/figure><\/div>\n\n\n\n<p>The best cars must be selected with the accuracy and the diversity of each car. The accuracy will be proportional to the  distance travelled calculated in the track system of the car. With the accuracy we will calculate the fitness of each car that will help us to calculate the best cars.<\/p>\n\n\n\n<p>Then a DNA some operation will be executed to create new childs that share DNA of their parents and also have little mutation changes.<\/p>\n\n\n\n<p>Here you can change the code of the selection of the cars:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>  GameObject[] highestCars = new GameObject[selectedCount];\n        if (controller.cars.Count > 0)\n        {\n            for (int a = 0; a &lt; selectedCount; a++)\n            {\n                \/\/Get highest fitness of the cars that are not selected\n\n                GameObject carMaxFitness = null;\n\n                for (int i = 0; i &lt; controller.cars.Count; i++)\n                {\n                    if (!controller.cars[i].GetComponent&lt;CarController>().selected)\n                    {\n                        if (carMaxFitness != null)\n                        {\n                            \/\/If a car has better fitness swap and set selected\n                            if (controller.cars[i].GetComponent&lt;CarController>().getFitness() > carMaxFitness.GetComponent&lt;CarController>().getFitness())\n                            {\n                                carMaxFitness.GetComponent&lt;CarController>().selected = false;\n\n                                controller.cars[i].GetComponent&lt;CarController>().selected = true;\n                                carMaxFitness = controller.cars[i];\n                            }\n                        }\n                        else\n                        {\n                            controller.cars[i].GetComponent&lt;CarController>().selected = true;\n                            carMaxFitness = controller.cars[i];\n\n                        }\n\n                    }\n                }\n\n                highestCars[a] = carMaxFitness;\n\n            }\n\n\n\n            for (int j = 0; j &lt; highestCars.Length; j++) {\n                selectedCars[j] = highestCars[j];\n               \n\n            }\n           \n\n            for (int i = 0; i &lt; controller.cars.Count; i++)\n            {\n\n\n                if (!controller.cars[i].GetComponent&lt;CarController>().selected &amp;&amp; !controller.cars[i].activeSelf)\n                {\n                    Destroy(controller.cars[i]);\n                    controller.cars.Remove(controller.cars[i]);\n\n                }\n            }\n\n\n            for (int i = 0; i &lt; controller.cars.Count; i++)\n            {\n                controller.cars[i].GetComponent&lt;CarController>().selected = false;\n\n            }\n        }<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\">SUPERVISED LEARNING &#8211; BACK-PROPAGATION<\/h4>\n\n\n\n<p>This is another way to learn. In this case with <a href=\"https:\/\/tutorials.retopall.com\/index.php\/2019\/03\/01\/feed-forward-neural-network\/\">gradient descent algorithms<\/a>. This is a much complex learning because it will try to learn with the movements of a human drived car. Because the Gradient Descent is a multidimensional problem, this learning won&#8217;t give  us the assurance that it will give always nice trainings. It will also depend on the error we made with the control of the car.<\/p>\n\n\n\n<p>The idea of the back-propagation algorithm is to edit the weights of the neural network to decrease the general error of the output data of the network.<\/p>\n\n\n\n<p>This error will be calculated with the movements of the human controlled car. Then we will execute the Gradient Descent Algorithm to try to decrease this error.<\/p>\n\n\n\n<p>Here you can see the calculation of the error signal:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/Output Layer error signal\n        float[] outputs = getOutputs();\n        for(int i = 0; i &lt; outputs.Length; i++)\n        {\n            float delta = -(desired[i] - outputs[i])*applyDerivativeActivationFunction(outputs[i]);\n            deltas[getLayers() - 1][i] = delta;\n        }\n        \/\/Hidden layers error signal\n        for (int i = getLayers() - 2; i >= 0; i--)\n        {\n            for (int j = 0; j &lt; neurons[i].Length; j++)\n            {\n                float sumDelta = 0;\n                for (int k = 0; k &lt; neurons[i + 1].Length; k++)\n                {\n                    sumDelta += deltas[i + 1][k] * weights[i][j,k];\n                }\n                float delta = sumDelta * applyDerivativeActivationFunction(neurons[i][j]);\n                deltas[i][j] = delta;           \n            }\n        }\n        \/\/Calculate gradient with this error signals.\n        calcGradients();<\/code><\/pre>\n\n\n\n<p>The adjustment of the weights of the neural network with this error signal is implemented here:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code> public void adjustWeights()\n    {\n    \n        \/\/Adjust weights and biases\n        for (int i = 0; i &lt; weights.Count ; i++)\n        {\n            for (int j = 0; j &lt; neurons[i + 1].Length; j++)\n            {\n                \/\/bias[i][j] -= biasLearningRate * deltas[i + 1][j];\n\n                for (int k = 0; k &lt; neurons[i].Length; k++)\n                {\n                    float variation = weightLearningRate * gradient[i][k, j];\n                    weights[i][k, j] -=variation;\n\n                }\n            }\n        }\n        \/\/Reset array of previous gradients\n        gradient = createGradientArray();\n    }<\/code><\/pre>\n\n\n\n<p>To improve the performance of this algorithms, I have implemented some optimization algorithms: minibatch gradient descent and momentum.<\/p>\n\n\n\n<p>To get better results with this algorithm, the initialization  of the weights and how are they has a lot of importance for the movement to a local minimum of the Gradient Descent. It&#8217;s important firstly to get cars that works well in the track with the Genetic Algorithm learning and then get accurate results of the movements with the backpropagation.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"mce_20\">DNA AND JSON LOADER<\/h2>\n\n\n\n<p>The DNA contains all the weight data of the neural network. This DNA can be written to a JSON file to analyze this weights and also the accuracy of the cars and other variables. Also it will help to use a DNA to create the cars in another simulation.<\/p>\n\n\n\n<p>In this fragment of code you can see how to import and export the DNA:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code> public void exportJson(DNA dna)\n    {   \n\n        string s = JsonUtility.ToJson(dna);\n        Debug.Log(s);\n       using (StreamWriter streamWriter = File.CreateText(Path.Combine(Application.persistentDataPath, fileName)))\n        {\n            streamWriter.Write(s);\n        }\n    }\n    public DNA importJson()\n    {\n        using (StreamReader streamReader = File.OpenText(Path.Combine(Application.persistentDataPath, fileName)))\n        {\n            string jsonString = streamReader.ReadToEnd();\n            return JsonUtility.FromJson&lt;DNA>(jsonString);\n        }\n    }<\/code><\/pre>\n\n\n\n<p>View of DNA in chart:<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter is-resized\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/tutorials.retopall.com\/wp-content\/uploads\/2019\/03\/Screenshot-38.png\" alt=\"\" class=\"wp-image-589\" width=\"413\" height=\"219\" srcset=\"https:\/\/tutorials.retopall.com\/wp-content\/uploads\/2019\/03\/Screenshot-38.png 460w, https:\/\/tutorials.retopall.com\/wp-content\/uploads\/2019\/03\/Screenshot-38-300x159.png 300w\" sizes=\"auto, (max-width: 413px) 100vw, 413px\" \/><figcaption>DNA<\/figcaption><\/figure><\/div>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"mce_19\">ENVIRONMENT AND CAMERA<\/h2>\n\n\n\n<p>The scene has different game objects apart from the cars: the track and the camera as the main objects. <\/p>\n\n\n\n<p>For the visual effects, the simulation includes glow effects, post proccessing, lighting and shaders.<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter is-resized\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/tutorials.retopall.com\/wp-content\/uploads\/2019\/03\/Screenshot-27-1024x576.png\" alt=\"\" class=\"wp-image-581\" width=\"742\" height=\"417\" srcset=\"https:\/\/tutorials.retopall.com\/wp-content\/uploads\/2019\/03\/Screenshot-27-1024x576.png 1024w, https:\/\/tutorials.retopall.com\/wp-content\/uploads\/2019\/03\/Screenshot-27-300x169.png 300w, https:\/\/tutorials.retopall.com\/wp-content\/uploads\/2019\/03\/Screenshot-27-768x432.png 768w, https:\/\/tutorials.retopall.com\/wp-content\/uploads\/2019\/03\/Screenshot-27.png 1920w\" sizes=\"auto, (max-width: 742px) 100vw, 742px\" \/><\/figure><\/div>\n\n\n\n<p> The camera follows the best car. You can turn this functionality off by locking the camera. <\/p>\n\n\n\n<p><strong>INTRUCTIONS FOR DOWNLOAD AND RESEARCH<\/strong><\/p>\n\n\n\n<p>The project will be able to download soon.<\/p>\n\n\n\n<p><strong>KEYS<\/strong><\/p>\n\n\n\n<p><strong>Tab <\/strong>&#8211; Switch from autonomous mode to manual mode<\/p>\n\n\n\n<p><strong>R\/T<\/strong> manage lighting<\/p>\n\n\n\n<p><strong>WASD <\/strong>manual car movement<\/p>\n\n\n\n<p><strong>Shift<\/strong>&#8211; Genetic algorithm generation<\/p>\n\n\n\n<p><strong>Control <\/strong>&#8211; Random generation<\/p>\n\n\n\n<p><strong>C <\/strong>&#8211; Lock\/unlock camera<\/p>\n\n\n\n<p><strong>Z<\/strong>&#8211; Switch car<\/p>\n\n\n\n<p><strong>F<\/strong> &#8211; Save DNA in a JSON file in Appdata<\/p>\n","protected":false},"excerpt":{"rendered":"<p>In this post you will learn how I have created this Self Driving Simulation with interesting features and innovative ideas that will help you to [&#8230;]<\/p>\n","protected":false},"author":1,"featured_media":581,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[9,8,5,89,10,7],"tags":[96,92,57,56,14,95,44,90,93,94],"class_list":["post-541","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-artificial-intelligence","category-c","category-explanation","category-self-driving-cars","category-simulation","category-unity-3d","tag-artificial-intelligence-neural-networks","tag-autonomous-driving","tag-back-propagation","tag-feed-forward","tag-genetic-algorithm","tag-gps","tag-neural-networks","tag-self-driving","tag-track-system","tag-trilateration"],"_links":{"self":[{"href":"https:\/\/tutorials.retopall.com\/index.php\/wp-json\/wp\/v2\/posts\/541","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/tutorials.retopall.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/tutorials.retopall.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/tutorials.retopall.com\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/tutorials.retopall.com\/index.php\/wp-json\/wp\/v2\/comments?post=541"}],"version-history":[{"count":31,"href":"https:\/\/tutorials.retopall.com\/index.php\/wp-json\/wp\/v2\/posts\/541\/revisions"}],"predecessor-version":[{"id":777,"href":"https:\/\/tutorials.retopall.com\/index.php\/wp-json\/wp\/v2\/posts\/541\/revisions\/777"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/tutorials.retopall.com\/index.php\/wp-json\/wp\/v2\/media\/581"}],"wp:attachment":[{"href":"https:\/\/tutorials.retopall.com\/index.php\/wp-json\/wp\/v2\/media?parent=541"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/tutorials.retopall.com\/index.php\/wp-json\/wp\/v2\/categories?post=541"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/tutorials.retopall.com\/index.php\/wp-json\/wp\/v2\/tags?post=541"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}