1. Package Description
As illustrated in the figure below, to implement the virtual traffic environment, it is necessary to provide concrete implementations of the abstract classes “CellController” and “Environemnt”. Those classes are collaboratively responsible for realizing the physical roles of the traffic environment. stimulus It is important to note here that it is possible to define new types of environment objects and events to be used in the traffic environment by extending the classes “EnvObjectState” and “EnvEvent” respectively. However, in this tutorial, we chose to use from the definitions that are already provided by the DIVAs framework.
2. Implementing the “TrafficCellController” class
As mentioned earlier, “Cells” are managed by “CellController”s which collaboratively realize the roles of the environment. A traffic cell controller combines all movement and change heading stimuli generated by vehicle agents within its boundaries, resolves conflicting intents (e.g., two vehicle agents want to be in the same position (x; y; z) at the same cycle) and returns to each agent an updated state that is legal with respect to the laws of the traffic environment.
Implementation Steps
- Inside the package “edu.utdallas.mavs.traffic.simulation.sim.env” create a class named “TrafficCellController” that extends the abstract class “SelfOrganizingCellController” defined in the package “edu.utdallas.mavs.divas.core.sim.env”.
- The class “TrafficCellController” provides an implementation of the abstract methods:
- “hasConflicts()”: this method is responsible for detecting any conflict between vehicle agents’ stimuli;
- “combineAgentStimuli()”: this method is responsible for combining vehicle agents stimuli and resolving any conflicts. In addition, it is responsible for computing the final state of the agent after applying the resolved stimuli;
- “createAgent”: this metod is responsible for creating a vehicle agent in a traffic cell.
- “processDestructiveEvent”: this method is responsible for processing destructive events. For instance, a bomb event can cause damage to a vehicle agent in close proximity and the vehicle cannot move anymore.
- “applyUserCommand”: this method is responsible for applying user commands on an agent as a result of a user interaction with the simulation through the visualizer.
- “createChild”: this method is responsible for creating a child cell controller. This is used for self-organizing the simulation to enhance perofrmance. Detailed description about this project can be found at the link.
The following code provides a full implementation for the class “TrafficCellController”:
package edu.utdallas.mavs.traffic.simulation.sim.env; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import edu.utdallas.mavs.divas.core.msg.RuntimeAgentCommandMsg; import edu.utdallas.mavs.divas.core.sim.agent.Agent; import edu.utdallas.mavs.divas.core.sim.common.event.EnvEvent; import edu.utdallas.mavs.divas.core.sim.common.state.AgentControlType; import edu.utdallas.mavs.divas.core.sim.common.state.AgentState; import edu.utdallas.mavs.divas.core.sim.common.state.CellState; import edu.utdallas.mavs.divas.core.sim.common.state.EnvObjectState; import edu.utdallas.mavs.divas.core.sim.common.state.VirtualState; import edu.utdallas.mavs.divas.core.sim.common.stimulus.AgentStimulus; import edu.utdallas.mavs.divas.core.sim.env.AgentStateModel; import edu.utdallas.mavs.divas.core.sim.env.SelfOrganizingCellController; import edu.utdallas.mavs.divas.mts.CommunicationModule; import edu.utdallas.mavs.traffic.simulation.sim.agent.VehicleAgent; import edu.utdallas.mavs.traffic.simulation.sim.common.state.VehicleAgentState; import edu.utdallas.mavs.traffic.simulation.sim.common.stimulus.ChangeHeadingStimulus; import edu.utdallas.mavs.traffic.simulation.sim.common.stimulus.MoveStimulus; public class TrafficCellController extends SelfOrganizingCellController<TrafficEnvironment> { private static final long serialVersionUID = 1L; private final static Logger logger = LoggerFactory.getLogger(TrafficCellController.class); public TrafficCellController(CellState rootCellState, CommunicationModule comModule, TrafficEnvironment environment) { super(rootCellState, comModule, environment); } @Override protected List<AgentStateModel> combineAgentStimuli() { Map<Integer, AgentStateModel> agentStates = new HashMap<Integer, AgentStateModel>(); for(AgentStimulus action : agentStimuli) { AgentState state = cellState.getAgentState(action.getId()); if(state != null) { if(action instanceof MoveStimulus) { AgentState myState = cellState.getAgentState(action.getId()); AgentStateModel agentStateModel = new AgentStateModel(myState); agentStateModel.move(((MoveStimulus) action).getPosition()); agentStates.put(myState.getID(), agentStateModel); } else if(action instanceof ChangeHeadingStimulus) { ChangeHeadingStimulus a = (ChangeHeadingStimulus) action; state.setHeading(a.getHeading()); } } } // clear the list of agent stimuli agentStimuli.clear(); // resolveConflicts(agentStates); return new ArrayList<AgentStateModel>(agentStates.values()); } @Override protected Agent createAgent(AgentState initialState) { Agent agent = null; if(initialState.getAgentType().equals("Vehicle")) { agent = new VehicleAgent((VehicleAgentState) initialState); logger.debug("Created " + initialState.getAgentType()); } else { logger.warn("Agent of type " + initialState.getAgentType() + " does not exist"); } return agent; } @Override @SuppressWarnings("unchecked") protected TrafficCellController createChild(CellState cellState) { return new TrafficCellController(cellState, comModule, environment); } @Override protected void processDestructiveEvent(EnvEvent arg0) { // TODO Auto-generated method stub } @Override protected void applyUserCommand(RuntimeAgentCommandMsg cmd) { VehicleAgentState agent = (VehicleAgentState) cellState.getAgentState(cmd.getAgentID()); if(agent != null) { if(cmd.getCommand() == RuntimeAgentCommandMsg.RuntimeAgentCommand.SET_CONTROL_TYPE) agent.setControlType(AgentControlType.valueOf(cmd.getDataAsString())); } } private boolean isRoad(EnvObjectState envObj) { return envObj.getType().equals("Streets") || envObj.getType().equals("road") || envObj.getType().equals("street") || envObj.getType().equals("road_horizntal") || envObj.getType().equals("Cross Walk"); } }
3. Implementing the “TrafficEnvironment” class
The “TrafficEnvironment” extends the “AbstractEnvironment” class to bind the “TrafficCellController” class to its generic template “CC:CellController”.
Implementation Steps
- Inside the package “edu.utdallas.mavs.traffic.simulation.sim.env” create a class named “TrafficEnvironment” that extends the abstract class “SelfOrganizingEnvironment” defined in the package “edu.utdallas.mavs.divas.core.sim.env”.
- The “TrafficEnvironment” class implements the abstract methods:
- “createCellController”: this method is responsible for creating traffic cell controllers;
- “createAgentLoader”: this method is responsible for createing the traffic agent loader.
The full implementation of the class “TrafficEnvironment” is provided in the following code:
package edu.utdallas.mavs.traffic.simulation.sim.env; import edu.utdallas.mavs.divas.core.sim.common.state.CellState; import edu.utdallas.mavs.divas.core.sim.env.SelfOrganizingEnvironment; import edu.utdallas.mavs.divas.core.spec.agent.AgentLoader; import edu.utdallas.mavs.divas.mts.CommunicationModule; import edu.utdallas.mavs.divas.mts.MTSClient; import edu.utdallas.mavs.traffic.simulation.sim.spec.TrafficAgentLoader; public class TrafficEnvironment extends SelfOrganizingEnvironment<TrafficCellController> { private static final long serialVersionUID = 1L; public TrafficEnvironment(MTSClient client) { super(client); } @Override protected TrafficCellController createCellController(CellState cellState, CommunicationModule commModule) { return new TrafficCellController(cellState, commModule, this); } @Override protected AgentLoader createAgentLoader() { return new TrafficAgentLoader(); } }