pycityagent 1.1.10__tar.gz → 1.1.11__tar.gz

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.
Files changed (64) hide show
  1. {pycityagent-1.1.10 → pycityagent-1.1.11}/PKG-INFO +1 -1
  2. {pycityagent-1.1.10 → pycityagent-1.1.11}/pycityagent/__init__.py +2 -1
  3. {pycityagent-1.1.10 → pycityagent-1.1.11}/pycityagent/ac/citizen_actions/trip.py +2 -3
  4. pycityagent-1.1.11/pycityagent/ac/hub_actions.py +295 -0
  5. {pycityagent-1.1.10 → pycityagent-1.1.11}/pycityagent/agent.py +2 -0
  6. {pycityagent-1.1.10 → pycityagent-1.1.11}/pycityagent/agent_citizen.py +10 -2
  7. {pycityagent-1.1.10 → pycityagent-1.1.11}/pycityagent/agent_func.py +16 -11
  8. pycityagent-1.1.11/pycityagent/agent_group.py +84 -0
  9. {pycityagent-1.1.10 → pycityagent-1.1.11}/pycityagent/brain/brain.py +1 -0
  10. {pycityagent-1.1.10 → pycityagent-1.1.11}/pycityagent/brain/memory.py +15 -15
  11. {pycityagent-1.1.10 → pycityagent-1.1.11}/pycityagent/brain/scheduler.py +1 -1
  12. {pycityagent-1.1.10 → pycityagent-1.1.11}/pycityagent/brain/sence.py +73 -63
  13. {pycityagent-1.1.10 → pycityagent-1.1.11}/pycityagent/hubconnector/__init__.py +1 -1
  14. pycityagent-1.1.11/pycityagent/hubconnector/hubconnector.py +476 -0
  15. pycityagent-1.1.11/pycityagent/simulator.py +334 -0
  16. pycityagent-1.1.11/pycityagent/urbanllm/urbanllm.py +500 -0
  17. {pycityagent-1.1.10 → pycityagent-1.1.11}/pycityagent/utils.py +34 -4
  18. {pycityagent-1.1.10 → pycityagent-1.1.11}/pycityagent.egg-info/PKG-INFO +1 -1
  19. {pycityagent-1.1.10 → pycityagent-1.1.11}/pycityagent.egg-info/SOURCES.txt +1 -0
  20. pycityagent-1.1.10/pycityagent/ac/hub_actions.py +0 -95
  21. pycityagent-1.1.10/pycityagent/hubconnector/hubconnector.py +0 -131
  22. pycityagent-1.1.10/pycityagent/simulator.py +0 -192
  23. pycityagent-1.1.10/pycityagent/urbanllm/urbanllm.py +0 -200
  24. {pycityagent-1.1.10 → pycityagent-1.1.11}/LICENSE +0 -0
  25. {pycityagent-1.1.10 → pycityagent-1.1.11}/README.md +0 -0
  26. {pycityagent-1.1.10 → pycityagent-1.1.11}/pycityagent/ac/__init__.py +0 -0
  27. {pycityagent-1.1.10 → pycityagent-1.1.11}/pycityagent/ac/ac.py +0 -0
  28. {pycityagent-1.1.10 → pycityagent-1.1.11}/pycityagent/ac/action.py +0 -0
  29. {pycityagent-1.1.10 → pycityagent-1.1.11}/pycityagent/ac/action_stream.py +0 -0
  30. {pycityagent-1.1.10 → pycityagent-1.1.11}/pycityagent/ac/citizen_actions/controled.py +0 -0
  31. {pycityagent-1.1.10 → pycityagent-1.1.11}/pycityagent/ac/citizen_actions/converse.py +0 -0
  32. {pycityagent-1.1.10 → pycityagent-1.1.11}/pycityagent/ac/citizen_actions/idle.py +0 -0
  33. {pycityagent-1.1.10 → pycityagent-1.1.11}/pycityagent/ac/citizen_actions/shop.py +0 -0
  34. {pycityagent-1.1.10 → pycityagent-1.1.11}/pycityagent/ac/sim_actions.py +0 -0
  35. {pycityagent-1.1.10 → pycityagent-1.1.11}/pycityagent/brain/__init__.py +0 -0
  36. {pycityagent-1.1.10 → pycityagent-1.1.11}/pycityagent/brain/brainfc.py +0 -0
  37. {pycityagent-1.1.10 → pycityagent-1.1.11}/pycityagent/brain/persistence/__init__.py +0 -0
  38. {pycityagent-1.1.10 → pycityagent-1.1.11}/pycityagent/brain/persistence/social.py +0 -0
  39. {pycityagent-1.1.10 → pycityagent-1.1.11}/pycityagent/brain/persistence/spatial.py +0 -0
  40. {pycityagent-1.1.10 → pycityagent-1.1.11}/pycityagent/brain/reason/__init__.py +0 -0
  41. {pycityagent-1.1.10 → pycityagent-1.1.11}/pycityagent/brain/reason/shop.py +0 -0
  42. {pycityagent-1.1.10 → pycityagent-1.1.11}/pycityagent/brain/reason/social.py +0 -0
  43. {pycityagent-1.1.10 → pycityagent-1.1.11}/pycityagent/brain/reason/trip.py +0 -0
  44. {pycityagent-1.1.10 → pycityagent-1.1.11}/pycityagent/brain/reason/user.py +0 -0
  45. {pycityagent-1.1.10 → pycityagent-1.1.11}/pycityagent/brain/retrive/__init__.py +0 -0
  46. {pycityagent-1.1.10 → pycityagent-1.1.11}/pycityagent/brain/retrive/social.py +0 -0
  47. {pycityagent-1.1.10 → pycityagent-1.1.11}/pycityagent/brain/static.py +0 -0
  48. {pycityagent-1.1.10 → pycityagent-1.1.11}/pycityagent/cc/__init__.py +0 -0
  49. {pycityagent-1.1.10 → pycityagent-1.1.11}/pycityagent/cc/cc.py +0 -0
  50. {pycityagent-1.1.10 → pycityagent-1.1.11}/pycityagent/cc/conve.py +0 -0
  51. {pycityagent-1.1.10 → pycityagent-1.1.11}/pycityagent/cc/idle.py +0 -0
  52. {pycityagent-1.1.10 → pycityagent-1.1.11}/pycityagent/cc/shop.py +0 -0
  53. {pycityagent-1.1.10 → pycityagent-1.1.11}/pycityagent/cc/trip.py +0 -0
  54. {pycityagent-1.1.10 → pycityagent-1.1.11}/pycityagent/cc/user.py +0 -0
  55. {pycityagent-1.1.10 → pycityagent-1.1.11}/pycityagent/image/__init__.py +0 -0
  56. {pycityagent-1.1.10 → pycityagent-1.1.11}/pycityagent/image/image.py +0 -0
  57. {pycityagent-1.1.10 → pycityagent-1.1.11}/pycityagent/st/__init__.py +0 -0
  58. {pycityagent-1.1.10 → pycityagent-1.1.11}/pycityagent/st/st.py +0 -0
  59. {pycityagent-1.1.10 → pycityagent-1.1.11}/pycityagent/urbanllm/__init__.py +0 -0
  60. {pycityagent-1.1.10 → pycityagent-1.1.11}/pycityagent.egg-info/dependency_links.txt +0 -0
  61. {pycityagent-1.1.10 → pycityagent-1.1.11}/pycityagent.egg-info/requires.txt +0 -0
  62. {pycityagent-1.1.10 → pycityagent-1.1.11}/pycityagent.egg-info/top_level.txt +0 -0
  63. {pycityagent-1.1.10 → pycityagent-1.1.11}/pyproject.toml +0 -0
  64. {pycityagent-1.1.10 → pycityagent-1.1.11}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: pycityagent
3
- Version: 1.1.10
3
+ Version: 1.1.11
4
4
  Summary: LLM-based城市模拟器agent构建库
5
5
  Author-email: Yuwei Yan <pinkgranite86@gmail.com>
6
6
  License: MIT License
@@ -6,5 +6,6 @@ from .simulator import Simulator
6
6
  from .agent import Agent
7
7
  from .agent_citizen import CitizenAgent
8
8
  from .agent_func import FuncAgent
9
+ from .agent_group import GroupAgent
9
10
 
10
- __all__ = [Simulator, Agent, CitizenAgent, FuncAgent]
11
+ __all__ = [Simulator, Agent, CitizenAgent, FuncAgent, GroupAgent]
@@ -13,10 +13,9 @@ class TripAction(Action):
13
13
  async def Forward(self):
14
14
  now = self._agent.Scheduler.now
15
15
  if now.is_set:
16
- # TODO: 目前仅支持传输一张图片至前端
17
16
  '''之前已经将schedule同步至模拟器了'''
18
- if self._agent.Hub != None:
19
- self._agent.Hub.Update(streetview=self._agent.Brain.Sence.sence_buffer['streetview'][0])
17
+ if self._agent.Hub != None and self._agent.Brain.Sence.sence_buffer['streetview'] != None:
18
+ self._agent.Hub.Update(streetview=self._agent.Brain.Sence.sence_buffer['streetview'])
20
19
  else:
21
20
  '''同步schedule至模拟器'''
22
21
  self._agent.Scheduler.now.is_set = True
@@ -0,0 +1,295 @@
1
+ """AppHub关联Action定义"""
2
+
3
+ from typing import Callable, Optional, Any, Union
4
+ from geojson import Feature, FeatureCollection, Point, LineString
5
+ from shapely.geometry import mapping
6
+ from pycitysim.apphub import AgentMessage
7
+ from .action import HubAction
8
+ from PIL.Image import Image
9
+ from ..utils import *
10
+
11
+ class SendUserMessage(HubAction):
12
+ """
13
+ 发送用户可见信息
14
+ Send messages to user
15
+ """
16
+ def __init__(self, agent, source: str = None, before: Callable[[list], Any] = None) -> None:
17
+ super().__init__(agent, source, before)
18
+
19
+ async def Forward(self, messages: Optional[list[AgentMessage]] = None):
20
+ if not messages == None:
21
+ self._agent.Hub.Update(messages = messages)
22
+ elif self._source != None:
23
+ messages = self.get_source()
24
+ if messages != None:
25
+ self._agent.Hub.Update(messages = messages)
26
+ else:
27
+ print("Error: without input data")
28
+
29
+ class SendStreetview(HubAction):
30
+ """
31
+ 发送街景图片至前端
32
+ Send streetview to frontend
33
+ """
34
+ def __init__(self, agent, source: str = None, before: Callable[[list], Any] = None) -> None:
35
+ super().__init__(agent, source, before)
36
+
37
+ async def Forward(self, images: Optional[list[Image]] = None):
38
+ if not images == None:
39
+ self._agent.Hub.Update(streetview = images)
40
+ elif self._source != None:
41
+ images = self.get_source()
42
+ if images != None:
43
+ self._agent.Hub.Update(streetview = images)
44
+ else:
45
+ print("Error: without input data")
46
+
47
+ class SendPop(HubAction):
48
+ """
49
+ 发送Pop信息 - agent头顶气泡信息
50
+ Send pop message to frontend, pop message shows above the target agent
51
+ """
52
+ def __init__(self, agent, source: str = None, before: Callable[[list], Any] = None) -> None:
53
+ super().__init__(agent, source, before)
54
+
55
+ async def Forward(self, pop:Optional[str] = None):
56
+ if not pop == None:
57
+ self._agent.Hub.Update(pop = pop)
58
+ elif self._source != None:
59
+ pop = self.get_source()
60
+ if pop != None:
61
+ self._agent.Hub.Update(pop = pop)
62
+ else:
63
+ print("Error: without input data")
64
+
65
+ class PositionUpdate(HubAction):
66
+ """
67
+ 同步当前agent的位置信息
68
+ Send the position of current agent to frontend
69
+ """
70
+ def __init__(self, agent, source: str = None, before: Callable[[list], Any] = None) -> None:
71
+ super().__init__(agent, source, before)
72
+
73
+ async def Forward(self, longlat: Optional[list[float]] = None):
74
+ if longlat != None:
75
+ self._agent.Hub.Update(longlat = longlat)
76
+ elif self._source != None:
77
+ longlat = self.get_source()
78
+ if longlat != None:
79
+ self._agent.Hub.Update(longlat = longlat)
80
+ else:
81
+ print("Error: without input data")
82
+
83
+ class ShowPosition(HubAction):
84
+ """
85
+ 在地图上展示特定地点
86
+ Show a position in frontend map
87
+ """
88
+ def __init__(self, agent, source: str = None, before: Callable[[list], Any] = None) -> None:
89
+ super().__init__(agent, source, before)
90
+
91
+ async def Forward(self, position: Union[int, list[float]], properties: Optional[dict]=None):
92
+ """
93
+ Args:
94
+ - position (Union[int, list[float]])
95
+ - int: 表示poi id
96
+ - list[float]: 具体的position经纬度坐标
97
+ - properties (Optional[dict]): 支持用户添加自定义属性, 默认为None
98
+ - 例如: {'description': "莲花超市"}
99
+ """
100
+ if isinstance(position, int):
101
+ # poi
102
+ if position in self._agent._simulator.map.pois:
103
+ poi = self._agent._simulator.map.pois[position]
104
+ lnglat_p = poi['shapely_lnglat']
105
+ position_feature = Feature(geometry=lnglat_p, properties=properties)
106
+ self._agent.Hub.ShowGeo(FeatureCollection([position_feature]))
107
+ else:
108
+ print("Error: wrong position (wrong poi id)")
109
+ else:
110
+ # longitude latitude
111
+ position_feature = Feature(geometry=Point(position), properties=properties)
112
+ self._agent.Hub.ShowGeo(FeatureCollection([position_feature]))
113
+
114
+ class ShowAoi(HubAction):
115
+ """
116
+ 在地图上显示Aoi
117
+ Show aoi in map
118
+ """
119
+ def __init__(self, agent, source: str = None, before: Callable[[list], Any] = None) -> None:
120
+ super().__init__(agent, source, before)
121
+
122
+ async def Forward(self, aoi_id:int, properties: Optional[dict]=None):
123
+ """
124
+ Args:
125
+ - aoi_id (int): Aoi id
126
+ - properties (Optional[dict]): 支持用户添加自定义属性, 默认为None
127
+ - 例如: {'description': "我居住的小区"}
128
+ """
129
+ properties_default = {
130
+ "stroke-width": 2,
131
+ "stroke-opacity": 1,
132
+ "fill": "#ff2600",
133
+ "fill-opacity": 0.5
134
+ }
135
+ if properties != None:
136
+ properties_default.update(properties)
137
+ if aoi_id in self._agent._simulator.map.aois:
138
+ aoi = self._agent._simulator.map.aois[aoi_id]
139
+ lnglat_poly = aoi['shapely_lnglat']
140
+ aoi_feature = Feature(geometry=lnglat_poly, properties=properties_default)
141
+ self._agent.Hub.ShowGeo(FeatureCollection([aoi_feature]))
142
+ else:
143
+ print("Error: wrong aoi id")
144
+
145
+ class ShowPath(HubAction):
146
+ """
147
+ 在地图上展示路径信息
148
+ Show a path in frontend map
149
+ """
150
+ def __init__(self, agent, source: str = None, before: Callable[[list], Any] = None) -> None:
151
+ super().__init__(agent, source, before)
152
+
153
+ async def Forward(self,
154
+ path: Optional[Union[int, list[list[float]]]]=None,
155
+ start_end: Optional[Union[float, tuple[float, float]]]=None,
156
+ direction: Optional[str]='front',
157
+ properties: Optional[dict]=None):
158
+ """
159
+ Args:
160
+ - path (Optional[Union[int, list[list[float]]]]): 如果为None, 从Reason池中基于source拿取数据
161
+ - int: lane id
162
+ - list[list[float]]: path node
163
+ - start_end: (Optional[Union[float, tuple[float, float]]]): 指定显示范围, 如path是list[list[float]]形式则无效
164
+ - float: 如果仅包含一个float, 则展示从指定位置开始到path结尾的位置
165
+ - tuple[float, end]: 分别表示起点与终点
166
+ - direction (str): 指定前进方向, 支持['front', 'back'], 默认为'front'
167
+ - properties (Optional[dict]): 支持用户添加自定义属性, 默认为None
168
+ """
169
+ properties_default = {'stroke-width': 10, 'stroke-opacity': 0.5}
170
+ if properties != None:
171
+ properties_default.update(properties)
172
+ if path != None:
173
+ if isinstance(path, int):
174
+ # lane id
175
+ if path in self._agent._simulator.map.lanes:
176
+ lane = self._agent._simulator.map.lanes[path]
177
+ nodes = lane['center_line']['nodes']
178
+ path_ls = mapping(lane['shapely_lnglat'])
179
+ path_ls['coordinates'] = list(path_ls['coordinates'])
180
+ for i in range(len(path_ls['coordinates'])):
181
+ path_ls['coordinates'][i] = list(path_ls['coordinates'][i])
182
+ # start-end与direction处理
183
+ if isinstance(start_end, float):
184
+ # start
185
+ if direction == 'back':
186
+ key_index = get_keyindex_in_lane(nodes, start_end, 'back')
187
+ path_ls['coordinates'] = path_ls['coordinates'][:key_index+1]
188
+ path_ls['coordinates'].reverse()
189
+ else:
190
+ key_index = get_keyindex_in_lane(nodes, start_end)
191
+ path_ls['coordinates'] = path_ls['coordinates'][key_index:]
192
+
193
+ path_ls['coordinates'][0] = [
194
+ self._agent.motion['position']['longlat_position']['longitude'],
195
+ self._agent.motion['position']['longlat_position']['latitude']
196
+ ]
197
+ elif isinstance(start_end, tuple) and len(start_end) == 2:
198
+ # start - end
199
+ start = start_end[0]
200
+ end = start_end[1]
201
+ if direction == 'back':
202
+ keyIndex_s = get_keyindex_in_lane(nodes, start, 'back')
203
+ keyIndex_e = get_keyindex_in_lane(nodes, end, 'back')
204
+ path_ls['coordinates'] = path_ls['coordinates'][keyIndex_e:keyIndex_s+1]
205
+ path_ls['coordinates'].reverse()
206
+ xy = get_xy_in_lane(nodes, end, 'back')
207
+ longlat = self._agent._simulator.map.xy2lnglat(x=xy[0], y=xy[1])
208
+ path_ls['coordinates'].append([longlat[0], longlat[1]])
209
+ else:
210
+ keyIndex_s = get_keyindex_in_lane(nodes, start)
211
+ keyIndex_e = get_keyindex_in_lane(nodes, end)
212
+ path_ls['coordinates'] = path_ls['coordinates'][keyIndex_s:keyIndex_e+1]
213
+ xy = get_xy_in_lane(nodes, end)
214
+ longlat = self._agent._simulator.map.xy2lnglat(x=xy[0], y=xy[1])
215
+ path_ls['coordinates'].append([longlat[0], longlat[1]])
216
+ path_ls['coordinates'][0] = [
217
+ self._agent.motion['position']['longlat_position']['longitude'],
218
+ self._agent.motion['position']['longlat_position']['latitude']
219
+ ]
220
+ path_feature = Feature(geometry=path_ls, properties=properties_default)
221
+ self._agent.Hub.ShowGeo(FeatureCollection([path_feature]))
222
+ else:
223
+ print("Error: wrong path (wrong lane id)")
224
+ else:
225
+ # list point
226
+ path_ls = LineString(path)
227
+ path_feature = Feature(geometry=path_ls, properties=properties_default)
228
+ self._agent.Hub.ShowGeo(FeatureCollection([path_feature]))
229
+ elif self._source != None:
230
+ path_coll = self.get_source()
231
+ if path_coll != None:
232
+ path = path_coll['path']
233
+ start_end = path_coll['start_end']
234
+ direction = path_coll['direction']
235
+ properties = path_coll['properties']
236
+ if properties != None:
237
+ properties_default.update(properties)
238
+ if isinstance(path, int):
239
+ # lane id
240
+ if path in self._agent._simulator.map.lanes:
241
+ lane = self._agent._simulator.map.lanes[path]
242
+ nodes = lane['center_line']['nodes']
243
+ path_ls = mapping(lane['shapely_lnglat'])
244
+ path_ls['coordinates'] = list(path_ls['coordinates'])
245
+ for i in range(len(path_ls['coordinates'])):
246
+ path_ls['coordinates'][i] = list(path_ls['coordinates'][i])
247
+ # start-end与direction处理
248
+ if isinstance(start_end, float):
249
+ # start
250
+ if direction == 'back':
251
+ key_index = get_keyindex_in_lane(nodes, start_end, 'back')
252
+ path_ls['coordinates'] = path_ls['coordinates'][:key_index+1]
253
+ path_ls['coordinates'].reverse()
254
+ else:
255
+ key_index = get_keyindex_in_lane(nodes, start_end)
256
+ path_ls['coordinates'] = path_ls['coordinates'][key_index:]
257
+
258
+ path_ls['coordinates'][0] = [
259
+ self._agent.motion['position']['longlat_position']['longitude'],
260
+ self._agent.motion['position']['longlat_position']['latitude']
261
+ ]
262
+ elif isinstance(start_end, tuple) and len(start_end) == 2:
263
+ # start - end
264
+ start = start_end[0]
265
+ end = start_end[1]
266
+ if direction == 'back':
267
+ keyIndex_s = get_keyindex_in_lane(nodes, start, 'back')
268
+ keyIndex_e = get_keyindex_in_lane(nodes, end, 'back')
269
+ path_ls['coordinates'] = path_ls['coordinates'][keyIndex_e:keyIndex_s+1]
270
+ path_ls['coordinates'].reverse()
271
+ xy = get_xy_in_lane(nodes, end, 'back')
272
+ longlat = self._agent._simulator.map.xy2lnglat(x=xy[0], y=xy[1])
273
+ path_ls['coordinates'].append([longlat[0], longlat[1]])
274
+ else:
275
+ keyIndex_s = get_keyindex_in_lane(nodes, start)
276
+ keyIndex_e = get_keyindex_in_lane(nodes, end)
277
+ path_ls['coordinates'] = path_ls['coordinates'][keyIndex_s:keyIndex_e+1]
278
+ xy = get_xy_in_lane(nodes, end)
279
+ longlat = self._agent._simulator.map.xy2lnglat(x=xy[0], y=xy[1])
280
+ path_ls['coordinates'].append([longlat[0], longlat[1]])
281
+ path_ls['coordinates'][0] = [
282
+ self._agent.motion['position']['longlat_position']['longitude'],
283
+ self._agent.motion['position']['longlat_position']['latitude']
284
+ ]
285
+ path_feature = Feature(geometry=path_ls, properties=properties_default)
286
+ self._agent.Hub.ShowGeo(FeatureCollection([path_feature]))
287
+ else:
288
+ print("Error: wrong path (wrong lane id)")
289
+ else:
290
+ # list point
291
+ path_ls = LineString(path)
292
+ path_feature = Feature(geometry=path_ls, properties=properties_default)
293
+ self._agent.Hub.ShowGeo(FeatureCollection([path_feature]))
294
+ else:
295
+ print("Error: without input")
@@ -22,9 +22,11 @@ class AgentType:
22
22
 
23
23
  - Citizen = 1, 指城市居民类型agent——行动受城市规则限制
24
24
  - Func = 2, 功能型agent——行动规则宽松——本质上模拟器无法感知到Func类型的agent
25
+ - Group = 3, 群体智能体
25
26
  """
26
27
  Citizen = 1
27
28
  Func = 2
29
+ Group = 3
28
30
 
29
31
  class Template:
30
32
  """
@@ -4,6 +4,8 @@ from pycityagent.urbanllm import UrbanLLM
4
4
  from .urbanllm import UrbanLLM
5
5
  from .agent import Agent, AgentType
6
6
  from .image.image import CitizenImage
7
+ from .hubconnector import Waypoint
8
+ import time
7
9
 
8
10
  class CitizenAgent(Agent):
9
11
  """
@@ -54,6 +56,8 @@ class CitizenAgent(Agent):
54
56
  - Schedule Init
55
57
  """
56
58
 
59
+ self._history_trajectory: list[Waypoint] = []
60
+
57
61
  def Bind(self):
58
62
  """
59
63
  - 将智能体绑定到AppHub
@@ -124,8 +128,12 @@ class CitizenAgent(Agent):
124
128
  await self._simulator.GetTime()
125
129
  # * 2. 拉取Agent最新状态
126
130
  resp = await self._client.person_service.GetPerson({'person_id':self._id})
127
- self.base = resp['base']
128
- self.motion = resp['motion']
131
+ self.base = resp['person']['base']
132
+ self.motion = resp['person']['motion']
133
+ longitude = self.motion['position']['longlat_position']['longitude']
134
+ latitude = self.motion['position']['longlat_position']['latitude']
135
+ if self.state == 'trip':
136
+ self._history_trajectory.append(Waypoint([longitude, latitude], int(time.time())))
129
137
  # * 3. Brain工作流
130
138
  await self._brain.Run()
131
139
  # * 4. Commond Controller工作流
@@ -7,6 +7,7 @@ from .agent import Agent, AgentType
7
7
  from .image.image import Image
8
8
  from .ac.hub_actions import PositionUpdate
9
9
  from .utils import *
10
+ from .hubconnector import Waypoint
10
11
 
11
12
  class FuncAgent(Agent):
12
13
  """
@@ -17,7 +18,6 @@ class FuncAgent(Agent):
17
18
  def __init__(
18
19
  self,
19
20
  name:str,
20
- id: int,
21
21
  server:str,
22
22
  soul:UrbanLLM=None,
23
23
  simulator=None,
@@ -34,12 +34,6 @@ class FuncAgent(Agent):
34
34
  """
35
35
 
36
36
  super().__init__(name, server, AgentType.Func, soul, simulator)
37
- self._id = id
38
- """
39
- - 智能体Id
40
- - Agent's id
41
- """
42
-
43
37
  self._image = Image(self)
44
38
  """
45
39
  - Func Agent画像——支持自定义内容
@@ -69,6 +63,7 @@ class FuncAgent(Agent):
69
63
  """
70
64
 
71
65
  self._posUpdate = PositionUpdate(self)
66
+ self._history_trajectory:list[Waypoint] = []
72
67
 
73
68
  async def set_position_aoi(self, aoi_id:int):
74
69
  """
@@ -78,10 +73,13 @@ class FuncAgent(Agent):
78
73
  - aoi_id (int): AOI id
79
74
  """
80
75
  if aoi_id in self._simulator.map.aois:
76
+ if 'aoi_position' in self.motion['position'].keys() and aoi_id == self.motion['position']['aoi_position']['aoi_id']:
77
+ return
81
78
  aoi = self._simulator.map.aois[aoi_id]
82
79
  self.motion['position'] = {}
83
80
  self.motion['position']['aoi_position'] = {'aoi_id': aoi_id}
84
81
  self.motion['position']['longlat_position'] = {'longitude': aoi['shapely_lnglat'].centroid.coords[0][0], 'latitude': aoi['shapely_lnglat'].centroid.coords[0][1]}
82
+ # self._history_trajectory.append([self.motion['position']['longlat_position']['longitude'], self.motion['position']['longlat_position']['latitude']])
85
83
  x, y = self._simulator.map.lnglat2xy(lng=self.motion['position']['longlat_position']['longitude'],
86
84
  lat=self.motion['position']['longlat_position']['latitude'])
87
85
  self.motion['position']['xy_position'] = {'x': x, 'y': y}
@@ -103,6 +101,8 @@ class FuncAgent(Agent):
103
101
  - 对于walking lane而言, 可以朝两个方向通行, 可以是'front'或'back'
104
102
  """
105
103
  if lane_id in self._simulator.map.lanes:
104
+ if 'lane_position' in self.motion['position'].keys() and lane_id == self.motion['position']['lane_position']['lane_id']:
105
+ return
106
106
  lane = self._simulator.map.lanes[lane_id]
107
107
  if s > lane['length']:
108
108
  print("Error: 's' too large")
@@ -124,12 +124,13 @@ class FuncAgent(Agent):
124
124
  else:
125
125
  # 计算方向角
126
126
  direction_ = get_direction_by_s(nodes, s, direction)
127
- self.motion['direction'] = direction_
127
+ self.motion['direction'] = direction_
128
+ # self._history_trajectory.append([self.motion['position']['longlat_position']['longitude'], self.motion['position']['longlat_position']['latitude']])
128
129
  await self._posUpdate.Forward(longlat=[self.motion['position']['longlat_position']['longitude'], self.motion['position']['longlat_position']['latitude']])
129
130
  else:
130
131
  print("Error: wrong lane id")
131
132
 
132
- async def set_position_poi(self, poi_id:int):
133
+ async def set_position_poi(self, poi_id:int, hub:bool=True):
133
134
  """
134
135
  - 将agent的位置设定到指定poi
135
136
 
@@ -138,10 +139,12 @@ class FuncAgent(Agent):
138
139
  """
139
140
  if poi_id in self._simulator.map.pois:
140
141
  poi = self._simulator.map.pois[poi_id]
142
+ aoi_id = poi['aoi_id']
143
+ if 'aoi_position' in self.motion['position'].keys() and aoi_id == self.motion['position']['aoi_position']['aoi_id']:
144
+ return
141
145
  x = poi['position']['x']
142
146
  y = poi['position']['y']
143
147
  longlat = self._simulator.map.xy2lnglat(x=x, y=y)
144
- aoi_id = poi['aoi_id']
145
148
  self.motion['position'] = {}
146
149
  self.motion['position']['aoi_position'] = {'aoi_id': aoi_id}
147
150
  self.motion['position']['longlat_position'] = {
@@ -152,7 +155,9 @@ class FuncAgent(Agent):
152
155
  'x': x,
153
156
  'y': y
154
157
  }
155
- await self._posUpdate.Forward(longlat=[self.motion['position']['longlat_position']['longitude'], self.motion['position']['longlat_position']['latitude']])
158
+ # self._history_trajectory.append([self.motion['position']['longlat_position']['longitude'], self.motion['position']['longlat_position']['latitude']])
159
+ if hub:
160
+ await self._posUpdate.Forward(longlat=[self.motion['position']['longlat_position']['longitude'], self.motion['position']['longlat_position']['latitude']])
156
161
  else:
157
162
  print("Error: wrong poi id")
158
163
 
@@ -0,0 +1,84 @@
1
+ """GroupAgent群体智能体"""
2
+
3
+ from typing import Union, Optional
4
+ from pycityagent.urbanllm import UrbanLLM
5
+ from .urbanllm import UrbanLLM
6
+ from .agent import Agent, AgentType
7
+ from .image.image import Image
8
+ from .ac.hub_actions import PositionUpdate
9
+ from .agent_func import FuncAgent
10
+ from .utils import *
11
+
12
+ class GroupAgent(Agent):
13
+ """
14
+ GroupAgent
15
+ 群体智能体
16
+ """
17
+
18
+ def __init__(
19
+ self,
20
+ name: str,
21
+ soul: UrbanLLM = None,
22
+ simulator=None
23
+ ) -> None:
24
+ super().__init__(name, simulator.config['simulator']['server'], AgentType.Group, soul, simulator)
25
+ self.agents:list[FuncAgent] = []
26
+ """
27
+ Agent列表
28
+ """
29
+
30
+ def add_agents(self, agents:Optional[list[FuncAgent]]=None, ids: Optional[Union[int, list[int], tuple]]=None, number:Optional[int]=1):
31
+ """
32
+ 添加一个或多个智能体
33
+
34
+ Args:
35
+ - agents: FuncAgent列表
36
+ - ids: 智能体id
37
+ - int: 添加单个智能体
38
+ - list[int]: 添加多个智能体
39
+ - tuple(int, int): 根据范围确定添加智能体个数
40
+ - number: 智能体个数
41
+ - 与int类型ids参数配合使用
42
+ """
43
+ if agents != None:
44
+ self.agents = agents
45
+ elif isinstance(ids, int):
46
+ for i in range(number):
47
+ agent = FuncAgent(
48
+ f"{self._name}_{ids+i}",
49
+ ids+i,
50
+ self._simulator.config['simulator']['server'],
51
+ simulator=self._simulator
52
+ )
53
+ self.agents.append(agent)
54
+ elif isinstance(ids, list):
55
+ for id in ids:
56
+ agent = FuncAgent(
57
+ f"{self._name}_{id}",
58
+ id,
59
+ self._simulator.config['simulator']['server'],
60
+ simulator=self._simulator
61
+ )
62
+ self.agents.append(agent)
63
+ elif isinstance(ids, tuple):
64
+ if len(ids) == 2 and ids[0] <= ids[0]:
65
+ for i in range(ids[0], ids[1]+1):
66
+ agent = FuncAgent(
67
+ f"{self._name}_{i}",
68
+ i,
69
+ self._simulator.config['simulator']['server'],
70
+ simulator=self._simulator
71
+ )
72
+ self.agents.append(agent)
73
+ else:
74
+ raise Exception(f"Error: wrong id tuple: {ids}")
75
+ else:
76
+ raise Exception("Wrong parameter")
77
+
78
+ def ConnectToHub(self, config: dict):
79
+ for agent in self.agents:
80
+ agent.ConnectToHub(config)
81
+
82
+ def Bind(self):
83
+ for agent in self.agents:
84
+ agent.Bind()
@@ -18,6 +18,7 @@ class Brain:
18
18
  感知模块
19
19
  Sence module
20
20
  """
21
+
21
22
  self._memory = MemoryController(agent)
22
23
  """
23
24
  记忆模块
@@ -440,21 +440,21 @@ class WorkingMemory(WMemory):
440
440
  """
441
441
  self.sence = sence
442
442
  # * social message
443
- social_message = sence['social_messages']
444
- for message in social_message:
445
- print(message)
446
- from_id = message['from']
447
- content = message['message']
448
- if from_id in self.msg_agent_unhandle.keys():
449
- self.msg_agent_unhandle[from_id] += [{
450
- 'role': 'user',
451
- 'content': content
452
- }]
453
- else:
454
- self.msg_agent_unhandle[from_id] = [{
455
- 'role': 'user',
456
- 'content': content
457
- }]
443
+ # social_message = sence['social_messages']
444
+ # for message in social_message:
445
+ # print(message)
446
+ # from_id = message['from']
447
+ # content = message['message']
448
+ # if from_id in self.msg_agent_unhandle.keys():
449
+ # self.msg_agent_unhandle[from_id] += [{
450
+ # 'role': 'user',
451
+ # 'content': content
452
+ # }]
453
+ # else:
454
+ # self.msg_agent_unhandle[from_id] = [{
455
+ # 'role': 'user',
456
+ # 'content': content
457
+ # }]
458
458
  # * user message
459
459
  self.msg_user_unhandle = sence['user_messages']
460
460
 
@@ -329,7 +329,7 @@ class Scheduler(BrainFunction):
329
329
  self.schedule_set(True)
330
330
  else:
331
331
  # * 基本行程注册
332
- if self.base_schedule_index >=0 and self.base_schedule[self.base_schedule_index].time <= self._agent._simulator.time:
332
+ if self.base_schedule_index >=0 and len(self.base_schedule) > 0 and self.base_schedule[self.base_schedule_index].time <= self._agent._simulator.time:
333
333
  self.now = self.base_schedule[self.base_schedule_index]
334
334
  if 'aoi_position' in self._agent.motion['position'].keys() and self._agent.motion['position']['aoi_position']['aoi_id'] == self.now.target_id_aoi:
335
335
  # 直接跳过该行程