Road Signage
Description
Road signage is considered an “actor” in Quanser Interactive Labs Open Worlds. The road signage library controls the road signage available to be placed in the QLabs environment. Road signage can be spawned anywhere in the Open Worlds.
See the Road Signage Tutorial to get a better understanding of using road signage in Quanser Interactive Labs.
Table of Contents
Important
All of the office objects have the same methods and member variables. To simplify this documentation, the methods and member variables are documented only once, see Shared Variables and Methods and the Road Signage Tutorial. No office object has connection points or different configurations.
Roundabout Sign
Library
Constants
- QLabsRoundaboutSign.ID_ROUNDABOUT_SIGN = 10060
Class ID
Stop Sign
Library
Constants
- QLabsStopSign.ID_STOP_SIGN = 10020
Class ID
Yield Sign
Library
Constants
- QLabsYieldSign.ID_YIELD_SIGN = 10070
Class ID
Road Signage Tutorial
Python Tutorial
Raw to download this tutorial: Road Signage Tutorial (.py).
1"""
2Road Signage Library Example
3----------------------------
4
5.. note::
6
7 Make sure you have Quanser Interactive Labs open before running this
8 example. This example is designed to best be run in QCar Cityscape
9 or Cityscape Lite.
10
11"""
12
13# imports to important libraries
14import sys
15import math
16import time
17
18from qvl.qlabs import QuanserInteractiveLabs
19from qvl.free_camera import QLabsFreeCamera
20from qvl.roundabout_sign import QLabsRoundaboutSign
21from qvl.system import QLabsSystem
22from qvl.yield_sign import QLabsYieldSign
23from qvl.stop_sign import QLabsStopSign
24
25# Clears the screen in Windows
26
27def main():
28
29 print("\n\n------------------------------ Communications --------------------------------\n")
30
31 # Creates a server connection with Quanser Interactive Labs and manages
32 # the communications
33 qlabs = QuanserInteractiveLabs()
34
35 # Ensure that QLabs is running on your local machine
36 print("Connecting to QLabs...")
37 if (not qlabs.open("localhost")):
38 print("Unable to connect to QLabs")
39 return
40
41 print("Connected")
42
43 # Use hSystem to set the tutorial title in the upper left of the qlabs window
44 hSystem = QLabsSystem(qlabs)
45 hSystem.set_title_string('Road Signage Tutorial')
46
47 num_destroyed = qlabs.destroy_all_spawned_actors()
48
49 # Switch the camera angle to see where we will be spawning the signs
50 camera0 = QLabsFreeCamera(qlabs)
51 camera0.spawn([-20.14, 29.472, 2.071], [0, 0.203, -0.024])
52 camera0.possess()
53
54
55 # Create two roundabouts in this qlabs instance
56 roundabout = QLabsRoundaboutSign(qlabs)
57 roundabout2 = QLabsRoundaboutSign(qlabs)
58
59 # Spawn the sign using radians and specifying the actorNumber
60 roundabout.spawn_id(0, [-17, 29, 0.0], [0, 0, math.pi], [1, 1, 1], 0, 1)
61 # Spawn the second sign using degrees and allowing the computer to
62 # generate an actorNumber internally
63 roundabout2.spawn_id_degrees(2, [-15, 29, 0.0], [0, 0, 180], [1, 1, 1], 0, 1)
64
65 # Wait to see the output
66 time.sleep(1.5)
67
68 # Destroying the sign we just created
69 roundabout.destroy()
70 time.sleep(1.5)
71
72 # Create two yield signs in this qlabs instance
73 yieldsign = QLabsYieldSign(qlabs)
74 yieldsign2 = QLabsYieldSign(qlabs)
75
76 # Spawn the sign using radians and specifying the actorNumber
77 yieldsign.spawn_id(0, [-17, 31, 0.0], [0, 0, math.pi], [1, 1, 1], 0, 1)
78 # Spawn the second sign using degrees and allowing the computer to
79 # generate an actorNumber internally
80 yieldsign2.spawn_degrees([-15, 31, 0.0], [0, 0, 180], [1, 1, 1], 0, 1)
81
82 # Wait to see the output
83 time.sleep(1.5)
84
85 # Destroying the sign we just created
86 yieldsign.destroy()
87 time.sleep(1.5)
88
89 # Create two stop signs in this qlabs instance
90 stop = QLabsStopSign(qlabs)
91 stop2 = QLabsStopSign(qlabs)
92
93 # Spawn the sign using radians
94 stop.spawn_id(1, [-16, 30, 0.0], [0, 0, math.pi], [1, 1, 1], 0, 1)
95 # Spawn the second sign using degrees and allowing the computer to
96 # generate an actorNumber internally
97 stop2.spawn_degrees([-15, 30, 0.0], [0, 0, 180], [1, 1, 1], 0, 1)
98
99 # Wait to see the output
100 time.sleep(1.5)
101
102 # Destroying the sign we just created
103 stop.destroy()
104 time.sleep(1.5)
105
106 # Destroy the signs one by one
107 roundabout2.destroy()
108 time.sleep(1)
109
110 stop2.destroy()
111 time.sleep(1)
112
113 yieldsign2.destroy()
114 time.sleep(1)
115
116 # Closing qlabs
117 qlabs.close()
118 print('Done!')
119
120
121if __name__ == "__main__":
122 main()
Complete Road Signage Python Tutorial
Raw to download this tutorial: Complete Road Signage Tutorial (.py).
1"""
2Road Signage Library Example
3----------------------------
4
5.. note::
6
7 Make sure you have Quanser Interactive Labs open before running this
8 example. This example is designed to best be run in QCar Cityscape
9 or Cityscape Lite. This is an example of a typical setup script
10 to populate the city with signage for subsequent use in a vehicle
11 simulation.
12
13"""
14
15# imports to important libraries
16import time
17import math
18
19from qvl.qlabs import QuanserInteractiveLabs
20from qvl.free_camera import QLabsFreeCamera
21from qvl.crosswalk import QLabsCrosswalk
22from qvl.roundabout_sign import QLabsRoundaboutSign
23from qvl.system import QLabsSystem
24from qvl.yield_sign import QLabsYieldSign
25from qvl.stop_sign import QLabsStopSign
26from qvl.traffic_cone import QLabsTrafficCone
27from qvl.traffic_light import QLabsTrafficLight
28
29
30# specify if you want the signage on the left or right side of the road.
31right_hand_driving = True
32
33def main(right_hand_driving):
34
35 # creates a server connection with Quanser Interactive Labs and manages the communications
36 qlabs = QuanserInteractiveLabs()
37
38 # trying to connect to QLabs and open the instance we have created - program will end if this fails
39 print("Connecting to QLabs...")
40 if (not qlabs.open("localhost")):
41 print("Unable to connect to QLabs")
42 return
43
44 print("Connected")
45
46 # destroying any spawned actors in our QLabs that currently exist
47 qlabs.destroy_all_spawned_actors()
48
49 # Use hSystem to set the tutorial title on the qlabs display screen
50 hSystem = QLabsSystem(qlabs)
51 hSystem.set_title_string('Complete Road Signage Tutorial')
52
53 spawn_crosswalk(qlabs)
54 spawn_signs(qlabs, right_hand_driving)
55 spawn_traffic_lights(qlabs, right_hand_driving)
56 spawn_cones(qlabs)
57
58 fly_through_animation(qlabs)
59
60 # Closing qlabs
61 qlabs.close()
62 print('Done!')
63
64
65
66
67def spawn_crosswalk(qlabs):
68 # Create a crosswalk in this qlabs instance. Since we don't need
69 # to access the actors again after creating them, we can use a single
70 # class object to spawn all the varieties. We also don't need to use
71 # the waitForConfirmation because we don't need to store the actor ID
72 # for future reference.
73
74 crosswalk = QLabsCrosswalk(qlabs)
75
76 # spawn crosswalk with degrees in config 0
77 crosswalk.spawn_degrees(location=[-12.992, -7.407, 0.005], rotation=[0,0,48], scale=[1,1,1], configuration=0, waitForConfirmation=False)
78
79 # spawn crosswalk with degrees in config 1
80 crosswalk.spawn_degrees(location=[-6.788, 45, 0.00], rotation=[0,0,90], scale=[1,1,1], configuration=1, waitForConfirmation=False)
81
82 # spawn crosswalk with degrees in config 2
83 crosswalk.spawn_degrees(location=[21.733, 3.347, 0.005], rotation=[0,0,0], scale=[1,1,1], configuration=2, waitForConfirmation=False)
84
85 # spawn the last crosswalk with waitForConfirmation=True to confirm everything is flushed from the send buffers
86 crosswalk.spawn_degrees(location=[21.733, 16, 0.005], rotation=[0,0,0], scale=[1,1,1], configuration=2, waitForConfirmation=True)
87
88
89def spawn_signs(qlabs, right_hand_driving):
90 # Like the crosswalks, we don't need to access the actors again after
91 # creating them.
92
93 roundabout_sign = QLabsRoundaboutSign(qlabs)
94 yield_sign = QLabsYieldSign(qlabs)
95 stop_sign = QLabsStopSign(qlabs)
96
97 if (right_hand_driving):
98 stop_sign.spawn_degrees([17.561, 17.677, 0.215], [0,0,90])
99 stop_sign.spawn_degrees([24.3, 1.772, 0.2], [0,0,-90])
100 stop_sign.spawn_degrees([14.746, 6.445, 0.215], [0,0,180])
101
102 roundabout_sign.spawn_degrees([3.551, 40.353, 0.215], [0,0,180])
103 roundabout_sign.spawn_degrees([10.938, 28.824, 0.215], [0,0,-135])
104 roundabout_sign.spawn_degrees([24.289, 32.591, 0.192], [0,0,-90])
105
106 yield_sign.spawn_degrees([-2.169, -12.594, 0.2], [0,0,180])
107 else:
108 stop_sign.spawn_degrees([24.333, 17.677, 0.215], [0,0,90])
109 stop_sign.spawn_degrees([18.03, 1.772, 0.2], [0,0,-90])
110 stop_sign.spawn_degrees([14.746, 13.01, 0.215], [0,0,180])
111
112 roundabout_sign.spawn_degrees([16.647, 28.404, 0.215], [0,0,-45])
113 roundabout_sign.spawn_degrees([6.987, 34.293, 0.215], [0,0,-130])
114 roundabout_sign.spawn_degrees([9.96, 46.79, 0.2], [0,0,-180])
115
116 yield_sign.spawn_degrees([-21.716, 7.596, 0.2], [0,0,-90])
117
118
119def spawn_traffic_lights(qlabs, right_hand_driving):
120 # In this case, we want to track each traffic light individually so we
121 # can subsequently set the color state. By using spawning with an ID,
122 # we'll know exactly which one is which and this will allow us to also
123 # reference them in separate programs, and we can also spawn without
124 # waiting for confirmation because the object already knows its own ID.
125
126
127 # initialize four traffic light instances in qlabs
128 trafficLight1 = QLabsTrafficLight(qlabs)
129 trafficLight2 = QLabsTrafficLight(qlabs)
130 trafficLight3 = QLabsTrafficLight(qlabs)
131 trafficLight4 = QLabsTrafficLight(qlabs)
132
133 if (right_hand_driving):
134
135 trafficLight1.spawn_id_degrees(actorNumber=0, location=[5.889, 16.048, 0.215], rotation=[0,0,0], configuration=0, waitForConfirmation=False)
136 trafficLight2.spawn_id_degrees(actorNumber=1, location=[-2.852, 1.65, 0], rotation=[0,0,180], configuration=0, waitForConfirmation=False)
137 trafficLight1.set_color(color=trafficLight1.COLOR_GREEN, waitForConfirmation=False)
138 trafficLight2.set_color(color=trafficLight2.COLOR_GREEN, waitForConfirmation=False)
139
140 trafficLight3.spawn_id_degrees(actorNumber=3, location=[8.443, 5.378, 0], rotation=[0,0,-90], configuration=0, waitForConfirmation=False)
141 trafficLight4.spawn_id_degrees(actorNumber=4, location=[-4.202, 13.984, 0.186], rotation=[0,0,90], configuration=0, waitForConfirmation=False)
142 trafficLight3.set_color(color=trafficLight3.COLOR_RED, waitForConfirmation=False)
143 trafficLight4.set_color(color=trafficLight4.COLOR_RED, waitForConfirmation=False)
144
145 else:
146 trafficLight1.spawn_id_degrees(actorNumber=0, location=[-2.831, 16.643, 0.186], rotation=[0,0,180], configuration=1, waitForConfirmation=False)
147 trafficLight2.spawn_id_degrees(actorNumber=1, location=[5.653, 1.879, 0], rotation=[0,0,0], configuration=1, waitForConfirmation=False)
148 trafficLight1.set_color(color=trafficLight1.COLOR_GREEN, waitForConfirmation=False)
149 trafficLight2.set_color(color=trafficLight2.COLOR_GREEN, waitForConfirmation=False)
150
151 trafficLight3.spawn_id_degrees(actorNumber=3, location=[8.779, 13.7, 0.215], rotation=[0,0,90], configuration=1, waitForConfirmation=False)
152 trafficLight4.spawn_id_degrees(actorNumber=4, location=[-4.714, 4.745, 0], rotation=[0,0,-90], configuration=1, waitForConfirmation=False)
153 trafficLight3.set_color(color=trafficLight3.COLOR_RED, waitForConfirmation=False)
154 trafficLight4.set_color(color=trafficLight4.COLOR_RED, waitForConfirmation=False)
155
156
157
158def spawn_cones(qlabs):
159
160 # We'll assume the cones don't need to be referenced after they're spawned so a
161 # single class object will suffice for spawning.
162
163 cone = QLabsTrafficCone(qlabs)
164
165 for count in range(10):
166 # Since we're going to set the color, we need to wait for QLabs to assign
167 # an actor number. This can be executed more quickly if you spawn by ID
168 # instead and manually assign the numbers.
169 #
170 # Also note that since this are physics objects, it's a good idea to
171 # spawn the actors slight above the surface so they can fall into place.
172 # If you spawn exactly at ground level, they may "pop" up from the surface.
173
174 cone.spawn(location=[-15.313, 35.374+count*-1.3, 0.25], configuration=1, waitForConfirmation=True)
175 cone.set_material_properties(materialSlot=0, color=[0,0,0],roughness=1,metallic=False)
176 cone.set_material_properties(materialSlot=1, color=HSVtoRGB([count/10, 1, 1]))
177
178
179def HSVtoRGB(hsv):
180
181 H = hsv[0]
182 S = hsv[1]
183 V = hsv[2]
184
185 kr = (5+H*6) % 6
186 kg = (3+H*6) % 6
187 kb = (1+H*6) % 6
188
189 r = 1 - max(min(min(kr, 4-kr), 1), 0)
190 g = 1 - max(min(min(kg, 4-kg), 1), 0)
191 b = 1 - max(min(min(kb, 4-kb), 1), 0)
192
193 return [r, g, b]
194
195
196def fly_through_animation(qlabs):
197 # Linearly interpolate through a series of points to fly the camera
198 # around the map. For each source and destination, calculate the distance
199 # so the step size is an even multiple that is approximately equal to the
200 # desired velocity.
201
202 # Translation/rotation point pairs
203 points = [[[1.5, -12.558, 1.708], [-0, 0.023, 1.405]],
204 [[0.721, -0.922, 1.721], [-0, 0.027, 1.255]],
205 [[6.082, 7.208, 1.566], [-0, 0.027, -0.309]],
206 [[20.732, 3.179, 1.997], [0, 0.049, 1.452]],
207 [[26.083, 30.157, 2.459], [0, 0.153, 2.491]],
208 [[17.211, 46.775, 11.61], [-0, 0.348, -2.189+2*math.pi]],
209 [[-17.739, 38.866, 0.956], [0, 0.142, -1.385+2*math.pi]],
210 [[-16.068, 24.53, 0.628], [-0, -0.043, -1.484+2*math.pi]],
211 [[-20.302, 1.82, 1.815], [-0, 0.03, -0.872+2*math.pi]],
212 [[-3.261, -14.664, 1.597], [-0, -0.038, 0.894+2*math.pi]]]
213
214 speed = 0.3
215 filter_translation_weight = 0.1
216 filter_rotation_weight = 0.1
217
218
219 camera = QLabsFreeCamera(qlabs)
220 camera.spawn_id(0,points[0][0], points[0][1])
221 camera.possess()
222
223 fx = points[0][0][0]
224 fy = points[0][0][1]
225 fz = points[0][0][2]
226
227 froll = points[0][1][0]
228 fpitch = points[0][1][1]
229 fyaw = points[0][1][2]
230
231 for index in range(len(points) - 1):
232 # Calculate the integer number of steps by dividing the distance by speed
233 translation_distance = dist(points[index][0], points[index+1][0])
234 total_steps = int(round(translation_distance/speed,0))
235
236
237 for step in range(total_steps):
238 # Linearly interpolate between each of the target points
239 x = interp(points[index][0][0], points[index+1][0][0], step, total_steps)
240 y = interp(points[index][0][1], points[index+1][0][1], step, total_steps)
241 z = interp(points[index][0][2], points[index+1][0][2], step, total_steps)
242
243 roll = interp(points[index][1][0], points[index+1][1][0], step, total_steps)
244 pitch = interp(points[index][1][1], points[index+1][1][1], step, total_steps)
245 yaw = interp(points[index][1][2], points[index+1][1][2], step, total_steps)
246
247 # Filter the calcuated values to smooth out the camera motion
248 fx = fx*(1-filter_translation_weight) + x*filter_translation_weight
249 fy = fy*(1-filter_translation_weight) + y*filter_translation_weight
250 fz = fz*(1-filter_translation_weight) + z*filter_translation_weight
251
252 froll = froll*(1-filter_rotation_weight) + roll*filter_rotation_weight
253 fpitch = fpitch*(1-filter_rotation_weight) + pitch*filter_rotation_weight
254 fyaw = fyaw*(1-filter_rotation_weight) + yaw*filter_rotation_weight
255
256
257 # To try to make the animation as consistent as possible across different
258 # hardware, measure the elapsed time and delay a variable amount to try
259 # to maintain 33 fps.
260
261 start_time = time.time()
262 camera.set_transform(location=[fx, fy, fz], rotation=[froll, fpitch, fyaw])
263 end_time = time.time()
264 while (end_time - start_time < 0.03):
265 end_time = time.time()
266
267def dist(v1, v2):
268 return pow( pow(v1[0]-v2[0], 2) + pow(v1[1]-v2[1], 2) + pow(v1[2]-v2[2], 2), 0.5 )
269
270def interp(start, finish, step, total_steps):
271 return (finish-start)/total_steps*step + start
272
273if __name__ == "__main__":
274 main(right_hand_driving)
Matlab Tutorial
Raw to download this tutorial: Road Signage Tutorial (.m).
1% Road signage Library Example
2% -------------------------
3%
4% .. note::
5%
6% Make sure you have Quanser Interactive Labs open before running this
7% example. This example is designed to best be run in QCar Cityscape
8% or Cityscape Lite.
9
10close all;
11clear all;
12clc;
13
14% --------------------------------------------------------------
15% Setting MATLAB Path for the libraries
16% Always keep at the start, it will make sure it finds the correct references
17newPathEntry = fullfile(getenv('QAL_DIR'), '0_libraries', 'matlab', 'qvl');
18pathCell = regexp(path, pathsep, 'split');
19if ispc % Windows is not case-sensitive
20 onPath = any(strcmpi(newPathEntry, pathCell));
21else
22 onPath = any(strcmp(newPathEntry, pathCell));
23end
24
25if onPath == 0
26 path(path, newPathEntry)
27 savepath
28end
29% --------------------------------------------------------------
30
31fprintf('\n\n----------------- Communications -------------------\n\n');
32
33qlabs = QuanserInteractiveLabs();
34connection_established = qlabs.open('localhost');
35
36if connection_established == false
37 disp("Failed to open connection.")
38 return
39end
40
41
42disp('Connected')
43
44num_destroyed = qlabs.destroy_all_spawned_actors();
45
46fprintf('%d actors destroyed', num_destroyed);
47
48% Use hSystem to set the tutorial title in the upper left of the qlabs window
49hSystem = QLabsSystem(qlabs);
50hSystem.set_title_string('Road Signage Tutorial')
51
52
53% Switch the camera angle to see where we will be spawning the rest of the objects
54camera0 = QLabsFreeCamera(qlabs);
55camera0.spawn([-20.14, 29.472, 2.071], [0, 0.203, -0.024]);
56camera0.possess();
57
58
59% Create two roundabouts in this qlabs instance
60roundabout = QLabsRoundaboutSign(qlabs);
61roundabout2 = QLabsRoundaboutSign(qlabs);
62
63% Spawn the sign using radians and specifying the actorNumber
64roundabout.spawn_id(0, [-17, 29, 0.0], [0, 0, pi], [1, 1, 1], 0, 1);
65% Spawn the second sign using degrees and allowing the computer to
66% generate an actorNumber internally
67roundabout2.spawn_id_degrees(2, [-15, 29, 0.0], [0, 0, 180], [1, 1, 1], 0, 1);
68
69% Wait to see the output
70pause(1.5);
71
72% Destroying the sign we just created
73roundabout.destroy();
74pause(1.5);
75
76% Create two yield signs in this qlabs instance
77yieldsign = QLabsYieldSign(qlabs);
78yieldsign2 = QLabsYieldSign(qlabs);
79
80% Spawn the sign using radians and specifying the actorNumber
81yieldsign.spawn_id(0, [-17, 31, 0.0], [0, 0, pi], [1, 1, 1], 0, 1);
82% Spawn the second sign using degrees and allowing the computer to
83% generate an actorNumber internally
84yieldsign2.spawn_degrees([-15, 31, 0.0], [0, 0, 180], [1, 1, 1], 0, 1);
85
86% Wait to see the output
87pause(1.5);
88
89% Destroying the sign we just created
90yieldsign.destroy();
91pause(1.5);
92
93% Create two stop signs in this qlabs instance
94stop = QLabsStopSign(qlabs);
95stop2 = QLabsStopSign(qlabs);
96
97% Spawn the sign using radians
98stop.spawn_id(1, [-16, 30, 0.0], [0, 0, pi], [1, 1, 1], 0, 1);
99% Spawn the second sign using degrees and allowing the computer to
100% generate an actorNumber internally
101stop2.spawn_degrees([-15, 30, 0.0], [0, 0, 180], [1, 1, 1], 0, 1);
102
103% Wait to see the output
104pause(1.5);
105
106% Destroying the sign we just created
107stop.destroy();
108pause(1.5);
109
110% Destroy the signs one by one
111roundabout2.destroy();
112pause(1);
113
114stop2.destroy();
115pause(1);
116
117yieldsign2.destroy();
118pause(1);
119
120% Closing qlabs
121qlabs.close();
122disp('Done!');
Complete Road Signage Matlab Tutorial
Raw to download this tutorial: Complete Road Signage Tutorial (.m).
1% Road signage Library Example
2% -------------------------
3%
4% .. note::
5%
6% Make sure you have Quanser Interactive Labs open before running this
7% example. This example is designed to best be run in QCar Cityscape
8% or Cityscape Lite
9
10close all;
11clear all;
12clc;
13
14% Select if you would like to spawn the signs for right or left hand
15% orientation.
16right_hand_driving = true;
17
18% --------------------------------------------------------------
19% Setting MATLAB Path for the libraries
20% Always keep at the start, it will make sure it finds the correct references
21newPathEntry = fullfile(getenv('QAL_DIR'), '0_libraries', 'matlab', 'qvl');
22pathCell = regexp(path, pathsep, 'split');
23if ispc % Windows is not case-sensitive
24 onPath = any(strcmpi(newPathEntry, pathCell));
25else
26 onPath = any(strcmp(newPathEntry, pathCell));
27end
28
29if onPath == 0
30 path(path, newPathEntry)
31 savepath
32end
33% --------------------------------------------------------------
34
35
36main(right_hand_driving);
37
38function main(right_hand_driving)
39
40 % creates a server connection with Quanser Interactive Labs and manages the communications
41 qlabs = QuanserInteractiveLabs();
42 connection_established = qlabs.open('localhost');
43
44 % trying to connect to QLabs and open the instance we have created - program will end if this fails
45 if connection_established == false
46 disp("Failed to open connection.")
47 return
48 end
49
50 disp('Connected')
51
52 % destroying any spawned actors in our QLabs that currently exist
53 num_destroyed = qlabs.destroy_all_spawned_actors();
54 fprintf('%d actors destroyed\n', num_destroyed);
55
56 % Use hSystem to set the tutorial title on the qlabs display screen
57 hSystem = QLabsSystem(qlabs);
58 hSystem.set_title_string('Complete Road Signage Tutorial');
59
60 spawn_crosswalk(qlabs);
61 spawn_signs(qlabs, right_hand_driving);
62 spawn_traffic_lights(qlabs, right_hand_driving);
63 spawn_cones(qlabs);
64
65 fly_through_animation(qlabs);
66
67 % Closing qlabs
68 qlabs.close();
69 disp('Done!');
70
71end
72
73function spawn_crosswalk(qlabs)
74 % Create a crosswalk in this qlabs instance. Since we don't need
75 % to access the actors again after creating them, we can use a single
76 % class object to spawn all the varieties. We also don't need to use
77 % the waitForConfirmation because we don't need to store the actor ID
78 % for future reference.
79
80 crosswalk = QLabsCrosswalk(qlabs);
81
82 % spawn crosswalk with degrees in config 0
83 crosswalk.spawn_degrees([-12.992, -7.407, 0.005], [0,0,48], [1,1,1], 0, false);
84
85 % spawn crosswalk with degrees in config 1
86 crosswalk.spawn_degrees([-6.788, 45, 0.00], [0,0,90], [1,1,1], 1, false);
87
88 % spawn crosswalk with degrees in config 2
89 crosswalk.spawn_degrees([21.733, 3.347, 0.005], [0,0,0], [1,1,1], 2, false);
90
91 % spawn the last crosswalk with waitForConfirmation=True to confirm everything is flushed from the send buffers
92 crosswalk.spawn_degrees([21.733, 16, 0.005], [0,0,0], [1,1,1], 2, true);
93end
94
95function spawn_signs(qlabs, right_hand_driving)
96 % Like the crosswalks, we don't need to access the actors again after
97 % creating them.
98
99 roundabout_sign = QLabsRoundaboutSign(qlabs);
100 yield_sign = QLabsYieldSign(qlabs);
101 stop_sign = QLabsStopSign(qlabs);
102
103 if (right_hand_driving)
104 stop_sign.spawn_degrees([17.561, 17.677, 0.215], [0,0,90]);
105 stop_sign.spawn_degrees([24.3, 1.772, 0.2], [0,0,-90]);
106 stop_sign.spawn_degrees([14.746, 6.445, 0.215], [0,0,180]);
107
108 roundabout_sign.spawn_degrees([3.551, 40.353, 0.215], [0,0,180]);
109 roundabout_sign.spawn_degrees([10.938, 28.824, 0.215], [0,0,-135]);
110 roundabout_sign.spawn_degrees([24.289, 32.591, 0.192], [0,0,-90]);
111
112 yield_sign.spawn_degrees([-2.169, -12.594, 0.2], [0,0,180]);
113 else
114 stop_sign.spawn_degrees([24.333, 17.677, 0.215], [0,0,90]);
115 stop_sign.spawn_degrees([18.03, 1.772, 0.2], [0,0,-90]);
116 stop_sign.spawn_degrees([14.746, 13.01, 0.215], [0,0,180]);
117
118 roundabout_sign.spawn_degrees([16.647, 28.404, 0.215], [0,0,-45]);
119 roundabout_sign.spawn_degrees([6.987, 34.293, 0.215], [0,0,-130]);
120 roundabout_sign.spawn_degrees([9.96, 46.79, 0.2], [0,0,-180]);
121
122 yield_sign.spawn_degrees([-21.716, 7.596, 0.2], [0,0,-90]);
123 end
124end
125
126function spawn_traffic_lights(qlabs, right_hand_driving)
127 % In this case, we want to track each traffic light individually so we
128 % can subsequently set the color state. By using spawning with an ID,
129 % we'll know exactly which one is which and this will allow us to also
130 % reference them in separate programs, and we can also spawn without
131 % waiting for confirmation because the object already knows its own ID.
132
133
134 % initialize four traffic light instances in qlabs
135 trafficLight1 = QLabsTrafficLight(qlabs);
136 trafficLight2 = QLabsTrafficLight(qlabs);
137 trafficLight3 = QLabsTrafficLight(qlabs);
138 trafficLight4 = QLabsTrafficLight(qlabs);
139
140 if (right_hand_driving)
141
142 trafficLight1.spawn_id_degrees(0, [5.889, 16.048, 0.215], [0,0,0], [1,1,1], 0, false);
143 trafficLight2.spawn_id_degrees(1, [-2.852, 1.65, 0], [0,0,180], [1,1,1], 0, false);
144 trafficLight1.set_color(trafficLight1.COLOR_GREEN, false);
145 trafficLight2.set_color(trafficLight2.COLOR_GREEN, false);
146
147 trafficLight3.spawn_id_degrees(3, [8.443, 5.378, 0], [0,0,-90], [1,1,1], 0, false);
148 trafficLight4.spawn_id_degrees(4, [-4.202, 13.984, 0.186], [0,0,90], [1,1,1], 0, false);
149 trafficLight3.set_color(trafficLight3.COLOR_RED, false);
150 trafficLight4.set_color(trafficLight4.COLOR_RED, false);
151
152 else
153 trafficLight1.spawn_id_degrees(0, [-2.831, 16.643, 0.186], [0,0,180], [1,1,1], 1, false);
154 trafficLight2.spawn_id_degrees(1, [5.653, 1.879, 0], [0,0,0], [1,1,1], 1, false);
155 trafficLight1.set_color(trafficLight1.COLOR_GREEN, false);
156 trafficLight2.set_color(trafficLight2.COLOR_GREEN, false);
157
158 trafficLight3.spawn_id_degrees(3, [8.779, 13.7, 0.215], [0,0,90], [1,1,1], 1, false);
159 trafficLight4.spawn_id_degrees(4, [-4.714, 4.745, 0], [0,0,-90], [1,1,1], 1, false);
160 trafficLight3.set_color(trafficLight3.COLOR_RED, false);
161 trafficLight4.set_color(trafficLight4.COLOR_RED, false);
162 end
163end
164
165
166function spawn_cones(qlabs)
167
168 % We'll assume the cones don't need to be referenced after they're spawned so a
169 % single class object will suffice for spawning.
170
171 cone = QLabsTrafficCone(qlabs, true);
172
173 for count = 1:10
174 % Since we're going to set the color, we need to wait for QLabs to assign
175 % an actor number. This can be executed more quickly if you spawn by ID
176 % instead and manually assign the numbers.
177 %
178 % Also note that since this are physics objects, it's a good idea to
179 % spawn the actors slight above the surface so they can fall into place.
180 % If you spawn exactly at ground level, they may "pop" up from the surface.
181
182 cone.spawn([-15.313, 35.374+(count-1)*-1.3, 0.25], [0,0,0], [1,1,1], 1, true);
183 cone.set_material_properties(0, [0,0,0], 1, true);
184 cone.set_material_properties(1, HSVtoRGB([(count-1)/10, 1, 1]));
185 end
186end
187
188
189function color = HSVtoRGB(hsv)
190
191 H = hsv(1);
192 S = hsv(2);
193 V = hsv(3);
194
195 kr = mod((5+H*6), 6);
196 kg = mod((3+H*6), 6);
197 kb = mod((1+H*6), 6);
198
199 r = 1 - max(min(min(kr, 4-kr), 1), 0);
200 g = 1 - max(min(min(kg, 4-kg), 1), 0);
201 b = 1 - max(min(min(kb, 4-kb), 1), 0);
202
203 color = [r, g, b];
204end
205
206function fly_through_animation(qlabs)
207 % Linearly interpolate through a series of points to fly the camera
208 % around the map. For each source and destination, calculate the distance
209 % so the step size is an even multiple that is approximately equal to the
210 % desired velocity.
211
212 % Translation/rotation point pairs
213 points = [[1.5, -12.558, 1.708], [-0, 0.023, 1.405]
214 [0.721, -0.922, 1.721], [-0, 0.027, 1.255]
215 [6.082, 7.208, 1.566], [-0, 0.027, -0.309]
216 [20.732, 3.179, 1.997], [0, 0.049, 1.452]
217 [26.083, 30.157, 2.459], [0, 0.153, 2.491]
218 [17.211, 46.775, 11.61], [-0, 0.348, -2.189+2*pi]
219 [-17.739, 38.866, 0.956], [0, 0.142, -1.385+2*pi]
220 [-16.068, 24.53, 0.628], [-0, -0.043, -1.484+2*pi]
221 [-20.302, 1.82, 1.815], [-0, 0.03, -0.872+2*pi]
222 [-3.261, -14.664, 1.597], [-0, -0.038, 0.894+2*pi]];
223
224 speed = 0.3;
225 filter_translation_weight = 0.1;
226 filter_rotation_weight = 0.1;
227
228
229 camera = QLabsFreeCamera(qlabs);
230 camera.spawn_id(0,points(1,1:3), points(1, 4:6));
231 camera.possess();
232
233 fx = points(1,1);
234 fy = points(1,2);
235 fz = points(1,3);
236
237 froll = points(1,4);
238 fpitch = points(1,5);
239 fyaw = points(1,6);
240
241 for index = 1:(size(points,1)-1)
242 % Calculate the integer number of steps by dividing the distance by speed
243 translation_distance = dist(points(index, 1:3), points(index+1, 1:3));
244 total_steps = round(translation_distance/speed);
245
246
247 for step = 1:total_steps
248 % Linearly interpolate between each of the target points
249 x = interp(points(index,1), points(index+1,1), step, total_steps);
250 y = interp(points(index,2), points(index+1,2), step, total_steps);
251 z = interp(points(index,3), points(index+1,3), step, total_steps);
252
253 roll = interp(points(index,4), points(index+1,4), step, total_steps);
254 pitch = interp(points(index,5), points(index+1,5), step, total_steps);
255 yaw = interp(points(index,6), points(index+1,6), step, total_steps);
256
257 % Filter the calcuated values to smooth out the camera motion
258 fx = fx*(1-filter_translation_weight) + x*filter_translation_weight;
259 fy = fy*(1-filter_translation_weight) + y*filter_translation_weight;
260 fz = fz*(1-filter_translation_weight) + z*filter_translation_weight;
261
262 froll = froll*(1-filter_rotation_weight) + roll*filter_rotation_weight;
263 fpitch = fpitch*(1-filter_rotation_weight) + pitch*filter_rotation_weight;
264 fyaw = fyaw*(1-filter_rotation_weight) + yaw*filter_rotation_weight;
265
266
267 % To try to make the animation as consistent as possible across different
268 % hardware, measure the elapsed time and delay a variable amount to try
269 % to maintain 33 fps. If QLabs can't run at 33fps, it will just
270 % run as fast as possible.
271
272 tic
273 camera.set_transform([fx, fy, fz], [froll, fpitch, fyaw]);
274 while (toc < 0.03)
275 pause(0.001);
276 end
277 end
278 end
279end
280
281function value = dist(v1, v2)
282 value = ((v1(1)-v2(1))^2 + (v1(2)-v2(2))^2 + (v1(3)-v2(3))^2)^0.5;
283end
284
285function value = interp(start, finish, step, total_steps)
286 value = (finish-start)/total_steps*step + start;
287end