{ "cells": [ { "cell_type": "markdown", "id": "1a063d05", "metadata": {}, "source": [ "# Random roads using prefabs\n", "\n", "It is cool to see that a little processed noise can generate something that looks like roads. But of course, roads are not really random. Instead, they are made of a sequence of 'prefabs', for example, a road between A and B may look like\n", "\n", "$$\n", "\\text{straight, turn left, straight, turn right, straight}\n", "$$\n", "\n", "Let's see how we can create a random road of length $L$ from a pre-determined set of prefabs.\n", "\n", "#### Random apportionment of total length\n", "\n", "Suppose we want to build a road of length $L$ out of $K$ segments. The total number of waypoints $N$ depends on the step size $\\Delta s$:\n", "\n", "$$\n", "N = \\frac{L}{\\Delta s}.\n", "$$\n", "\n", "Let $\\left( p_1, p_2, \\dots, p_K \\right)$ represent the proportion of $N$ that each prefab will be assigned, where $\\sum p_i = 1$. One useful distribution here is the [Dirichlet distribution](https://en.wikipedia.org/wiki/Dirichlet_distribution), which is parametrized by a vector $\\mathbf{\\alpha} = \\left(\\alpha_1, \\alpha_2, \\dots, \\alpha_K \\right)$. The special case where all $\\alpha_i$, the scalar parameter $\\alpha$ is called a *concentration parameter*. Setting the same $\\alpha$ across the entire parameter space makes the distribution symmetric, meaning no prior assumptions are made regarding the proportion of $N$ that will be assigned to each segment. $\\alpha = 1$ leads to what is known as a flat Dirichlet distribution, whereas higher values lead to more dense and evenly distributed $\\left( p_1, p_2, \\dots, p_K \\right)$. On the other hand, keeping $\\alpha \\leq 1$ gives a sparser distribution which can lead to larger variance in apportioned number of waypoints to $\\left( p_1, p_2, \\dots, p_K \\right)$.\n", "\n", "#### Expectation value and variance of Dirichlet distribution\n", "\n", "Suppose we draw our samples for proportion of length from the Dirichlet distribution\n", "\n", "$$\n", "(p_1, p_2, \\ldots, p_K) \\sim \\text{Dirichlet}(\\alpha, \\alpha, \\ldots, \\alpha)\n", "$$\n", "\n", "with $\\alpha _{0}=\\sum _{i=1}^{K}\\alpha _{i}$, the mean and variance are then\n", "\n", "$$\n", "\\operatorname {E} [p_{i}]={\\frac {\\alpha _{i}}{\\alpha _{0}}}, \\; \\operatorname {Var} [p_{i}]={\\frac {\\alpha _{i}(\\alpha _{0}-\\alpha _{i})}{\\alpha _{0}^{2}(\\alpha _{0}+1)}}.\n", "$$\n", "\n", "If $\\alpha$ is a scalar, then $\\alpha _{0}= K \\alpha$ and the above simplifies to\n", "\n", "$$\n", "\\operatorname {E} [p_{i}]={\\frac {\\alpha}{K \\alpha}}={\\frac {1}{K}}, \\; \\operatorname {Var} [p_{i}]={\\frac {\\alpha(K \\alpha -\\alpha)}{(K \\alpha)^{2}(K \\alpha +1)}}.\n", "$$\n", "\n", "We see that $\\operatorname {Var} [p_{i}] \\propto \\frac{1}{\\alpha}$ meaning that the variance reduces with increasing $\\alpha$. We can simply scale the proportions\n", "\n", "$$\n", "(N \\cdot p_1, N \\cdot p_2, \\ldots, N \\cdot p_K)\n", "$$\n", "\n", "to get the randomly assigned number of waypoints for each prefab. We now have a distribution which can give randomly assigned lengths to a given list of prefabs, with a parameter to control the degree of randomness. With a large concentration parameter $\\alpha$, the distribution of lengths will be more uniform, with each prefab getting $N \\cdot \\operatorname {E} [p_{i}]={\\frac {N}{K}}$ waypoints assigned to it. Likewise, keeping $\\alpha$ low increases variance and allows for a more random assignment of proportions of waypoints to each prefab segment.\n", "\n", "#### Random angles\n", "\n", "Suppose a turn of a pre-defined arc length $l$ made of $N/K$ waypoints. If one wants to create a random angle, one has to keep in mind that the minimum radius $R_{min}$ depends on the speed of the vehicle and the weather conditions:\n", "\n", "$$\n", "R_{\\text{min,vehicle}} = \\frac{v^2}{g\\mu},\n", "$$\n", "\n", "where\n", "- $v$ is the velocity of the vehicle in $\\text{m/s}$,\n", "- $g$ is the gravitational acceleration (about $9.8$ $\\text{m/s}^{2}$), and\n", "- $\\mu$ is the friction coefficient (about $0.7$ for dry asphalt).\n", "\n", "A regular turn (not a U-turn or roundabout) should also have an lower and upper limit on the angle, say, 30 degrees to 90 degrees for a conservative estimate. In terms of radii, it becomes\n", "\n", "$$\n", "R_{\\text{min}} = \\max\\left(R_{\\text{min,vehicle}}, \\frac{l}{\\pi/2}\\right)\n", "$$\n", "\n", "and\n", "\n", "$$\n", "R_{\\text{max}} = \\frac{l}{\\pi/6}.\n", "$$\n", "\n", "We then sample\n", "\n", "$$\n", "R \\sim \\text{Uniform}\\left(R_{\\text{min}}, R_{\\text{max\\_angle}}\\right)\n", "$$\n", "\n", "and obtain a random radius for a turn of arc length $l$ with limits to ensure the radius is large enough given the velocity of the vehicle. Finally, the curvature profile is related to the radius by\n", "\n", "$$\n", "\\kappa = \\frac{1}{R}\n", "$$\n", "\n", "which means that the curvature profile of a turn is simply a vector $\\mathbf{\\kappa} = (1/R, \\dots, 1/R)$ with a length of $N/K$ waypoints." ] } ], "metadata": { "kernelspec": { "display_name": ".venv", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.12.9" } }, "nbformat": 4, "nbformat_minor": 5 }