pycityagent 1.0.0__py3-none-any.whl → 1.1.1__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,5 +1,7 @@
1
1
  from typing import Optional, Union
2
2
  from datetime import datetime
3
+ import math
4
+ import copy
3
5
  from pycitysim.apphub import UserMessage, AgentMessage
4
6
  from citystreetview import (
5
7
  BaiduStreetView,
@@ -10,6 +12,81 @@ from citystreetview import (
10
12
  from .brainfc import BrainFunction
11
13
  from .static import POI_TYPE_DICT, LEVEL_ONE_PRE
12
14
 
15
+ def point_on_line_given_distance(start_node, end_node, distance):
16
+ """
17
+ Given two points (start_point and end_point) defining a line, and a distance s to travel along the line,
18
+ return the coordinates of the point reached after traveling s units along the line, starting from start_point.
19
+
20
+ Args:
21
+ start_point (tuple): Tuple of (x, y) representing the starting point on the line.
22
+ end_point (tuple): Tuple of (x, y) representing the ending point on the line.
23
+ distance (float): Distance to travel along the line, starting from start_point.
24
+
25
+ Returns:
26
+ tuple: Tuple of (x, y) representing the new point reached after traveling s units along the line.
27
+ """
28
+
29
+ x1, y1 = start_node['x'], start_node['y']
30
+ x2, y2 = end_node['x'], end_node['y']
31
+
32
+ # Calculate the slope m and the y-intercept b of the line
33
+ if x1 == x2:
34
+ # Vertical line, distance is only along the y-axis
35
+ return (x1, y1 + distance if distance >= 0 else y1 - abs(distance))
36
+ else:
37
+ m = (y2 - y1) / (x2 - x1)
38
+ b = y1 - m * x1
39
+
40
+ # Calculate the direction vector (dx, dy) along the line
41
+ dx = (x2 - x1) / math.sqrt((x2 - x1)**2 + (y2 - y1)**2)
42
+ dy = (y2 - y1) / math.sqrt((x2 - x1)**2 + (y2 - y1)**2)
43
+
44
+ # Scale the direction vector by the given distance
45
+ scaled_dx = dx * distance
46
+ scaled_dy = dy * distance
47
+
48
+ # Calculate the new point's coordinates
49
+ x = x1 + scaled_dx
50
+ y = y1 + scaled_dy
51
+
52
+ return [x, y]
53
+
54
+ def get_xy_in_lane(nodes, distance, direction:str='front'):
55
+ temp_sum = 0
56
+ remain_s = 0
57
+ if direction == 'front':
58
+ # 顺道路方向前进
59
+ if distance == 0:
60
+ return [nodes[0]['x'], nodes[0]['y']]
61
+ key_index = 0
62
+ for i in range(1, len(nodes)):
63
+ x1, y1 = nodes[i-1]['x'], nodes[i-1]['y']
64
+ x2, y2 = nodes[i]['x'], nodes[i]['y']
65
+ temp_sum += math.sqrt((x2 - x1)**2 + (y2-y1)**2)
66
+ if temp_sum > distance:
67
+ remain_s = distance - (temp_sum - math.sqrt((x2 - x1)**2 + (y2-y1)**2))
68
+ break;
69
+ key_index += 1
70
+ if remain_s < 0.5:
71
+ return [nodes[-1]['x'], nodes[-1]['y']]
72
+ longlat = point_on_line_given_distance(nodes[key_index], nodes[key_index+1], remain_s)
73
+ return longlat
74
+ else:
75
+ # 逆道路方向前进
76
+ key_index = len(nodes)
77
+ for i in range(len(nodes)-1, 0, -1):
78
+ x1, y1 = nodes[i]['x'], nodes[i]['y']
79
+ x2, y2 = nodes[i-1]['x'], nodes[i-1]['y']
80
+ temp_sum += math.sqrt((x2 - x1)**2 + (y2-y1)**2)
81
+ if temp_sum > distance:
82
+ remain_s = distance - (temp_sum - math.sqrt((x2 - x1)**2 + (y2-y1)**2))
83
+ break;
84
+ key_index -= 1
85
+ if remain_s < 0.5:
86
+ return [nodes[0]['x'], nodes[0]['y']]
87
+ longlat = point_on_line_given_distance(nodes[key_index], nodes[key_index-1], remain_s)
88
+ return longlat
89
+
13
90
  class SencePlug:
14
91
  """
15
92
  感知模块插件
@@ -31,35 +108,57 @@ class Sence(BrainFunction):
31
108
  """
32
109
  def __init__(self, agent, sence_raduis:int=10) -> None:
33
110
  super().__init__(agent)
34
- self._streetview_engine = ""
35
- self._streetviewAK = ""
36
- self._streetviewProxy = None
111
+
112
+ self._engine = None
113
+ self._baiduAK = None
114
+ self._googleProxy = None
37
115
  self._sence_radius = sence_raduis
38
116
  """
39
117
  感知半径
40
118
  The sence raduis: meter
41
119
  """
120
+
121
+ self._sence_contents = None
122
+ """
123
+ 感知内容 如果为None, 则感知所有数据类型
124
+ Sence content
125
+ """
126
+
42
127
  self.sence_buffer = {}
43
128
  """
44
129
  感知Buffer: 用于存储感知到的内容
45
130
  Sence Buffer: used to stroe those senced content
46
131
  """
132
+
47
133
  self.plugs = []
48
134
  """
49
135
  感知插件集合
50
136
  Collection of SencePlugs
51
137
  """
138
+
52
139
  self.plug_buffer = {}
53
140
  """
54
141
  感知插件结果Buffer: 用于存储感知插件的输出结果
55
142
  SencePlug Buffer: used to store those sence plug content
56
143
  """
144
+
57
145
  self.enable_streeview = False
58
146
  """
59
147
  街景感知功能接口, 默认为False
60
148
  Interface of streetview function, defualt: False
61
149
  """
62
150
 
151
+ self._lane_type_mapping = {1: 'driving', 2: 'walking'}
152
+
153
+ def set_sence(self, content: list):
154
+ """
155
+ 感知配置接口
156
+
157
+ Args:
158
+ - config: 配置选项——包含需要感知的内容
159
+ """
160
+ self._sence_contents = content
161
+
63
162
  def add_plugs(self, plugs:list[SencePlug]):
64
163
  """
65
164
  添加感知插件
@@ -87,7 +186,7 @@ class Sence(BrainFunction):
87
186
  """
88
187
  return super().state_influence()
89
188
 
90
- async def Sence(self) -> dict:
189
+ async def Sence(self):
91
190
  """
92
191
  感知功能主体
93
192
  Main function of sence
@@ -95,43 +194,71 @@ class Sence(BrainFunction):
95
194
  Returns:
96
195
  - (dict): the sence content in dict format
97
196
  - time (int): current time in second (from 00:00:00)
98
- - pois ()
197
+ - pois (list[tuple]): sorted with distance
198
+ - information of the poi
199
+ - distance(m)
200
+ - walking time (s)
201
+ - walking route (list)
202
+ - driving time (s)
203
+ - driving route (list)
204
+ - poi_time_walk (list[tuple]): sorted with walking time
205
+ - poi_time_drive (list[tuple]): sorted with driving time
206
+ - positions (list[position]): reachable positions
207
+ - lanes
208
+ - lane_ids
209
+ - persons
210
+ - streetview
211
+ - user_messages
212
+ - social_messages
99
213
  """
100
- self.state_influence()
101
214
  # * time
102
- self.sence_buffer['time'] = self._agent._simulator.time
215
+ if self._sence_contents == None or 'time' in self._sence_contents:
216
+ self.sence_buffer['time'] = self._agent._simulator.time
103
217
 
104
218
  # * pois
105
- self.sence_buffer['pois'] = self.PerceivePoi()
219
+ if self._sence_contents == None or 'poi' in self._sence_contents:
220
+ self.sence_buffer['pois'] = await self.PerceivePoi()
221
+ self.sence_buffer['poi_time_walk'] = sorted(self.sence_buffer['pois'], key=lambda x:x[2])
222
+ self.sence_buffer['poi_time_drive'] = sorted(self.sence_buffer['pois'], key=lambda x:x[4])
223
+
224
+ # * reachable positions
225
+ if self._sence_contents == None or 'position' in self._sence_contents:
226
+ self.sence_buffer['positions'] = await self.PerceiveReachablePosition()
106
227
 
107
228
  # * lanes
108
- self.sence_buffer['lanes'] = self.PerceiveLane()
109
- lane_ids = self.PerceiveLane(only_id=True)
110
- self.sence_buffer['lane_ids'] = lane_ids
229
+ if self._sence_contents == None or 'lane' in self._sence_contents:
230
+ self.sence_buffer['lanes'] = self.PerceiveLane()
231
+ lane_ids = self.PerceiveLane(only_id=True)
232
+ self.sence_buffer['lane_ids'] = lane_ids
111
233
 
112
234
  # * person
113
- self.sence_buffer['persons'] = []
114
- for lane_id in lane_ids:
115
- self.sence_buffer['persons'] += await self.PerceivePersonInLanes([lane_id])
116
- if 'aoi_position' in self._agent.motion['position'].keys():
117
- # 说明agent在aoi中
118
- persons_aoi = await self.PerceiveAoi(only_person=True)
119
- self.sence_buffer['persons'] += persons_aoi
235
+ if self._sence_contents == None or 'person' in self._sence_contents:
236
+ lane_ids = self.PerceiveLane(only_id=True)
237
+ self.sence_buffer['persons'] = []
238
+ for lane_id in lane_ids:
239
+ self.sence_buffer['persons'] += await self.PerceivePersonInLanes([lane_id])
240
+ if 'aoi_position' in self._agent.motion['position'].keys():
241
+ # 说明agent在aoi中
242
+ persons_aoi = await self.PerceiveAoi(only_person=True)
243
+ self.sence_buffer['persons'] += persons_aoi
120
244
 
121
245
  # * streetview
122
- if self.enable_streeview:
123
- self.sence_buffer['streetview'] = self.PerceiveStreetView()
124
- else:
125
- self.sence_buffer['streetview'] = None
246
+ if self._sence_contents == None or 'streetview' in self._sence_contents:
247
+ if self.enable_streeview:
248
+ self.sence_buffer['streetview'] = self.PerceiveStreetView()
249
+ else:
250
+ self.sence_buffer['streetview'] = None
126
251
 
127
252
  # * user message
128
- if self._agent.Hub != None:
129
- self.sence_buffer['user_messages'] = self.PerceiveUserMessage()
130
- else:
131
- self.sence_buffer['user_messages'] = []
253
+ if self._sence_contents == None or 'user_message' in self._sence_contents:
254
+ if self._agent.Hub != None:
255
+ self.sence_buffer['user_messages'] = self.PerceiveUserMessage()
256
+ else:
257
+ self.sence_buffer['user_messages'] = []
132
258
 
133
259
  # * agent message
134
- self.sence_buffer['social_messages'] = await self.PerceiveMessageFromPerson()
260
+ if self._sence_contents == None or 'agent_message' in self._sence_contents:
261
+ self.sence_buffer['social_messages'] = await self.PerceiveMessageFromPerson()
135
262
 
136
263
  # * 插件感知
137
264
  if len(self.plugs) > 0:
@@ -140,8 +267,6 @@ class Sence(BrainFunction):
140
267
  out = plug.user_func(self.sence_buffer)
141
268
  self.plug_buffer[out_key] = out
142
269
 
143
- return self.sence_buffer
144
-
145
270
  # * AOI and POI Related
146
271
  async def PerceiveAoi(self, only_person:bool=False):
147
272
  """
@@ -160,7 +285,145 @@ class Sence(BrainFunction):
160
285
  return persons
161
286
  return resp['states'][0]
162
287
 
163
- def PerceivePoi(self, radius:int=None, category:str=None):
288
+ async def PerceiveReachablePosition(self, radius:int=None) -> Optional[list[dict]]:
289
+ '''
290
+ 可达位置感知
291
+ Reachable Position Perceive
292
+
293
+ Args:
294
+ - radius (int): 感知半径; Perceive radius
295
+
296
+ Returns:
297
+ - List[dict]: 可达位置列表
298
+ - lane_id (int)
299
+ - s (float)
300
+ - xy (Tuple[float, float]): (x, y)
301
+ - longlat (Tuple[float, float]): (longitude, latitude)
302
+ - type (str): 'driving' / 'walking' / 'unspecified'
303
+ '''
304
+ radius_ = self._sence_radius
305
+ if radius != None:
306
+ radius_ = radius
307
+ positions = []
308
+ if 'aoi_position' in self._agent.motion['position'].keys():
309
+ # agent in aoi
310
+ positions = []
311
+ aoi_id = self._agent.motion['position']['aoi_position']['aoi_id']
312
+ aoi = copy.deepcopy(self._agent._simulator.map.get_aoi(aoi_id))
313
+ driving_positions = aoi['driving_positions']
314
+ driving_gates = aoi['driving_gates']
315
+ walking_positions = aoi['walking_positions']
316
+ walking_gates = aoi['walking_gates']
317
+ for i in range(len(driving_positions)):
318
+ longlat = self._agent._simulator.map.xy2lnglat(x=driving_gates[i]['x'], y=driving_gates[i]['y'])
319
+ positions.append({
320
+ 'lane_id': driving_positions[i]['lane_id'],
321
+ 's': driving_positions[i]['s'],
322
+ 'xy': (driving_gates[i]['x'], driving_gates[i]['y']),
323
+ 'longlat': longlat,
324
+ 'type': 'driving'
325
+ })
326
+ for i in range(len(walking_positions)):
327
+ longlat = self._agent._simulator.map.xy2lnglat(x=walking_gates[i]['x'], y=walking_gates[i]['y'])
328
+ positions.append({
329
+ 'lane_id': walking_positions[i]['lane_id'],
330
+ 's': walking_positions[i]['s'],
331
+ 'xy': (walking_gates[i]['x'], walking_gates[i]['y']),
332
+ 'longlat': longlat,
333
+ 'type': 'walking'
334
+ })
335
+ else:
336
+ # agent in lane
337
+ lane_id = self._agent.motion['position']['lane_position']['lane_id'] # 所在lane_id
338
+ lane = copy.deepcopy(self._agnet._simualtor.map.get_lane(lane_id)) # 获取lane信息
339
+ agent_s = self._agent.motion['position']['lane_position']['s'] # 所处位置——用s距离表示
340
+ nodes = lane['center_line']['nodes']
341
+ if agent_s == 0:
342
+ # 处于当前道路的首部端点位置
343
+ # 1. 当前道路
344
+ tmp_s = radius_
345
+ tmp_s = tmp_s if tmp_s <= lane['length'] else lane['length']
346
+ x, y = get_xy_in_lane(nodes, tmp_s)
347
+ longlat = self._agent._simulator.map.xy2lnglat(x=x, y=y)
348
+ type = copy.deepcopy(self._lane_type_mapping.get(lane['type'], 'unspecified'))
349
+ positions += [{'lane_id': lane_id,
350
+ 's': tmp_s,
351
+ 'xy': (x, y),
352
+ 'longlat': longlat,
353
+ 'type': type}]
354
+
355
+ # 2. 前驱道路
356
+ pre_lanes = lane['predecessors']
357
+ for pre_lane in pre_lanes:
358
+ pre_lane_id = pre_lane['id']
359
+ pre_lane_ = copy.deepcopy(self._agent._simulator.map.get_lane(pre_lane_id))
360
+ pre_lane_nodes = pre_lane_['center_line']['nodes']
361
+ tmp_s = pre_lane_['length'] - radius_
362
+ tmp_s = tmp_s if tmp_s >= 0 else 0
363
+ x, y = get_xy_in_lane(pre_lane_nodes, tmp_s, 'back')
364
+ longlat = self._agent._simulator.map.xy2lnglat(x=x, y=y)
365
+ type = self._lane_type_mapping.get(pre_lane_['type'], 'unspecified')
366
+ positions += [{'lane_id': pre_lane_id,
367
+ 's': tmp_s,
368
+ 'xy': (x, y),
369
+ 'longlat': longlat,
370
+ 'type': type}]
371
+ elif agent_s == lane['length']:
372
+ # 处于当前道路的尾部端点位置
373
+ # 1. 当前道路
374
+ tmp_s = agent_s - radius_
375
+ tmp_s = tmp_s if tmp_s >= 0 else 0
376
+ x, y = get_xy_in_lane(nodes, tmp_s, 'back')
377
+ longlat = self._agent._simulator.map.xy2loglat(x=x, y=y)
378
+ type = self._lane_type_mapping.get(lane['type'], 'unspecified')
379
+ positions += [{'lane_id': lane_id,
380
+ 's': tmp_s,
381
+ 'xy': (x, y),
382
+ 'longlat': longlat,
383
+ 'type': type}]
384
+
385
+ # 2. 后继道路
386
+ suc_lanes = lane['successors']
387
+ for suc_lane in suc_lanes:
388
+ suc_lane_id = suc_lane['id']
389
+ suc_lane_ = copy.deepcopy(self._agent._simulator.map.get_lane(suc_lane_id))
390
+ suc_lane_nodes = suc_lane_['center_line']['nodes']
391
+ tmp_s = radius_
392
+ tmp_s = tmp_s if tmp_s <= suc_lane_['length'] else suc_lane_['length']
393
+ x, y = get_xy_in_lane(suc_lane_nodes, tmp_s)
394
+ longlat = self._agent._simulator.map.xy2loglat(x=x, y=y)
395
+ type = self._lane_type_mapping.get(lane['type'], 'unspecified')
396
+ positions += [{'lane_id': suc_lane_id,
397
+ 's': tmp_s,
398
+ 'xy': (x, y),
399
+ 'longlat': longlat,
400
+ 'type': type}]
401
+ else:
402
+ # 非端点位置
403
+ neg_s = agent_s - radius_
404
+ neg_s = neg_s if neg_s >= 0 else 0
405
+ x, y = get_xy_in_lane(nodes, neg_s, 'back')
406
+ longlat = self._agent._simulator.map.xy2loglat(x=x, y=y)
407
+ type = self._lane_type_mapping.get(lane['type'], 'unspecified')
408
+ positions += [{'lans_id': lane_id,
409
+ 's': neg_s,
410
+ 'xy': (x, y),
411
+ 'longlat': longlat,
412
+ 'type': type}]
413
+
414
+ pos_s = agent_s + radius_
415
+ pos_s = pos_s if pos_s <= lane['length'] else lane['length']
416
+ x, y = get_xy_in_lane(nodes, pos_s)
417
+ longlat = self._agent._simulator.map.xy2loglat(x=x, y=y)
418
+ type = self._lane_type_mapping.get(lane['type'], 'unspecified')
419
+ positions += [{'lans_id': lane_id,
420
+ 's': neg_s,
421
+ 'xy': (x, y),
422
+ 'longlat': longlat,
423
+ 'type': type}]
424
+ return positions
425
+
426
+ async def PerceivePoi(self, radius:int=None, category:str=None):
164
427
  """
165
428
  POI感知
166
429
  Sence POI
@@ -170,31 +433,78 @@ class Sence(BrainFunction):
170
433
  - category: 6位数字类型编码, 如果为None则获取所有类型POI. 6-digit coding which represents the poi type, if None, then sence all type of poi
171
434
 
172
435
  Returns:
173
- - List[Tuple[Any, float]]: poi列表, 每个元素为(poi, 距离). poi list, each element is (poi, distance).
436
+ - List[Tuple[Any, float]]: poi列表, 每个元素为:
437
+ - poi
438
+ - 距离: 单位m
439
+ - 步行前往需要的时间: 单位s, -1表示不可达或无需进入城市道路(处于同一aoi)
440
+ - 步行路线
441
+ - 驾车前往需要的时间: 单位s, -1表示驾车不可达或无需进入城市道路(处于同一aoi)
442
+ - 行车路线
174
443
  """
175
444
  radius_ = self._sence_radius
176
445
  if radius != None:
177
446
  radius_ = radius
178
447
  if category != None:
179
448
  category_prefix = category
180
- resp = self._agent._simulator.map.query_pois(
449
+ resp = copy.deepcopy(self._agent._simulator.map.query_pois(
181
450
  center=(self._agent.motion['position']['xy_position']['x'], self._agent.motion['position']['xy_position']['y']),
182
451
  radius=radius_,
183
452
  category_prefix=category_prefix
184
- )
453
+ ))
185
454
  else:
186
455
  resp = []
187
456
  for category_prefix in LEVEL_ONE_PRE:
188
- resp += self._agent._simulator.map.query_pois(
457
+ resp += copy.deepcopy(self._agent._simulator.map.query_pois(
189
458
  center=(self._agent.motion['position']['xy_position']['x'], self._agent.motion['position']['xy_position']['y']),
190
459
  radius=radius_,
191
460
  category_prefix=category_prefix
192
- )
193
- # * 从六位代码转变为具体类型
461
+ ))
462
+
463
+ # 从六位代码转变为具体类型
464
+ results = []
465
+ start_position = {}
466
+ if 'aoi_position' in self._agent.motion['position']:
467
+ start_position = {'aoi_position': {'aoi_id': self._agent.motion['position']['aoi_position']['aoi_id']}}
468
+ else:
469
+ start_position = {'lane_position': {'lane_id': self._agent.motion['position']['lane_position']['lane_id'], 's': self._agent.motion['position']['lane_position']['s']}}
194
470
  for poi in resp:
195
471
  cate_str = poi[0]['category']
196
472
  poi[0]['category'] = POI_TYPE_DICT[cate_str]
197
- return resp
473
+ info = poi[0]
474
+ distance = poi[1]
475
+ # walking
476
+ rout_walking_res = await self._agent._simulator.routing.GetRoute(
477
+ {
478
+ 'type': 2,
479
+ 'start': start_position,
480
+ 'end': {'aoi_position': {'aoi_id': info['aoi_id']}},
481
+ }
482
+ )
483
+ if len(rout_walking_res['journeys']) <= 0:
484
+ walking_time = -1
485
+ walking_route = []
486
+ else:
487
+ walking_time = rout_walking_res['journeys'][0]['walking']['eta']
488
+ walking_route = rout_walking_res['journeys'][0]['walking']['route']
489
+
490
+ # driving
491
+ rout_driving_res = await self._agent._simulator.routing.GetRoute(
492
+ {
493
+ 'type': 1,
494
+ 'start': start_position,
495
+ 'end': {'aoi_position': {'aoi_id': info['aoi_id']}},
496
+ }
497
+ )
498
+ if len(rout_driving_res['journeys']) <= 0:
499
+ driving_time = -1
500
+ driving_route = []
501
+ else:
502
+ driving_time = rout_driving_res['journeys'][0]['driving']['eta']
503
+ driving_route = rout_driving_res['journeys'][0]['driving']['road_ids']
504
+
505
+ # append
506
+ results.append((info, distance, walking_time, walking_route, driving_time, driving_route))
507
+ return results
198
508
 
199
509
  # * Lane Related
200
510
  def PerceiveLane(self, radius:int=None, type:int=3, only_id:bool=False) -> Union[list, dict]:
@@ -224,28 +534,28 @@ class Sence(BrainFunction):
224
534
  radius_ = radius
225
535
  if type == 3:
226
536
  resp = {}
227
- resp['roadway'] = self._agent._simulator.map.query_lane(
537
+ resp['roadway'] = copy.deepcopy(self._agent._simulator.map.query_lane(
228
538
  xy=(self._agent.motion['position']['xy_position']['x'], self._agent.motion['position']['xy_position']['y']),
229
539
  radius=radius_,
230
540
  lane_type=1
231
- )
232
- resp['sidewalk'] = resp = self._agent._simulator.map.query_lane(
541
+ ))
542
+ resp['sidewalk'] = resp = copy.deepcopy(self._agent._simulator.map.query_lane(
233
543
  xy=(self._agent.motion['position']['xy_position']['x'], self._agent.motion['position']['xy_position']['y']),
234
544
  radius=radius_,
235
545
  lane_type=2
236
- )
546
+ ))
237
547
  elif type == 2:
238
- resp = self._agent._simulator.map.query_lane(
548
+ resp = copy.deepcopy(self._agent._simulator.map.query_lane(
239
549
  xy=(self._agent.motion['position']['xy_position']['x'], self._agent.motion['position']['xy_position']['y']),
240
550
  radius=radius_,
241
551
  lane_type=2
242
- )
552
+ ))
243
553
  else:
244
- resp = self._agent._simulator.map.query_lane(
554
+ resp = copy.deepcopy(self._agent._simulator.map.query_lane(
245
555
  xy=(self._agent.motion['position']['xy_position']['x'], self._agent.motion['position']['xy_position']['y']),
246
556
  radius=radius_,
247
557
  lane_type=1
248
- )
558
+ ))
249
559
  if only_id:
250
560
  ids = []
251
561
  for ele in resp:
@@ -256,6 +566,7 @@ class Sence(BrainFunction):
256
566
  # * StreetView Related
257
567
  def PerceiveStreetView(
258
568
  self,
569
+ # engine:str="baidumap",
259
570
  heading:str="front",
260
571
  save:bool=False,
261
572
  save_dir:str=None
@@ -271,14 +582,20 @@ class Sence(BrainFunction):
271
582
  - save_dir (str): 存储文件夹. save directory
272
583
 
273
584
  Returns:
274
- - PIL.Image.Image
275
- """
585
+ - List[PIL.Image.Image] = [left, front, right, back]
586
+ """
587
+ if self._engine == None:
588
+ print("Can't get streetview, please check the streetview config")
589
+ return []
590
+ if self._engine == 'baidumap' and self._baiduAK == None:
591
+ print("Can't get streetview, please provide a baidumap AK")
592
+ return []
593
+ if self._engine == 'googlemap' and self._googleProxy == None:
594
+ print("Can't get streetview, please provide a googlemap proxy")
595
+ return []
596
+
276
597
  coords = [(self._agent.motion['position']['longlat_position']['longitude'], self._agent.motion['position']['longlat_position']['latitude'])]
277
- """
278
- 模拟人眼视角
279
- 水平FOV: 160
280
- 垂直角暂时不支持
281
- """
598
+
282
599
  if heading == "front":
283
600
  heading_direction = self._agent.motion['direction']
284
601
  elif heading == "back":
@@ -289,32 +606,36 @@ class Sence(BrainFunction):
289
606
  heading_direction += 90
290
607
  else:
291
608
  print("Wrong HEADING, Use FRONT")
292
- if self._streetview_engine == "baidumap":
293
- points = wgs842bd09mc(coords, self._streetviewAK)
609
+ persp = []
610
+ if self._engine == "baidumap":
611
+ points = wgs842bd09mc(coords, self._baiduAK)
294
612
  sv = BaiduStreetView.search(points[0][0], points[0][1])
295
613
  eq = Equirectangular(sv)
296
- persp = eq.get_perspective(120, heading_direction, 20, 256, 512)
614
+ persp.append(eq.get_perspective(120, heading_direction-90, 20, 256, 512))
615
+ persp.append(eq.get_perspective(120, heading_direction, 20, 256, 512))
616
+ persp.append(eq.get_perspective(120, heading_direction+90, 20, 256, 512))
617
+ persp.append(eq.get_perspective(120, heading_direction+180, 20, 256, 512))
297
618
  if save:
298
619
  date_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
299
- sv.panorama.save("{}/{}_{}_panorama.jpg".format(save_dir, self._agent.name, date_time))
300
- persp.save("{}/{}_{}_persp.jpg".format(save_dir, self._agent.name, date_time))
620
+ sv.panorama.save("{}/{}_{}_panorama_{}.jpg".format(save_dir, self._agent.name, date_time))
621
+ for i in range(len(persp)):
622
+ persp[i].save("{}/{}_{}_persp_{}.jpg".format(save_dir, self._agent.name, date_time, i))
301
623
  return persp
302
- elif self._streetview_engine == "googlemap":
624
+ elif self._engine == "googlemap":
303
625
  sv = GoogleStreetView.search(
304
626
  points[0][0],
305
627
  points[0][1],
306
- proxies=self._streetviewProxy,
628
+ proxies=self._googleProxy,
307
629
  cache_dir=save_dir
308
630
  )
309
631
  eq = Equirectangular(sv)
310
632
  persp = eq.get_perspective(120, heading_direction, 20, 256, 512)
311
633
  if save:
312
- sv.panorama.save("{}/{}_{}_panorama.jpg".format(save_dir, self._agent.name, datetime.now().strftime("%Y-%m-%d %H:%M:%S")))
313
- persp.save("{}/{}_{}_persp.jpg".format(save_dir, self._agent.name, datetime.now().strftime("%Y-%m-%d %H:%M:%S")))
634
+ date_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
635
+ sv.panorama.save("{}/{}_{}_panorama_{}.jpg".format(save_dir, self._agent.name, date_time))
636
+ for i in range(len(persp)):
637
+ persp[i].save("{}/{}_{}_persp_{}.jpg".format(save_dir, self._agent.name, date_time, i))
314
638
  return persp
315
- else:
316
- print("Error StreetView Engine")
317
- return None
318
639
 
319
640
  # * Person Related
320
641
  def PerceivePersonCircule(self, raduis=30):
@@ -1,5 +1,5 @@
1
1
  '''Commond Control - 根据Brain组织的信息, 发起指令'''
2
2
 
3
- from .cc import *
3
+ from .cc import CommandController, Command
4
4
 
5
- __all__ = [CommondController, Commond]
5
+ __all__ = [CommandController, Command]