Skip to content

Commit

Permalink
Merge pull request #44 from symuvia/dev
Browse files Browse the repository at this point in the history
Fix signatures, constants, others
  • Loading branch information
aladinoster authored Nov 9, 2020
2 parents 9cf53e3 + 8385f70 commit f0388f3
Show file tree
Hide file tree
Showing 16 changed files with 452 additions and 234 deletions.
2 changes: 1 addition & 1 deletion MANIFEST.IN
Original file line number Diff line number Diff line change
@@ -1 +1 @@
include *.md LICENSE
include *.md LICENSE settings.ini
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ test: ## run tests quickly with the default Python
docs: ## generate Sphinx HTML documentation, including API docs
rm -f docs/source/symupy.rst
rm -f docs/source/modules.rst
rm -f docs/source/symupy.*.rst
# rm -f docs/source/symupy.*.rst
sphinx-apidoc -o docs/source symupy
$(MAKE) -C docs clean
$(MAKE) -C docs html
Expand Down
6 changes: 3 additions & 3 deletions docs/source/tutorials/1_run_simulation.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,9 @@ simulator.run()
You can also use your own simulator. In this case you may also enable other flags

```{python}
simulator = Simulator(libraryPath = path_simulator,
traceFlow = True, # Export trajectory
writeXML = True, # Write output XML
simulator = Simulator(library_path = path_simulator,
trace_flow = True, # Export trajectory
write_xml = True, # Write output XML
)
simulator.register_simulation(path_simulation)
simulator.run()
Expand Down
4 changes: 4 additions & 0 deletions settings.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
[settings]
DEFAULT_LIB_OSX=/Users/andresladino/Documents/01-Code/04-Platforms/dev-symuvia/build/lib/libSymuVia.dylib
DEFAULT_LIB_LINUX=/home/build-symuvia/build/symuvia/libSymuVia.so
DEFAULT_LIB_WINDOWS=/home/build-symuvia/build/symuvia/libSymuVia.dll
1 change: 1 addition & 0 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
"pandas>=0.24",
"scipy>=1.4.1",
"click>=7.0",
"python-decouple>=3.3",
],
author="Andres Ladino",
author_email="[email protected]",
Expand Down
137 changes: 102 additions & 35 deletions symupy/api/connector.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
>>> from symupy.api import Simulator
>>> path_symuvia = "path/to/libSymuyVia.dylib"
>>> simulator = Simulator(libraryPath=path_symuvia)
>>> simulator = Simulator(library_path=path_symuvia)
Other parameters can also be send to the simulator in order to provide other configurations:
Expand All @@ -17,7 +17,7 @@
To increase change the flag that traces the flow:
>>> simulator = Simulator(traceFlow = True)
>>> simulator = Simulator(trace_flow = True)
"""

# ============================================================================
Expand Down Expand Up @@ -85,7 +85,7 @@ class Simulator(Configurator, RuntimeDevice):
>>> from symupy.api import Simulator
>>> path_symuvia = "path/to/libSymuyVia.dylib"
>>> simulator = Simulator(libraryPath=path_symuvia)
>>> simulator = Simulator(library_path=path_symuvia)
This object describes is a configurator manager for the interface between the traffic simulator and the python interface. For more details on the optinal keyword parameters please refer to :py:class:`~symupy.utils.configurator.Configurator` class.
Expand All @@ -110,11 +110,12 @@ class Simulator(Configurator, RuntimeDevice):
"""

def __init__(self, **kwargs) -> None:
super(Simulator, self).__init__(**kwargs)
Configurator.__init__(self, **kwargs)
RuntimeDevice.__init__(self)
self._net = []

def __repr__(self):
return f"{self.__class__.__name__}({self.libraryPath})"
return f"{self.__class__.__name__}({self.library_path})"

# ============================================================================
# LOADING METHODS
Expand All @@ -123,9 +124,9 @@ def __repr__(self):
def load_symuvia(self) -> None:
""" load SymuVia shared library """
try:
lib_symuvia = cdll.LoadLibrary(self.libraryPath)
lib_symuvia = cdll.LoadLibrary(self.library_path)
except OSError:
raise SymupyLoadLibraryError("Library not found", self.libraryPath)
raise SymupyLoadLibraryError("Library not found", self.library_path)
self.__library = lib_symuvia

def load_network(self) -> int:
Expand Down Expand Up @@ -183,11 +184,15 @@ def run(self, sim_object: Simulation = "") -> None:
def request_answer(self):
"""Request simulator answer and maps the data locally
"""
if self.stepLaunchMode == "lite":
self._bContinue = self.__library.SymRunNextStepLiteEx(self.writeXML, byref(self._b_end))
if self.step_launch_mode == "lite":
self._bContinue = self.__library.SymRunNextStepLiteEx(
self.write_xml, byref(self._b_end)
)
return
self._bContinue = self.__library.SymRunNextStepEx(self.bufferString, self.writeXML, byref(self._b_end))
self.request.parse_data(self.bufferString)
self._bContinue = self.__library.SymRunNextStepEx(
self.buffer_string, self.write_xml, byref(self._b_end)
)
self.request.parse_data(self.buffer_string)

# @printer_time
def run_step(self) -> int:
Expand All @@ -209,7 +214,14 @@ def stop_step(self):
"""
self._bContinue = False

def create_vehicle(self, vehtype: str, origin: str, destination: str, lane: int = 1, simid: int = 0) -> int:
def create_vehicle(
self,
vehtype: str,
origin: str,
destination: str,
lane: int = 1,
simid: int = 0,
) -> int:
"""Creates a vehicle within the network
:param vehtype: vehicle type according to simulation definitions
Expand All @@ -233,19 +245,33 @@ def create_vehicle(self, vehtype: str, origin: str, destination: str, lane: int

# Consistency checks
if vehtype not in vehid:
raise SymupyVehicleCreationError("Unexisting Vehicle Class in File: ", self.scenarioFilename())
raise SymupyVehicleCreationError(
"Unexisting Vehicle Class in File: ", self.scenarioFilename()
)

if (origin not in endpoints) or (destination not in endpoints):
raise SymupyVehicleCreationError("Unexisting Network Endpoint File: ", self.scenarioFilename())
raise SymupyVehicleCreationError(
"Unexisting Network Endpoint File: ", self.scenarioFilename()
)

# Vehicle creation
vehid = self.__library.SymCreateVehicleEx(
vehtype.encode("UTF8"), origin.encode("UTF8"), destination.encode("UTF8"), c_int(lane), c_double(dbTime)
vehtype.encode("UTF8"),
origin.encode("UTF8"),
destination.encode("UTF8"),
c_int(lane),
c_double(dbTime),
)
return vehid

def create_vehicle_with_route(
self, vehtype: str, origin: str, destination: str, lane: int = 1, creation_time: float = 0, route: str = ""
self,
vehtype: str,
origin: str,
destination: str,
lane: int = 1,
creation_time: float = 0,
route: str = "",
) -> int:
""" Creates a vehicle with a specific route
Expand Down Expand Up @@ -275,10 +301,14 @@ def create_vehicle_with_route(

# Consistency checks
if vehtype not in vehid:
raise SymupyVehicleCreationError("Unexisting Vehicle Class in File: ", self.scenarioFilename())
raise SymupyVehicleCreationError(
"Unexisting Vehicle Class in File: ", self.scenarioFilename()
)

if (origin not in endpoints) or (destination not in endpoints):
raise SymupyVehicleCreationError("Unexisting Network Endpoint File: ", self.scenarioFilename())
raise SymupyVehicleCreationError(
"Unexisting Network Endpoint File: ", self.scenarioFilename()
)

# Vehicle creation
vehid = self.__library.SymCreateVehicleWithRouteEx(
Expand All @@ -291,7 +321,9 @@ def create_vehicle_with_route(
)
return vehid

def drive_vehicle(self, vehid: int, new_pos: float, destination: str = None, lane: str = 1) -> None:
def drive_vehicle(
self, vehid: int, new_pos: float, destination: str = None, lane: str = 1
) -> None:
"""Drives a vehicle to a specific position
:param vehid: vehicle id to drive
Expand All @@ -312,16 +344,24 @@ def drive_vehicle(self, vehid: int, new_pos: float, destination: str = None, lan
destination = self.request.query_vehicle_link(str(vehid))[0]

if destination not in links:
raise SymupyDriveVehicleError("Unexisting Network Endpoint File: ", self.scenarioFilename())
raise SymupyDriveVehicleError(
"Unexisting Network Endpoint File: ", self.scenarioFilename()
)

# TODO: Validate that position do not overpass the max pos
dr_state = self.__library.SymDriveVehicleEx(
c_int(vehid), destination.encode("UTF8"), c_int(lane), c_double(new_pos), 1
c_int(vehid),
destination.encode("UTF8"),
c_int(lane),
c_double(new_pos),
1,
)
self.request_answer()
return dr_state

def drive_vehicle_with_control(self, vehcontrol, vehid: int, destination: str = None, lane: str = 1):
def drive_vehicle_with_control(
self, vehcontrol, vehid: int, destination: str = None, lane: str = 1
):
# TODO: Basic prototyping
vehcontrol.set_current_state(self.request)
new_pos = vehcontrol.new_position
Expand Down Expand Up @@ -361,12 +401,17 @@ def get_total_travel_time(self, sensors_mfd: list = []):
"""
# TODO: Improvement → Better organizadtion
if isinstance(sensors_mfd, str):
return self.__library.SymGetTotalTravelTimeEx(sensors_mfd.encode("UTF8"))
return self.__library.SymGetTotalTravelTimeEx(
sensors_mfd.encode("UTF8")
)

if not sensors_mfd:
sensors_mfd = self.simulation.get_mfd_sensor_names()

return tuple(self.__library.SymGetTotalTravelTimeEx(sensor.encode("UTF8")) for sensor in sensors_mfd)
return tuple(
self.__library.SymGetTotalTravelTimeEx(sensor.encode("UTF8"))
for sensor in sensors_mfd
)

def get_total_travel_distance(self, sensors_mfd: list = []):
""" Computes the total travel distance of vehicles in a MFD region
Expand All @@ -377,12 +422,17 @@ def get_total_travel_distance(self, sensors_mfd: list = []):
"""
# TODO: Improvement → Better organizadtion
if isinstance(sensors_mfd, str):
return self.__library.SymGetTotalTravelDistanceEx(sensors_mfd.encode("UTF8"))
return self.__library.SymGetTotalTravelDistanceEx(
sensors_mfd.encode("UTF8")
)

if not sensors_mfd:
sensors_mfd = self.simulation.get_mfd_sensor_names()

return tuple(self.__library.SymGetTotalTravelDistanceEx(sensor.encode("UTF8")) for sensor in sensors_mfd)
return tuple(
self.__library.SymGetTotalTravelDistanceEx(sensor.encode("UTF8"))
for sensor in sensors_mfd
)

def get_mfd_speed(self, sensors_mfd: list = []):
""" Computes the total speed of vehicles in a MFD region
Expand All @@ -398,7 +448,10 @@ def get_mfd_speed(self, sensors_mfd: list = []):
spd = d / t if t != 0 else 10
return spd

itdsttm = zip(self.get_total_travel_distance(sensors_mfd), self.get_total_travel_time(sensors_mfd))
itdsttm = zip(
self.get_total_travel_distance(sensors_mfd),
self.get_total_travel_time(sensors_mfd),
)
spd = []
for d, t in itdsttm:
if t != 0:
Expand All @@ -407,7 +460,9 @@ def get_mfd_speed(self, sensors_mfd: list = []):
spd.append(10) # minimum speed?
return tuple(spd)

def add_control_probability_zone_mfd(self, access_probability: dict, minimum_distance: dict) -> None:
def add_control_probability_zone_mfd(
self, access_probability: dict, minimum_distance: dict
) -> None:
"""
Add a probability to control the access to a specific zone within the network
Expand All @@ -418,19 +473,26 @@ def add_control_probability_zone_mfd(self, access_probability: dict, minimum_dis
"""
self.dctidzone = {}

for tp_zn_pb, tp_zn_md in zip(access_probability.items(), minimum_distance.items()):
for tp_zn_pb, tp_zn_md in zip(
access_probability.items(), minimum_distance.items()
):
sensor, accrate = tp_zn_pb
_, min_dst = tp_zn_md
links = self.simulation.get_links_in_mfd_sensor(sensor)
links_str = " ".join(links)
self.dctidzone[sensor] = self.__library.SymAddControlZoneEx(
-1, c_double(accrate), c_double(min_dst), f"{links_str}".encode("UTF8")
-1,
c_double(accrate),
c_double(min_dst),
f"{links_str}".encode("UTF8"),
)
# Apply set control
self.__library.SymApplyControlZonesEx(-1)
return self.dctidzone

def modify_control_probability_zone_mfd(self, access_probability: dict) -> None:
def modify_control_probability_zone_mfd(
self, access_probability: dict
) -> None:
"""
Modifies a probability to control the access to a specific zone within the network
Expand All @@ -439,7 +501,9 @@ def modify_control_probability_zone_mfd(self, access_probability: dict) -> None:
"""

for sensor, probablity in access_probability.items():
self.__library.SymModifyControlZoneEx(-1, self.dctidzone[sensor], c_double(probablity))
self.__library.SymModifyControlZoneEx(
-1, self.dctidzone[sensor], c_double(probablity)
)
# Apply set control
self.__library.SymApplyControlZonesEx(-1)
return self.dctidzone
Expand Down Expand Up @@ -475,7 +539,10 @@ def __exit__(self, type, value, traceback) -> bool:
def build_dynamic_param(self):
"""Construct parameters for vehicle dynamics
"""
self.__dct_par = {"time_step": self.simulation.time_step, "engine_tau": CT.ENGINE_CONSTANT}
self.__dct_par = {
"time_step": self.simulation.time_step,
"engine_tau": CT.ENGINE_CONSTANT,
}

# ============================================================================
# STATE MACHINE
Expand Down Expand Up @@ -559,7 +626,7 @@ def s_response_dec(self):
:return: last query from simulator
:rtype: str
"""
return self.bufferString.value.decode("UTF8")
return self.buffer_string.value.decode("UTF8")

@property
def do_next(self) -> bool:
Expand Down Expand Up @@ -635,6 +702,6 @@ def from_path(cls, filename_path, symuvia_path):
>>> simulator = Simulator.from_path(path,scenario)
"""
sim = cls(libraryPath=symuvia_path)
sim = cls(library_path=symuvia_path)
sim.register_simulation(filename_path)
return sim
1 change: 1 addition & 0 deletions symupy/utils/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
"""Expose specific functions for accessbility"""
from symupy.utils.tools import timer_func, logger_func, printer_time
from symupy.utils.parser import SimulatorRequest
from symupy.utils.configurator import Configurator
Loading

0 comments on commit f0388f3

Please sign in to comment.