Skip to content

Commit

Permalink
Add generate_taxi_drivers to TripGenerator
Browse files Browse the repository at this point in the history
Rename `default_vehicle_template_generator` to `default_person_template_generator`
  • Loading branch information
chenchenplus committed Nov 22, 2024
1 parent 2996b76 commit b60d66c
Show file tree
Hide file tree
Showing 10 changed files with 110 additions and 27 deletions.
7 changes: 3 additions & 4 deletions examples/gen_pt_drivers.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,10 @@
with open("data/temp/srt.map_with_pt.pb", "rb") as f:
m = Map()
m.ParseFromString(f.read())
tg = TripGenerator(
m=m,
template_func=default_bus_template_generator,
tg = TripGenerator(m=m)
bus_drivers = tg.generate_public_transport_drivers(
template_func=default_bus_template_generator
)
bus_drivers = tg.generate_public_transport_drivers()
persons_output_path = "data/temp/bus_drivers.pb"
pb = Persons(persons=bus_drivers)
with open(persons_output_path, "wb") as f:
Expand Down
4 changes: 2 additions & 2 deletions examples/random_persons.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from mosstool.trip.generator import (PositionMode, RandomGenerator,
default_vehicle_template_generator)
default_person_template_generator)
from mosstool.trip.route import RoutingClient, pre_route
from mosstool.type import Map, Person, Persons, TripMode
from mosstool.util.format_converter import pb2json
Expand All @@ -13,7 +13,7 @@ async def main():
m,
[PositionMode.LANE, PositionMode.LANE],
TripMode.TRIP_MODE_DRIVE_ONLY,
template_func=default_vehicle_template_generator,
template_func=default_person_template_generator,
)
persons = rg.uniform(
num=100,
Expand Down
4 changes: 2 additions & 2 deletions mosstool/trip/generator/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,14 @@
ProbabilisticTemplateGenerator,
UniformTemplateGenerator,
default_bus_template_generator,
default_vehicle_template_generator)
default_person_template_generator)

__all__ = [
"ProbabilisticTemplateGenerator",
"GaussianTemplateGenerator",
"UniformTemplateGenerator",
"CalibratedTemplateGenerator",
"default_vehicle_template_generator",
"default_person_template_generator",
"default_bus_template_generator",
"RandomGenerator",
"PositionMode",
Expand Down
5 changes: 3 additions & 2 deletions mosstool/trip/generator/_util/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,13 +40,14 @@
]
TRIP_MODES_DICT = {
BUS: "bus",
BUS_SUBWAY:"bus_subway",
SUBWAY:"subway",
BUS_SUBWAY: "bus_subway",
SUBWAY: "subway",
CAR: "drive",
TAXI: "taxi",
WALK: "walk",
}
PT_START_ID = 1_0000_0000
TAXI_START_ID = 2_0000_0000
PRIMARY_SCHOOL, JUNIOR_HIGH_SCHOOL, HIGH_SCHOOL, COLLEGE, BACHELOR, MASTER, DOCTOR = (
personv2.EDUCATION_PRIMARY_SCHOOL,
personv2.EDUCATION_JUNIOR_HIGH_SCHOOL,
Expand Down
29 changes: 28 additions & 1 deletion mosstool/trip/generator/_util/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import numpy as np
from pycityproto.city.person.v2.person_pb2 import (BusAttribute, BusType,
Person, PersonAttribute,
PersonType,
VehicleAttribute)
from pycityproto.city.routing.v2.routing_pb2 import (DrivingJourneyBody,
Journey, JourneyType)
Expand Down Expand Up @@ -356,7 +357,7 @@ def _aoi_road_ids(station_connection_road_ids) -> List[int]:
p_trip_stops.append(trip_stop)
# eta for bus journey
bus_eta = sum(subline.schedules.offset_times)
sl_drivers = []
sl_drivers: List[Person] = []
if bus_type == BusType.BUS_TYPE_BUS:
for tm in depart_times:
p = Person()
Expand Down Expand Up @@ -396,3 +397,29 @@ def _aoi_road_ids(station_connection_road_ids) -> List[int]:
person_id += 1

return (person_id, sl_drivers)


def gen_taxi_drivers(
person_id: int,
person_template_generator: Callable[[], Person],
home_position: Union[LanePosition, AoiPosition],
num: int = 1,
) -> Tuple[int, List[Person]]:
taxi_drivers: List[Person] = []
for _ in range(num):
p = Person()
p.CopyFrom(person_template_generator())
p.id = person_id
p.type = PersonType.PERSON_TYPE_TAXI
if isinstance(home_position, LanePosition):
p.home.CopyFrom(Position(lane_position=home_position))
elif isinstance(home_position, AoiPosition):
p.home.CopyFrom(Position(aoi_position=home_position))
else:
logging.warning(
f"Invalid type of `parking_position` {type(home_position).__name__}!"
)
continue
taxi_drivers.append(p)
person_id += 1
return (person_id, taxi_drivers)
63 changes: 58 additions & 5 deletions mosstool/trip/generator/generate_from_od.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,9 @@
from ...util.format_converter import dict2pb, pb2dict
from ._util.const import *
from ._util.utils import (extract_HWEO_from_od_matrix, gen_bus_drivers,
gen_departure_times, gen_profiles,
gen_departure_times, gen_profiles, gen_taxi_drivers,
recalculate_trip_mode_prob, recalculate_trip_modes)
from .template import default_vehicle_template_generator
from .template import default_person_template_generator


# from ...util.geo_match_pop import geo2pop
Expand Down Expand Up @@ -417,7 +417,7 @@ def __init__(
bus_expense: float = 5.0,
bike_speed: float = 10 / 3.6,
bike_penalty: float = 0.0,
template_func: Callable[[], Person] = default_vehicle_template_generator,
template_func: Callable[[], Person] = default_person_template_generator,
add_pop: bool = False,
multiprocessing_chunk_size: int = 500,
workers: int = cpu_count(),
Expand Down Expand Up @@ -493,6 +493,7 @@ def _read_aois(self):
]
for p in i.positions
)
a["has_driving_gates"] = len(i.driving_gates) > 0
aois.append(a)

def get_aoi_catg(urban_land_use: str):
Expand Down Expand Up @@ -775,7 +776,7 @@ def generate_persons(
self._generate_mobi(agent_num, area_pops, person_profiles, seed)
return self.persons

def _get_driving_pos_dict(self) -> Dict[Tuple[int, int], geov2.LanePosition]:
def _get_driving_pos_dict(self) -> Dict[Tuple[int, int], LanePosition]:
road_aoi_id2d_pos = {}
road_id2d_lane_ids = {}
lane_id2parent_road_id = {}
Expand Down Expand Up @@ -808,11 +809,13 @@ def _get_driving_pos_dict(self) -> Dict[Tuple[int, int], geov2.LanePosition]:

def generate_public_transport_drivers(
self,
template_func: Optional[Callable[[], Person]] = None,
stop_duration_time: float = 30.0,
seed: int = 0,
) -> List[Person]:
"""
Args:
- template_func (Optional[Callable[[],Person]]): The template function of generated person object, whose `schedules`, `home` will be replaced and others will be copied. If not provided, the `temp_func` provided in `__init__` will be utilized.
- stop_duration_time (float): The duration time (in second) for bus at each stop.
- seed (int): The random seed.
Expand All @@ -822,13 +825,14 @@ def generate_public_transport_drivers(
self.persons = []
road_aoi_id2d_pos = self._get_driving_pos_dict()
person_id = PT_START_ID
_template = template_func if template_func is not None else self.template
for sl in self.m.sublines:
departure_times = list(sl.schedules.departure_times)
if not sl.type in {mapv2.SUBLINE_TYPE_BUS, mapv2.SUBLINE_TYPE_SUBWAY}:
continue
person_id, generated_drivers = gen_bus_drivers(
person_id,
self.template,
_template,
departure_times,
stop_duration_time,
road_aoi_id2d_pos,
Expand Down Expand Up @@ -1003,3 +1007,52 @@ def fill_person_schedules(
self._generate_schedules(input_persons, seed)

return self.persons

def generate_taxi_drivers(
self,
template_func: Optional[Callable[[], Person]] = None,
parking_positions: Optional[List[Union[LanePosition, AoiPosition]]] = None,
agent_num: Optional[int] = None,
seed: int = 0,
) -> List[Person]:
"""
Args:
- template_func (Optional[Callable[[],Person]]): The template function of generated person object, whose `schedules`, `home` will be replaced and others will be copied. If not provided, the `temp_func` provided in `__init__` will be utilized.
- parking_positions (Optional[List[Union[LanePosition,AoiPosition]]]): The parking positions of each taxi.
- agent_num (Optional[int]): The taxi driver num.
- seed (int): The random seed.
Returns:
- List[Person]: The generated driver objects.
"""
self.persons = []
person_id = TAXI_START_ID
_template = template_func if template_func is not None else self.template
self._read_aois()
if parking_positions is not None:
logging.info(f"")
_taxi_home_positions = parking_positions
elif agent_num is not None:
logging.info(f"")
if not agent_num >= 1:
logging.warning("agent_num should >=1")
return []
rng = np.random.default_rng(seed)
has_driving_aoi_ids = [a["id"] for a in self.aois if a["has_driving_gates"]]
_taxi_home_positions = [
AoiPosition(aoi_id=_id)
for _id in rng.choice(has_driving_aoi_ids, int(agent_num))
]
else:
logging.warning(
"Either `agent_num` or `parking_positions` should be provided!"
)
return []
for _pos in _taxi_home_positions:
person_id, generated_drivers = gen_taxi_drivers(
person_id,
_template,
_pos,
)
self.persons.extend(generated_drivers)
return self.persons
4 changes: 2 additions & 2 deletions mosstool/trip/generator/random.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

from ...map._map_util.const import JUNC_START_ID
from ._util.utils import is_walking
from .template import default_vehicle_template_generator
from .template import default_person_template_generator

__all__ = ["PositionMode", "RandomGenerator"]

Expand All @@ -29,7 +29,7 @@ def __init__(
m: Map,
position_modes: List[PositionMode],
trip_mode: TripMode,
template_func: Callable[[], Person] = default_vehicle_template_generator,
template_func: Callable[[], Person] = default_person_template_generator,
):
"""
Args:
Expand Down
16 changes: 9 additions & 7 deletions mosstool/trip/generator/template.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
from pycityproto.city.person.v2.person_pb2 import (BikeAttribute,
EmissionAttribute,
PedestrianAttribute, Person,
PersonAttribute,
PersonAttribute, PersonType,
VehicleAttribute,
VehicleEngineEfficiency,
VehicleEngineType)
Expand All @@ -15,15 +15,16 @@
CALIBRATED_MAX_ACC_VALUES)

__all__ = [
"default_vehicle_template_generator",
"default_person_template_generator",
"default_bus_template_generator",
"ProbabilisticTemplateGenerator",
]


def default_vehicle_template_generator() -> Person:
def default_person_template_generator() -> Person:
return Person(
attribute=PersonAttribute(),
type=PersonType.PERSON_TYPE_NORMAL,
vehicle_attribute=VehicleAttribute(
length=5,
width=2,
Expand Down Expand Up @@ -57,6 +58,7 @@ def default_vehicle_template_generator() -> Person:
def default_bus_template_generator() -> Person:
return Person(
attribute=PersonAttribute(),
type=PersonType.PERSON_TYPE_NORMAL,
vehicle_attribute=VehicleAttribute(
length=15,
width=2,
Expand Down Expand Up @@ -124,7 +126,7 @@ def __init__(
"""
self.template_p = template
if self.template_p is None:
self.template_p = default_vehicle_template_generator()
self.template_p = default_person_template_generator()
self.template_p.ClearField("schedules")
# max speed
self.max_speed_values = max_speed_values
Expand Down Expand Up @@ -317,7 +319,7 @@ def __init__(
"""
self.template_p = template
if self.template_p is None:
self.template_p = default_vehicle_template_generator()
self.template_p = default_person_template_generator()
self.template_p.ClearField("schedules")
# max speed
self.max_speed_mean = max_speed_mean
Expand Down Expand Up @@ -429,7 +431,7 @@ def __init__(
"""
self.template_p = template
if self.template_p is None:
self.template_p = default_vehicle_template_generator()
self.template_p = default_person_template_generator()
self.template_p.ClearField("schedules")
# max speed
self.max_speed_min = max_speed_min
Expand Down Expand Up @@ -515,7 +517,7 @@ def __init__(self, seed: int = 0, template: Optional[Person] = None) -> None:
"""
self.template_p = template
if self.template_p is None:
self.template_p = default_vehicle_template_generator()
self.template_p = default_person_template_generator()
self.template_p.ClearField("schedules")
# radom engine
self.rng = np.random.default_rng(seed)
Expand Down
3 changes: 2 additions & 1 deletion mosstool/type/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
from pycityproto.city.map.v2.map_pb2 import (Aoi, AoiType, Lane, LaneTurn,
LaneType, Map)
from pycityproto.city.person.v2.person_pb2 import (Consumption, Education,
Gender, Person,
Gender, Person,PersonType,
PersonProfile, Persons)
from pycityproto.city.routing.v2.routing_pb2 import (DrivingJourneyBody,
Journey, JourneyType)
Expand All @@ -23,6 +23,7 @@
"LaneType",
"LaneTurn",
"Person",
"PersonType",
"Persons",
"TripMode",
"Position",
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[tool.poetry]
name = "mosstool"
version = "1.0.23"
version = "1.0.24"
description = "MObility Simulation System toolbox "
authors = ["Jun Zhang <zhangjun990222@qq.com>","Junbo Yan <yanjb20thu@gmali.com>"]
license = "MIT"
Expand Down

0 comments on commit b60d66c

Please sign in to comment.