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
@@ -0,0 +1,294 @@
|
|
1
|
+
import warnings
|
2
|
+
from typing import Any, Awaitable, Coroutine, Dict, Union, cast
|
3
|
+
|
4
|
+
import grpc
|
5
|
+
from google.protobuf.json_format import ParseDict
|
6
|
+
from mosstool.trip.generator import default_person_template_generator
|
7
|
+
from mosstool.util.format_converter import pb2dict
|
8
|
+
from pycityproto.city.person.v2 import person_pb2 as person_pb2
|
9
|
+
from pycityproto.city.person.v2 import person_service_pb2 as person_service
|
10
|
+
from pycityproto.city.person.v2 import person_service_pb2_grpc as person_grpc
|
11
|
+
|
12
|
+
from ..utils.protobuf import async_parse
|
13
|
+
|
14
|
+
__all__ = ["PersonService"]
|
15
|
+
|
16
|
+
|
17
|
+
class PersonService:
|
18
|
+
"""
|
19
|
+
交通模拟person服务
|
20
|
+
Traffic simulation person service
|
21
|
+
"""
|
22
|
+
|
23
|
+
def __init__(self, aio_channel: grpc.aio.Channel):
|
24
|
+
self._aio_stub = person_grpc.PersonServiceStub(aio_channel)
|
25
|
+
|
26
|
+
@staticmethod
|
27
|
+
def default_person() -> person_pb2.Person:
|
28
|
+
"""
|
29
|
+
获取person基本模板
|
30
|
+
Get person basic template
|
31
|
+
|
32
|
+
需要补充的字段有person.home,person.schedules,person.labels
|
33
|
+
The fields that need to be supplemented are person.home, person.schedules, person.labels
|
34
|
+
"""
|
35
|
+
person = default_person_template_generator()
|
36
|
+
return person
|
37
|
+
|
38
|
+
@staticmethod
|
39
|
+
def default_dict_person() -> dict:
|
40
|
+
"""
|
41
|
+
获取person基本模板,字典格式
|
42
|
+
Get person basic template in dict format.
|
43
|
+
|
44
|
+
需要补充的字段有person.home,person.schedules,person.labels
|
45
|
+
The fields that need to be supplemented are person.home, person.schedules, person.labels
|
46
|
+
"""
|
47
|
+
person = default_person_template_generator()
|
48
|
+
return pb2dict(person)
|
49
|
+
|
50
|
+
def GetPerson(
|
51
|
+
self,
|
52
|
+
req: Union[person_service.GetPersonRequest, dict],
|
53
|
+
dict_return: bool = True,
|
54
|
+
) -> Coroutine[Any, Any, Union[Dict[str, Any], person_service.GetPersonResponse]]:
|
55
|
+
"""
|
56
|
+
获取person信息
|
57
|
+
Get person information
|
58
|
+
|
59
|
+
Args:
|
60
|
+
- req (dict): https://cityproto.sim.fiblab.net/#city.person.v2.GetPersonRequest
|
61
|
+
|
62
|
+
Returns:
|
63
|
+
- https://cityproto.sim.fiblab.net/#city.person.v2.GetPersonResponse
|
64
|
+
"""
|
65
|
+
if type(req) != person_service.GetPersonRequest:
|
66
|
+
req = ParseDict(req, person_service.GetPersonRequest())
|
67
|
+
res = cast(
|
68
|
+
Awaitable[person_service.GetPersonResponse], self._aio_stub.GetPerson(req)
|
69
|
+
)
|
70
|
+
return async_parse(res, dict_return)
|
71
|
+
|
72
|
+
def AddPerson(
|
73
|
+
self,
|
74
|
+
req: Union[person_service.AddPersonRequest, dict],
|
75
|
+
dict_return: bool = True,
|
76
|
+
) -> Coroutine[Any, Any, Union[Dict[str, Any], person_service.AddPersonResponse]]:
|
77
|
+
"""
|
78
|
+
新增person
|
79
|
+
Add a new person
|
80
|
+
|
81
|
+
Args:
|
82
|
+
- req (dict): https://cityproto.sim.fiblab.net/#city.person.v2.AddPersonRequest
|
83
|
+
|
84
|
+
Returns:
|
85
|
+
- https://cityproto.sim.fiblab.net/#city.person.v2.AddPersonResponse
|
86
|
+
"""
|
87
|
+
if type(req) != person_service.AddPersonRequest:
|
88
|
+
req = ParseDict(req, person_service.AddPersonRequest())
|
89
|
+
res = cast(
|
90
|
+
Awaitable[person_service.AddPersonResponse], self._aio_stub.AddPerson(req)
|
91
|
+
)
|
92
|
+
return async_parse(res, dict_return)
|
93
|
+
|
94
|
+
def SetSchedule(
|
95
|
+
self,
|
96
|
+
req: Union[person_service.SetScheduleRequest, dict],
|
97
|
+
dict_return: bool = True,
|
98
|
+
) -> Coroutine[Any, Any, Union[Dict[str, Any], person_service.SetScheduleResponse]]:
|
99
|
+
"""
|
100
|
+
修改person的schedule
|
101
|
+
set person's schedule
|
102
|
+
|
103
|
+
Args:
|
104
|
+
- req (dict): https://cityproto.sim.fiblab.net/#city.person.v2.SetScheduleRequest
|
105
|
+
|
106
|
+
Returns:
|
107
|
+
- https://cityproto.sim.fiblab.net/#city.person.v2.SetScheduleResponse
|
108
|
+
"""
|
109
|
+
if type(req) != person_service.SetScheduleRequest:
|
110
|
+
req = ParseDict(req, person_service.SetScheduleRequest())
|
111
|
+
res = cast(
|
112
|
+
Awaitable[person_service.SetScheduleResponse],
|
113
|
+
self._aio_stub.SetSchedule(req),
|
114
|
+
)
|
115
|
+
return async_parse(res, dict_return)
|
116
|
+
|
117
|
+
def GetPersons(
|
118
|
+
self,
|
119
|
+
req: Union[person_service.GetPersonsRequest, dict],
|
120
|
+
dict_return: bool = True,
|
121
|
+
) -> Coroutine[Any, Any, Union[Dict[str, Any], person_service.GetPersonsResponse]]:
|
122
|
+
"""
|
123
|
+
获取多个person信息
|
124
|
+
Get information of multiple persons
|
125
|
+
|
126
|
+
Args:
|
127
|
+
- req (dict): https://cityproto.sim.fiblab.net/#city.person.v2.GetPersonsRequest
|
128
|
+
|
129
|
+
Returns:
|
130
|
+
- https://cityproto.sim.fiblab.net/#city.person.v2.GetPersonsResponse
|
131
|
+
"""
|
132
|
+
if type(req) != person_service.GetPersonsRequest:
|
133
|
+
req = ParseDict(req, person_service.GetPersonsRequest())
|
134
|
+
res = cast(
|
135
|
+
Awaitable[person_service.GetPersonsResponse],
|
136
|
+
self._aio_stub.GetPersons(req),
|
137
|
+
)
|
138
|
+
return async_parse(res, dict_return)
|
139
|
+
|
140
|
+
def GetPersonByLongLatBBox(
|
141
|
+
self,
|
142
|
+
req: Union[person_service.GetPersonByLongLatBBoxRequest, dict],
|
143
|
+
dict_return: bool = True,
|
144
|
+
) -> Coroutine[
|
145
|
+
Any, Any, Union[Dict[str, Any], person_service.GetPersonByLongLatBBoxResponse]
|
146
|
+
]:
|
147
|
+
"""
|
148
|
+
获取特定区域内的person
|
149
|
+
Get persons in a specific region
|
150
|
+
|
151
|
+
Args:
|
152
|
+
- req (dict): https://cityproto.sim.fiblab.net/#city.person.v2.GetPersonByLongLatBBoxRequest
|
153
|
+
|
154
|
+
Returns:
|
155
|
+
- https://cityproto.sim.fiblab.net/#city.person.v2.GetPersonByLongLatBBoxResponse
|
156
|
+
"""
|
157
|
+
if type(req) != person_service.GetPersonByLongLatBBoxRequest:
|
158
|
+
req = ParseDict(req, person_service.GetPersonByLongLatBBoxRequest())
|
159
|
+
res = cast(
|
160
|
+
Awaitable[person_service.GetPersonByLongLatBBoxResponse],
|
161
|
+
self._aio_stub.GetPersonByLongLatBBox(req),
|
162
|
+
)
|
163
|
+
return async_parse(res, dict_return)
|
164
|
+
|
165
|
+
def GetAllVehicles(
|
166
|
+
self,
|
167
|
+
req: Union[person_service.GetAllVehiclesRequest, dict],
|
168
|
+
dict_return: bool = True,
|
169
|
+
) -> Coroutine[
|
170
|
+
Any, Any, Union[Dict[str, Any], person_service.GetAllVehiclesResponse]
|
171
|
+
]:
|
172
|
+
"""
|
173
|
+
获取所有车辆
|
174
|
+
Get all vehicles
|
175
|
+
|
176
|
+
Args:
|
177
|
+
- req (dict): https://cityproto.sim.fiblab.net/#city.person.v2.GetAllVehiclesRequest
|
178
|
+
|
179
|
+
Returns:
|
180
|
+
- https://cityproto.sim.fiblab.net/#city.person.v2.GetAllVehiclesResponse
|
181
|
+
"""
|
182
|
+
if type(req) != person_service.GetAllVehiclesRequest:
|
183
|
+
req = ParseDict(req, person_service.GetAllVehiclesRequest())
|
184
|
+
res = cast(
|
185
|
+
Awaitable[person_service.GetAllVehiclesResponse],
|
186
|
+
self._aio_stub.GetAllVehicles(req),
|
187
|
+
)
|
188
|
+
return async_parse(res, dict_return)
|
189
|
+
|
190
|
+
def ResetPersonPosition(
|
191
|
+
self,
|
192
|
+
req: Union[person_service.ResetPersonPositionRequest, dict],
|
193
|
+
dict_return: bool = True,
|
194
|
+
) -> Coroutine[
|
195
|
+
Any, Any, Union[Dict[str, Any], person_service.ResetPersonPositionResponse]
|
196
|
+
]:
|
197
|
+
"""
|
198
|
+
重置人的位置(将停止当前正在进行的出行,转为sleep状态)
|
199
|
+
Reset person's position (stop the current trip and switch to sleep status)
|
200
|
+
|
201
|
+
Args:
|
202
|
+
- req (dict): https://cityproto.sim.fiblab.net/#city.person.v2.ResetPersonPositionRequest
|
203
|
+
|
204
|
+
Returns:
|
205
|
+
- https://cityproto.sim.fiblab.net/#city.person.v2.ResetPersonPositionResponse
|
206
|
+
"""
|
207
|
+
if type(req) != person_service.ResetPersonPositionRequest:
|
208
|
+
req = ParseDict(req, person_service.ResetPersonPositionRequest())
|
209
|
+
res = cast(
|
210
|
+
Awaitable[person_service.ResetPersonPositionResponse],
|
211
|
+
self._aio_stub.ResetPersonPosition(req),
|
212
|
+
)
|
213
|
+
return async_parse(res, dict_return)
|
214
|
+
|
215
|
+
# RL接口
|
216
|
+
|
217
|
+
def SetControlledVehicleIDs(
|
218
|
+
self,
|
219
|
+
req: Union[person_service.SetControlledVehicleIDsRequest, dict],
|
220
|
+
dict_return: bool = True,
|
221
|
+
) -> Coroutine[
|
222
|
+
Any, Any, Union[Dict[str, Any], person_service.SetControlledVehicleIDsResponse]
|
223
|
+
]:
|
224
|
+
"""
|
225
|
+
设置由外部控制行为的vehicle
|
226
|
+
Set controlled vehicle ID
|
227
|
+
|
228
|
+
Args:
|
229
|
+
- req (dict): https://cityproto.sim.fiblab.net/#city.person.v2.SetControlledVehicleIDsRequest
|
230
|
+
|
231
|
+
Returns:
|
232
|
+
- https://cityproto.sim.fiblab.net/#city.person.v2.SetControlledVehicleIDsResponse
|
233
|
+
"""
|
234
|
+
if type(req) != person_service.SetControlledVehicleIDsRequest:
|
235
|
+
req = ParseDict(req, person_service.SetControlledVehicleIDsRequest())
|
236
|
+
res = cast(
|
237
|
+
Awaitable[person_service.SetControlledVehicleIDsResponse],
|
238
|
+
self._aio_stub.SetControlledVehicleIDs(req),
|
239
|
+
)
|
240
|
+
return async_parse(res, dict_return)
|
241
|
+
|
242
|
+
def FetchControlledVehicleEnvs(
|
243
|
+
self,
|
244
|
+
req: Union[person_service.FetchControlledVehicleEnvsRequest, dict],
|
245
|
+
dict_return: bool = True,
|
246
|
+
) -> Coroutine[
|
247
|
+
Any,
|
248
|
+
Any,
|
249
|
+
Union[Dict[str, Any], person_service.FetchControlledVehicleEnvsResponse],
|
250
|
+
]:
|
251
|
+
"""
|
252
|
+
获取由外部控制行为的vehicle的环境信息
|
253
|
+
Fetch controlled vehicle environment information
|
254
|
+
|
255
|
+
Args:
|
256
|
+
- req (dict): https://cityproto.sim.fiblab.net/#city.person.v2.FetchControlledVehicleEnvsRequest
|
257
|
+
|
258
|
+
Returns:
|
259
|
+
- https://cityproto.sim.fiblab.net/#city.person.v2.FetchControlledVehicleEnvsResponse
|
260
|
+
"""
|
261
|
+
if type(req) != person_service.FetchControlledVehicleEnvsRequest:
|
262
|
+
req = ParseDict(req, person_service.FetchControlledVehicleEnvsRequest())
|
263
|
+
res = cast(
|
264
|
+
Awaitable[person_service.FetchControlledVehicleEnvsResponse],
|
265
|
+
self._aio_stub.FetchControlledVehicleEnvs(req),
|
266
|
+
)
|
267
|
+
return async_parse(res, dict_return)
|
268
|
+
|
269
|
+
def SetControlledVehicleActions(
|
270
|
+
self,
|
271
|
+
req: Union[person_service.SetControlledVehicleActionsRequest, dict],
|
272
|
+
dict_return: bool = True,
|
273
|
+
) -> Coroutine[
|
274
|
+
Any,
|
275
|
+
Any,
|
276
|
+
Union[Dict[str, Any], person_service.SetControlledVehicleActionsResponse],
|
277
|
+
]:
|
278
|
+
"""
|
279
|
+
设置由外部控制行为的vehicle的行为
|
280
|
+
Set controlled vehicle actions
|
281
|
+
|
282
|
+
Args:
|
283
|
+
- req (dict): https://cityproto.sim.fiblab.net/#city.person.v2.SetControlledVehicleActionsRequest
|
284
|
+
|
285
|
+
Returns:
|
286
|
+
- https://cityproto.sim.fiblab.net/#city.person.v2.SetControlledVehicleActionsResponse
|
287
|
+
"""
|
288
|
+
if type(req) != person_service.SetControlledVehicleActionsRequest:
|
289
|
+
req = ParseDict(req, person_service.SetControlledVehicleActionsRequest())
|
290
|
+
res = cast(
|
291
|
+
Awaitable[person_service.SetControlledVehicleActionsResponse],
|
292
|
+
self._aio_stub.SetControlledVehicleActions(req),
|
293
|
+
)
|
294
|
+
return async_parse(res, dict_return)
|
@@ -0,0 +1,38 @@
|
|
1
|
+
from typing import Any, Awaitable, Coroutine, cast, Union, Dict
|
2
|
+
|
3
|
+
import grpc
|
4
|
+
from google.protobuf.json_format import ParseDict
|
5
|
+
from pycityproto.city.map.v2 import road_service_pb2 as road_service
|
6
|
+
from pycityproto.city.map.v2 import road_service_pb2_grpc as road_grpc
|
7
|
+
|
8
|
+
from ..utils.protobuf import async_parse
|
9
|
+
|
10
|
+
__all__ = ["RoadService"]
|
11
|
+
|
12
|
+
|
13
|
+
class RoadService:
|
14
|
+
"""
|
15
|
+
交通模拟road服务
|
16
|
+
Traffic simulation road service
|
17
|
+
"""
|
18
|
+
|
19
|
+
def __init__(self, aio_channel: grpc.aio.Channel):
|
20
|
+
self._aio_stub = road_grpc.RoadServiceStub(aio_channel)
|
21
|
+
|
22
|
+
def GetRoad(
|
23
|
+
self, req: Union[road_service.GetRoadRequest, dict], dict_return: bool = True
|
24
|
+
) -> Coroutine[Any, Any, Union[Dict[str, Any], road_service.GetRoadResponse]]:
|
25
|
+
"""
|
26
|
+
查询道路信息
|
27
|
+
Query road information
|
28
|
+
|
29
|
+
Args:
|
30
|
+
- req (dict): https://cityproto.sim.fiblab.net/#city.map.v2.GetRoadRequest
|
31
|
+
|
32
|
+
Returns:
|
33
|
+
- https://cityproto.sim.fiblab.net/#city.map.v2.GetRoadResponse
|
34
|
+
"""
|
35
|
+
if type(req) != road_service.GetRoadRequest:
|
36
|
+
req = ParseDict(req, road_service.GetRoadRequest())
|
37
|
+
res = cast(Awaitable[road_service.GetRoadResponse], self._aio_stub.GetRoad(req))
|
38
|
+
return async_parse(res, dict_return)
|
@@ -0,0 +1,145 @@
|
|
1
|
+
import logging
|
2
|
+
import os
|
3
|
+
import time
|
4
|
+
import atexit
|
5
|
+
from subprocess import DEVNULL, Popen
|
6
|
+
from typing import Optional
|
7
|
+
|
8
|
+
from pycitydata.map import Map
|
9
|
+
|
10
|
+
from ..utils import encode_to_base64, find_free_port
|
11
|
+
|
12
|
+
__all__ = ["ControlSimEnv"]
|
13
|
+
|
14
|
+
|
15
|
+
def _generate_yaml_config(map_file: str, start_step: int, total_step: int) -> str:
|
16
|
+
map_file = os.path.abspath(map_file)
|
17
|
+
return f"""
|
18
|
+
input:
|
19
|
+
# 地图
|
20
|
+
map:
|
21
|
+
file: "{map_file}"
|
22
|
+
|
23
|
+
control:
|
24
|
+
step:
|
25
|
+
# 模拟器起始步
|
26
|
+
start: {start_step}
|
27
|
+
# 模拟总步数,结束步为起始步+总步数
|
28
|
+
total: {total_step}
|
29
|
+
# 每步的时间间隔
|
30
|
+
interval: 1
|
31
|
+
skip_overtime_trip_when_init: true
|
32
|
+
enable_platoon: false
|
33
|
+
enable_indoor: false
|
34
|
+
prefer_fixed_light: true
|
35
|
+
enable_collision_avoidance: false # 计算性能下降10倍,需要保证subloop>=5
|
36
|
+
enable_go_astray: true # 引入串行的路径规划调用,计算性能下降(幅度不确定)
|
37
|
+
lane_change_model: earliest # mobil (主动变道+强制变道,默认值) earliest (总是尽可能早地变道)
|
38
|
+
|
39
|
+
output:
|
40
|
+
"""
|
41
|
+
|
42
|
+
|
43
|
+
class ControlSimEnv:
|
44
|
+
def __init__(
|
45
|
+
self,
|
46
|
+
task_name: str,
|
47
|
+
map_file: str,
|
48
|
+
# person_file,
|
49
|
+
start_step: int,
|
50
|
+
total_step: int,
|
51
|
+
log_dir: str,
|
52
|
+
min_step_time: int = 1000,
|
53
|
+
timeout: int = 5,
|
54
|
+
simuletgo_addr: Optional[str] = None,
|
55
|
+
):
|
56
|
+
self._task_name = task_name
|
57
|
+
self._map_file = map_file
|
58
|
+
# self._person_file = person_file
|
59
|
+
self._start_step = start_step
|
60
|
+
self._total_step = total_step
|
61
|
+
self._log_dir = log_dir
|
62
|
+
self._min_step_time = min_step_time
|
63
|
+
self._timeout = timeout
|
64
|
+
self.m = Map(pb_path=map_file)
|
65
|
+
"""
|
66
|
+
地图数据
|
67
|
+
"""
|
68
|
+
|
69
|
+
# 检查二进制文件是否存在
|
70
|
+
# simulet-go: ~/.local/bin/simulet-go
|
71
|
+
self._simuletgo_path = os.path.expanduser("~/.local/bin/simulet-go")
|
72
|
+
if not os.path.exists(os.path.expanduser(self._simuletgo_path)):
|
73
|
+
raise FileNotFoundError("simulet-go not found, please install it first")
|
74
|
+
|
75
|
+
self._simuletgo_config = _generate_yaml_config(map_file, start_step, total_step)
|
76
|
+
self.simuletgo_port = None
|
77
|
+
self._simuletgo_proc = None
|
78
|
+
self._traffic_client = None
|
79
|
+
|
80
|
+
os.makedirs(log_dir, exist_ok=True)
|
81
|
+
|
82
|
+
self.simuletgo_addr = self.reset(simuletgo_addr)
|
83
|
+
|
84
|
+
def reset(
|
85
|
+
self,
|
86
|
+
simuletgo_addr: Optional[str] = None,
|
87
|
+
):
|
88
|
+
"""
|
89
|
+
Args:
|
90
|
+
- simuletgo_addr: str, simulet-go的地址。如果为None,则启动一个新的simulet-go
|
91
|
+
"""
|
92
|
+
|
93
|
+
# 三个地址必须同时为None或者同时不为None
|
94
|
+
if simuletgo_addr is None:
|
95
|
+
# 1. 启动simulet-go
|
96
|
+
# ./simulet-go -config-data configbase64 -job test -syncer http://localhost:53001 -listen :51102
|
97
|
+
assert self.simuletgo_port is None
|
98
|
+
assert self._simuletgo_proc is None
|
99
|
+
self.simuletgo_port = find_free_port()
|
100
|
+
config_base64 = encode_to_base64(self._simuletgo_config)
|
101
|
+
self._simuletgo_proc = Popen(
|
102
|
+
[
|
103
|
+
self._simuletgo_path,
|
104
|
+
"-config-data",
|
105
|
+
config_base64,
|
106
|
+
"-job",
|
107
|
+
self._task_name,
|
108
|
+
"-listen",
|
109
|
+
f":{self.simuletgo_port}",
|
110
|
+
"-run.min_step_time",
|
111
|
+
f"{self._min_step_time}",
|
112
|
+
"-output",
|
113
|
+
self._log_dir,
|
114
|
+
"-cache",
|
115
|
+
"",
|
116
|
+
"-log.level",
|
117
|
+
"error",
|
118
|
+
],
|
119
|
+
# 忽略输出
|
120
|
+
# stdout=DEVNULL,
|
121
|
+
)
|
122
|
+
logging.info(
|
123
|
+
f"start simulet-go at localhost:{self.simuletgo_port}, PID={self._simuletgo_proc.pid}"
|
124
|
+
)
|
125
|
+
simuletgo_addr = f"http://localhost:{self.simuletgo_port}"
|
126
|
+
atexit.register(self.close)
|
127
|
+
time.sleep(1)
|
128
|
+
elif simuletgo_addr is not None:
|
129
|
+
pass
|
130
|
+
else:
|
131
|
+
# raise ValueError(
|
132
|
+
# "simuletgo_addr, syncer_addr, routing_addr must be all None or all not None"
|
133
|
+
# )
|
134
|
+
pass
|
135
|
+
return simuletgo_addr
|
136
|
+
|
137
|
+
def close(self):
|
138
|
+
if self._simuletgo_proc is not None:
|
139
|
+
self._simuletgo_proc.terminate()
|
140
|
+
simuletgo_code = self._simuletgo_proc.wait()
|
141
|
+
logging.info(f"simulet-go exit with code {simuletgo_code}")
|
142
|
+
|
143
|
+
self.simuletgo_port = None
|
144
|
+
self._simuletgo_proc = None
|
145
|
+
self._traffic_client = None
|
@@ -0,0 +1,58 @@
|
|
1
|
+
from typing import Any, Awaitable, Coroutine, cast, Union, Dict
|
2
|
+
|
3
|
+
import grpc
|
4
|
+
from google.protobuf.json_format import ParseDict
|
5
|
+
from pycityproto.city.social.v1 import social_service_pb2 as social_service
|
6
|
+
from pycityproto.city.social.v1 import social_service_pb2_grpc as social_grpc
|
7
|
+
|
8
|
+
from ..utils.protobuf import async_parse
|
9
|
+
|
10
|
+
__all__ = ["SocialService"]
|
11
|
+
|
12
|
+
|
13
|
+
class SocialService:
|
14
|
+
"""
|
15
|
+
城市模拟社交服务
|
16
|
+
City simulation social service
|
17
|
+
"""
|
18
|
+
|
19
|
+
def __init__(self, aio_channel: grpc.aio.Channel):
|
20
|
+
self._aio_stub = social_grpc.SocialServiceStub(aio_channel)
|
21
|
+
|
22
|
+
def Send(
|
23
|
+
self, req: Union[social_service.SendRequest, dict], dict_return: bool = True
|
24
|
+
) -> Coroutine[Any, Any, Union[Dict[str, Any], social_service.SendResponse]]:
|
25
|
+
"""
|
26
|
+
发送消息
|
27
|
+
Send message
|
28
|
+
|
29
|
+
Args:
|
30
|
+
- req (dict): https://cityproto.sim.fiblab.net/#city.social.v1.SendRequest
|
31
|
+
|
32
|
+
Returns:
|
33
|
+
- https://cityproto.sim.fiblab.net/#city.social.v1.SendResponse
|
34
|
+
"""
|
35
|
+
if type(req) != social_service.SendRequest:
|
36
|
+
req = ParseDict(req, social_service.SendRequest())
|
37
|
+
res = cast(Awaitable[social_service.SendResponse], self._aio_stub.Send(req))
|
38
|
+
return async_parse(res, dict_return)
|
39
|
+
|
40
|
+
def Receive(
|
41
|
+
self, req: Union[social_service.ReceiveRequest, dict], dict_return: bool = True
|
42
|
+
) -> Coroutine[Any, Any, Union[Dict[str, Any], social_service.ReceiveResponse]]:
|
43
|
+
"""
|
44
|
+
接收消息
|
45
|
+
Receive message
|
46
|
+
|
47
|
+
Args:
|
48
|
+
- req (dict): https://cityproto.sim.fiblab.net/#city.social.v1.ReceiveRequest
|
49
|
+
|
50
|
+
Returns:
|
51
|
+
- https://cityproto.sim.fiblab.net/#city.social.v1.ReceiveResponse
|
52
|
+
"""
|
53
|
+
if type(req) != social_service.ReceiveRequest:
|
54
|
+
req = ParseDict(req, social_service.ReceiveRequest())
|
55
|
+
res = cast(
|
56
|
+
Awaitable[social_service.ReceiveResponse], self._aio_stub.Receive(req)
|
57
|
+
)
|
58
|
+
return async_parse(res, dict_return)
|