|
1 | 1 | ## 3.1 Obstacle |
2 | | -In this section, Obstacle class and Landmark class are implemented. These class are used for locating the obstacles object in the world. The located obstacles can be observed by an sensor model. |
| 2 | +This section explains the obstacle models used by the sensor simulations. The repository provides two modules: |
3 | 3 |
|
4 | | -### 3.1.1 Rectangle obstacle |
5 | | -The obstacle class is implemented as follow. [State class implemented in Chapter 2](/doc/2_vehicle_model/2_vehicle_model.md) is given to the constructor for computing the position and pose of the obstacle. And then, [XYArray class](/doc/2_vehicle_model/2_vehicle_model.md) is also imported in the class for representing the shape as rectangle. |
6 | | - |
7 | | -[obstacle.py](/src/components/obstacle/obstacle.py) |
8 | | -```python |
9 | | -""" |
10 | | -obstacle.py |
11 | | -
|
12 | | -Author: Shisato Yano |
13 | | -""" |
14 | | - |
15 | | -import numpy as np |
16 | | -import sys |
17 | | -from pathlib import Path |
18 | | - |
19 | | -sys.path.append(str(Path(__file__).absolute().parent) + "/../array") |
20 | | -from xy_array import XYArray |
| 4 | +- [obstacle.py](/src/components/obstacle/obstacle.py): Represents one obstacle (static or dynamic). |
| 5 | +- [obstacle_list.py](/src/components/obstacle/obstacle_list.py): Manages multiple obstacles. |
21 | 6 |
|
| 7 | +### 3.1.1 Rectangle Obstacle |
| 8 | +The `Obstacle` class stores its own state and geometric shape. The constructor takes a [State class](/doc/2_vehicle_model/2_vehicle_model.md) instance and shape/motion parameters. |
22 | 9 |
|
| 10 | +```python |
23 | 11 | class Obstacle: |
24 | | - """ |
25 | | - Obstacle's data and logic class |
26 | | - """ |
27 | | - |
28 | 12 | def __init__(self, state, accel_mps2=0.0, yaw_rate_rps=0.0, |
29 | 13 | length_m=2.0, width_m=2.0): |
30 | | - """ |
31 | | - Constructor |
32 | | - state: Obstacle's state object |
33 | | - accel_mps2: acceleration input to move[m/s2] |
34 | | - yaw_rate_rps: yaw rate input to move[rad/s] |
35 | | - length_m: Obstacle's longitudinal size[m] |
36 | | - width_m: Obstacle's half of lateral size[m] |
37 | | - """ |
38 | | - |
39 | 14 | self.state = state |
40 | 15 | self.accel_mps2 = accel_mps2 |
41 | 16 | self.yaw_rate_rps = yaw_rate_rps |
42 | | - |
43 | | - contour = np.array([[length_m, -length_m, -length_m, length_m, length_m], |
44 | | - [width_m, width_m, -width_m, -width_m, width_m]]) |
45 | | - self.array = XYArray(contour) |
| 17 | + self.length_m = length_m |
| 18 | + self.width_m = width_m |
46 | 19 | ``` |
47 | 20 |
|
48 | | -The given arguments, accel_mps2 and yaw_rate_rps are used for making the obstacle moved as a dynamic obstacle. If these values are default 0.0, the obstacle is represented as a static obstacle. Additionally, length_m and width_m are used for setting the size of the obstacle. |
| 21 | +Notes: |
49 | 22 |
|
50 | | -The member methods, update, draw and vertex_xy are implemented. The method, update is used to compute the state including position(x, y) and yaw angle of the obstacle. |
51 | | -```python |
52 | | - def update(self, time_s): |
53 | | - """ |
54 | | - Function to update obstacle's state |
55 | | - time_s: Time interval value[sec] |
56 | | - """ |
57 | | - |
58 | | - self.state.update(self.accel_mps2, self.yaw_rate_rps, time_s) |
59 | | -``` |
| 23 | +- `accel_mps2` and `yaw_rate_rps` control obstacle motion. |
| 24 | +- When both are `0.0`, the obstacle behaves as a static object. |
| 25 | +- `width_m` is treated as half-width in the class contour definition. |
60 | 26 |
|
61 | | -The method, draw is used to visualize the obstacle in the world. The vertexes and lines of obstacle are transformed based on the state and visualized. |
62 | | -```python |
63 | | - def draw(self, axes, elems): |
64 | | - """ |
65 | | - Function to draw obstacle |
66 | | - axes: Axes object of figure |
67 | | - elems: List of plot objects |
68 | | - """ |
69 | | - |
70 | | - x_m = self.state.get_x_m() |
71 | | - y_m = self.state.get_y_m() |
72 | | - yaw_rad = self.state.get_yaw_rad() |
73 | | - |
74 | | - transformed_array = self.array.homogeneous_transformation(x_m, y_m, yaw_rad) |
75 | | - obstacle_plot, = axes.plot(transformed_array.get_x_data(), |
76 | | - transformed_array.get_y_data(), |
77 | | - lw=1.0, color='k', ls='-') |
78 | | - elems.append(obstacle_plot) |
79 | | -``` |
| 27 | +The update function advances obstacle motion using the state model: |
80 | 28 |
|
81 | | -The method, vertex_xy is used to get the vertexes coordinates (x, y) of the obstacle and to generate a point cloud by the sensor models. |
82 | 29 | ```python |
83 | | - def vertex_xy(self): |
84 | | - """ |
85 | | - Function to get obstacle's vertex point coordinates |
86 | | - """ |
87 | | - |
88 | | - x_m = self.state.get_x_m() |
89 | | - y_m = self.state.get_y_m() |
90 | | - yaw_rad = self.state.get_yaw_rad() |
91 | | - |
92 | | - transformed_array = self.array.homogeneous_transformation(x_m, y_m, yaw_rad) |
93 | | - |
94 | | - return transformed_array.get_x_data(), transformed_array.get_y_data() |
| 30 | +def update(self, time_s): |
| 31 | + self.state.update(self.accel_mps2, self.yaw_rate_rps, time_s) |
95 | 32 | ``` |
96 | 33 |
|
97 | | -### 3.1.2 Obstacles list |
98 | | -ObstacleList class is implemented to execute update and draw the data of multiple obstacles sequencially. An object of this list is given to a visualizer object and a sensor model object. |
| 34 | +The draw function transforms the rectangle contour from obstacle coordinates to global coordinates and plots it: |
99 | 35 |
|
100 | | -[obstacle_list.py](/src/components/obstacle/obstacle_list.py) |
101 | 36 | ```python |
102 | | -""" |
103 | | -obstacle_list.py |
| 37 | +def draw(self, axes, elems): |
| 38 | + x_m = self.state.get_x_m() |
| 39 | + y_m = self.state.get_y_m() |
| 40 | + yaw_rad = self.state.get_yaw_rad() |
| 41 | + |
| 42 | + transformed_array = self.array.homogeneous_transformation(x_m, y_m, yaw_rad) |
| 43 | + obstacle_plot, = axes.plot(transformed_array.get_x_data(), |
| 44 | + transformed_array.get_y_data(), |
| 45 | + lw=1.0, color='k', ls='-') |
| 46 | + elems.append(obstacle_plot) |
| 47 | +``` |
104 | 48 |
|
105 | | -Author: Shisato Yano |
106 | | -""" |
| 49 | +The `vertex_xy()` method returns transformed corner coordinates for downstream modules such as LiDAR point-cloud generation. |
107 | 50 |
|
| 51 | +### 3.1.2 Obstacles List |
| 52 | +`ObstacleList` is a small container class for multiple obstacles: |
| 53 | + |
| 54 | +```python |
108 | 55 | class ObstacleList: |
109 | | - """ |
110 | | - Obstacles list class |
111 | | - """ |
112 | | - |
113 | 56 | def __init__(self): |
114 | | - """ |
115 | | - Constructor |
116 | | - """ |
117 | | - |
118 | 57 | self.list = [] |
119 | | - |
| 58 | + |
120 | 59 | def add_obstacle(self, obstacle): |
121 | | - """ |
122 | | - Function to add obstacle object into list |
123 | | - obstacle: Obstacle class's object |
124 | | - """ |
125 | | - |
126 | 60 | self.list.append(obstacle) |
127 | | - |
128 | | - def update(self, times_s): |
129 | | - """ |
130 | | - Function to update each obstacle's state in list |
131 | | - time_s: Time interval value[sec] |
132 | | - """ |
133 | | - |
134 | | - for obst in self.list: obst.update(times_s) |
135 | | - |
136 | | - def draw(self, axes, elems): |
137 | | - """ |
138 | | - Function to draw each obstacles in list |
139 | | - axes: Axes object of figure |
140 | | - elems: List of plot objects |
141 | | - """ |
142 | | - |
143 | | - for obst in self.list: obst.draw(axes, elems) |
144 | | - |
145 | | - def get_list(self): |
146 | | - """ |
147 | | - Function to get obstacle's list |
148 | | - """ |
149 | | - |
150 | | - return self.list |
151 | 61 | ``` |
152 | 62 |
|
153 | | -This class has a list to store each obstacle objects as a member. Each obstacles can be stored by using a method, add_obstacle. The data of the obstacles can be updated and drawn sequencially by using update and draw methods. Finally, get_list method is implemented to get the list for a sensor model object. |
| 63 | +It also provides batch `update()` and `draw()` calls, plus `get_list()` for other modules (for example, LiDAR). |
154 | 64 |
|
155 | 65 | ### 3.1.3 Visualization |
156 | | -A sample program for visualizing some obstacles in the simulation world is implemented as follow. A static obstacle and two dynamic obstacles can be drawn by giving an acceleration input and a yaw rate input. |
| 66 | +A sample script for obstacle visualization is provided: |
157 | 67 |
|
158 | | -[visualize_obstacle.py](/doc/3_sensor_models/visualize_obstacle.py) |
159 | | -```python |
160 | | -""" |
161 | | -visualize_obstacle.py |
162 | | -
|
163 | | -Author: Shisato Yano |
164 | | -""" |
165 | | - |
166 | | -# import path setting |
167 | | -import numpy as np |
168 | | -import sys |
169 | | -from pathlib import Path |
170 | | - |
171 | | -abs_dir_path = str(Path(__file__).absolute().parent) |
172 | | -relative_path = "/../../src/components/" |
173 | | - |
174 | | -sys.path.append(abs_dir_path + relative_path + "visualization") |
175 | | -sys.path.append(abs_dir_path + relative_path + "state") |
176 | | -sys.path.append(abs_dir_path + relative_path + "vehicle") |
177 | | -sys.path.append(abs_dir_path + relative_path + "obstacle") |
178 | | - |
179 | | - |
180 | | -# import component modules |
181 | | -from global_xy_visualizer import GlobalXYVisualizer |
182 | | -from min_max import MinMax |
183 | | -from time_parameters import TimeParameters |
184 | | -from vehicle_specification import VehicleSpecification |
185 | | -from state import State |
186 | | -from four_wheels_vehicle import FourWheelsVehicle |
187 | | -from obstacle import Obstacle |
188 | | -from obstacle_list import ObstacleList |
189 | | - |
190 | | - |
191 | | -# flag to show plot figure |
192 | | -# when executed as unit test, this flag is set as false |
193 | | -show_plot = True |
194 | | - |
195 | | - |
196 | | -def main(): |
197 | | - """ |
198 | | - Main process function |
199 | | - """ |
200 | | - |
201 | | - # set simulation parameters |
202 | | - x_lim, y_lim = MinMax(-30, 30), MinMax(-30, 30) |
203 | | - vis = GlobalXYVisualizer(x_lim, y_lim, TimeParameters(span_sec=20)) |
204 | | - |
205 | | - # create obstacle instances |
206 | | - obst_list = ObstacleList() |
207 | | - obst1 = Obstacle(State(x_m=-5.0, y_m=15.0, speed_mps=1.0), yaw_rate_rps=np.deg2rad(10), width_m=1.0) |
208 | | - obst_list.add_obstacle(obst1) |
209 | | - obst2 = Obstacle(State(x_m=-15.0, y_m=-15.0), length_m=10.0, width_m=5.0) |
210 | | - obst_list.add_obstacle(obst2) |
211 | | - obst3 = Obstacle(State(x_m=20.0), yaw_rate_rps=np.deg2rad(15)) |
212 | | - obst_list.add_obstacle(obst3) |
213 | | - vis.add_object(obst_list) |
214 | | - |
215 | | - # create vehicle instance |
216 | | - spec = VehicleSpecification(area_size=30.0) # spec instance |
217 | | - vehicle = FourWheelsVehicle(State(color=spec.color), spec) # set state, spec as arguments |
218 | | - vis.add_object(vehicle) |
219 | | - |
220 | | - # plot figure is not shown when executed as unit test |
221 | | - if not show_plot: vis.not_show_plot() |
222 | | - |
223 | | - # show plot figure |
224 | | - vis.draw() |
225 | | - |
226 | | - |
227 | | -# execute main process |
228 | | -if __name__ == "__main__": |
229 | | - main() |
230 | | -``` |
| 68 | +- [visualize_obstacle.py](/doc/3_sensor_models/visualize_obstacle.py) |
| 69 | + |
| 70 | +This script creates one static obstacle and two dynamic obstacles, then draws them in the simulation world together with a vehicle model. |
| 71 | + |
| 72 | +The output example is: |
231 | 73 |
|
232 | | -The following simulation can be visualized by executing the above program. |
233 | | - |
| 74 | + |
0 commit comments