View Javadoc
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 }