autoverse-cli 0.15.6__py3-none-any.whl → 0.16.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: autoverse-cli
3
- Version: 0.15.6
3
+ Version: 0.16.0
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,5 +1,5 @@
1
1
  avrs/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
- avrs/app_version.py,sha256=v9Br085iieKNuq_J6EGpa-bvsQvMt3AKhZyvMLN7GQ8,856
2
+ avrs/app_version.py,sha256=7W2iCUcjMLDoPUFUQQ3wOD_8Y6jZGALXahaqavBW6Lk,856
3
3
  avrs/argparse_help.py,sha256=EoEaohGXZXqJvs1dFEzbo9vh47CYdHdSY2Im2Ps2iFo,945
4
4
  avrs/avrs.py,sha256=bGF35a72MZU41OVWnFHmchqmgKXBKh9djokzGA_4pL4,4621
5
5
  avrs/can_tool.py,sha256=IBoctKobBJ3wCq4ZdtuXuXH4AMEUxazCfYT6YP0Luw8,7161
@@ -7,10 +7,11 @@ avrs/can_tool_util.py,sha256=G3q21dTGMLc09SDq_RieoW7kSn-kXPkXxPDjavPh4hQ,7710
7
7
  avrs/cfg.py,sha256=kMn08Z4Ms1PAu2-U1QI8weEJeIVEppP4A4_tFfwnjtg,2924
8
8
  avrs/launcher.py,sha256=kk1lyHHLgFZ4zsFfa_zV5f1kYbUODT6wEILJ8TZ16rQ,9353
9
9
  avrs/launcher_util.py,sha256=sO3k_z3A-HIQdJVkVXNXUAE_MGFwAYiZUqQBoFwOqew,5325
10
- avrs/race_cloud.py,sha256=8VHOrmCgdXKBBmAiX2e-muJ3dMxijwyJ7acR-LxytFo,19011
10
+ avrs/race_cloud.py,sha256=Fm0hA7eCYnh3occXD6hWt7svoyXg90b3_ChZS6AELeA,19802
11
+ avrs/race_cloud_bridge_can.py,sha256=aPA9AWjHa93axB4-J4F4LrAil_qcecHMsCaMOkssR5I,2329
11
12
  avrs/race_cloud_cfg_util.py,sha256=H3MLxkb-PBwFVXdA5IBGzWGjLeD-uBvPqIgkh7RGjfo,7214
12
13
  avrs/race_cloud_fwd_api.py,sha256=HuLE5kfmzVq08aP3tlEh3f8WNjGL5N3K5EbXg9uQomo,1506
13
- avrs/race_cloud_util.py,sha256=7pi6x2lgCqEgwmo3HXbdBZiCj43rTw5U9a1UDcClLm8,10753
14
+ avrs/race_cloud_util.py,sha256=RWD6-zZVQ_iud1QzhdtRtZ8r0jEPcxbYcDaMJ7vb6-Q,12555
14
15
  avrs/simconfig.py,sha256=UZc4FrxVHUkk2e9IglSpuojXkaL_nPrJW7trbEGgOOo,2907
15
16
  avrs/simconfig_util.py,sha256=1RmnmhK5C4HlCicTQeqn-1ORz3Xrku_QMt1Fqr9XjZs,4839
16
17
  avrs/tests.py,sha256=3JeYBjn0tRqHXERDROfzmYuW1KXeCcKur5Bw-EIegto,153
@@ -37,9 +38,9 @@ avrs/requests/toggle_hud.py,sha256=sV5t5QZc4uvRihPVk8jEKZiQNsyF9tsUwq5b4jjZplc,3
37
38
  avrs/requests/vd.py,sha256=gdt5XCdCCVdECL3qt8y-PKDrlArjeY_lxtT4VpZmAJo,1804
38
39
  avrs/requests/vehicle_input.py,sha256=R1b1xkRtOBkwyU6OSN4bWVlYsIUroZG0WKbYbc4pEH8,729
39
40
  avrs/requests/vehicle_replay.py,sha256=nCAE21VNyKoeIjjXBGAihgOLO7zYHcu-HWvPZYxdQ2c,11099
40
- autoverse_cli-0.15.6.dist-info/LICENSE,sha256=d4eWXho-u18HkBsX4K21uHX_bBb2UXZSrJdsb7Z_JlM,2647
41
- autoverse_cli-0.15.6.dist-info/METADATA,sha256=sqc7xxvBENurbIEumRCVIlFV-FbVPacL8sfFVpNlMZM,3342
42
- autoverse_cli-0.15.6.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
43
- autoverse_cli-0.15.6.dist-info/entry_points.txt,sha256=Cb9qsUyU5AKkklehCcvtfT0-N3SXbUEqvjze4iEU5kE,40
44
- autoverse_cli-0.15.6.dist-info/top_level.txt,sha256=-AJO2e4MCVej6hY0U84pu5NfMeMW5qaAPSMisDT5rmA,5
45
- autoverse_cli-0.15.6.dist-info/RECORD,,
41
+ autoverse_cli-0.16.0.dist-info/LICENSE,sha256=d4eWXho-u18HkBsX4K21uHX_bBb2UXZSrJdsb7Z_JlM,2647
42
+ autoverse_cli-0.16.0.dist-info/METADATA,sha256=HTEM3UstpFdi9vnb1ohrOFEEzpVobYM0faeRbBed8Wo,3342
43
+ autoverse_cli-0.16.0.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
44
+ autoverse_cli-0.16.0.dist-info/entry_points.txt,sha256=Cb9qsUyU5AKkklehCcvtfT0-N3SXbUEqvjze4iEU5kE,40
45
+ autoverse_cli-0.16.0.dist-info/top_level.txt,sha256=-AJO2e4MCVej6hY0U84pu5NfMeMW5qaAPSMisDT5rmA,5
46
+ autoverse_cli-0.16.0.dist-info/RECORD,,
avrs/app_version.py CHANGED
@@ -2,7 +2,7 @@ import http.client
2
2
  import json
3
3
 
4
4
  def get_app_version():
5
- return '0.15.6'
5
+ return '0.16.0'
6
6
 
7
7
  def check_app_is_latest():
8
8
  pass
avrs/race_cloud.py CHANGED
@@ -123,23 +123,6 @@ class AvrsRaceCloud(AvrsApiRequest):
123
123
  help='the id of the peer to enable')
124
124
  disable_peer_qos_parser.set_defaults(func=self.disable_peer_qos)
125
125
 
126
- fwd_server_parser = sps.add_parser(
127
- 'fwd-api',
128
- help='forwards incoming external api requests to the simulator api')
129
- fwd_server_parser.add_argument(
130
- 'source_port',
131
- type=int,
132
- help='the external port to listen to external api requests on')
133
- fwd_server_parser.add_argument(
134
- 'target_port',
135
- type=int,
136
- help='the local port to forward api requests too')
137
- fwd_server_parser.add_argument(
138
- '--background',
139
- action='store_true',
140
- help='if true, will run the server in the background')
141
- fwd_server_parser.set_defaults(func=self.fwd_api)
142
-
143
126
  fwd_server_parser = sps.add_parser(
144
127
  'fwd-api',
145
128
  help='forwards incoming external api requests to the simulator api')
@@ -157,6 +140,31 @@ class AvrsRaceCloud(AvrsApiRequest):
157
140
  help='the local port to forward api requests too')
158
141
  fwd_server_parser.set_defaults(func=self.fwd_api)
159
142
 
143
+ bridge_can_parser = sps.add_parser(
144
+ 'bridge-can',
145
+ help='bridges a local vcan with a remote vcan over udp')
146
+
147
+ bridge_can_parser.add_argument(
148
+ 'vcan_name')
149
+
150
+ bridge_can_parser.add_argument(
151
+ 'mode',
152
+ choices=['bg', 'fg'],
153
+ help='whether to run in forground or background')
154
+
155
+ bridge_can_parser.add_argument(
156
+ 'peer_ip')
157
+
158
+ bridge_can_parser.add_argument(
159
+ 'peer_port',
160
+ type=int)
161
+
162
+ bridge_can_parser.add_argument(
163
+ 'local_port',
164
+ type=int)
165
+
166
+ bridge_can_parser.set_defaults(func=self.bridge_can)
167
+
160
168
  def race_connect(self, args):
161
169
  logger = logging.getLogger('avrs')
162
170
 
@@ -430,11 +438,13 @@ class AvrsRaceCloud(AvrsApiRequest):
430
438
  def enable_peer_qos(self, args):
431
439
  print('enabling peer qos for id {} using ip address {}'.format(
432
440
  args.peer_id, args.ip))
433
- enable_peer_qos(args.peer_id, args.ip)
441
+ out = enable_peer_qos(args.peer_id, args.ip)
442
+ print('{} {}'.format(out.out, out.err))
434
443
 
435
444
  def disable_peer_qos(self, args):
436
445
  print('disabling peer qos for id {}'.format(args.peer_id))
437
- disable_peer_qos(args.peer_id)
446
+ out = disable_peer_qos(args.peer_id)
447
+ print('{} {}'.format(out.out, out.err))
438
448
 
439
449
  def fwd_api(self, args):
440
450
  # start a server that listens for http on some port and forwards
@@ -443,7 +453,6 @@ class AvrsRaceCloud(AvrsApiRequest):
443
453
 
444
454
  if args.mode == 'bg':
445
455
  # call the cli so that it starts the forwarding server in the background
446
-
447
456
  # stop it if its already running
448
457
  try:
449
458
  stop_result = stop_fwd_api()
@@ -474,3 +483,20 @@ class AvrsRaceCloud(AvrsApiRequest):
474
483
  save_cfg('avrs', self.cfg)
475
484
  return elapsed
476
485
 
486
+ def bridge_can(self, args):
487
+ logger = logging.getLogger('avrs')
488
+
489
+ if args.mode == 'bg':
490
+ # call the cli so that it starts the forwarding server in the background
491
+ # stop it if its already running
492
+ try:
493
+ stop_result = stop_can_brdige()
494
+ logger.info('stopped can bridge: {}'.format(stop_result))
495
+ start_result = start_can_bridge(args)
496
+ logger.info('started can bridge: {}'.format(start_result))
497
+ except Exception as e:
498
+ logger.error('failed to restart can bridge: {}'.format(e))
499
+
500
+ else:
501
+ logger.info('starting can bridge in forground')
502
+ can_bridge_loop(args)
@@ -0,0 +1,77 @@
1
+ import can
2
+ import argparse
3
+ import socket
4
+ import struct
5
+
6
+ BUFFER_SIZE = 512
7
+
8
+ class UdpTxCanListener(can.Listener):
9
+ def __init__(self, target_port, target_ip):
10
+ self.target_port = target_port
11
+ self.target_ip = target_ip
12
+ self.s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
13
+
14
+ def on_message_received(self, msg):
15
+ #print('l got m {}'.format(msg))
16
+ data = struct.pack('=HBBBBBBBB', msg.arbitration_id, *msg.data)
17
+ self.s.sendto(data, (self.target_ip, self.target_port))
18
+
19
+ def can_bridge_loop(args):
20
+ logger = logging.getLogger('avrs')
21
+ logger.info('starting can bridge tx on {} to {}:{} (listen on {})'.format(
22
+ args.vcan_name, args.peer_ip, args.peer_port, args.local_port))
23
+ try:
24
+ s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
25
+ #s.settimeout(0.1)
26
+ s.bind(('', args.local_port))
27
+ with can.interface.Bus(args.vcan_name, interface='socketcan') as bus:
28
+ l = UdpTxCanListener(args.peer_port, args.peer_ip)
29
+ can.Notifier(bus, [l])
30
+ while True:
31
+ try:
32
+ data, server = s.recvfrom(BUFFER_SIZE)
33
+ #print('got udp data {}'.format(data))
34
+ up = struct.unpack('=HBBBBBBBB', data)
35
+
36
+ tx_msg = can.Message(
37
+ arbitration_id=up[0],
38
+ data=up[1:],
39
+ is_extended_id=False,
40
+ dlc=8)
41
+
42
+ bus.send(tx_msg)
43
+ except Exception as e:
44
+ logger.error('can bridge error: {}'.format(e))
45
+ break
46
+ except Exception as e:
47
+ logger.('can bridge setup error: {}'.format(e))
48
+ return
49
+
50
+ if __name__ == '__main__':
51
+
52
+ parser = argparse.ArgumentParser(
53
+ prog='canbridge',
54
+ description='can bridge')
55
+
56
+ vcan_name_psr = parser.add_argument(
57
+ 'vcan_name')
58
+
59
+ peer_ip_psr = parser.add_argument(
60
+ 'peer_ip')
61
+
62
+ peer_port_psr = parser.add_argument(
63
+ 'peer_port',
64
+ type=int)
65
+
66
+ peer_port_psr = parser.add_argument(
67
+ 'local_port',
68
+ type=int)
69
+
70
+ version_psr = parser.add_argument(
71
+ '--peer_ip',
72
+ help='')
73
+
74
+ parser.set_defaults(func=bridge_loop)
75
+
76
+ args = parser.parse_args()
77
+ args.func(args)
avrs/race_cloud_util.py CHANGED
@@ -62,11 +62,37 @@ DEFAULT_RMW_QOS = '''
62
62
  </profiles>
63
63
  '''
64
64
 
65
+ DEFAULT_RMW_CYCLONE = '''
66
+ <?xml version="1.0" encoding="UTF-8" ?>
67
+ <CycloneDDS>
68
+ <Domain id="any">
69
+ <Discovery>
70
+ <ParticipantIndex>auto</ParticipantIndex>
71
+ <Peers>
72
+ <Peer address='127.0.0.1'/>
73
+ <!--<Peer address='PEER_0'/>PEER0-->
74
+ <!--<Peer address='PEER_1'/>PEER1-->
75
+ <!--<Peer address='PEER_2'/>PEER2-->
76
+ <!--<Peer address='PEER_3'/>PEER3-->
77
+ <!--<Peer address='PEER_4'/>PEER4-->
78
+ <!--<Peer address='PEER_5'/>PEER5-->
79
+ </Peers>
80
+ </Discovery>
81
+ </Domain>
82
+ </CycloneDDS>
83
+ '''
84
+
65
85
  DISABLE_PEER_QOS_SCRIPT = '''
66
86
  QOS_FILE_PATH={qos_path}
87
+ CYCLONE_PATH={cyclone_path}
67
88
  PEER_ID={peer_id}
89
+
90
+ # for the origin rmw qos file
68
91
  sed -i -E "s,(<locator> <udpv4> <address>)(.+)(</address> </udpv4> </locator>)<!--(PEER$PEER_ID-->),<!--\\1PEER$PEER_ID\\3\\4,g" $QOS_FILE_PATH
69
92
 
93
+ # for the cyclone file
94
+ sed -i -E "s,(<Peer address=')(.+)('/>)<!--(PEER$PEER_ID-->),<!--\\1PEER$PEER_ID\\3\\4,g" $CYCLONE_PATH
95
+
70
96
  VCAN_NAME=vcan$PEER_ID
71
97
  if [[ -e $VCAN_NAME.lock ]]; then
72
98
  echo "stopping existing cannelloni connection with pid $(cat $VCAN_NAME.lock)"
@@ -77,9 +103,15 @@ DISABLE_PEER_QOS_SCRIPT = '''
77
103
 
78
104
  ENABLE_PEER_QOS_SCRIPT = '''
79
105
  QOS_FILE_PATH={qos_path}
106
+ CYCLONE_PATH={cyclone_path}
80
107
  PEER_ID={peer_id}
81
108
  PEER_ADDRESS={peer_ip}
109
+
110
+ # for the origin rmw qos file
82
111
  sed -i -E "s,(<!--?)(<locator> <udpv4> <address>)(.+)(</address> </udpv4> </locator>)(PEER$PEER_ID-->),\\2$PEER_ADDRESS\\4<!--\\5,g" $QOS_FILE_PATH
112
+
113
+ # for the cyclone file
114
+ sed -i -E "s,(<!--?)(<Peer address=')(.+)('/>)(PEER$PEER_ID-->),\\2$PEER_ADDRESS\\4<!--\\5,g" $CYCLONE_PATH
83
115
  '''
84
116
 
85
117
  CONNECT_PEER_VCAN_SCRIPT = '''
@@ -96,13 +128,13 @@ CONNECT_PEER_VCAN_SCRIPT = '''
96
128
  echo "connecting peer id $PEER_ID using local port $LOCAL_PORT and remote port $REMOTE_PORT and vcan name $VCAN_NAME" > "$LOG_FILE" 2>&1
97
129
 
98
130
  if [[ -e $LOCK_FILE ]]; then
99
- echo "stopping existing cannelloni connection with pid $(cat $LOCK_FILE)"
131
+ echo "stopping existing can_bridge connection with pid $(cat $LOCK_FILE)"
100
132
  kill $(cat $LOCK_FILE)
101
133
  fi
102
134
 
103
135
  # https://stackoverflow.com/questions/29142/getting-ssh-to-execute-a-command-in-the-background-on-target-machine
104
136
  # nohup to avoid SSH issues, send stdout to loni.log, send stderr to stdout, dont expect input, and background with "&"
105
- nohup cannelloni -I $VCAN_NAME -R $PEER_ADDRESS -r $REMOTE_PORT -l $LOCAL_PORT >>"$LOG_FILE" 2>&1 < /dev/null &
137
+ nohup avrs race-cloud bridge-can fg $PEER_ADDRESS $REMOTE_PORT $LOCAL_PORT >>"$LOG_FILE" 2>&1 < /dev/null &
106
138
  echo "$!" > $LOCK_FILE
107
139
  '''
108
140
 
@@ -166,15 +198,25 @@ def get_sim_exe_path():
166
198
  def get_rmw_qos_path():
167
199
  return os.path.join(os.environ['HOME'], '.rmw_qos.xml')
168
200
 
201
+ def get_rmw_cyclone_qos_path():
202
+ return os.path.join(os.environ['HOME'], '.cyclone.xml')
203
+
169
204
  def reset_rmw_qos():
170
205
  with open(get_rmw_qos_path(), 'w', encoding='utf-8') as f:
171
206
  f.write(DEFAULT_RMW_QOS)
172
207
 
208
+ def reset_rmw_cyclone_qos():
209
+ with open(get_rmw_cyclone_qos_path(), 'w', encoding='utf-8') as f:
210
+ f.write(DEFAULT_RMW_CYCLONE)
211
+
173
212
  def disable_peer_qos(peer_id):
174
213
  if not os.path.isfile(get_rmw_qos_path()):
175
214
  reset_rmw_qos()
215
+ if not os.path.isfile(get_rmw_cyclone_qos_path()):
216
+ reset_rmw_cyclone_qos()
176
217
  pargs = {
177
218
  'qos_path': get_rmw_qos_path(),
219
+ 'cyclone_path': get_rmw_cyclone_qos_path(),
178
220
  'peer_id': peer_id
179
221
  }
180
222
  return run_process(['bash', '-c',
@@ -184,6 +226,7 @@ def enable_peer_qos(peer_id, peer_ip):
184
226
  disable_peer_qos(peer_ip) # disable first
185
227
  pargs = {
186
228
  'qos_path': get_rmw_qos_path(),
229
+ 'cyclone_path': get_rmw_cyclone_qos_path(),
187
230
  'peer_id': peer_id,
188
231
  'peer_ip': peer_ip
189
232
  }
@@ -220,10 +263,18 @@ def stop_fwd_api():
220
263
  pres = run_process(['bash', '-c', STOP_FWD_API_SCRIPT])
221
264
  return pres.out
222
265
 
223
- def check_fwd_api_is_running():
224
- pres = run_process(['bash', '-c', CHECK_FWD_API_IS_RUNNING])
225
- print(pres.out)
226
- return pres.out == 'yes'
266
+ def start_can_bridge(args):
267
+ pargs = {
268
+ 'peer_ip': args.peer_ip,
269
+ 'peer_port': args.peer_port,
270
+ 'local_port': args.local_port
271
+ }
272
+ pres = run_process(['bash', 'c', START_CAN_BRIDGE_SCRIPT.format(**pargs)])
273
+ return pres.out
274
+
275
+ def stop_can_brdige():
276
+ pres = run_process(['bash'], '-c', STOP_CAN_BRIDGE_SCRIPT)
277
+ return pres.out
227
278
 
228
279
  def get_auto_vcan_name(peer_id, vcan_id):
229
280
  return 'vcan{}_{}'.format(peer_id, vcan_id)
@@ -252,6 +303,7 @@ def get_local_instance_ip():
252
303
 
253
304
  def reset_race_cloud_connection():
254
305
  reset_rmw_qos()
306
+ reset_rmw_cyclone_qos()
255
307
  run_process(['bash', '-c', 'rm ~/.simslot*']) # remove slot reservations
256
308
  run_process(['bash', '-c', 'rm ~/.vcan*']) # remove lock files
257
309
  bash_kill_process('cannelloni')