
io.github.agentsoz.bdimatsim.EventsMonitorRegistry Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of bdi-matsim Show documentation
Show all versions of bdi-matsim Show documentation
Allows the use of MATsim (www.matsim.org) as the underlying ABM
The newest version!
package io.github.agentsoz.bdimatsim;
/*
* #%L
* BDI-ABM Integration Package
* %%
* Copyright (C) 2014 - 2015 by its authors. See AUTHORS file.
* %%
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Lesser Public License for more details.
*
* You should have received a copy of the GNU General Lesser Public
* License along with this program. If not, see
* .
* #L%
*/
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import org.matsim.api.core.v01.Id;
import org.matsim.api.core.v01.events.*;
import org.matsim.api.core.v01.events.handler.*;
import org.matsim.api.core.v01.network.Link;
import org.matsim.api.core.v01.population.Person;
import io.github.agentsoz.nonmatsim.BDIPerceptHandler;
import org.matsim.core.events.algorithms.Vehicle2DriverEventHandler;
import org.matsim.core.events.handler.BasicEventHandler;
import org.matsim.core.gbl.Gbl;
import org.matsim.vehicles.Vehicle;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import static io.github.agentsoz.bdimatsim.EventsMonitorRegistry.MonitoredEventType.*;
/**
* Acts as a simple listener for Matsim agent events then
* passes to MATSimAgentManager
*
*
* @author Edmund Kemsley
*/
public final class EventsMonitorRegistry implements LinkEnterEventHandler, LinkLeaveEventHandler,
PersonArrivalEventHandler, PersonDepartureEventHandler, ActivityEndEventHandler,
VehicleEntersTrafficEventHandler, VehicleLeavesTrafficEventHandler, BasicEventHandler
{
private Map,Double> linkEnterEventsMap = new LinkedHashMap<>() ;
/**
* if these event types were sitting in bdi-abm, I would understand this. But given that they are sitting here,
* why not use the matsim events directly? kai, nov'17
* Well, in the end this here is an events concentrator/filter: it listens to all events once, and decides which ones to
* pass on to where. We would not want all BDI agents subscribe to all events directly. kai, nov'17
*
* yy But why can't we use MATSim event names directly? kai, nov'18
*
*/
public enum MonitoredEventType {
@Deprecated // confusing nomenclature; corresponds to enter link in matsim
EnteredNode,
@Deprecated // confusing nomenclature; corresponds to exit link in matsim
ExitedNode,
AgentInCongestion,
ArrivedAtDestination,
DepartedDestination,
EndedActivity,
EnteredLink,
ExitedLink,
NextLinkBlocked
}
private static final Logger log = LoggerFactory.getLogger(EventsMonitorRegistry.class ) ;
private final Map,Monitor>> monitors = Collections.synchronizedMap(new LinkedHashMap<>());
private final Map,Monitor>> toAdd = Collections.synchronizedMap(new LinkedHashMap<>());
public EventsMonitorRegistry() {
// supposedly works like this:
// ((ch.qos.logback.classic.Logger) log).setLevel(ch.qos.logback.classic.Level.DEBUG);
// so the slf4j interface does not have these commands, but the logback implementation does.
// kai, based on pointer by dhirendra
}
@Override public void handleEvent(VehicleEntersTrafficEvent event) {
vehicle2Driver.handleEvent(event);
}
@Override public void handleEvent(VehicleLeavesTrafficEvent event) {
vehicle2Driver.handleEvent(event);
}
public Id getDriverOfVehicle(Id vehicleId) {
return vehicle2Driver.getDriverOfVehicle(vehicleId);
}
private Vehicle2DriverEventHandler vehicle2Driver = new Vehicle2DriverEventHandler() ;
@Override public final void reset(int iteration) { }
@Override public final void handleEvent(LinkEnterEvent event) { callRegisteredHandlers(event); }
@Override public void handleEvent(LinkLeaveEvent event) {
callRegisteredHandlers(event);
}
@Override public final void handleEvent(PersonDepartureEvent event) {
callRegisteredHandlers(event);
}
@Override public final void handleEvent(PersonArrivalEvent event) {
callRegisteredHandlers(event);
}
@Override public void handleEvent(ActivityEndEvent event) {
callRegisteredHandlers(event);
}
@Override public void handleEvent( Event event ) {
if (event instanceof NextLinkBlockedEvent || event instanceof AgentInCongestionEvent ) {
callRegisteredHandlers(event);
}
}
private void callRegisteredHandlers(Event ev) {
// Register any new monitors waiting to be added
// Synchronise on toAdd which is allowed to be updated by other threads
synchronized (toAdd) {
// for(Id agentId : toAdd.keySet()) {
// Monitor monitor = toAdd.get(agentId);
// if (!monitors.containsKey(monitor.getEvent())) {
// monitors.put(monitor.getEvent(), new ConcurrentHashMap<>());
// }
// monitors.get(monitor.getEvent()).put(agentId,monitor);
// }
// toAdd.clear();
for(MonitoredEventType eventType : toAdd.keySet()) {
if (!monitors.containsKey(eventType)) {
monitors.put(eventType, new ConcurrentHashMap<>());
}
Map, Monitor> map = toAdd.get(eventType);
for (Id agentId : map.keySet()) {
Monitor monitor = map.get(agentId);
monitors.get(eventType).put(agentId,monitor);
}
}
toAdd.clear();
}
if (ev instanceof AgentInCongestionEvent && monitors.containsKey(AgentInCongestion)) {
handleAgentInCongestionEvent((AgentInCongestionEvent) ev);
} else if (ev instanceof NextLinkBlockedEvent && monitors.containsKey(NextLinkBlocked)) {
handleNextLinkBlockedEvent((NextLinkBlockedEvent) ev);
} else if (ev instanceof LinkEnterEvent && monitors.containsKey(EnteredLink)) {
handleLinkEnterEvent((LinkEnterEvent) ev);
} else if (ev instanceof LinkLeaveEvent && monitors.containsKey(ExitedLink)) {
handleLinkLeaveEvent((LinkLeaveEvent) ev);
} else if (ev instanceof PersonArrivalEvent && monitors.containsKey(ArrivedAtDestination)) {
handlePersonArrivalEvent((PersonArrivalEvent) ev);
} else if (ev instanceof PersonDepartureEvent && monitors.containsKey(DepartedDestination)) {
handlePersonDepartureEvent((PersonDepartureEvent) ev);
} else if (ev instanceof ActivityEndEvent && monitors.containsKey(EndedActivity)) {
handleActivityEndEvent((ActivityEndEvent) ev);
}
}
private void handleAgentInCongestionEvent( AgentInCongestionEvent ev) {
Map, Monitor> toRemove = new HashMap<>();
Id driverId = this.getDriverOfVehicle( ev.getVehicleId());
Gbl.assertNotNull(driverId);
Monitor monitor = monitors.get(AgentInCongestion).get(driverId);
if (monitor != null) {
log.debug("handling AgentInCongestion event");
if (monitor.getAgentId().equals(driverId)) {
if (monitor.getHandler().handle(monitor.getAgentId(), ev.getCurrentLinkId(), monitor.getEvent())) {
toRemove.put(driverId, monitor);
Monitor arrivedMonitor = monitors.get(ArrivedAtDestination).get(driverId);
if (arrivedMonitor != null) {
toRemove.put(driverId,arrivedMonitor);
}
}
}
synchronized (monitors.get(AgentInCongestion)) {
monitors.get(AgentInCongestion).entrySet().removeAll(toRemove.entrySet());
}
}
}
private void handleNextLinkBlockedEvent(NextLinkBlockedEvent ev) {
Map, Monitor> toRemove = new HashMap<>();
NextLinkBlockedEvent event = ev;
Id driverId = event.getDriverId();
Monitor monitor = monitors.get(NextLinkBlocked).get(driverId);
if (monitor != null) {
log.debug("catching a nextLinkBlocked event");
if (monitor.getAgentId().equals(event.getDriverId())) {
if (monitor.getHandler().handle(monitor.getAgentId(), event.currentLinkId(), monitor.getEvent())) {
toRemove.put(driverId,monitor);
Monitor arrivedMonitor = monitors.get(ArrivedAtDestination).get(driverId);
if (arrivedMonitor != null) {
toRemove.put(driverId,arrivedMonitor);
}
}
}
synchronized (monitors.get(NextLinkBlocked)) {
monitors.get(NextLinkBlocked).entrySet().removeAll(toRemove.entrySet());
}
}
}
private void handleLinkEnterEvent(LinkEnterEvent ev) {
Map, Monitor> toRemove = new HashMap<>();
LinkEnterEvent event = ev;
Id driverId = this.getDriverOfVehicle(event.getVehicleId());
Gbl.assertNotNull(driverId);
Monitor monitor = monitors.get(EnteredLink).get(driverId);
if (monitor != null) {
if (monitor.getAgentId().equals(driverId) && event.getLinkId().equals(monitor.getLinkId())) {
if (monitor.getHandler().handle(monitor.getAgentId(), monitor.getLinkId(), monitor.getEvent())) {
toRemove.put(driverId,monitor);
}
}
}
synchronized (monitors.get(EnteredLink)) {
monitors.get(EnteredLink).entrySet().removeAll(toRemove.entrySet());
}
}
private void handleLinkLeaveEvent(LinkLeaveEvent ev) {
Map, Monitor> toRemove = new HashMap<>();
LinkLeaveEvent event = ev;
Id driverId = this.getDriverOfVehicle(event.getVehicleId());
Gbl.assertNotNull(driverId);
Monitor monitor = monitors.get(ExitedLink).get(driverId);
if (monitor != null) {
if (monitor.getAgentId().equals(event.getDriverId()) && monitor.getLinkId().equals(event.getLinkId())) {
if (monitor.getHandler().handle(monitor.getAgentId(), monitor.getLinkId(), monitor.getEvent())) {
toRemove.put(driverId,monitor);
}
}
}
synchronized (monitors.get(ExitedLink)) {
monitors.get(ExitedLink).entrySet().removeAll(toRemove.entrySet());
}
}
private void handlePersonArrivalEvent(PersonArrivalEvent ev) {
Map, Monitor> toRemove = new HashMap<>();
PersonArrivalEvent event = ev;
Id driverId = event.getPersonId();
Gbl.assertNotNull(driverId);
Monitor monitor = monitors.get(ArrivedAtDestination).get(driverId);
if (monitor != null) {
if (monitor.getAgentId().equals(event.getPersonId()) && monitor.getLinkId().equals(event.getLinkId())) {
if (monitor.getHandler().handle(monitor.getAgentId(), monitor.getLinkId(), monitor.getEvent())) {
toRemove.put(driverId,monitor);
}
Monitor blockedMonitor = monitors.get(NextLinkBlocked).get(driverId);
if (blockedMonitor != null) {
toRemove.put(driverId,blockedMonitor);
}
}
}
synchronized (monitors.get(ArrivedAtDestination)) {
monitors.get(ArrivedAtDestination).entrySet().removeAll(toRemove.entrySet());
}
}
private void handlePersonDepartureEvent(PersonDepartureEvent ev) {
Map, Monitor> toRemove = new HashMap<>();
PersonDepartureEvent event = ev;
Id driverId = event.getPersonId();
Gbl.assertNotNull(driverId);
Monitor monitor = monitors.get(DepartedDestination).get(driverId);
if (monitor != null) {
if (monitor.getAgentId().equals(event.getPersonId()) && monitor.getLinkId().equals(event.getLinkId())) {
if (monitor.getHandler().handle(monitor.getAgentId(), monitor.getLinkId(), monitor.getEvent())) {
toRemove.put(driverId,monitor);
}
}
}
synchronized (monitors.get(DepartedDestination)) {
monitors.get(DepartedDestination).entrySet().removeAll(toRemove.entrySet());
}
}
private void handleActivityEndEvent(ActivityEndEvent ev) {
Map, Monitor> toRemove = new HashMap<>();
Id driverId = ev.getPersonId();
Gbl.assertNotNull(driverId);
Monitor monitor = monitors.get(EndedActivity).get(driverId);
if (monitor != null) {
if (monitor.getAgentId().equals( ev.getPersonId()) && monitor.getLinkId().equals( ev.getLinkId())) {
if (monitor.getHandler().handle(monitor.getAgentId(), monitor.getLinkId(), monitor.getEvent())) {
toRemove.put(driverId,monitor);
}
}
}
synchronized (monitors.get(EndedActivity)) {
monitors.get(EndedActivity).entrySet().removeAll(toRemove.entrySet());
}
}
/**
* For a given agent, registers a {@link BDIPerceptHandler} to be called
* whenever an event of type {@link MonitoredEventType} is triggered
* for {@code linkId}.
* @param agentId
* @param linkId
* @param event
* @param handler
* @return
*/
public int registerMonitor(String agentId, MonitoredEventType event,String linkId, BDIPerceptHandler handler) {
synchronized (toAdd) {
if (!toAdd.containsKey(event)) {
toAdd.put(event, new ConcurrentHashMap<>());
}
Map, Monitor> map = toAdd.get(event);
map.put(Id.createPersonId(agentId), new Monitor(agentId, linkId, event, handler));
toAdd.put(event, map);
return toAdd.size();
}
}
/**
* Internal structure used to store information about MATSim events to monitor
* @author dsingh
*
*/
private class Monitor {
private Id agentId;
private Id linkId;
private MonitoredEventType event;
private BDIPerceptHandler handler;
public Monitor(String agentId2, String linkId, MonitoredEventType event, BDIPerceptHandler handler) {
super();
this.agentId = Id.createPersonId(agentId2);
// (this is now one of the places where the bdi ids (= Strings) get translated into matsim ids)
if ( linkId!=null ) {
this.linkId = Id.createLinkId(linkId);
}
this.event = event;
this.handler = handler;
}
public Id getAgentId() {
return agentId;
}
public Id getLinkId() {
return linkId;
}
public MonitoredEventType getEvent() {
return event;
}
public BDIPerceptHandler getHandler() {
return handler;
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy