pycityagent 1.0.0__py3-none-any.whl → 2.0.0a2__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.
- pycityagent/__init__.py +7 -3
- pycityagent/agent.py +180 -284
- pycityagent/economy/__init__.py +5 -0
- pycityagent/economy/econ_client.py +307 -0
- pycityagent/environment/__init__.py +7 -0
- pycityagent/environment/interact/interact.py +141 -0
- pycityagent/environment/sence/__init__.py +0 -0
- pycityagent/{brain → environment/sence}/static.py +1 -1
- pycityagent/environment/sidecar/__init__.py +8 -0
- pycityagent/environment/sidecar/sidecarv2.py +109 -0
- pycityagent/environment/sim/__init__.py +29 -0
- pycityagent/environment/sim/aoi_service.py +38 -0
- pycityagent/environment/sim/client.py +126 -0
- pycityagent/environment/sim/clock_service.py +43 -0
- pycityagent/environment/sim/economy_services.py +191 -0
- pycityagent/environment/sim/lane_service.py +110 -0
- pycityagent/environment/sim/light_service.py +120 -0
- pycityagent/environment/sim/person_service.py +294 -0
- pycityagent/environment/sim/road_service.py +38 -0
- pycityagent/environment/sim/sim_env.py +145 -0
- pycityagent/environment/sim/social_service.py +58 -0
- pycityagent/environment/simulator.py +320 -0
- pycityagent/environment/utils/__init__.py +10 -0
- pycityagent/environment/utils/base64.py +16 -0
- pycityagent/environment/utils/const.py +242 -0
- pycityagent/environment/utils/geojson.py +26 -0
- pycityagent/environment/utils/grpc.py +57 -0
- pycityagent/environment/utils/map_utils.py +157 -0
- pycityagent/environment/utils/port.py +11 -0
- pycityagent/environment/utils/protobuf.py +39 -0
- pycityagent/llm/__init__.py +6 -0
- pycityagent/llm/embedding.py +136 -0
- pycityagent/llm/llm.py +430 -0
- pycityagent/llm/llmconfig.py +15 -0
- pycityagent/llm/utils.py +6 -0
- pycityagent/memory/__init__.py +11 -0
- pycityagent/memory/const.py +41 -0
- pycityagent/memory/memory.py +453 -0
- pycityagent/memory/memory_base.py +168 -0
- pycityagent/memory/profile.py +165 -0
- pycityagent/memory/self_define.py +165 -0
- pycityagent/memory/state.py +173 -0
- pycityagent/memory/utils.py +27 -0
- pycityagent/message/__init__.py +0 -0
- pycityagent/simulation/__init__.py +7 -0
- pycityagent/simulation/interview.py +36 -0
- pycityagent/simulation/simulation.py +352 -0
- pycityagent/simulation/survey/__init__.py +9 -0
- pycityagent/simulation/survey/manager.py +67 -0
- pycityagent/simulation/survey/models.py +49 -0
- pycityagent/simulation/ui/__init__.py +3 -0
- pycityagent/simulation/ui/interface.py +602 -0
- pycityagent/utils/__init__.py +0 -0
- pycityagent/utils/decorators.py +89 -0
- pycityagent/utils/parsers/__init__.py +12 -0
- pycityagent/utils/parsers/code_block_parser.py +37 -0
- pycityagent/utils/parsers/json_parser.py +86 -0
- pycityagent/utils/parsers/parser_base.py +60 -0
- pycityagent/workflow/__init__.py +24 -0
- pycityagent/workflow/block.py +164 -0
- pycityagent/workflow/prompt.py +72 -0
- pycityagent/workflow/tool.py +246 -0
- pycityagent/workflow/trigger.py +150 -0
- pycityagent-2.0.0a2.dist-info/METADATA +208 -0
- pycityagent-2.0.0a2.dist-info/RECORD +69 -0
- {pycityagent-1.0.0.dist-info → pycityagent-2.0.0a2.dist-info}/WHEEL +1 -2
- pycityagent/ac/__init__.py +0 -6
- pycityagent/ac/ac.py +0 -50
- pycityagent/ac/action.py +0 -14
- pycityagent/ac/controled.py +0 -13
- pycityagent/ac/converse.py +0 -31
- pycityagent/ac/idle.py +0 -17
- pycityagent/ac/shop.py +0 -80
- pycityagent/ac/trip.py +0 -37
- pycityagent/brain/__init__.py +0 -10
- pycityagent/brain/brain.py +0 -52
- pycityagent/brain/brainfc.py +0 -10
- pycityagent/brain/memory.py +0 -541
- pycityagent/brain/persistence/social.py +0 -1
- pycityagent/brain/persistence/spatial.py +0 -14
- pycityagent/brain/reason/shop.py +0 -37
- pycityagent/brain/reason/social.py +0 -148
- pycityagent/brain/reason/trip.py +0 -67
- pycityagent/brain/reason/user.py +0 -122
- pycityagent/brain/retrive/social.py +0 -6
- pycityagent/brain/scheduler.py +0 -408
- pycityagent/brain/sence.py +0 -375
- pycityagent/cc/__init__.py +0 -5
- pycityagent/cc/cc.py +0 -102
- pycityagent/cc/conve.py +0 -6
- pycityagent/cc/idle.py +0 -20
- pycityagent/cc/shop.py +0 -6
- pycityagent/cc/trip.py +0 -13
- pycityagent/cc/user.py +0 -13
- pycityagent/hubconnector/__init__.py +0 -3
- pycityagent/hubconnector/hubconnector.py +0 -137
- pycityagent/image/__init__.py +0 -3
- pycityagent/image/image.py +0 -158
- pycityagent/simulator.py +0 -161
- pycityagent/st/__init__.py +0 -4
- pycityagent/st/st.py +0 -96
- pycityagent/urbanllm/__init__.py +0 -3
- pycityagent/urbanllm/urbanllm.py +0 -132
- pycityagent-1.0.0.dist-info/LICENSE +0 -21
- pycityagent-1.0.0.dist-info/METADATA +0 -181
- pycityagent-1.0.0.dist-info/RECORD +0 -48
- pycityagent-1.0.0.dist-info/top_level.txt +0 -1
- /pycityagent/{brain/persistence/__init__.py → config.py} +0 -0
- /pycityagent/{brain/reason → environment/interact}/__init__.py +0 -0
- /pycityagent/{brain/retrive → environment/message}/__init__.py +0 -0
pycityagent/brain/sence.py
DELETED
@@ -1,375 +0,0 @@
|
|
1
|
-
from typing import Optional, Union
|
2
|
-
from datetime import datetime
|
3
|
-
from pycitysim.apphub import UserMessage, AgentMessage
|
4
|
-
from citystreetview import (
|
5
|
-
BaiduStreetView,
|
6
|
-
GoogleStreetView,
|
7
|
-
Equirectangular,
|
8
|
-
wgs842bd09mc,
|
9
|
-
)
|
10
|
-
from .brainfc import BrainFunction
|
11
|
-
from .static import POI_TYPE_DICT, LEVEL_ONE_PRE
|
12
|
-
|
13
|
-
class SencePlug:
|
14
|
-
"""
|
15
|
-
感知模块插件
|
16
|
-
Plugin of Sence Module
|
17
|
-
|
18
|
-
Args:
|
19
|
-
- user_func (function): user defined function
|
20
|
-
- out (str): the output target in sence, the sence result will be insert to Sence.plug_buffer[out]
|
21
|
-
"""
|
22
|
-
def __init__(self, user_func, out:str) -> None:
|
23
|
-
# TODO: 添加合法性检查
|
24
|
-
self.user_func = user_func
|
25
|
-
self.out = out
|
26
|
-
|
27
|
-
class Sence(BrainFunction):
|
28
|
-
"""
|
29
|
-
Agent感知模块
|
30
|
-
Agent Sence module
|
31
|
-
"""
|
32
|
-
def __init__(self, agent, sence_raduis:int=10) -> None:
|
33
|
-
super().__init__(agent)
|
34
|
-
self._streetview_engine = ""
|
35
|
-
self._streetviewAK = ""
|
36
|
-
self._streetviewProxy = None
|
37
|
-
self._sence_radius = sence_raduis
|
38
|
-
"""
|
39
|
-
感知半径
|
40
|
-
The sence raduis: meter
|
41
|
-
"""
|
42
|
-
self.sence_buffer = {}
|
43
|
-
"""
|
44
|
-
感知Buffer: 用于存储感知到的内容
|
45
|
-
Sence Buffer: used to stroe those senced content
|
46
|
-
"""
|
47
|
-
self.plugs = []
|
48
|
-
"""
|
49
|
-
感知插件集合
|
50
|
-
Collection of SencePlugs
|
51
|
-
"""
|
52
|
-
self.plug_buffer = {}
|
53
|
-
"""
|
54
|
-
感知插件结果Buffer: 用于存储感知插件的输出结果
|
55
|
-
SencePlug Buffer: used to store those sence plug content
|
56
|
-
"""
|
57
|
-
self.enable_streeview = False
|
58
|
-
"""
|
59
|
-
街景感知功能接口, 默认为False
|
60
|
-
Interface of streetview function, defualt: False
|
61
|
-
"""
|
62
|
-
|
63
|
-
def add_plugs(self, plugs:list[SencePlug]):
|
64
|
-
"""
|
65
|
-
添加感知插件
|
66
|
-
Add SencePlug
|
67
|
-
|
68
|
-
Args:
|
69
|
-
- plugs (list[SencePlug]): the list of SencePlug
|
70
|
-
"""
|
71
|
-
self.plugs += plugs
|
72
|
-
|
73
|
-
def set_sence_radius(self, radius:int):
|
74
|
-
"""
|
75
|
-
设置感知半径
|
76
|
-
Set sence radius
|
77
|
-
|
78
|
-
Args:
|
79
|
-
- radius (int): meter
|
80
|
-
"""
|
81
|
-
self._sence_radius = radius
|
82
|
-
|
83
|
-
def state_influence(self):
|
84
|
-
"""
|
85
|
-
状态-感知影响接口, 该函数会在感知前自动执行
|
86
|
-
State-Sence influence interface, this function will be automatically invoked
|
87
|
-
"""
|
88
|
-
return super().state_influence()
|
89
|
-
|
90
|
-
async def Sence(self) -> dict:
|
91
|
-
"""
|
92
|
-
感知功能主体
|
93
|
-
Main function of sence
|
94
|
-
|
95
|
-
Returns:
|
96
|
-
- (dict): the sence content in dict format
|
97
|
-
- time (int): current time in second (from 00:00:00)
|
98
|
-
- pois ()
|
99
|
-
"""
|
100
|
-
self.state_influence()
|
101
|
-
# * time
|
102
|
-
self.sence_buffer['time'] = self._agent._simulator.time
|
103
|
-
|
104
|
-
# * pois
|
105
|
-
self.sence_buffer['pois'] = self.PerceivePoi()
|
106
|
-
|
107
|
-
# * lanes
|
108
|
-
self.sence_buffer['lanes'] = self.PerceiveLane()
|
109
|
-
lane_ids = self.PerceiveLane(only_id=True)
|
110
|
-
self.sence_buffer['lane_ids'] = lane_ids
|
111
|
-
|
112
|
-
# * 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
|
120
|
-
|
121
|
-
# * streetview
|
122
|
-
if self.enable_streeview:
|
123
|
-
self.sence_buffer['streetview'] = self.PerceiveStreetView()
|
124
|
-
else:
|
125
|
-
self.sence_buffer['streetview'] = None
|
126
|
-
|
127
|
-
# * user message
|
128
|
-
if self._agent.Hub != None:
|
129
|
-
self.sence_buffer['user_messages'] = self.PerceiveUserMessage()
|
130
|
-
else:
|
131
|
-
self.sence_buffer['user_messages'] = []
|
132
|
-
|
133
|
-
# * agent message
|
134
|
-
self.sence_buffer['social_messages'] = await self.PerceiveMessageFromPerson()
|
135
|
-
|
136
|
-
# * 插件感知
|
137
|
-
if len(self.plugs) > 0:
|
138
|
-
for plug in self.plugs:
|
139
|
-
out_key = plug.out
|
140
|
-
out = plug.user_func(self.sence_buffer)
|
141
|
-
self.plug_buffer[out_key] = out
|
142
|
-
|
143
|
-
return self.sence_buffer
|
144
|
-
|
145
|
-
# * AOI and POI Related
|
146
|
-
async def PerceiveAoi(self, only_person:bool=False):
|
147
|
-
"""
|
148
|
-
感知Agent当前所在的AOI
|
149
|
-
Sence AOI where Agent currently in
|
150
|
-
|
151
|
-
Args:
|
152
|
-
- only_person (bool): whether only return persons in AOI, default: False
|
153
|
-
|
154
|
-
Returns:
|
155
|
-
- Union[https://cityproto.sim.fiblab.net/#city.map.v2.AoiState, list[https://cityproto.sim.fiblab.net/#city.person.v1.PersonMotion]]
|
156
|
-
"""
|
157
|
-
resp = await self._agent._simulator._client.aoi_service.GetAoi({'aoi_ids': [self._agent.motion['position']['aoi_position']['aoi_id']]})
|
158
|
-
if only_person:
|
159
|
-
persons = resp['states'][0]['persons']
|
160
|
-
return persons
|
161
|
-
return resp['states'][0]
|
162
|
-
|
163
|
-
def PerceivePoi(self, radius:int=None, category:str=None):
|
164
|
-
"""
|
165
|
-
POI感知
|
166
|
-
Sence POI
|
167
|
-
|
168
|
-
Args:
|
169
|
-
- radius: 感知范围, 默认使用统一感知半径. Sence raduis, default use basic radius
|
170
|
-
- category: 6位数字类型编码, 如果为None则获取所有类型POI. 6-digit coding which represents the poi type, if None, then sence all type of poi
|
171
|
-
|
172
|
-
Returns:
|
173
|
-
- List[Tuple[Any, float]]: poi列表, 每个元素为(poi, 距离). poi list, each element is (poi, distance).
|
174
|
-
"""
|
175
|
-
radius_ = self._sence_radius
|
176
|
-
if radius != None:
|
177
|
-
radius_ = radius
|
178
|
-
if category != None:
|
179
|
-
category_prefix = category
|
180
|
-
resp = self._agent._simulator.map.query_pois(
|
181
|
-
center=(self._agent.motion['position']['xy_position']['x'], self._agent.motion['position']['xy_position']['y']),
|
182
|
-
radius=radius_,
|
183
|
-
category_prefix=category_prefix
|
184
|
-
)
|
185
|
-
else:
|
186
|
-
resp = []
|
187
|
-
for category_prefix in LEVEL_ONE_PRE:
|
188
|
-
resp += self._agent._simulator.map.query_pois(
|
189
|
-
center=(self._agent.motion['position']['xy_position']['x'], self._agent.motion['position']['xy_position']['y']),
|
190
|
-
radius=radius_,
|
191
|
-
category_prefix=category_prefix
|
192
|
-
)
|
193
|
-
# * 从六位代码转变为具体类型
|
194
|
-
for poi in resp:
|
195
|
-
cate_str = poi[0]['category']
|
196
|
-
poi[0]['category'] = POI_TYPE_DICT[cate_str]
|
197
|
-
return resp
|
198
|
-
|
199
|
-
# * Lane Related
|
200
|
-
def PerceiveLane(self, radius:int=None, type:int=3, only_id:bool=False) -> Union[list, dict]:
|
201
|
-
"""
|
202
|
-
Agent视角下的Lane感知
|
203
|
-
Lane Sence
|
204
|
-
|
205
|
-
Args:
|
206
|
-
- radius: 感知半径, 默认使用基础半径. Sence radius, default use basic radius
|
207
|
-
- type: 感知的道路类型. Sence type
|
208
|
-
- 3: 车道+人行道. drive lane + sidewalk
|
209
|
-
- 2: 人行道. sidewalk
|
210
|
-
- 1: 车道. drive lane
|
211
|
-
- only_with_person: 仅返回包含人的车道. only those lanes with persons/cars
|
212
|
-
- only_id: 仅返回laneid. only lane id
|
213
|
-
|
214
|
-
Returns:
|
215
|
-
- Union[list, dict]
|
216
|
-
- if only_id, return a list of lane id
|
217
|
-
- if sence type equal 2 or 1, return a List[Tuple[Any, float, float]]: lane列表, 每个元素为(lane, s, distance)
|
218
|
-
- if sence type equal 3, return a dict
|
219
|
-
- 'roadway': List[Tuple[Any, float, float]]: lane列表, 每个元素为(lane, s, distance)
|
220
|
-
- 'sidewalk': List[Tuple[Any, float, float]]: lane列表, 每个元素为(lane, s, distance)
|
221
|
-
"""
|
222
|
-
radius_ = self._sence_radius
|
223
|
-
if radius != None:
|
224
|
-
radius_ = radius
|
225
|
-
if type == 3:
|
226
|
-
resp = {}
|
227
|
-
resp['roadway'] = self._agent._simulator.map.query_lane(
|
228
|
-
xy=(self._agent.motion['position']['xy_position']['x'], self._agent.motion['position']['xy_position']['y']),
|
229
|
-
radius=radius_,
|
230
|
-
lane_type=1
|
231
|
-
)
|
232
|
-
resp['sidewalk'] = resp = self._agent._simulator.map.query_lane(
|
233
|
-
xy=(self._agent.motion['position']['xy_position']['x'], self._agent.motion['position']['xy_position']['y']),
|
234
|
-
radius=radius_,
|
235
|
-
lane_type=2
|
236
|
-
)
|
237
|
-
elif type == 2:
|
238
|
-
resp = self._agent._simulator.map.query_lane(
|
239
|
-
xy=(self._agent.motion['position']['xy_position']['x'], self._agent.motion['position']['xy_position']['y']),
|
240
|
-
radius=radius_,
|
241
|
-
lane_type=2
|
242
|
-
)
|
243
|
-
else:
|
244
|
-
resp = self._agent._simulator.map.query_lane(
|
245
|
-
xy=(self._agent.motion['position']['xy_position']['x'], self._agent.motion['position']['xy_position']['y']),
|
246
|
-
radius=radius_,
|
247
|
-
lane_type=1
|
248
|
-
)
|
249
|
-
if only_id:
|
250
|
-
ids = []
|
251
|
-
for ele in resp:
|
252
|
-
ids.append(ele[0]['id'])
|
253
|
-
return ids
|
254
|
-
return resp
|
255
|
-
|
256
|
-
# * StreetView Related
|
257
|
-
def PerceiveStreetView(
|
258
|
-
self,
|
259
|
-
heading:str="front",
|
260
|
-
save:bool=False,
|
261
|
-
save_dir:str=None
|
262
|
-
):
|
263
|
-
"""
|
264
|
-
街景图像感知
|
265
|
-
Sence streetview
|
266
|
-
|
267
|
-
Args:
|
268
|
-
- engine: 需要使用的街景获取引擎. streetview engine, default: 'baidumap'
|
269
|
-
- heading (str): 朝向,默认正前方; 同时支持back, left, right. sence towards, defualt 'front', support ['front', 'back', 'left', 'right']
|
270
|
-
- save (bool): 是否存储. save or not
|
271
|
-
- save_dir (str): 存储文件夹. save directory
|
272
|
-
|
273
|
-
Returns:
|
274
|
-
- PIL.Image.Image
|
275
|
-
"""
|
276
|
-
coords = [(self._agent.motion['position']['longlat_position']['longitude'], self._agent.motion['position']['longlat_position']['latitude'])]
|
277
|
-
"""
|
278
|
-
模拟人眼视角
|
279
|
-
水平FOV: 160
|
280
|
-
垂直角暂时不支持
|
281
|
-
"""
|
282
|
-
if heading == "front":
|
283
|
-
heading_direction = self._agent.motion['direction']
|
284
|
-
elif heading == "back":
|
285
|
-
heading_direction += 180
|
286
|
-
elif heading == "left":
|
287
|
-
heading_direction += -90
|
288
|
-
elif heading == "right":
|
289
|
-
heading_direction += 90
|
290
|
-
else:
|
291
|
-
print("Wrong HEADING, Use FRONT")
|
292
|
-
if self._streetview_engine == "baidumap":
|
293
|
-
points = wgs842bd09mc(coords, self._streetviewAK)
|
294
|
-
sv = BaiduStreetView.search(points[0][0], points[0][1])
|
295
|
-
eq = Equirectangular(sv)
|
296
|
-
persp = eq.get_perspective(120, heading_direction, 20, 256, 512)
|
297
|
-
if save:
|
298
|
-
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))
|
301
|
-
return persp
|
302
|
-
elif self._streetview_engine == "googlemap":
|
303
|
-
sv = GoogleStreetView.search(
|
304
|
-
points[0][0],
|
305
|
-
points[0][1],
|
306
|
-
proxies=self._streetviewProxy,
|
307
|
-
cache_dir=save_dir
|
308
|
-
)
|
309
|
-
eq = Equirectangular(sv)
|
310
|
-
persp = eq.get_perspective(120, heading_direction, 20, 256, 512)
|
311
|
-
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")))
|
314
|
-
return persp
|
315
|
-
else:
|
316
|
-
print("Error StreetView Engine")
|
317
|
-
return None
|
318
|
-
|
319
|
-
# * Person Related
|
320
|
-
def PerceivePersonCircule(self, raduis=30):
|
321
|
-
"""Person环形感知"""
|
322
|
-
print("Not Implemented")
|
323
|
-
pass
|
324
|
-
|
325
|
-
async def PerceivePersonInLanes(self, lane_ids:list[int], only_id:bool=False):
|
326
|
-
"""
|
327
|
-
感知指定lane集合上的person
|
328
|
-
Sence persons in target lane collection
|
329
|
-
|
330
|
-
Args:
|
331
|
-
- lane_ids: 指定的lane id列表. list of lane id
|
332
|
-
- only_id: 仅需要对应person id即可 - 否则返回person motion. whether only need person_id, default: False
|
333
|
-
|
334
|
-
Returns:
|
335
|
-
- Union[list[int], list[https://cityproto.sim.fiblab.net/#city.person.v1.PersonMotion]]
|
336
|
-
- if only_id, return a list of person id
|
337
|
-
- if not only_id, return a list of PersonMotion
|
338
|
-
"""
|
339
|
-
req = {'lane_ids': lane_ids, 'exclude_person': False}
|
340
|
-
resp = await self._agent._client.lane_service.GetLane(req)
|
341
|
-
persons = []
|
342
|
-
for lane in resp['states']:
|
343
|
-
if only_id:
|
344
|
-
if len(lane['persons']) > 0:
|
345
|
-
for pson in lane['persons']:
|
346
|
-
persons.append(pson['id'])
|
347
|
-
else:
|
348
|
-
if len(lane['persons']) > 0:
|
349
|
-
persons += lane['persons']
|
350
|
-
return persons
|
351
|
-
|
352
|
-
async def PerceiveMessageFromPerson(self):
|
353
|
-
"""
|
354
|
-
接受对话消息
|
355
|
-
Receive Conve Message
|
356
|
-
|
357
|
-
Returns:
|
358
|
-
- list[Message https://cityproto.sim.fiblab.net/#city.social.v1.Message]
|
359
|
-
"""
|
360
|
-
messages = await self._agent._client.social_service.Receive({'id': self._agent._id})
|
361
|
-
return messages['messages']
|
362
|
-
|
363
|
-
def PerceiveUserMessage(self) -> list[UserMessage]:
|
364
|
-
"""
|
365
|
-
从AppHub获取消息
|
366
|
-
Get user messages from AppHub
|
367
|
-
|
368
|
-
Returns:
|
369
|
-
- list[UserMessage]
|
370
|
-
"""
|
371
|
-
return self._agent._hub_connector.GetMessageFromHub()
|
372
|
-
|
373
|
-
@property
|
374
|
-
def Buffer(self):
|
375
|
-
return self.sence_buffer
|
pycityagent/cc/__init__.py
DELETED
pycityagent/cc/cc.py
DELETED
@@ -1,102 +0,0 @@
|
|
1
|
-
from typing import Any
|
2
|
-
from .idle import *
|
3
|
-
from .shop import *
|
4
|
-
from .trip import *
|
5
|
-
from .conve import *
|
6
|
-
from .user import *
|
7
|
-
|
8
|
-
class Commond:
|
9
|
-
"""
|
10
|
-
BrainCommond: 即脑部发出的指令; The commond from Agent's Brain
|
11
|
-
|
12
|
-
Args:
|
13
|
-
- target (str): 即指令目标(状态转移指令). The commond target(state transformer)
|
14
|
-
- user_func (func):
|
15
|
-
- 自定义函数, 返回结果为bool类型, 如果返回True, 则表示执行target指令. Self-defined function, the return type is bool, if this function returns 'True', then forward the target commond.
|
16
|
-
"""
|
17
|
-
def __init__(self, target:str, user_func) -> None:
|
18
|
-
self.target = target
|
19
|
-
self.user_func = user_func
|
20
|
-
|
21
|
-
class CommondController:
|
22
|
-
"""
|
23
|
-
Commond控制器模组: 连接Brain以及StateTranformer
|
24
|
-
Commond Controller module: Used to connect the Brain module and StateTransformer module
|
25
|
-
"""
|
26
|
-
def __init__(self, agent, config=None) -> None:
|
27
|
-
'''默认初始化'''
|
28
|
-
# TODO: config配置
|
29
|
-
self._agent = agent
|
30
|
-
self._brain = agent._brain
|
31
|
-
self.commond_control = {}
|
32
|
-
"""
|
33
|
-
控制序列: 与state关联的BrainCommond集合
|
34
|
-
Control Hub: connect the state with a BrainCommond collection
|
35
|
-
Type: dict[str, list[BrainCommond]]
|
36
|
-
Default:
|
37
|
-
- idle: [whetherUserControl, whetherGoTrip, whetherGoShop, whetherGoConverse]
|
38
|
-
- trip: [whetherUserControl, whetherRouteFailed, whetherTripArrived]
|
39
|
-
- shop: [whetherUserControl, whetherShopFinished]
|
40
|
-
- conve: [whetherUserControl, whetherStopConverse]
|
41
|
-
- controled: [whetherEndControl]
|
42
|
-
"""
|
43
|
-
if config != None:
|
44
|
-
pass
|
45
|
-
else:
|
46
|
-
self.commond_control['idle'] = [
|
47
|
-
Commond('gousercontrol', whetherUserControl),
|
48
|
-
Commond('gotrip', whetherGoTrip),
|
49
|
-
Commond('goshop', whetherGoShop),
|
50
|
-
Commond('goconverse', whetherGoConverse)
|
51
|
-
]
|
52
|
-
self.commond_control['trip'] = [
|
53
|
-
Commond('gousercontrol', whetherUserControl),
|
54
|
-
Commond('routefailed', whetherRouteFailed),
|
55
|
-
Commond('arrived', whetherTripArrived)
|
56
|
-
]
|
57
|
-
self.commond_control['shop'] = [
|
58
|
-
Commond('gousercontrol', whetherUserControl),
|
59
|
-
Commond('shopdone', whetherShopFinished)
|
60
|
-
]
|
61
|
-
self.commond_control['conve'] = [
|
62
|
-
Commond('gousercontrol', whetherUserControl),
|
63
|
-
Commond('convedone', whetherStopConverse)
|
64
|
-
]
|
65
|
-
self.commond_control['controled'] = [
|
66
|
-
Commond('controlback', whetherEndControl)
|
67
|
-
]
|
68
|
-
|
69
|
-
def insertCommond(self, target_state:list[str], commond:Commond):
|
70
|
-
"""
|
71
|
-
插入指令
|
72
|
-
Insert Commond: This function will insert the commond to those control sequences show in target_state
|
73
|
-
|
74
|
-
Args:
|
75
|
-
- target_state (list[str]): the list of state names
|
76
|
-
- commond (Comond): the commond to be inserted
|
77
|
-
"""
|
78
|
-
for target in target_state:
|
79
|
-
if target in self.commond_control.keys():
|
80
|
-
self.commond_control.append(commond)
|
81
|
-
else:
|
82
|
-
self.commond_control[target] = [commond]
|
83
|
-
|
84
|
-
async def Run(self):
|
85
|
-
"""
|
86
|
-
AC主执行函数
|
87
|
-
The main function of AC
|
88
|
-
Note: By now, AC do not support priority invoke. You can manipulate the sequnce of Commond to create fake priority
|
89
|
-
|
90
|
-
Basic Logic:
|
91
|
-
- Based on the current state of Agent, AC invoke those functions in sequence
|
92
|
-
- If there is a 'True' of function, returns the target commond
|
93
|
-
- Else, return 'nothing' commond
|
94
|
-
"""
|
95
|
-
if self._agent.state not in self.commond_control.keys():
|
96
|
-
print(f"No commond control line match with current state: {self._agent.state}")
|
97
|
-
control_line = self.commond_control[self._agent.state] # 获取agent状态对应的控制链
|
98
|
-
for control in control_line:
|
99
|
-
result = await control.user_func(self._agent.Brain.Memory.Working)
|
100
|
-
if result:
|
101
|
-
return control.target
|
102
|
-
return 'nothing'
|
pycityagent/cc/conve.py
DELETED
pycityagent/cc/idle.py
DELETED
@@ -1,20 +0,0 @@
|
|
1
|
-
async def whetherGoTrip(wk):
|
2
|
-
'''判断是否可以开始出行'''
|
3
|
-
reason = wk.Reason
|
4
|
-
if reason['startTrip']:
|
5
|
-
return True
|
6
|
-
return False
|
7
|
-
|
8
|
-
async def whetherGoShop(wk):
|
9
|
-
'''判断是否可以开始购物'''
|
10
|
-
reason = wk.Reason
|
11
|
-
if reason['startShop']:
|
12
|
-
return True
|
13
|
-
return False
|
14
|
-
|
15
|
-
async def whetherGoConverse(wk):
|
16
|
-
'''判断是否开始对话'''
|
17
|
-
reason = wk.Reason
|
18
|
-
if reason['startConve']:
|
19
|
-
return True
|
20
|
-
return False
|
pycityagent/cc/shop.py
DELETED
pycityagent/cc/trip.py
DELETED
@@ -1,13 +0,0 @@
|
|
1
|
-
async def whetherTripArrived(wk):
|
2
|
-
'''是否到达目的地'''
|
3
|
-
reason = wk.Reason
|
4
|
-
if reason['tripArrived']:
|
5
|
-
return True
|
6
|
-
return False
|
7
|
-
|
8
|
-
async def whetherRouteFailed(wk):
|
9
|
-
'''是否到达目的地'''
|
10
|
-
reason = wk.Reason
|
11
|
-
if reason['routeFailed']:
|
12
|
-
return True
|
13
|
-
return False
|
pycityagent/cc/user.py
DELETED
@@ -1,137 +0,0 @@
|
|
1
|
-
from typing import Optional
|
2
|
-
import geojson
|
3
|
-
from pycitysim.apphub import AppHubClient, AgentMessage, UserMessage
|
4
|
-
import PIL.Image as Image
|
5
|
-
import traceback
|
6
|
-
|
7
|
-
class HubConnector:
|
8
|
-
"""
|
9
|
-
AppHub连接组件
|
10
|
-
AppHub connection module
|
11
|
-
"""
|
12
|
-
def __init__(self, hub_url:str=None, app_id:int=None, app_secret:str=None, agent=None, profile_img:str=None) -> None:
|
13
|
-
if hub_url == None:
|
14
|
-
self._client = None
|
15
|
-
else:
|
16
|
-
self._client = AppHubClient(
|
17
|
-
app_hub_url=hub_url,
|
18
|
-
app_id=app_id,
|
19
|
-
app_secret=app_secret
|
20
|
-
)
|
21
|
-
if agent == None:
|
22
|
-
self._agent = None
|
23
|
-
self._agent_id = None
|
24
|
-
else:
|
25
|
-
self._agent = agent
|
26
|
-
try:
|
27
|
-
self._agent_id = self._client.bind_person(
|
28
|
-
self._agent.base['id'],
|
29
|
-
self._agent.agent_name,
|
30
|
-
Image.open(profile_img)
|
31
|
-
)
|
32
|
-
except Exception as e:
|
33
|
-
traceback.print_exc()
|
34
|
-
print(e)
|
35
|
-
self._agent_id = 7
|
36
|
-
self.messageBuffer:list[AgentMessage] = []
|
37
|
-
"""
|
38
|
-
用于存储历史前端交互信息
|
39
|
-
Used to store the history message in frontend
|
40
|
-
"""
|
41
|
-
|
42
|
-
def ConnectToHub(self, hub_url:str, app_id:int, app_secret:str):
|
43
|
-
"""
|
44
|
-
连接AppHub
|
45
|
-
Connect with AppHub
|
46
|
-
|
47
|
-
Args:
|
48
|
-
- hub_url (str): the url of AppHub
|
49
|
-
- app_id (int): the allocated app_id
|
50
|
-
- app_secret (str): the allocated app_secret
|
51
|
-
"""
|
52
|
-
self._client = AppHubClient(
|
53
|
-
app_hub_url=hub_url,
|
54
|
-
app_id=app_id,
|
55
|
-
app_secret=app_secret
|
56
|
-
)
|
57
|
-
|
58
|
-
def BindAgent(self, agent, profile_img:str):
|
59
|
-
"""
|
60
|
-
绑定Agent
|
61
|
-
Bind an Agent through AppHub
|
62
|
-
|
63
|
-
Args:
|
64
|
-
- agent (Agent): the Agent needs to be bind with
|
65
|
-
- profile_img (str) : the path of profile_img, which will be shown in frontend and dashboard
|
66
|
-
"""
|
67
|
-
if self._client == None:
|
68
|
-
print("Not Connect To AppHub Yet")
|
69
|
-
return
|
70
|
-
self._agent = agent
|
71
|
-
self._agent_id = self._client.bind_person(
|
72
|
-
self._agent.base['id'],
|
73
|
-
self._agent.agent_name,
|
74
|
-
Image.open(profile_img)
|
75
|
-
)
|
76
|
-
|
77
|
-
def Update(self, messages:Optional[list[AgentMessage]]=None, streetview:Image=None, longlat:list[float]=None, pop:str=None):
|
78
|
-
"""
|
79
|
-
交互更新
|
80
|
-
FrontEnd Related Update
|
81
|
-
Note: This function is used by the lib developer. Normally, the user has no need to use this function
|
82
|
-
|
83
|
-
Default Action: no message, no streetview, locate based on the Agent's position, Agent's name as pop
|
84
|
-
|
85
|
-
Args:
|
86
|
-
- messages (Optional[list[AgentMessage]]):
|
87
|
-
- 需要传递到前端侧边栏的消息. Messsages that will be shown in the message bar in frontend
|
88
|
-
- 默认为None(即当前无需传递消息). Default: None(i.e. No new messages need to be shown in frontend)
|
89
|
-
- streetview (PIL.Image.Image):
|
90
|
-
- 街景图片. Streetview Image
|
91
|
-
- 默认为None(即本次更新不展示街景). Default: None(i.e. No streetview in this update)
|
92
|
-
- longlat (list(float)):
|
93
|
-
- 经纬度坐标, 用于前端定位, 默认为None(即根据Agent当前位置进行设置). The longitude and latitude, which helps locate the Agent, default: None(i.e. locate the Agent by the current position of agent)
|
94
|
-
- 只有在有特殊展示需求的情况下才设置该参数. Only when you have special display requirements, you will set the attribute
|
95
|
-
- pop (str):
|
96
|
-
- 气泡信息. The pop message
|
97
|
-
- 默认为None(即没有气泡信息). Default: None(i.e. No pop message)
|
98
|
-
"""
|
99
|
-
if self._client == None:
|
100
|
-
print("AppHub: Not Bind Agent Yet")
|
101
|
-
return
|
102
|
-
else:
|
103
|
-
pop_ = self._agent.agent_name
|
104
|
-
if pop != None:
|
105
|
-
pop_ = self._agent.agent_name + ": " + pop
|
106
|
-
longlat_ = [self._agent.motion['position']['longlat_position']['longitude'], self._agent.motion['position']['longlat_position']['latitude']]
|
107
|
-
if longlat != None:
|
108
|
-
longlat_ = longlat
|
109
|
-
|
110
|
-
self._client.update_agent_map(
|
111
|
-
agent_id = self._agent_id,
|
112
|
-
lnglat = longlat_,
|
113
|
-
street_view=streetview,
|
114
|
-
popup=pop_
|
115
|
-
)
|
116
|
-
if messages != None:
|
117
|
-
self.messageBuffer += messages
|
118
|
-
self._client.update_agent_messages(
|
119
|
-
agent_id=self._agent_id,
|
120
|
-
messages=self.messageBuffer
|
121
|
-
)
|
122
|
-
|
123
|
-
def GetMessageFromHub(self) -> list[UserMessage]:
|
124
|
-
"""
|
125
|
-
获取前端messages
|
126
|
-
Get User messages from AppHub
|
127
|
-
|
128
|
-
Returns:
|
129
|
-
- list[UserMessage]
|
130
|
-
"""
|
131
|
-
resp = self._client.fetch_user_messages(self._agent_id)
|
132
|
-
if len(resp) > 0:
|
133
|
-
u2a = []
|
134
|
-
for re in resp:
|
135
|
-
u2a.append(AgentMessage(re.id, re.timestamp, re.content, None, None))
|
136
|
-
self.messageBuffer += u2a
|
137
|
-
return resp
|