pycityagent 1.1.9__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.
- {pycityagent-1.1.9 → pycityagent-1.1.11}/PKG-INFO +1 -1
- {pycityagent-1.1.9 → pycityagent-1.1.11}/pycityagent/__init__.py +2 -1
- {pycityagent-1.1.9 → pycityagent-1.1.11}/pycityagent/ac/__init__.py +1 -1
- {pycityagent-1.1.9 → pycityagent-1.1.11}/pycityagent/ac/citizen_actions/trip.py +2 -3
- pycityagent-1.1.11/pycityagent/ac/hub_actions.py +295 -0
- {pycityagent-1.1.9 → pycityagent-1.1.11}/pycityagent/agent.py +2 -0
- {pycityagent-1.1.9 → pycityagent-1.1.11}/pycityagent/agent_citizen.py +10 -2
- pycityagent-1.1.11/pycityagent/agent_func.py +216 -0
- pycityagent-1.1.11/pycityagent/agent_group.py +84 -0
- {pycityagent-1.1.9 → pycityagent-1.1.11}/pycityagent/brain/brain.py +1 -0
- {pycityagent-1.1.9 → pycityagent-1.1.11}/pycityagent/brain/memory.py +15 -15
- {pycityagent-1.1.9 → pycityagent-1.1.11}/pycityagent/brain/scheduler.py +1 -1
- {pycityagent-1.1.9 → pycityagent-1.1.11}/pycityagent/brain/sence.py +74 -140
- {pycityagent-1.1.9 → pycityagent-1.1.11}/pycityagent/hubconnector/__init__.py +1 -1
- pycityagent-1.1.11/pycityagent/hubconnector/hubconnector.py +476 -0
- pycityagent-1.1.11/pycityagent/simulator.py +334 -0
- pycityagent-1.1.11/pycityagent/urbanllm/urbanllm.py +500 -0
- pycityagent-1.1.11/pycityagent/utils.py +178 -0
- {pycityagent-1.1.9 → pycityagent-1.1.11}/pycityagent.egg-info/PKG-INFO +1 -1
- {pycityagent-1.1.9 → pycityagent-1.1.11}/pycityagent.egg-info/SOURCES.txt +2 -0
- pycityagent-1.1.9/pycityagent/ac/hub_actions.py +0 -95
- pycityagent-1.1.9/pycityagent/agent_func.py +0 -136
- pycityagent-1.1.9/pycityagent/hubconnector/hubconnector.py +0 -131
- pycityagent-1.1.9/pycityagent/simulator.py +0 -192
- pycityagent-1.1.9/pycityagent/urbanllm/urbanllm.py +0 -200
- {pycityagent-1.1.9 → pycityagent-1.1.11}/LICENSE +0 -0
- {pycityagent-1.1.9 → pycityagent-1.1.11}/README.md +0 -0
- {pycityagent-1.1.9 → pycityagent-1.1.11}/pycityagent/ac/ac.py +0 -0
- {pycityagent-1.1.9 → pycityagent-1.1.11}/pycityagent/ac/action.py +0 -0
- {pycityagent-1.1.9 → pycityagent-1.1.11}/pycityagent/ac/action_stream.py +0 -0
- {pycityagent-1.1.9 → pycityagent-1.1.11}/pycityagent/ac/citizen_actions/controled.py +0 -0
- {pycityagent-1.1.9 → pycityagent-1.1.11}/pycityagent/ac/citizen_actions/converse.py +0 -0
- {pycityagent-1.1.9 → pycityagent-1.1.11}/pycityagent/ac/citizen_actions/idle.py +0 -0
- {pycityagent-1.1.9 → pycityagent-1.1.11}/pycityagent/ac/citizen_actions/shop.py +0 -0
- {pycityagent-1.1.9 → pycityagent-1.1.11}/pycityagent/ac/sim_actions.py +0 -0
- {pycityagent-1.1.9 → pycityagent-1.1.11}/pycityagent/brain/__init__.py +0 -0
- {pycityagent-1.1.9 → pycityagent-1.1.11}/pycityagent/brain/brainfc.py +0 -0
- {pycityagent-1.1.9 → pycityagent-1.1.11}/pycityagent/brain/persistence/__init__.py +0 -0
- {pycityagent-1.1.9 → pycityagent-1.1.11}/pycityagent/brain/persistence/social.py +0 -0
- {pycityagent-1.1.9 → pycityagent-1.1.11}/pycityagent/brain/persistence/spatial.py +0 -0
- {pycityagent-1.1.9 → pycityagent-1.1.11}/pycityagent/brain/reason/__init__.py +0 -0
- {pycityagent-1.1.9 → pycityagent-1.1.11}/pycityagent/brain/reason/shop.py +0 -0
- {pycityagent-1.1.9 → pycityagent-1.1.11}/pycityagent/brain/reason/social.py +0 -0
- {pycityagent-1.1.9 → pycityagent-1.1.11}/pycityagent/brain/reason/trip.py +0 -0
- {pycityagent-1.1.9 → pycityagent-1.1.11}/pycityagent/brain/reason/user.py +0 -0
- {pycityagent-1.1.9 → pycityagent-1.1.11}/pycityagent/brain/retrive/__init__.py +0 -0
- {pycityagent-1.1.9 → pycityagent-1.1.11}/pycityagent/brain/retrive/social.py +0 -0
- {pycityagent-1.1.9 → pycityagent-1.1.11}/pycityagent/brain/static.py +0 -0
- {pycityagent-1.1.9 → pycityagent-1.1.11}/pycityagent/cc/__init__.py +0 -0
- {pycityagent-1.1.9 → pycityagent-1.1.11}/pycityagent/cc/cc.py +0 -0
- {pycityagent-1.1.9 → pycityagent-1.1.11}/pycityagent/cc/conve.py +0 -0
- {pycityagent-1.1.9 → pycityagent-1.1.11}/pycityagent/cc/idle.py +0 -0
- {pycityagent-1.1.9 → pycityagent-1.1.11}/pycityagent/cc/shop.py +0 -0
- {pycityagent-1.1.9 → pycityagent-1.1.11}/pycityagent/cc/trip.py +0 -0
- {pycityagent-1.1.9 → pycityagent-1.1.11}/pycityagent/cc/user.py +0 -0
- {pycityagent-1.1.9 → pycityagent-1.1.11}/pycityagent/image/__init__.py +0 -0
- {pycityagent-1.1.9 → pycityagent-1.1.11}/pycityagent/image/image.py +0 -0
- {pycityagent-1.1.9 → pycityagent-1.1.11}/pycityagent/st/__init__.py +0 -0
- {pycityagent-1.1.9 → pycityagent-1.1.11}/pycityagent/st/st.py +0 -0
- {pycityagent-1.1.9 → pycityagent-1.1.11}/pycityagent/urbanllm/__init__.py +0 -0
- {pycityagent-1.1.9 → pycityagent-1.1.11}/pycityagent.egg-info/dependency_links.txt +0 -0
- {pycityagent-1.1.9 → pycityagent-1.1.11}/pycityagent.egg-info/requires.txt +0 -0
- {pycityagent-1.1.9 → pycityagent-1.1.11}/pycityagent.egg-info/top_level.txt +0 -0
- {pycityagent-1.1.9 → pycityagent-1.1.11}/pyproject.toml +0 -0
- {pycityagent-1.1.9 → pycityagent-1.1.11}/setup.cfg +0 -0
@@ -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]
|
@@ -5,4 +5,4 @@ from .action import *
|
|
5
5
|
from .hub_actions import *
|
6
6
|
from .sim_actions import *
|
7
7
|
|
8
|
-
__all__ = [ActionController, Action, HubAction, SimAction, SendUserMessage, SendStreetview, SendPop,
|
8
|
+
__all__ = [ActionController, Action, HubAction, SimAction, SendUserMessage, SendStreetview, SendPop, ShowPath, ShowPosition, SetSchedule, SendAgentMessage]
|
@@ -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']
|
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")
|
@@ -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工作流
|
@@ -0,0 +1,216 @@
|
|
1
|
+
"""FuncAgent: 功能性智能体及其定义"""
|
2
|
+
|
3
|
+
from typing import Union
|
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 .utils import *
|
10
|
+
from .hubconnector import Waypoint
|
11
|
+
|
12
|
+
class FuncAgent(Agent):
|
13
|
+
"""
|
14
|
+
Fuctional Agent
|
15
|
+
功能型Agent
|
16
|
+
"""
|
17
|
+
|
18
|
+
def __init__(
|
19
|
+
self,
|
20
|
+
name:str,
|
21
|
+
server:str,
|
22
|
+
soul:UrbanLLM=None,
|
23
|
+
simulator=None,
|
24
|
+
) -> None:
|
25
|
+
"""
|
26
|
+
初始化 Init
|
27
|
+
|
28
|
+
Args:
|
29
|
+
- name (str): 智能体名称; name of your agent
|
30
|
+
- id (int): 智能体Id; id of your agent
|
31
|
+
- server (str): 模拟器grpc服务地址; server address of simulator
|
32
|
+
- soul (UrbanLLM): 基础模型模块; base model
|
33
|
+
- simulator (Simulator): 模拟器对象; simulator
|
34
|
+
"""
|
35
|
+
|
36
|
+
super().__init__(name, server, AgentType.Func, soul, simulator)
|
37
|
+
self._image = Image(self)
|
38
|
+
"""
|
39
|
+
- Func Agent画像——支持自定义内容
|
40
|
+
"""
|
41
|
+
|
42
|
+
self.motion = {'id': id, 'position': {}, 'direction': 0}
|
43
|
+
"""
|
44
|
+
Func Agent状态信息——与agent的sence高度相关
|
45
|
+
Keys:
|
46
|
+
- id (int): 即agent id
|
47
|
+
- position (https://cityproto.sim.fiblab.net/#city.geo.v2.Position): 即agent当前的位置描述信息
|
48
|
+
- lane_position (dict): 当position中包含该key时表示agent当前位于lane上——与aoi_position不可同时存在
|
49
|
+
- lane_id (int)
|
50
|
+
- s (double)
|
51
|
+
- aoi_position (dict): 当position中包含该key时表示agent当前位于aoi中——与lane_position不可同时存在
|
52
|
+
- aoi_id (int)
|
53
|
+
- poi_id (optional[int])
|
54
|
+
- longlat_position (dict): WGS84经纬度坐标位置
|
55
|
+
- longitude (double): 经度
|
56
|
+
- latitude (double): 纬度
|
57
|
+
- z (optional[double]): 高程信息
|
58
|
+
- xy_position (dict): 坐标系表示的位置
|
59
|
+
- x (double)
|
60
|
+
- y (double)
|
61
|
+
- z (double)
|
62
|
+
- direction (double): 朝向-方向角
|
63
|
+
"""
|
64
|
+
|
65
|
+
self._posUpdate = PositionUpdate(self)
|
66
|
+
self._history_trajectory:list[Waypoint] = []
|
67
|
+
|
68
|
+
async def set_position_aoi(self, aoi_id:int):
|
69
|
+
"""
|
70
|
+
- 将agent的位置设定到指定aoi
|
71
|
+
|
72
|
+
Args:
|
73
|
+
- aoi_id (int): AOI id
|
74
|
+
"""
|
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
|
78
|
+
aoi = self._simulator.map.aois[aoi_id]
|
79
|
+
self.motion['position'] = {}
|
80
|
+
self.motion['position']['aoi_position'] = {'aoi_id': aoi_id}
|
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']])
|
83
|
+
x, y = self._simulator.map.lnglat2xy(lng=self.motion['position']['longlat_position']['longitude'],
|
84
|
+
lat=self.motion['position']['longlat_position']['latitude'])
|
85
|
+
self.motion['position']['xy_position'] = {'x': x, 'y': y}
|
86
|
+
await self._posUpdate.Forward(longlat=[self.motion['position']['longlat_position']['longitude'], self.motion['position']['longlat_position']['latitude']])
|
87
|
+
else:
|
88
|
+
print("Error: wrong aoi id")
|
89
|
+
|
90
|
+
async def set_position_lane(self, lane_id:int, s:float=0.0, direction:Union[float, str]='front'):
|
91
|
+
"""
|
92
|
+
- 将agent的位置设定到指定lane
|
93
|
+
|
94
|
+
Args:
|
95
|
+
- lane_id (int): Lane id
|
96
|
+
- s (float): distance from the start point of the lane, default None, if None, then set to the start point
|
97
|
+
- direction (Union[float, str]): agent方向角, 默认值为'front'
|
98
|
+
- float: 直接设置为给定方向角(atan2计算得到)
|
99
|
+
- str: 可选项['front', 'back'], 指定agent的行走方向
|
100
|
+
- 对于driving lane而言, 只能朝一个方向通行, 只能是'front'
|
101
|
+
- 对于walking lane而言, 可以朝两个方向通行, 可以是'front'或'back'
|
102
|
+
"""
|
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
|
+
lane = self._simulator.map.lanes[lane_id]
|
107
|
+
if s > lane['length']:
|
108
|
+
print("Error: 's' too large")
|
109
|
+
self.motion['position'] = {}
|
110
|
+
self.motion['position']['lane_position'] = {'lane_id': lane_id, 's': s}
|
111
|
+
nodes = lane['center_line']['nodes']
|
112
|
+
x, y = get_xy_in_lane(nodes, s)
|
113
|
+
longlat = self._simulator.map.xy2lnglat(x=x, y=y)
|
114
|
+
self.motion['position']['longlat_position'] = {
|
115
|
+
'longitude': longlat[0],
|
116
|
+
'latitude': longlat[1]
|
117
|
+
}
|
118
|
+
self.motion['position']['xy_position'] = {
|
119
|
+
'x': x,
|
120
|
+
'y': y
|
121
|
+
}
|
122
|
+
if isinstance(direction, float):
|
123
|
+
self.motion['direction'] = direction
|
124
|
+
else:
|
125
|
+
# 计算方向角
|
126
|
+
direction_ = get_direction_by_s(nodes, s, direction)
|
127
|
+
self.motion['direction'] = direction_
|
128
|
+
# self._history_trajectory.append([self.motion['position']['longlat_position']['longitude'], self.motion['position']['longlat_position']['latitude']])
|
129
|
+
await self._posUpdate.Forward(longlat=[self.motion['position']['longlat_position']['longitude'], self.motion['position']['longlat_position']['latitude']])
|
130
|
+
else:
|
131
|
+
print("Error: wrong lane id")
|
132
|
+
|
133
|
+
async def set_position_poi(self, poi_id:int, hub:bool=True):
|
134
|
+
"""
|
135
|
+
- 将agent的位置设定到指定poi
|
136
|
+
|
137
|
+
Args:
|
138
|
+
- poi_id (int): Poi id
|
139
|
+
"""
|
140
|
+
if poi_id in self._simulator.map.pois:
|
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
|
145
|
+
x = poi['position']['x']
|
146
|
+
y = poi['position']['y']
|
147
|
+
longlat = self._simulator.map.xy2lnglat(x=x, y=y)
|
148
|
+
self.motion['position'] = {}
|
149
|
+
self.motion['position']['aoi_position'] = {'aoi_id': aoi_id}
|
150
|
+
self.motion['position']['longlat_position'] = {
|
151
|
+
'longitude': longlat[0],
|
152
|
+
'latitude': longlat[1]
|
153
|
+
}
|
154
|
+
self.motion['position']['xy_position'] = {
|
155
|
+
'x': x,
|
156
|
+
'y': y
|
157
|
+
}
|
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']])
|
161
|
+
else:
|
162
|
+
print("Error: wrong poi id")
|
163
|
+
|
164
|
+
def Bind(self):
|
165
|
+
"""
|
166
|
+
- 将智能体绑定到AppHub
|
167
|
+
- Bind the Agent with AppHub
|
168
|
+
"""
|
169
|
+
if self._hub_connector == None:
|
170
|
+
print("ERROR: connect with apphub first")
|
171
|
+
else:
|
172
|
+
self._hub_connector.InsertFuncAgent()
|
173
|
+
|
174
|
+
def set_image(self, image: Image):
|
175
|
+
"""
|
176
|
+
- 设置image——支持自由扩展Image
|
177
|
+
"""
|
178
|
+
self._image = image
|
179
|
+
|
180
|
+
async def Step(self, log:bool):
|
181
|
+
"""
|
182
|
+
单步Agent执行流
|
183
|
+
Single step entrance
|
184
|
+
(Not recommended, use Run() method)
|
185
|
+
|
186
|
+
Args:
|
187
|
+
- log (bool): 是否输出log信息. Whether console log message
|
188
|
+
"""
|
189
|
+
# * 1. 模拟器时间更新
|
190
|
+
await self._simulator.GetTime()
|
191
|
+
# * 2. Brain工作流
|
192
|
+
await self._brain.Run()
|
193
|
+
# * 3. Commond Controller工作流
|
194
|
+
command = await self._cc.Run()
|
195
|
+
# * 4. State Transformer工作流
|
196
|
+
self._st.trigger(command)
|
197
|
+
# * 5. Action Controller工作流
|
198
|
+
if self._step_with_action:
|
199
|
+
await self._ac.Run()
|
200
|
+
if log:
|
201
|
+
print(f"---------------------- SIM TIME: {self._simulator.time} ----------------------")
|
202
|
+
self.show_yourself()
|
203
|
+
|
204
|
+
def show_yourself(self):
|
205
|
+
"""
|
206
|
+
- Log信息输出
|
207
|
+
- Pring log message
|
208
|
+
"""
|
209
|
+
pass
|
210
|
+
|
211
|
+
@property
|
212
|
+
def Image(self):
|
213
|
+
"""
|
214
|
+
- The Agent's Image
|
215
|
+
"""
|
216
|
+
return self._image
|