1 package org.opentrafficsim.imb.transceiver.urbanstrategy;
2
3 import org.opentrafficsim.core.dsol.OTSDEVSRealTimeClock;
4 import org.opentrafficsim.core.dsol.OTSDEVSSimulatorInterface;
5 import org.opentrafficsim.imb.IMBException;
6 import org.opentrafficsim.imb.connector.Connector;
7 import org.opentrafficsim.imb.transceiver.AbstractTransceiver;
8 import org.opentrafficsim.imb.transceiver.IMBMessageHandler;
9 import org.opentrafficsim.imb.transceiver.OTSToIMBTransformer;
10
11 import nl.tno.imb.TByteBuffer;
12 import nl.tudelft.simulation.dsol.SimRuntimeException;
13 import nl.tudelft.simulation.dsol.simulators.DEVSRealTimeClock;
14 import nl.tudelft.simulation.dsol.simulators.SimulatorInterface;
15 import nl.tudelft.simulation.event.EventInterface;
16
17 /**
18 * The SimulatorTranseiver sends and listens to start, stop and change speed messages. The SimulatorTransceiver publishes the
19 * following information on the IMB bus:
20 * <ol>
21 * <li>SimulatorInterface.START_EVENT when the simulator starts executing.</li>
22 * <li>SimulatorInterface.STOP_EVENT when the simulator stops executing.</li>
23 * <li>DEVSRealTimeClock.CHANGE_SPEED_FACTOR_EVENT when the simulator speed changes. Note that the simulation speed values are
24 * limited to the following: {0.1, 0.2, 0.5, 1.0, 2.0, 5.0, 10.0, 20.0, 50.0, 100.0, 200.0, 500.0, 1000.0,
25 * Double.MAX_DOUBLE}</li>
26 * </ol>
27 * <p>
28 * Copyright (c) 2013-2016 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
29 * BSD-style license. See <a href="http://opentrafficsim.org/docs/license.html">OpenTrafficSim License</a>.
30 * </p>
31 * $LastChangedDate: 2015-07-24 02:58:59 +0200 (Fri, 24 Jul 2015) $, @version $Revision: 1147 $, by $Author: averbraeck $,
32 * initial version Sep 11, 2016 <br>
33 * @author <a href="http://www.tbm.tudelft.nl/averbraeck">Alexander Verbraeck</a>
34 * @author <a href="http://www.tudelft.nl/pknoppers">Peter Knoppers</a>
35 * @author <a href="http://www.transport.citg.tudelft.nl">Wouter Schakel</a>
36 */
37 public class SimulatorTransceiver extends AbstractTransceiver
38 {
39 /** */
40 private static final long serialVersionUID = 20160911L;
41
42 /** the Empty transformer for IMB. */
43 private final EmptyTransformer emptyTransformer = new EmptyTransformer();
44
45 /** the simulation speed transformer for IMB. */
46 private final SpeedTransformer speedTransformer = new SpeedTransformer();
47
48 /**
49 * Construct a new SimulatorTransceiver.
50 * @param connector Connector; the IMB connector through which this transceiver communicates
51 * @param simulator OTSDEVSSimulatorInterface; the simulator to schedule the incoming notifications on
52 * @throws IMBException when the registration of one of the channels fails
53 * @throws NullPointerException in case one of the arguments is null.
54 */
55 public SimulatorTransceiver(final Connector connector, final OTSDEVSSimulatorInterface simulator) throws IMBException
56 {
57 super("Simulator Control", connector, simulator);
58
59 // register the OTS to IMB updates for the simulator
60 final OTSDEVSRealTimeClock animator = (OTSDEVSRealTimeClock) simulator;
61 addOTSToIMBChannel(animator, SimulatorInterface.START_EVENT, "Sim_Start", new Object[] {}, this.emptyTransformer);
62 addOTSToIMBChannel(animator, SimulatorInterface.STOP_EVENT, "Sim_Stop", new Object[] {}, this.emptyTransformer);
63 addOTSToIMBChannel(animator, DEVSRealTimeClock.CHANGE_SPEED_FACTOR_EVENT, "Sim_Speed", new Object[] { new Double(1.0) },
64 this.speedTransformer);
65
66 // register the IMB to OTS updates for the simulator
67 final IMBMessageHandler startHandler = new IMBMessageHandler()
68 {
69 @Override
70 public void handle(TByteBuffer imbPayload) throws IMBException
71 {
72 try
73 {
74 if (!animator.isRunning()) // to break message cycle between OTS and IMB
75 {
76 animator.start(true);
77 }
78 }
79 catch (SimRuntimeException exception)
80 {
81 throw new IMBException(exception);
82 }
83 }
84
85 @Override
86 public String getIMBEventName()
87 {
88 return "Sim_Start";
89 }
90 };
91 addIMBtoOTSChannel("Sim_Start", startHandler);
92
93 final IMBMessageHandler stopHandler = new IMBMessageHandler()
94 {
95 @Override
96 public void handle(TByteBuffer imbPayload) throws IMBException
97 {
98 if (animator.isRunning()) // to break message cycle between OTS and IMB
99 {
100 animator.stop(true);
101 }
102 }
103
104 @Override
105 public String getIMBEventName()
106 {
107 return "Sim_Stop";
108 }
109 };
110 addIMBtoOTSChannel("Sim_Stop", stopHandler);
111
112 final IMBMessageHandler speedHandler = new IMBMessageHandler()
113 {
114 @Override
115 public void handle(TByteBuffer imbPayload) throws IMBException
116 {
117 System.out.println("About to read the new speed value");
118 double speed = imbPayload.readDouble();
119 System.out.println(
120 "Sim_Stop event handler: new speed is " + speed + " current speed is " + animator.getSpeedFactor());
121 if (speed != animator.getSpeedFactor()) // to break message cycle between OTS and IMB
122 {
123 animator.setSpeedFactor(speed, true); // TODO callback for speed not 100% ok yet...
124 }
125 }
126
127 @Override
128 public String getIMBEventName()
129 {
130 return "Sim_Speed";
131 }
132 };
133 addIMBtoOTSChannel("Sim_Speed", speedHandler);
134 }
135
136 /**
137 * Transform the an event without content to a corresponding IMB message.
138 * <p>
139 * Copyright (c) 2013-2016 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved.
140 * <br>
141 * BSD-style license. See <a href="http://opentrafficsim.org/docs/license.html">OpenTrafficSim License</a>.
142 * </p>
143 * $LastChangedDate: 2015-07-24 02:58:59 +0200 (Fri, 24 Jul 2015) $, @version $Revision: 1147 $, by $Author: averbraeck $,
144 * initial version Sep 11, 2016 <br>
145 * @author <a href="http://www.tbm.tudelft.nl/averbraeck">Alexander Verbraeck</a>
146 * @author <a href="http://www.tudelft.nl/pknoppers">Peter Knoppers</a>
147 * @author <a href="http://www.transport.citg.tudelft.nl">Wouter Schakel</a>
148 */
149 static class EmptyTransformer implements OTSToIMBTransformer
150 {
151 /** {@inheritDoc} */
152 @Override
153 public Object[] transform(final EventInterface event)
154 {
155 return new Object[] {};
156 }
157 }
158
159 /**
160 * Transform the a simulation speed change event to a corresponding IMB message.<br>
161 * Event is sent from OTS to IMB to indicate that the OTS simulation has changed the intended execution speed (there is,
162 * however, no guarantee that the simulator is able to reach that particular speed). The speed is coded as a 64-bits double,
163 * where 1.0 indicates exactly real-time; values less than 1.0 slower than real time, and larger than 1.0 indicates faster
164 * than real-time. The simulation speed values are limited to the following: {0.1, 0.2, 0.5, 1.0, 2.0, 5.0, 10.0, 20.0,
165 * 50.0, 100.0, 200.0, 500.0, 1000.0, Double.MAX_DOUBLE}.
166 * <p>
167 * <style>table,th,td {border:1px solid grey; border-style:solid; text-align:left; border-collapse: collapse;}</style>
168 * <H2>NEW</H2> Empty message, no payload
169 * </p>
170 * <p>
171 * <h2>CHANGE</h2>
172 * <table summary="" style="width:800px;">
173 * <thead>
174 * <tr>
175 * <th style="width:25%;">Variable</th>
176 * <th style="width:15%;">Type</th>
177 * <th style="width:60%;">Comments</th>
178 * </tr>
179 * </thead><tbody>
180 * <tr>
181 * <td>newSimulationSpeed</td>
182 * <td>double</td>
183 * <td>Limit to {1,2,5} E {-1, 0, 1, 2}, 1000, MAX_DOUBLE</td>
184 * </tr>
185 * </tbody>
186 * </table>
187 * </p>
188 * <p>
189 * <h2>DELETE</h2> Not sent
190 * </p>
191 * <p>
192 * Copyright (c) 2013-2016 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved.
193 * <br>
194 * BSD-style license. See <a href="http://opentrafficsim.org/docs/license.html">OpenTrafficSim License</a>.
195 * </p>
196 * $LastChangedDate: 2015-07-24 02:58:59 +0200 (Fri, 24 Jul 2015) $, @version $Revision: 1147 $, by $Author: averbraeck $,
197 * initial version Sep 11, 2016 <br>
198 * @author <a href="http://www.tbm.tudelft.nl/averbraeck">Alexander Verbraeck</a>
199 * @author <a href="http://www.tudelft.nl/pknoppers">Peter Knoppers</a>
200 * @author <a href="http://www.transport.citg.tudelft.nl">Wouter Schakel</a>
201 */
202 static class SpeedTransformer implements OTSToIMBTransformer
203 {
204 /** {@inheritDoc} */
205 @Override
206 public Object[] transform(final EventInterface event)
207 {
208 Double speed = ((Double) event.getContent());
209 System.out.println("Transmitting speed " + speed + " to IMB");
210 return new Object[] { speed };
211 }
212 }
213 }