mirror of
https://github.com/pim-n/road-gen.git
synced 2026-02-03 09:23:09 +01:00
Compare commits
8 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 36f4abb425 | |||
| 784f22bd63 | |||
| 3b7c37f7c4 | |||
| 8a1fad0b94 | |||
| 0a6aa4a7fc | |||
| 2fde08cf21 | |||
| 79cda5f094 | |||
| 46fe5d559d |
@ -70,4 +70,6 @@ You can reproduce results by adding a seed with the `--seed` flag.
|
||||
|
||||
## Other
|
||||
|
||||
For more info, see `road-gen --help` or `road-gen random --help`.
|
||||
For more info, see `road-gen --help` or `road-gen random --help`.
|
||||
|
||||
There are some Jupyter notebooks explaining [roads as planar curves](docs/planar_curve.ipynb), as well as the actual implementation of [random segmented roads](docs/prefab_roads.ipynb) and [random roads from noise](docs/random_roads.ipynb).
|
||||
203
docs/planar_curve.ipynb
Normal file
203
docs/planar_curve.ipynb
Normal file
File diff suppressed because one or more lines are too long
118
docs/prefab_roads.ipynb
Normal file
118
docs/prefab_roads.ipynb
Normal file
@ -0,0 +1,118 @@
|
||||
{
|
||||
"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
|
||||
}
|
||||
266
docs/random_roads.ipynb
Normal file
266
docs/random_roads.ipynb
Normal file
File diff suppressed because one or more lines are too long
@ -47,8 +47,9 @@ class SegmentedRoadGenerator(BaseRoadGenerator):
|
||||
Returns:
|
||||
Tuple[np.ndarray, np.ndarray]: x and y coordinates of the waypoints describing the random road.
|
||||
"""
|
||||
if not all(segment in prefabs.PREFABS.keys() for segment in segments):
|
||||
raise ValueError(f"Invalid segment type provided. Available choices: {prefabs.SEGMENTS.keys()}")
|
||||
existing_prefabs = prefabs.PREFABS.keys()
|
||||
if not all(segment in existing_prefabs for segment in segments):
|
||||
raise ValueError(f"Invalid segment type provided. Available choices: {existing_prefabs}")
|
||||
|
||||
self.segments = segments
|
||||
self.alpha = alpha
|
||||
|
||||
Reference in New Issue
Block a user