autoverse-cli 0.11.0__tar.gz → 0.12.1__tar.gz

Sign up to get free protection for your applications and to get access to all the features.
Files changed (50) hide show
  1. {autoverse_cli-0.11.0 → autoverse_cli-0.12.1}/PKG-INFO +2 -2
  2. {autoverse_cli-0.11.0 → autoverse_cli-0.12.1}/pyproject.toml +1 -1
  3. {autoverse_cli-0.11.0 → autoverse_cli-0.12.1}/src/autoverse_cli.egg-info/PKG-INFO +2 -2
  4. {autoverse_cli-0.11.0 → autoverse_cli-0.12.1}/src/autoverse_cli.egg-info/SOURCES.txt +5 -1
  5. {autoverse_cli-0.11.0 → autoverse_cli-0.12.1}/src/avrs/app_version.py +1 -1
  6. {autoverse_cli-0.11.0 → autoverse_cli-0.12.1}/src/avrs/avrs.py +4 -2
  7. autoverse_cli-0.12.1/src/avrs/race_cloud.py +296 -0
  8. autoverse_cli-0.12.1/src/avrs/race_cloud_cfg_util.py +106 -0
  9. autoverse_cli-0.12.1/src/avrs/race_cloud_util.py +237 -0
  10. autoverse_cli-0.12.1/src/avrs/requests/dump_sim_config.py +14 -0
  11. {autoverse_cli-0.11.0 → autoverse_cli-0.12.1}/src/avrs/requests/request.py +6 -1
  12. {autoverse_cli-0.11.0 → autoverse_cli-0.12.1}/src/avrs/simconfig_util.py +4 -4
  13. autoverse_cli-0.12.1/src/avrs/util.py +13 -0
  14. autoverse_cli-0.11.0/src/avrs/requests/reserve_mv_slot.py +0 -112
  15. {autoverse_cli-0.11.0 → autoverse_cli-0.12.1}/LICENSE +0 -0
  16. {autoverse_cli-0.11.0 → autoverse_cli-0.12.1}/README.md +0 -0
  17. {autoverse_cli-0.11.0 → autoverse_cli-0.12.1}/setup.cfg +0 -0
  18. {autoverse_cli-0.11.0 → autoverse_cli-0.12.1}/src/autoverse_cli.egg-info/dependency_links.txt +0 -0
  19. {autoverse_cli-0.11.0 → autoverse_cli-0.12.1}/src/autoverse_cli.egg-info/entry_points.txt +0 -0
  20. {autoverse_cli-0.11.0 → autoverse_cli-0.12.1}/src/autoverse_cli.egg-info/requires.txt +0 -0
  21. {autoverse_cli-0.11.0 → autoverse_cli-0.12.1}/src/autoverse_cli.egg-info/top_level.txt +0 -0
  22. {autoverse_cli-0.11.0 → autoverse_cli-0.12.1}/src/avrs/__init__.py +0 -0
  23. {autoverse_cli-0.11.0 → autoverse_cli-0.12.1}/src/avrs/argparse_help.py +0 -0
  24. {autoverse_cli-0.11.0 → autoverse_cli-0.12.1}/src/avrs/can_tool.py +0 -0
  25. {autoverse_cli-0.11.0 → autoverse_cli-0.12.1}/src/avrs/can_tool_util.py +0 -0
  26. {autoverse_cli-0.11.0 → autoverse_cli-0.12.1}/src/avrs/cfg.py +0 -0
  27. {autoverse_cli-0.11.0 → autoverse_cli-0.12.1}/src/avrs/launcher.py +0 -0
  28. {autoverse_cli-0.11.0 → autoverse_cli-0.12.1}/src/avrs/launcher_util.py +0 -0
  29. {autoverse_cli-0.11.0 → autoverse_cli-0.12.1}/src/avrs/requests/change_camera.py +0 -0
  30. {autoverse_cli-0.11.0 → autoverse_cli-0.12.1}/src/avrs/requests/code_booz.py +0 -0
  31. {autoverse_cli-0.11.0 → autoverse_cli-0.12.1}/src/avrs/requests/demo.py +0 -0
  32. {autoverse_cli-0.11.0 → autoverse_cli-0.12.1}/src/avrs/requests/environment.py +0 -0
  33. {autoverse_cli-0.11.0 → autoverse_cli-0.12.1}/src/avrs/requests/fault_injection.py +0 -0
  34. {autoverse_cli-0.11.0 → autoverse_cli-0.12.1}/src/avrs/requests/get_object_config.py +0 -0
  35. {autoverse_cli-0.11.0 → autoverse_cli-0.12.1}/src/avrs/requests/list_sim_objects.py +0 -0
  36. {autoverse_cli-0.11.0 → autoverse_cli-0.12.1}/src/avrs/requests/log_path.py +0 -0
  37. {autoverse_cli-0.11.0 → autoverse_cli-0.12.1}/src/avrs/requests/misc.py +0 -0
  38. {autoverse_cli-0.11.0 → autoverse_cli-0.12.1}/src/avrs/requests/move_to_landmark.py +0 -0
  39. {autoverse_cli-0.11.0 → autoverse_cli-0.12.1}/src/avrs/requests/npc.py +0 -0
  40. {autoverse_cli-0.11.0 → autoverse_cli-0.12.1}/src/avrs/requests/reset_to_track.py +0 -0
  41. {autoverse_cli-0.11.0 → autoverse_cli-0.12.1}/src/avrs/requests/restart.py +0 -0
  42. {autoverse_cli-0.11.0 → autoverse_cli-0.12.1}/src/avrs/requests/scenario_control.py +0 -0
  43. {autoverse_cli-0.11.0 → autoverse_cli-0.12.1}/src/avrs/requests/spawn_object.py +0 -0
  44. {autoverse_cli-0.11.0 → autoverse_cli-0.12.1}/src/avrs/requests/teleport.py +0 -0
  45. {autoverse_cli-0.11.0 → autoverse_cli-0.12.1}/src/avrs/requests/toggle_hud.py +0 -0
  46. {autoverse_cli-0.11.0 → autoverse_cli-0.12.1}/src/avrs/requests/vd.py +0 -0
  47. {autoverse_cli-0.11.0 → autoverse_cli-0.12.1}/src/avrs/requests/vehicle_input.py +0 -0
  48. {autoverse_cli-0.11.0 → autoverse_cli-0.12.1}/src/avrs/requests/vehicle_replay.py +0 -0
  49. {autoverse_cli-0.11.0 → autoverse_cli-0.12.1}/src/avrs/simconfig.py +0 -0
  50. {autoverse_cli-0.11.0 → autoverse_cli-0.12.1}/src/avrs/tests.py +0 -0
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.2
2
2
  Name: autoverse-cli
3
- Version: 0.11.0
3
+ Version: 0.12.1
4
4
  Summary: The Autoverse CLI
5
5
  Author-email: Dan Kamrath <dan.kamrath@autonomalabs.com>
6
6
  License: # End-User License Agreement (EULA) of the Autonoma AutoVerse CLI
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "autoverse-cli"
3
- version = "0.11.0"
3
+ version = "0.12.1"
4
4
  dependencies = [
5
5
  "boto3",
6
6
  "cantools"
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.2
2
2
  Name: autoverse-cli
3
- Version: 0.11.0
3
+ Version: 0.12.1
4
4
  Summary: The Autoverse CLI
5
5
  Author-email: Dan Kamrath <dan.kamrath@autonomalabs.com>
6
6
  License: # End-User License Agreement (EULA) of the Autonoma AutoVerse CLI
@@ -16,12 +16,17 @@ src/avrs/can_tool_util.py
16
16
  src/avrs/cfg.py
17
17
  src/avrs/launcher.py
18
18
  src/avrs/launcher_util.py
19
+ src/avrs/race_cloud.py
20
+ src/avrs/race_cloud_cfg_util.py
21
+ src/avrs/race_cloud_util.py
19
22
  src/avrs/simconfig.py
20
23
  src/avrs/simconfig_util.py
21
24
  src/avrs/tests.py
25
+ src/avrs/util.py
22
26
  src/avrs/requests/change_camera.py
23
27
  src/avrs/requests/code_booz.py
24
28
  src/avrs/requests/demo.py
29
+ src/avrs/requests/dump_sim_config.py
25
30
  src/avrs/requests/environment.py
26
31
  src/avrs/requests/fault_injection.py
27
32
  src/avrs/requests/get_object_config.py
@@ -31,7 +36,6 @@ src/avrs/requests/misc.py
31
36
  src/avrs/requests/move_to_landmark.py
32
37
  src/avrs/requests/npc.py
33
38
  src/avrs/requests/request.py
34
- src/avrs/requests/reserve_mv_slot.py
35
39
  src/avrs/requests/reset_to_track.py
36
40
  src/avrs/requests/restart.py
37
41
  src/avrs/requests/scenario_control.py
@@ -2,7 +2,7 @@ import http.client
2
2
  import json
3
3
 
4
4
  def get_app_version():
5
- return '0.11.0'
5
+ return '0.12.1'
6
6
 
7
7
  def check_app_is_latest():
8
8
  pass
@@ -7,6 +7,7 @@ from avrs.app_version import *
7
7
  from avrs.cfg import *
8
8
  from avrs.launcher import *
9
9
  from avrs.can_tool import *
10
+ from avrs.race_cloud import *
10
11
  from avrs.argparse_help import *
11
12
 
12
13
  from avrs.requests.move_to_landmark import MoveToLandmarkRequest
@@ -14,7 +15,6 @@ from avrs.requests.restart import Restart
14
15
  from avrs.requests.reset_to_track import ResetToTrack
15
16
  from avrs.requests.teleport import Teleport
16
17
  from avrs.requests.npc import Npc
17
- from avrs.requests.reserve_mv_slot import ReserveMvSlot
18
18
  from avrs.requests.vd import Vd
19
19
  from avrs.requests.vehicle_input import AvrsConfigureVehicleInputRequest
20
20
  from avrs.requests.log_path import LogPath
@@ -31,6 +31,7 @@ from avrs.simconfig import *
31
31
  from avrs.requests.get_object_config import *
32
32
  from avrs.requests.misc import *
33
33
  from avrs.requests.spawn_object import *
34
+ from avrs.requests.dump_sim_config import *
34
35
 
35
36
 
36
37
  def get_version():
@@ -67,7 +68,7 @@ def main():
67
68
  ResetToTrack(sps, cfg)
68
69
  Teleport(sps, cfg)
69
70
  #Npc(sps, cfg)
70
- #ReserveMvSlot(sps, cfg)
71
+ AvrsRaceCloud(sps, cfg)
71
72
  Vd(sps, cfg)
72
73
  AvrsConfigureVehicleInputRequest(sps, cfg)
73
74
  LogPath(sps, cfg)
@@ -86,6 +87,7 @@ def main():
86
87
  AvrsPingRequest(sps, cfg)
87
88
  AvrsConfigureSimLodRequest(sps, cfg)
88
89
  AvrsSpawnObjectRequest(sps, cfg)
90
+ AvrsDumpSimConfigRequest(sps, cfg)
89
91
 
90
92
  if os.environ.get('AVRS_WITH_DEMO', '0') == '1':
91
93
  AvrsDemoRequest(sps, cfg)
@@ -0,0 +1,296 @@
1
+ import subprocess
2
+ import base64
3
+ from avrs.cfg import *
4
+ from avrs.race_cloud_util import *
5
+ from avrs.race_cloud_cfg_util import *
6
+ from avrs.util import *
7
+ from avrs.requests.request import AvrsApiRequest
8
+ from argparse import RawTextHelpFormatter
9
+
10
+ class AvrsRaceCloud(AvrsApiRequest):
11
+ def __init__(self, parser, cfg):
12
+ self.cfg = cfg
13
+ race_cloud_parser = parser.add_parser(
14
+ 'race-cloud',
15
+ help='cloud racing\n\n')
16
+
17
+ sps = race_cloud_parser.add_subparsers(required=True, help='race-cloud options')
18
+
19
+ connect_parser = sps.add_parser(
20
+ 'connect',
21
+ help='connect to an instance for cloud racing')
22
+ connect_parser.add_argument(
23
+ 'sim_index',
24
+ type = int,
25
+ choices = [0, 1, 2, 3, 4, 5],
26
+ help='the index of the simulator instance to connect to')
27
+ connect_parser.add_argument(
28
+ 'team_name',
29
+ help='the name of the team to race under')
30
+ connect_parser.add_argument(
31
+ 'vehicle_config',
32
+ help='the path the vehicle configuration file to use when racing')
33
+ connect_parser.add_argument(
34
+ '--instance-id',
35
+ default = '',
36
+ help='can be used directly instead of instance name if needed')
37
+ connect_parser.add_argument(
38
+ '--no-check-cans',
39
+ action='store_true',
40
+ help='if set, vcan interfaces will not be checked for validity')
41
+ connect_parser.set_defaults(func=self.race_connect)
42
+
43
+ rx_connect_parser = sps.add_parser(
44
+ 'rx-connection',
45
+ help='execute steps to receive a connection (only relevant to sim-side)')
46
+ rx_connect_parser.add_argument(
47
+ 'team_name',
48
+ help='the name of the connecting team')
49
+ rx_connect_parser.add_argument(
50
+ 'ip',
51
+ help='the ip address of the incoming connection')
52
+ rx_connect_parser.add_argument(
53
+ 'cfg_data',
54
+ help='the incoming vehicle configuration data')
55
+ rx_connect_parser.set_defaults(func=self.rx_connect)
56
+
57
+ sim_ctrl_parser = sps.add_parser(
58
+ 'sim-ctrl',
59
+ help='control the sim program (start, stop, restart, reset)')
60
+ sim_ctrl_parser.add_argument(
61
+ 'sim_index',
62
+ type=int,
63
+ choices=[0, 1, 2, 3, 4, 5],
64
+ help='the index of the simulator instance to apply the action')
65
+ sim_ctrl_parser.add_argument(
66
+ 'action',
67
+ choices=['start', 'stop', 'restart', 'reset-connection'],
68
+ help='what action to apply to the simulator program')
69
+ sim_ctrl_parser.add_argument(
70
+ '--local',
71
+ action='store_true',
72
+ help='if set, this command will run on this system locally (not for use from dev instances)')
73
+ sim_ctrl_parser.add_argument(
74
+ '--instance-id',
75
+ default = '',
76
+ help='can be used directly instead of sim index if needed')
77
+ sim_ctrl_parser.add_argument(
78
+ '--clear-autospawns',
79
+ action='store_true',
80
+ help='can be used with the reset-connection action to clear sim autospawn config')
81
+ sim_ctrl_parser.set_defaults(func=self.sim_ctrl)
82
+
83
+ reset_qos_parser = sps.add_parser(
84
+ 'reset-qos',
85
+ help='reset the qos file on this system')
86
+ reset_qos_parser.set_defaults(func=self.reset_qos)
87
+
88
+ enable_peer_qos_parser = sps.add_parser(
89
+ 'enable-peer-qos',
90
+ help='enable a peer in this systems qos file')
91
+ enable_peer_qos_parser.add_argument(
92
+ 'peer_id',
93
+ type=int,
94
+ choices=[0, 1, 2, 3, 4, 5],
95
+ help='the id of the peer to enable')
96
+ enable_peer_qos_parser.add_argument(
97
+ 'ip',
98
+ help='the ip address to add to the qos file')
99
+ enable_peer_qos_parser.set_defaults(func=self.enable_peer_qos)
100
+
101
+ disable_peer_qos_parser = sps.add_parser(
102
+ 'disable-peer-qos',
103
+ help='disable a peer in this systems qos file')
104
+ disable_peer_qos_parser.add_argument(
105
+ 'peer_id',
106
+ type=int,
107
+ choices=[0, 1, 2, 3, 4, 5],
108
+ help='the id of the peer to enable')
109
+ disable_peer_qos_parser.set_defaults(func=self.disable_peer_qos)
110
+
111
+
112
+ def race_connect(self, args):
113
+ print('connecting to race with team name: {}'.format(args.team_name))
114
+
115
+ # validate / load vehicle config
116
+
117
+ vcfg_ok, vcfg_data, bsu_vcan, kistler_vcan, badenia_vcan = prepare_vehicle_cfg(args.vehicle_config)
118
+
119
+ if not vcfg_ok:
120
+ print('error sending config file: {}'.format(vcfg_data))
121
+ return
122
+
123
+ vcan_ok = True
124
+ if not check_vcan_exists(bsu_vcan) and not args.no_check_cans:
125
+ print('bsu vcan {} does not appear to exist'.format(bsu_vcan))
126
+ vcan_ok = False
127
+ if not check_vcan_exists(kistler_vcan) and not args.no_check_cans:
128
+ print('kistler vcan {} does not appear to exist'.format(kistler_vcan))
129
+ vcan_ok = False
130
+ if not check_vcan_exists(badenia_vcan) and not args.no_check_cans:
131
+ print('badenia vcan {} does not appear to exist'.format(badenia_vcan))
132
+ vcan_ok = False
133
+
134
+ if not vcan_ok:
135
+ return
136
+
137
+ # make api call to begin connection
138
+ our_ip = get_local_instance_ip()
139
+
140
+ connection_request = {
141
+ 'action': 'connect',
142
+ 'sim_index': args.sim_index,
143
+ 'ip_to_reserve': our_ip,
144
+ 'team_name': args.team_name,
145
+ 'sim_id_override': args.instance_id,
146
+ 'ensure_instance_is_running': False,
147
+ 'config_data': vcfg_data
148
+ }
149
+
150
+ ok, response = call_race_cloud_api(connection_request)
151
+ if not ok:
152
+ print('connect api error: {}'.format(response))
153
+
154
+ ok, rbody, sim_ip = get_api_script_response(response)
155
+ if not ok:
156
+ print(rbody)
157
+ return
158
+
159
+ print(rbody)
160
+ #print(sim_ip)
161
+
162
+ slot_info = {}
163
+ for k, v in rbody.items():
164
+ #print('out: {}'.format(v['stdout']))
165
+ #print('err: {}'.format(v['stderr']))
166
+ slot_info = json.loads(v['stdout'])
167
+
168
+ if not slot_info['ok']:
169
+ print('issue reserving slot: {}'.format(slot_info['msg']))
170
+ return
171
+
172
+ sim_slot = slot_info['slot']
173
+
174
+ # enable first peer since this is on a client (only will ever have 1, the sim)
175
+ enable_peer_qos(sim_slot, sim_ip)
176
+
177
+ # will need to get port from received slot id to connect peer vcans
178
+ connect_peer_vcan(sim_slot, sim_ip, 0, bsu_vcan)
179
+ connect_peer_vcan(sim_slot, sim_ip, 1, kistler_vcan)
180
+ connect_peer_vcan(sim_slot, sim_ip, 2, badenia_vcan)
181
+
182
+ # configure the CLI to communicate with the cloud sim instance
183
+ self.cfg['sim_address'] = sim_ip
184
+ save_cfg('avrs', self.cfg)
185
+
186
+ print('connection success with team name {} and slot id {}'.format(args.team_name, sim_slot))
187
+
188
+ # this should only run on sim instances (not dev instances)
189
+ def rx_connect(self, args):
190
+ ok, msg, slot = try_get_open_slot(args.team_name, args.ip)
191
+
192
+ bsu_vcan = get_auto_vcan_name(slot, 0)
193
+ kistler_vcan = get_auto_vcan_name(slot, 1)
194
+ badenia_vcan = get_auto_vcan_name(slot, 2)
195
+
196
+ # get CAN names from this
197
+ register_received_vehicle(
198
+ args.team_name, slot, args.cfg_data, bsu_vcan, kistler_vcan, badenia_vcan)
199
+
200
+ vcan_ok = True
201
+ vcan_msg = ''
202
+ if not check_vcan_exists(bsu_vcan):
203
+ vcan_msg = 'bsu vcan {} does not appear to exist'.format(bsu_vcan)
204
+ vcan_ok = False
205
+ if not check_vcan_exists(kistler_vcan):
206
+ vcan_msg = 'kistler vcan {} does not appear to exist'.format(kistler_vcan)
207
+ vcan_ok = False
208
+ if not check_vcan_exists(badenia_vcan):
209
+ vcan_msg = 'badenia vcan {} does not appear to exist'.format(badenia_vcan)
210
+ vcan_ok = False
211
+
212
+ if not vcan_ok:
213
+ print(json.dumps({
214
+ 'ok': vcan_ok,
215
+ 'msg': vcan_msg,
216
+ 'slot': -1
217
+ }))
218
+ return
219
+
220
+ if ok:
221
+ enable_peer_qos(slot, args.ip)
222
+ connect_peer_vcan(slot, args.ip, 0)
223
+ connect_peer_vcan(slot, args.ip, 1)
224
+ connect_peer_vcan(slot, args.ip, 2)
225
+
226
+ response = {
227
+ 'ok': ok,
228
+ 'msg': msg,
229
+ 'slot': slot
230
+ }
231
+
232
+ print(json.dumps(response)) # print this so that when called from the ssh lambda we can get the result
233
+
234
+ def sim_ctrl(self, args):
235
+ if args.local:
236
+ self.local_sim_ctrl(args)
237
+ else:
238
+ self.remote_sim_ctrl(args)
239
+
240
+ def local_sim_ctrl(self, args):
241
+ if args.action == 'reset-connection':
242
+ print('resetting race cloud connection')
243
+ print('resetting qos file, removing CAN lock files, stopping all cannelloni instances')
244
+ reset_race_cloud_connection()
245
+ if args.clear_autospawns:
246
+ clear_autospawns()
247
+ if args.action == 'stop' or args.action == 'restart':
248
+ print('stopping sim program on sim instance {}'.format(args.sim_index))
249
+ bash_kill_process('Autoverse')
250
+ if args.action == 'start' or args.action == 'restart':
251
+ print('starting sim program on sim instance {}'.format(args.sim_index))
252
+ exe_path = os.path.join(get_sim_install_path(), 'Linux', 'Autoverse.sh')
253
+ start_exe(exe_path)
254
+
255
+ def remote_sim_ctrl(self, args):
256
+
257
+ # go ahead and reset local connection as well
258
+ if args.action == 'reset-connection':
259
+ reset_race_cloud_connection()
260
+
261
+ our_ip = get_local_instance_ip()
262
+
263
+ reset_request = {
264
+ 'action': args.action,
265
+ 'sim_index': args.sim_index,
266
+ 'ip_to_reserve': our_ip,
267
+ 'sim_id_override': args.instance_id,
268
+ 'ensure_instance_is_running': False
269
+ }
270
+
271
+ ok, response = call_race_cloud_api(reset_request)
272
+ #print(response)
273
+ if not ok:
274
+ print(response)
275
+ return
276
+
277
+ ok, rbody, sim_ip = get_api_script_response(response)
278
+ if not ok:
279
+ print(rbody)
280
+ return
281
+
282
+ for k, v in rbody.items():
283
+ print(v['stdout'])
284
+
285
+ def reset_qos(self, args):
286
+ print('resetting qos file')
287
+ reset_rmw_qos()
288
+
289
+ def enable_peer_qos(self, args):
290
+ print('enabling peer qos for id {} using ip address {}'.format(
291
+ args.peer_id, args.ip))
292
+ enable_peer_qos(args.peer_id, args.ip)
293
+
294
+ def disable_peer_qos(self, args):
295
+ print('disabling peer qos for id {}'.format(args.peer_id))
296
+ disable_peer_qos(args.peer_id)
@@ -0,0 +1,106 @@
1
+ import os
2
+ import json
3
+ import base64
4
+
5
+ from avrs.simconfig_util import *
6
+
7
+ def get_payload(cfg_object, payload_name):
8
+ for p in cfg_object['payloads']:
9
+ if p['typeName'] == payload_name:
10
+ return p
11
+ return None
12
+
13
+ def clear_autospawns():
14
+ # also need to edit the yas_marina_env.json to have autospawn for this config
15
+ sim_path = os.environ.get('AVRS_INSTALL_PATH',
16
+ os.path.join(os.environ['HOME'], 'autoverse-linux'))
17
+ sim_saved = os.path.join(sim_path, 'Linux', 'Autoverse', 'Saved')
18
+ cfg_files = SimConfigFiles(sim_saved)
19
+
20
+ cfg_ok, msg = cfg_files.validate()
21
+ if not cfg_ok:
22
+ print(msg)
23
+ return
24
+
25
+ cfg_files.files['yas']['autoSpawnObjects'] = []
26
+ cfg_files.save()
27
+
28
+ def register_received_vehicle(team_name, slot, cfg_data, bsu_vcan, kistler_vcan, badenia_vcan):
29
+ cfg_string = base64.b64decode(cfg_data)
30
+ cfg_object = json.loads(cfg_string.decode('utf-8'))
31
+
32
+ # ensure perception is disabled
33
+ eav24 = get_payload(cfg_object, 'Eav24Initializer')
34
+ if eav24 is None:
35
+ return (False, 'no eav24 payload found')
36
+
37
+ eav24['body']['bLidarEnabled'] = False
38
+ eav24['body']['bCameraEnabled'] = False
39
+ eav24['body']['bRadarEnabled'] = False
40
+ eav24['body']['bPublishGroundTruth'] = False
41
+ eav24['body']['bPublishInputs'] = False
42
+ eav24['body']['bsuCanName'] = bsu_vcan
43
+ eav24['body']['kistlerCanName'] = kistler_vcan
44
+ eav24['body']['badeniaCanName'] = badenia_vcan
45
+
46
+ # do not allow default object name (collision)
47
+ if cfg_object['name'] == 'eav24':
48
+ cfg_object['name'] = team_name
49
+ cfg_object['specName'] = 'eav24_{}'.format(team_name)
50
+
51
+ # also need to edit the yas_marina_env.json to have autospawn for this config
52
+ sim_path = os.environ.get('AVRS_INSTALL_PATH',
53
+ os.path.join(os.environ['HOME'], 'autoverse-linux'))
54
+ sim_saved = os.path.join(sim_path, 'Linux', 'Autoverse', 'Saved')
55
+ cfg_files = SimConfigFiles(sim_saved)
56
+
57
+ cfg_ok, msg = cfg_files.validate()
58
+ if not cfg_ok:
59
+ print(msg)
60
+ return
61
+
62
+ start_landmark = 'MvStart{}'.format(slot)
63
+
64
+ entry_exists = False
65
+ for i in cfg_files.files['yas']['autoSpawnObjects']:
66
+ if 'objectSpec' in i and i['objectSpec'] == cfg_object['specName']:
67
+ entry_exists = True
68
+
69
+ if not entry_exists:
70
+ cfg_files.files['yas']['autoSpawnObjects'].append({
71
+ 'bShouldSpawn': True,
72
+ 'objectType': 'Eav24',
73
+ 'objectSpec': cfg_object['specName'],
74
+ 'bSpawnAtLandmark': True,
75
+ 'spawnLandmarkName': start_landmark
76
+ })
77
+ cfg_files.save()
78
+
79
+ target_path = os.path.join(os.environ['HOME'], 'test_cfg.json')
80
+ with open(target_path, 'w', encoding='utf-8') as f:
81
+ json.dump(cfg_object, f, ensure_ascii=False, indent=4)
82
+
83
+ def prepare_vehicle_cfg(cfg_path):
84
+
85
+ #print('preparing config for transmission: {}'.format(cfg_path))
86
+
87
+ if not os.path.isfile(cfg_path):
88
+ return (False, '{} is not a valid file'.format(cfg_path))
89
+
90
+ cfg_object = {}
91
+ with open(cfg_path, 'r', encoding='utf-8') as f:
92
+ cfg_object = json.load(f)
93
+
94
+
95
+ # obtain desired CAN names to start cannelloni
96
+ eav24 = get_payload(cfg_object, 'Eav24Initializer')
97
+ if eav24 is None:
98
+ return (False, 'no eav24 payload found')
99
+
100
+ bsu_vcan = eav24['body']['bsuCanName']
101
+ kistler_vcan = eav24['body']['kistlerCanName']
102
+ badenia_vcan = eav24['body']['badeniaCanName']
103
+
104
+ cfg_data = base64.b64encode(json.dumps(cfg_object).encode('utf-8')).decode('utf-8')
105
+ return (True, cfg_data, bsu_vcan, kistler_vcan, badenia_vcan)
106
+
@@ -0,0 +1,237 @@
1
+ import os
2
+ import json
3
+ import http.client
4
+ from avrs.util import *
5
+
6
+ BASH_KILL_PROCESS_SCRIPT = '''
7
+ PROC_NAME={pname}
8
+ I=0
9
+ TRIES=20
10
+ while [ $I -le $TRIES ]; do
11
+
12
+ pkill $PROC_NAME
13
+ PROC_RUNNING=$(ps -A | grep $PROC_NAME)
14
+ if [[ ! -z $PROC_RUNNING ]]; then
15
+ echo process $PROC_NAME is still running
16
+ if [ $I == $(( TRIES - 1 )) ]; then
17
+ echo process is resisting. crushing its dreams with sigkill
18
+ pkill -SIGKILL $PROC_NAME
19
+ fi
20
+ else
21
+ echo process $PROC_NAME is not running
22
+ break
23
+ fi
24
+ I=$(( I + 1 ))
25
+ sleep 1
26
+ done
27
+ '''
28
+
29
+ DEFAULT_RMW_QOS = '''
30
+ <?xml version="1.0" encoding="UTF-8" ?>
31
+ <profiles xmlns="http://www.eprosima.com/XMLSchemas/fastRTPS_Profiles">
32
+ <transport_descriptors>
33
+ <transport_descriptor>
34
+ <transport_id>morepeers</transport_id> <!-- string -->
35
+ <type>UDPv4</type> <!-- string -->
36
+ <maxInitialPeersRange>100</maxInitialPeersRange> <!-- uint32 -->
37
+ </transport_descriptor>
38
+ </transport_descriptors>
39
+ <participant profile_name="participant_profile_ros2" is_default_profile="true">
40
+ <rtps>
41
+ <builtin>
42
+ <metatrafficUnicastLocatorList>
43
+ <locator/>
44
+ </metatrafficUnicastLocatorList>
45
+ <initialPeersList>
46
+ <locator> <udpv4> <address>127.0.0.1</address> </udpv4> </locator>
47
+ <!--<locator> <udpv4> <address>PEER_0</address> </udpv4> </locator>PEER0-->
48
+ <!--<locator> <udpv4> <address>PEER_1</address> </udpv4> </locator>PEER1-->
49
+ <!--<locator> <udpv4> <address>PEER_2</address> </udpv4> </locator>PEER2-->
50
+ <!--<locator> <udpv4> <address>PEER_3</address> </udpv4> </locator>PEER3-->
51
+ <!--<locator> <udpv4> <address>PEER_4</address> </udpv4> </locator>PEER4-->
52
+ <!--<locator> <udpv4> <address>PEER_5</address> </udpv4> </locator>PEER5-->
53
+ </initialPeersList>
54
+ </builtin>
55
+ <userTransports>
56
+ <transport_id>morepeers</transport_id>
57
+ </userTransports>
58
+ <useBuiltinTransports>false</useBuiltinTransports>
59
+ </rtps>
60
+ </participant>
61
+ </profiles>
62
+ '''
63
+
64
+ DISABLE_PEER_QOS_SCRIPT = '''
65
+ QOS_FILE_PATH={qos_path}
66
+ PEER_ID={peer_id}
67
+ sed -i -E "s,(<locator> <udpv4> <address>)(.+)(</address> </udpv4> </locator>)<!--(PEER$PEER_ID-->),<!--\\1PEER$PEER_ID\\3\\4,g" $QOS_FILE_PATH
68
+
69
+ VCAN_NAME=vcan$PEER_ID
70
+ if [[ -e $VCAN_NAME.lock ]]; then
71
+ echo "stopping existing cannelloni connection with pid $(cat $VCAN_NAME.lock)"
72
+ kill $(cat $VCAN_NAME.lock)
73
+ rm $VCAN_NAME.lock
74
+ fi
75
+ '''
76
+
77
+ ENABLE_PEER_QOS_SCRIPT = '''
78
+ QOS_FILE_PATH={qos_path}
79
+ PEER_ID={peer_id}
80
+ PEER_ADDRESS={peer_ip}
81
+ sed -i -E "s,(<!--?)(<locator> <udpv4> <address>)(.+)(</address> </udpv4> </locator>)(PEER$PEER_ID-->),\\2$PEER_ADDRESS\\4<!--\\5,g" $QOS_FILE_PATH
82
+ '''
83
+
84
+ CONNECT_PEER_VCAN_SCRIPT = '''
85
+ PEER_ID={peer_id}
86
+ PEER_ADDRESS={peer_ip}
87
+ REMOTE_PORT={remote_port}
88
+ LOCAL_PORT={local_port}
89
+ VCAN_NAME={vcan_name}
90
+ LOCK_FILE=$HOME/.$VCAN_NAME.lock
91
+ LOG_FILE="$HOME/.$VCAN_NAME.log"
92
+ if [[ -z $VCAN_NAME ]]; then
93
+ VCAN_NAME=vcan$PEER_ID
94
+ fi
95
+ echo "connecting peer id $PEER_ID using local port $LOCAL_PORT and remote port $REMOTE_PORT and vcan name $VCAN_NAME"
96
+
97
+ if [[ -e $LOCK_FILE ]]; then
98
+ echo "stopping existing cannelloni connection with pid $(cat $LOCK_FILE)"
99
+ kill $(cat $LOCK_FILE)
100
+ fi
101
+
102
+ # https://stackoverflow.com/questions/29142/getting-ssh-to-execute-a-command-in-the-background-on-target-machine
103
+ # nohup to avoid SSH issues, send stdout to loni.log, send stderr to stdout, dont expect input, and background with "&"
104
+ nohup cannelloni -I $VCAN_NAME -R $PEER_ADDRESS -r $REMOTE_PORT -l $LOCAL_PORT >"$LOG_FILE" 2>&1 < /dev/null &
105
+ echo "$!" > $LOCK_FILE
106
+ '''
107
+
108
+ CHECK_VCAN_EXISTS_SCRIPT = '''
109
+ if [[ -z $(ip addr show | grep {vcan_name}) ]]; then
110
+ echo -n "no"
111
+ else
112
+ echo -n "yes"
113
+ fi
114
+ '''
115
+
116
+ GET_EC2_LOCAL_IP_SCRIPT = '''
117
+ echo -n $(ec2metadata --local-ipv4)
118
+ '''
119
+
120
+ # kill a process with a given name
121
+ def bash_kill_process(pname):
122
+ return run_process(['bash', '-c',
123
+ BASH_KILL_PROCESS_SCRIPT.format(**{'pname': pname})])
124
+
125
+ # start an exectuable in the background, sending output to a file
126
+ # stored at root with its name
127
+ def start_exe(exe_path):
128
+ return run_process(['bash', '-c',
129
+ 'nohup {} > ~/{}_output.log 2>&1 < /dev/null &'.format(exe_path, os.path.basename(exe_path))])
130
+
131
+ def get_sim_install_path():
132
+ sim_path = os.environ.get('AVRS_INSTALL_PATH',
133
+ os.path.join(os.environ['HOME'], 'autoverse-linux'))
134
+ return sim_path
135
+
136
+ def get_rmw_qos_path():
137
+ return os.path.join(os.environ['HOME'], '.rmw_qos.xml')
138
+
139
+ def reset_rmw_qos():
140
+ with open(get_rmw_qos_path(), 'w', encoding='utf-8') as f:
141
+ f.write(DEFAULT_RMW_QOS)
142
+
143
+ def disable_peer_qos(peer_id):
144
+ if not os.path.isfile(get_rmw_qos_path()):
145
+ reset_rmw_qos()
146
+ pargs = {
147
+ 'qos_path': get_rmw_qos_path(),
148
+ 'peer_id': peer_id
149
+ }
150
+ return run_process(['bash', '-c',
151
+ DISABLE_PEER_QOS_SCRIPT.format(**pargs)])
152
+
153
+ def enable_peer_qos(peer_id, peer_ip):
154
+ disable_peer_qos(peer_ip) # disable first
155
+ pargs = {
156
+ 'qos_path': get_rmw_qos_path(),
157
+ 'peer_id': peer_id,
158
+ 'peer_ip': peer_ip
159
+ }
160
+ return run_process(['bash', '-c',
161
+ ENABLE_PEER_QOS_SCRIPT.format(**pargs)])
162
+
163
+ def check_vcan_exists(vcan_name):
164
+ pargs = {
165
+ 'vcan_name': vcan_name
166
+ }
167
+ pres = run_process(['bash', '-c',
168
+ CHECK_VCAN_EXISTS_SCRIPT.format(**pargs)])
169
+ return pres.out == 'yes'
170
+
171
+ def get_auto_vcan_name(peer_id, vcan_id):
172
+ return 'vcan{}_{}'.format(peer_id, vcan_id)
173
+
174
+ def connect_peer_vcan(peer_id, peer_ip, vcan_id, vcan_name=''):
175
+ vcan_id = 0
176
+ pargs = {
177
+ 'peer_id': peer_id,
178
+ 'peer_ip': peer_ip,
179
+ 'remote_port': 20000 + peer_id * 3 + vcan_id, # three ports per peer_id
180
+ 'local_port': 20000 + peer_id * 3 + vcan_id,
181
+ 'vcan_name': vcan_name if vcan_name != '' else get_auto_vcan_name(peer_id, vcan_id)
182
+ }
183
+ return run_process(['bash', '-c',
184
+ CONNECT_PEER_VCAN_SCRIPT.format(**pargs)])
185
+
186
+ def get_local_instance_ip():
187
+ try:
188
+ pres = run_process(['bash', '-c', GET_EC2_LOCAL_IP_SCRIPT])
189
+ return pres.out
190
+ except:
191
+ return '127.0.0.1'
192
+
193
+ def reset_race_cloud_connection():
194
+ reset_rmw_qos()
195
+ run_process(['bash', '-c', 'rm ~/.simslot*']) # remove slot reservations
196
+ run_process(['bash', '-c', 'rm ~/.vcan*']) # remove lock files
197
+ bash_kill_process('cannelloni')
198
+
199
+ def try_get_open_slot(team_name, ip):
200
+
201
+ slot_file_dir = os.environ['HOME']
202
+ for i in range(6):
203
+ slot_file_path = os.path.join(slot_file_dir, '.simslot_{}'.format(i))
204
+
205
+ if os.path.isfile(slot_file_path):
206
+ with open(slot_file_path, 'r', encoding='utf-8') as f:
207
+ content = f.read()
208
+ if content == ip:
209
+ return (True, 'slot {} is already reserved by you'.format(i), i)
210
+ else:
211
+ with open(slot_file_path, 'w', encoding='utf-8') as f:
212
+ f.write(ip)
213
+ return (True, 'reserved slot {}'.format(i), i)
214
+ return (False, 'no open slots', i)
215
+
216
+
217
+ def call_race_cloud_api(body):
218
+ api_url = 'gitzels0l7.execute-api.us-east-1.amazonaws.com'
219
+
220
+ connection = http.client.HTTPSConnection(api_url)
221
+ headers = {
222
+ 'Content-type': 'application/json',
223
+ 'x-api-key': '7aQ83sJ89Q2DZ8NdIi9aUTBuUS2uyix5QoDwrl1j'
224
+ }
225
+ body = json.dumps(body).encode('utf-8')
226
+ connection.request('POST', '/beta/connect', body, headers)
227
+ response = connection.getresponse()
228
+ if response.status != 200:
229
+ return (False, 'response had status code {}'.format(response))
230
+ return (True, response.read().decode('utf-8'))
231
+
232
+ def get_api_script_response(raw):
233
+ decoded = json.loads(raw)['body']
234
+ if decoded['script_response']['statusCode'] != 200:
235
+ return (False, 'inner response had bad status code {}'.format(decoded))
236
+ #print(decoded)
237
+ return (True, json.loads(decoded['script_response']['body']), decoded['sim_private_ip'])
@@ -0,0 +1,14 @@
1
+ from avrs.requests.request import AvrsApiRequest
2
+
3
+ class AvrsDumpSimConfigRequest(AvrsApiRequest):
4
+ def __init__(self, parser, cfg):
5
+ AvrsApiRequest.__init__(self, parser, cfg, 'DumpSimConfig', '')
6
+ psr = parser.add_parser(
7
+ 'dump-sim-config',
8
+ help='dump all currently loaded configuration from the simulation')
9
+
10
+ psr.set_defaults(func=self.send_request)
11
+
12
+ def get_request_body(self, args):
13
+ return {
14
+ }
@@ -12,6 +12,7 @@ class AvrsApiRequest:
12
12
  self.target_object_id = target_id
13
13
  self.request_type = request_type
14
14
  self.verbose = False
15
+ self.cfg = cfg
15
16
 
16
17
  def get_request(self, args):
17
18
  body = self.get_request_body(args)
@@ -38,7 +39,11 @@ class AvrsApiRequest:
38
39
  # print('{}'.format(response))
39
40
 
40
41
  def send_http_request(self, args):
41
- connection = http.client.HTTPConnection("localhost", 30313, timeout=10)
42
+ sim_address = 'localhost'
43
+ if 'sim_address' in self.cfg:
44
+ sim_address = self.cfg['sim_address']
45
+ connection_addr = os.environ.get('AVRS_SIM_ADDRESS', 'localhost')
46
+ connection = http.client.HTTPConnection(connection_addr, 30313, timeout=10)
42
47
  headers = {'Content-type': 'application/json'}
43
48
  body = json.dumps(self.get_request(args)).encode('utf-8')
44
49
  connection.request('POST', '/post', body, headers)
@@ -11,13 +11,13 @@ class SimConfigFiles():
11
11
  }
12
12
  self.files = {}
13
13
 
14
- ok, status = self.valdiate()
14
+ ok, status = self.validate()
15
15
  if ok:
16
16
  for name, path in self.required_files.items():
17
17
  with open(path, 'r', encoding='utf-8') as f:
18
18
  self.files[name] = json.load(f)
19
19
 
20
- def valdiate(self):
20
+ def validate(self):
21
21
  for name, path in self.required_files.items():
22
22
  if not os.path.exists(path):
23
23
  return (False, '{} not found'.format(path))
@@ -32,11 +32,11 @@ def compare_simconfig_defaults(sim_saved_dir, new_defaults_dir):
32
32
  old_cfg_files = SimConfigFiles(sim_saved_dir)
33
33
  new_cfg_files = SimConfigFiles(new_defaults_dir)
34
34
 
35
- ok, status = old_cfg_files.valdiate()
35
+ ok, status = old_cfg_files.validate()
36
36
  if not ok:
37
37
  print(status)
38
38
  return
39
- ok, status = new_cfg_files.valdiate()
39
+ ok, status = new_cfg_files.validate()
40
40
  if not ok:
41
41
  print(status)
42
42
  return
@@ -0,0 +1,13 @@
1
+ import subprocess
2
+
3
+ class ProcessResult():
4
+ def __init__(self, pres):
5
+ self.out = pres.stdout.decode('utf-8')
6
+ self.err = pres.stderr.decode('utf-8')
7
+
8
+ def run_process(args):
9
+ result = subprocess.run(
10
+ args,
11
+ stdout=subprocess.PIPE,
12
+ stderr=subprocess.PIPE)
13
+ return ProcessResult(result)
@@ -1,112 +0,0 @@
1
- from avrs.requests.request import AvrsApiRequest
2
- from argparse import RawTextHelpFormatter
3
-
4
- RESERVE_MV_SLOT_HELP = '''
5
- slot (if an open slot exists, there are 4 total) using the given name to add a new vehicle and the appropriate topics.
6
- It will despawn the default vehicle and remove the default ROS topics when it is first run. Each vehicle added will be
7
- given its own topics prefixed by the given name, and the slot index will correspond to the vcan it will use.
8
- Note that this will require having active vcans for each vehicle you wish to use.
9
- (eg, if you want to use 4 vehicles, you will need vcan0, vcan1, vcan2, and vcan3)
10
- '''
11
-
12
- # use these to spawn MVs
13
- MV_LANDMARKS = [
14
- 'MvStart0',
15
- 'MvStart1',
16
- 'MvStart2',
17
- 'MvStart3'
18
- ]
19
-
20
- class ReserveMvSlot(AvrsApiRequest):
21
- def __init__(self, parser, cfg):
22
- AvrsApiRequest.__init__(self, parser, cfg, 'SpawnObject', 0)
23
- psr = parser.add_parser('reserve-mv-slot', help=RESERVE_MV_SLOT_HELP, formatter_class=RawTextHelpFormatter)
24
-
25
- psr.add_argument(
26
- 'slot_name',
27
- help='the name of the vehicle to put in the specified slot')
28
-
29
- psr.add_argument(
30
- 'slot_index',
31
- type=int,
32
- choices=[0, 1, 2, 3],
33
- help='the slot index (0-4) to reserve')
34
-
35
- psr.add_argument(
36
- '--bsu-can-name',
37
- default='vcan0',
38
- help='the name of the CAN interface to use for the BSU CAN bus on the new vehicle')
39
-
40
- psr.add_argument(
41
- '--kistler-can-name',
42
- default='vcan1',
43
- help='the name of the CAN interface to use for the Kistler CAN bus on the new vehicle')
44
-
45
- psr.add_argument(
46
- '--badenia-can-name',
47
- default='vcan2',
48
- help='the name of the CAN interface to use for the bandanania CAN bus on the new vehicle')
49
-
50
- psr.add_argument(
51
- '--with-view-cameras',
52
- action='store_true',
53
- help='if the new vehicle should have cameras attached to it')
54
-
55
- psr.add_argument(
56
- '--enable-lidar',
57
- action='store_true',
58
- help='if set, the lidar will be enabled on the new vehicle')
59
-
60
- psr.add_argument(
61
- '--enable-camera-sensor',
62
- action='store_true',
63
- help='if set, the camera will be enabled on the new vehicle')
64
-
65
- psr.add_argument(
66
- '--disable-hud',
67
- action='store_true',
68
- help='if set, the new vehicle will not create a HUD (mutiple HUDs will clutter the screen)')
69
-
70
-
71
- psr.set_defaults(func=self.send_request)
72
-
73
- def get_request_body(self, args):
74
-
75
- eav_init_pld = {
76
- 'TypeName': 'Eav24Initializer',
77
- 'Body': {
78
- 'bsuCanName': args.bsu_can_name,
79
- 'kistlerCanNam': args.kistler_can_name,
80
- 'badeniaCanName': args.badenia_can_name,
81
- 'bHudEnabled': not args.disable_hud,
82
- 'bEnableLidar': args.enable_lidar,
83
- 'bEnableCameraSensor': args.enable_camera_sensor
84
- }
85
- }
86
-
87
- plds = [
88
- eav_init_pld
89
- ]
90
-
91
- if args.with_view_cameras:
92
- plds.append(
93
- {
94
- 'TypeName': 'InitializerTemplates',
95
- 'Body': {
96
- 'Templates': [
97
- {
98
- 'PayloadType': 'SimViewTargetIpd',
99
- 'PayloadSpec': 'DefaultCarCams'
100
- }
101
- ]
102
- }
103
- })
104
-
105
- return {
106
- 'Name': args.slot_name,
107
- 'Type': 'Eav24',
108
- 'Location': {},
109
- 'Rotation': {},
110
- 'Landmark': MV_LANDMARKS[args.slot_index],
111
- 'Payloads': plds
112
- }
File without changes
File without changes
File without changes