/** * Transmit the specified token to the specified receiver with the specified properties. If * <i>propagationSpeed</i> is less than Infinity, then this results in a call to fireAt() of the * director for each receiver that is in range. The token is not actually transmitted to the * receiver until the corresponding invocation of fire() occurs. The time delay is equal to * distance/<i>propagationSpeed</i>. See the class comments for the assumptions that make this * correct. * * <p>If the <i>lossProbability</i> is zero, (the default) then the specified receiver will * receive the token if it has room. If <i>lossProbability</i> is greater than zero, the token * will be lost with the specified probability, independently for each receiver in range. Note * that in this base class, a port is in range if it refers to this channel by name and is at the * right place in the hierarchy. This base class makes no use of the properties argument. But * derived classes may limit the range or otherwise change transmission properties using this * argument. * * @param token The token to transmit, or null to clear the specified receiver. * @param sender The sending port. * @param receiver The receiver to which to transmit. * @param properties The transmit properties (ignored in this base class). * @exception IllegalActionException If the token cannot be converted or if the token argument is * null and the destination receiver does not support clear. */ protected void _transmitTo( Token token, WirelessIOPort sender, WirelessReceiver receiver, RecordToken properties) throws IllegalActionException { double speed = ((DoubleToken) propagationSpeed.getToken()).doubleValue(); if (speed == Double.POSITIVE_INFINITY) { super._transmitTo(token, sender, receiver, properties); } else { Director director = getDirector(); // FIXME: This isn't right because the receiver // may have moved during propagation. Maybe // register a ValueListener to the _location attributes // of the receiver actors, and continually recalculate // the correct arrival time for the message each time the // receiver location changes. Even so, this will be // an approximation, and needs to be fully characterized. // Also, the receiver needs to be in range at the // conclusion of the propagation, whereas this method is // called only if the receiver is in range at the // initiation of the transmission. WirelessIOPort destination = (WirelessIOPort) receiver.getContainer(); double distance = _distanceBetween(sender, destination); Time time = director.getModelTime().add(distance / speed); if (_receptions == null) { _receptions = new HashMap(); } Double timeDouble = Double.valueOf(time.getDoubleValue()); Reception reception = new Reception(); reception.token = token; reception.sender = sender; reception.receiver = receiver; reception.properties = properties; _receptions.put(timeDouble, reception); _fireAt(time); } }