Skip to content

Commit

Permalink
Merge pull request #211 from NREL/rjf/remove-eval
Browse files Browse the repository at this point in the history
fixes for handling LinkIds
  • Loading branch information
robfitzgerald committed Oct 2, 2023
2 parents ad61d89 + dd16f29 commit c353d05
Show file tree
Hide file tree
Showing 6 changed files with 61 additions and 15 deletions.
20 changes: 20 additions & 0 deletions nrel/hive/dispatcher/instruction/instructions.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
from nrel.hive.state.vehicle_state.dispatch_trip import DispatchTrip
from nrel.hive.state.vehicle_state.idle import Idle
from nrel.hive.state.vehicle_state.repositioning import Repositioning
from nrel.hive.state.vehicle_state.out_of_service import OutOfService
from nrel.hive.state.vehicle_state.reserve_base import ReserveBase
from nrel.hive.state.vehicle_state.servicing_pooling_trip import ServicingPoolingTrip
from nrel.hive.util.exception import SimulationStateError, InstructionError
Expand Down Expand Up @@ -341,3 +342,22 @@ def apply_instruction(
next_state = ReserveBase.build(self.vehicle_id, self.base_id)

return None, InstructionResult(prev_state, next_state)


@dataclass(frozen=True)
class OutOfServiceInstruction(Instruction):
vehicle_id: VehicleId

def apply_instruction(
self, sim_state: SimulationState, env: Environment
) -> Tuple[Optional[Exception], Optional[InstructionResult]]:
vehicle = sim_state.vehicles.get(self.vehicle_id)
if not vehicle:
msg = (
f"vehicle {self.vehicle_id} not found; context: applying out of service instruction"
)
return (SimulationStateError(msg), None)

prev_state = vehicle.vehicle_state
next_state = OutOfService.build(self.vehicle_id)
return None, InstructionResult(prev_state, next_state)
28 changes: 24 additions & 4 deletions nrel/hive/model/roadnetwork/link_id.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
from ast import literal_eval
from typing import Optional, Tuple, Any

from nrel.hive.util.typealiases import LinkId

NodeId = Any
Expand Down Expand Up @@ -39,14 +37,36 @@ def extract_node_ids(
)
else:
try:
src = literal_eval(result[0])
dst = literal_eval(result[1])
src = str(result[0])
dst = str(result[1])
except ValueError:
return Exception(f"LinkId {link_id} cannot be parsed."), None

return None, (src, dst)


def extract_node_ids_int(link_id: LinkId) -> Tuple[Optional[Exception], Optional[Tuple[int, int]]]:
"""node ids can be strings for the haversine case but for networkx graphs they must be
integers as they are treated as indices.
:param link_id: link id to read
:type link_id: LinkId
:return: _description_
:rtype: Tuple[Optional[Exception], Optional[Tuple[int, int]]]
"""
err, ids = extract_node_ids(link_id)
if err is not None or ids is None:
return err, None
else:
try:
src_str, dst_str = ids
src = int(src_str)
dst = int(dst_str)
return None, (src, dst)
except ValueError as e:
return e, None


def reverse_link_id(
link_id: LinkId,
) -> Tuple[Optional[Exception], Optional[LinkId]]:
Expand Down
10 changes: 7 additions & 3 deletions nrel/hive/model/roadnetwork/osm/osm_roadnetwork.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

from nrel.hive.model.entity_position import EntityPosition
from nrel.hive.model.roadnetwork.link import Link
from nrel.hive.model.roadnetwork.link_id import extract_node_ids
from nrel.hive.model.roadnetwork.link_id import extract_node_ids_int
from nrel.hive.model.roadnetwork.osm.osm_builders import osm_graph_from_polygon
from nrel.hive.model.roadnetwork.osm.osm_road_network_link_helper import OSMRoadNetworkLinkHelper
from nrel.hive.model.roadnetwork.osm.osm_roadnetwork_ops import (
Expand Down Expand Up @@ -50,6 +50,7 @@ def __init__(
# validate network

# road network must be strongly connected
log.info(f"testing graph connectivity")
if not nx.is_strongly_connected(graph):
raise RuntimeError("Only strongly connected graphs are allowed.")

Expand All @@ -66,6 +67,7 @@ def _valid_node_id(nid: Union[int, tuple]) -> bool:
raise TypeError("all node ids must be either an integer or a tuple of integers")

# check to make sure the graph has the right information on the links
log.info(f"testing graph speed data")
missing_speed = 0
missing_time = 0
for u, v, d in graph.edges(data=True):
Expand Down Expand Up @@ -98,6 +100,7 @@ def _valid_node_id(nid: Union[int, tuple]) -> bool:
)

# build tables on the network edges for spatial lookup and LinkId lookup
log.info(f"building spatial index for graph")
link_helper_error, link_helper = OSMRoadNetworkLinkHelper.build(
graph, sim_h3_resolution, default_speed_kmph
)
Expand Down Expand Up @@ -155,6 +158,7 @@ def from_file(
if road_network_path.suffix == ".json":
with road_network_path.open("r") as f:
graph = nx.node_link_graph(json.load(f))
log.info(f"loaded graph with {len(graph.edges)} edges")
return OSMRoadNetwork(graph, sim_h3_resolution, default_speed_kmph)
else:
raise TypeError(
Expand Down Expand Up @@ -188,8 +192,8 @@ def _astar_cost_heuristic(source, dest) -> float:

# start path search from the end of the origin link, terminate search at the start of the
# destination link
extract_src_err, src_nodes = extract_node_ids(origin.link_id)
extract_dst_err, dst_nodes = extract_node_ids(destination.link_id)
extract_src_err, src_nodes = extract_node_ids_int(origin.link_id)
extract_dst_err, dst_nodes = extract_node_ids_int(destination.link_id)
if extract_src_err:
log.error(extract_src_err)
return empty_route()
Expand Down
12 changes: 6 additions & 6 deletions nrel/hive/model/station/station.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ def geoid(self) -> GeoId:
@classmethod
def build(
cls,
id: StationId,
station_id: StationId,
geoid: GeoId,
road_network: RoadNetwork,
chargers: immutables.Map[ChargerId, int],
Expand Down Expand Up @@ -100,7 +100,7 @@ def _chargers(acc, charger_data):
charger = env.chargers.get(charger_id)
if charger is None:
msg = (
f"attempting to create station {id} with charger type {charger_id} "
f"attempting to create station {station_id} with charger type {charger_id} "
f"but that charger type has not been defined for this scenario"
)
return TypeError(msg), None
Expand All @@ -114,20 +114,20 @@ def _chargers(acc, charger_data):
if error is not None:
raise error
if charger_states is None:
msg = f"internal error after building station chargers for station {id}"
msg = f"internal error after building station chargers for station {station_id}"
raise Exception(msg)

energy_dispensed = immutables.Map({energy_type: 0.0 for energy_type in EnergyType})
position = road_network.position_from_geoid(geoid)
if position is None:
msg = (
"could not find a road network position matching the position "
f"provided for station {id}"
f"provided for station {station_id}"
)
raise H3Error(msg)

return Station(
id=id,
id=station_id,
position=position,
state=charger_states,
energy_dispensed=energy_dispensed,
Expand Down Expand Up @@ -222,7 +222,7 @@ def from_row(
elif station_id not in builder:
# create this station
return Station.build(
id=station_id,
station_id=station_id,
geoid=geoid,
road_network=road_network,
chargers=immutables.Map({charger_id: charger_count}),
Expand Down
4 changes: 3 additions & 1 deletion nrel/hive/model/vehicle/mechatronics/bev.py
Original file line number Diff line number Diff line change
Expand Up @@ -151,8 +151,10 @@ def is_full(self, vehicle: Vehicle) -> bool:
:param vehicle:
:return:
"""
battery = vehicle.energy[EnergyType.ELECTRIC]
full_kwh = self.battery_capacity_kwh - self.battery_full_threshold_kwh
return vehicle.energy[EnergyType.ELECTRIC] >= full_kwh
is_full = battery >= full_kwh
return is_full

def consume_energy(self, vehicle: Vehicle, route: Route) -> Vehicle:
"""
Expand Down
2 changes: 1 addition & 1 deletion nrel/hive/resources/mock_lobster.py
Original file line number Diff line number Diff line change
Expand Up @@ -341,7 +341,7 @@ def mock_station_from_geoid(
env = mock_env()

return Station.build(
id=station_id,
station_id=station_id,
geoid=geoid,
road_network=road_network,
chargers=chargers,
Expand Down

0 comments on commit c353d05

Please sign in to comment.