#X3D V3.3 utf8 PROFILE Immersive # [X3D] version=3.3 # [X3D] noNamespaceSchemaLocation=https://www.web3d.org/specifications/x3d-3.3.xsd # X3D-to-ClassicVRML XSL translation autogenerated by X3dToClassicVrmlEncoding.xslt and X3dToVrml97.xslt # https://www.web3d.org/x3d/content/X3dToClassicVrmlEncoding.xslt # https://www.web3d.org/x3d/content/X3dToVrml97.xslt # Transformation using XSLT processor: Saxonica # head META "title" "BuoyCommunicationsGridPrototype.x3d" META "description" "Takes a communication-message input from a traversing vehicle (such as an AUV or submarine), then sets up the route/relay time delays, directions, animation and visualization of SeaWeb buoy communications among each other, all the way to the SeaWeb RACOM RF-relay buoy at the surface." META "creator" "Don Brutzman and MV4205 class" META "created" "8 June 2004" META "modified" "2 January 2025" META "subject" "Buoy, SeaWeb" META "reference" "BuoyCommunicationsGridExampleRoutingTable.xls" META "warning" "Under development, need to check timing and routing table" META "identifier" "https://savage.nps.edu/Savage/CommunicationsAndSensors/SeaWeb/BuoyCommunicationsGridPrototype.x3d" META "license" "../../license.html" # [Scene] ========== ========== ========== # ========== # ExternProtoDeclare statements precede the scene elements utilizing them # ========== EXTERNPROTO BeamCylinder [ # [appinfo] Produce wireframe or transparent beam cylinders. Typical uses include propeller/thruster water flow or line-of-sight sonar/radar/light beams. Negative range values invert base and apex at same relative location. Default: beam with apex at (0 0 0) and base of radius 1 in x-z plane at (1 0 0). inputOnly SFBool contact # [appinfo] (communications) is transmitted signal in contact with receiver or (sensor) is a target return detected? inputOnly SFFloat range # [appinfo] distance in meters along x axis initializeOnly SFFloat defaultRange # [appinfo] distance in meters used until eventIn range sent initializeOnly SFBool wireframe # [appinfo] whether wireframe beam is drawn initializeOnly SFBool solid # [appinfo] whether solid beam is drawn initializeOnly SFFloat beamHeight # [appinfo] meters across vertical y axis initializeOnly SFFloat beamWidth # [appinfo] meters across horizontal z axis initializeOnly SFColor contactColor # [appinfo] rendering color when contact=true initializeOnly SFColor noContactColor # [appinfo] rendering color when contact=false inputOutput SFFloat transparency # [appinfo] 1 = fully transparent wireframe only ][ "../../CommunicationsAndSensors/Beam/BeamCylinderPrototype.x3d#BeamCylinder" "https://savage.nps.edu/Savage/CommunicationsAndSensors/Beam/BeamCylinderPrototype.x3d#BeamCylinder" "../../CommunicationsAndSensors/Beam/BeamCylinderPrototype.wrl#BeamCylinder" "https://savage.nps.edu/Savage/CommunicationsAndSensors/Beam/BeamCylinderPrototype.wrl#BeamCylinder" ] EXTERNPROTO CameraCompass36 [ # [appinfo] Circular set of compass bearings that follow the active viewpoint set at 360/36 = 10 degree intervals. North = +X axis East = +Z axis up = +Y axis. inputOutput SFBool enabled inputOutput SFVec3f positionOffsetFromCamera inputOutput SFColor markerColor inputOutput SFColor labelColor ][ "../../../Savage/Tools/HeadsUpDisplays/CameraCompassPrototypes.x3d#CameraCompass36" "https://savage.nps.edu/Savage/Tools/HeadsUpDisplays/CameraCompassPrototypes.x3d#CameraCompass36" "../../../Savage/Tools/HeadsUpDisplays/CameraCompassPrototypes.wrl#CameraCompass36" "https://savage.nps.edu/Savage/Tools/HeadsUpDisplays/CameraCompassPrototypes.wrl#CameraCompass36" ] EXTERNPROTO CrossHair [ # [appinfo] The CrossHair prototype provides a heads-up display (HUD) crosshair showing center of screen useful for assessing NavigationInfo lookAt point initializeOnly SFBool enabled inputOnly SFBool set_enabled inputOutput SFColor markerColor inputOutput SFVec3f scale inputOutput SFVec3f positionOffsetFromCamera ][ "../../../Savage/Tools/HeadsUpDisplays/CrossHairPrototype.x3d#CrossHair" "https://savage.nps.edu/Savage/Tools/HeadsUpDisplays/CrossHairPrototype.x3d#CrossHair" "../../../Savage/Tools/HeadsUpDisplays/CrossHairPrototype.wrl#CrossHair" "https://savage.nps.edu/Savage/Tools/HeadsUpDisplays/CrossHairPrototype.wrl#CrossHair" ] EXTERNPROTO DvdController [ initializeOnly SFString description # [appinfo] Short description of what is animated by this DvdController. initializeOnly SFBool playEnabled # [appinfo] Whether or not play mode is enabled including during startup. initializeOnly SFString displayMode # [appinfo] Initializes how control buttons and slider are displayed. The control buttons include DIS control (i.e. Master Ghost Local) and Playback control (i.e. Reset to Start Fast Rewind Rewind Pause Play Fast Forward Reset to End). Possible values are (case sensitive): ALL DIS_ONLY PLAYBACK_ONLY SLIDER_ONLY DIS_PLAYBACK DIS_SLIDER PLAYBACK_SLIDER and NONE. inputOnly SFString setDisplayMode # [appinfo] Sets how control buttons and slider are displayed. The control buttons include DIS control (i.e. Master Ghost Local) and Playback control (i.e. Reset to Start Fast Rewind Rewind Pause Play Fast Forward Reset to End). Possible values are (case sensitive): ALL DIS_ONLY PLAYBACK_ONLY SLIDER_ONLY DIS_PLAYBACK DIS_SLIDER PLAYBACK_SLIDER and NONE. initializeOnly SFColor buttonColor # [appinfo] Default button color. initializeOnly SFColor selectedButtonColor # [appinfo] Button color when selected by user. initializeOnly SFColor labelColor # [appinfo] Default label color. initializeOnly SFColor selectedLabelColor # [appinfo] Label color when selected by user. initializeOnly SFVec3f locationOffset # [appinfo] Modified screen location and distance (for size). initializeOnly SFBool clockEnabled initializeOnly SFTime cycleInterval # [appinfo] Time for complete loop cycle in seconds. inputOnly SFTime set_cycleInterval outputOnly SFTime cycleInterval_changed initializeOnly SFFloat speedFactor # [appinfo] Factor used to determine the speed increase/decrease for Fast Rewind and Fast Forward action. outputOnly SFBool isActive outputOnly SFTime startTime_changed outputOnly SFTime stopTime_changed outputOnly SFTime time_changed outputOnly SFFloat fraction_changed outputOnly SFTime secondsElapsed outputOnly SFBool isMaster # [appinfo] isMaster isRemote and isLocal are booleans represent a 3-way toggle. Only one of them can have a true value at any time. outputOnly SFBool isRemote # [appinfo] isMaster isRemote and isLocal are booleans represent a 3-way toggle. Only one of them can have a true value at any time. outputOnly SFBool isLocal # [appinfo] isMaster isRemote and isLocal are booleans represent a 3-way toggle. Only one of them can have a true value at any time. outputOnly SFBool isPaused # [appinfo] isPaused and isRunning always have opposite values. When isPaused is true isRunning will be false and vice versa. outputOnly SFBool isRunning # [appinfo] isPaused and isRunning always have opposite values. When isPaused is true isRunning will be false and vice versa. initializeOnly SFBool traceEnabled # [appinfo] Enable/disable console output for troubleshooting. initializeOnly SFTime testTimeVal ][ "../../../Savage/Tools/HeadsUpDisplays/DvdControllerPrototype.x3d#DvdController" "https://savage.nps.edu/Savage/Tools/HeadsUpDisplays/DvdControllerPrototype.x3d#DvdController" "../../../Savage/Tools/HeadsUpDisplays/DvdControllerPrototype.wrl#DvdController" "https://savage.nps.edu/Savage/Tools/HeadsUpDisplays/DvdControllerPrototype.wrl#DvdController" ] EXTERNPROTO GridXZ [ # [appinfo] Line grid authoring tool to enable precise measurement of objects in 3D space - fixed position. Oriented along XZ plane size 20m by 20m. initializeOnly SFString description inputOutput SFColor labelColor inputOutput SFVec3f scale # [appinfo] default unscaled size: 10m by 10m inputOutput MFString originLabel inputOutput MFString WestLabel # [appinfo] -X axis inputOutput MFString NorthWestLabel inputOutput MFString NorthLabel # [appinfo] -Z axis inputOutput MFString NorthEastLabel inputOutput MFString EastLabel # [appinfo] +X axis inputOutput MFString SouthEastLabel inputOutput MFString SouthLabel # [appinfo] +Z axis inputOutput MFString SouthWestLabel inputOutput SFVec3f labelsOffset # [appinfo] label location offset (in meters) to improve readability ][ "../../../Savage/Tools/Authoring/GridXZPrototype.x3d#GridXZ" "https://savage.nps.edu/Savage/Tools/Authoring/GridXZPrototype.x3d#GridXZ" "../../../Savage/Tools/Authoring/GridXZPrototype.wrl#GridXZ" "https://savage.nps.edu/Savage/Tools/Authoring/GridXZPrototype.wrl#GridXZ" ] EXTERNPROTO SeaWebBuoy [ inputOnly SFVec3f set_position # [appinfo] Position of buoy. initializeOnly SFVec3f position # [appinfo] Position of buoy. inputOnly SFVec3f set_targetPosition # [appinfo] Position of target of transmission. initializeOnly SFVec3f targetPosition # [appinfo] Position of target of transmission. initializeOnly SFInt32 targetIdNumber # [appinfo] Id number of target. inputOnly SFInt32 set_targetIdNumber # [appinfo] Id number of target. inputOnly SFBool set_enabled # [appinfo] Enable buoy for transmission. initializeOnly SFBool enabled # [appinfo] Enable buoy for transmission. inputOnly SFBool set_activated # [appinfo] Start transmission. initializeOnly SFBool activated # [appinfo] Start transmission. inputOnly SFFloat set_transmissionDuration # [appinfo] Duration in seconds needed to transmit message (does not include transmissionTimeDelay or propagation delay). initializeOnly SFFloat transmissionDuration # [appinfo] Duration in seconds needed to transmit message (does not include transmissionTimeDelay or propagation delay). initializeOnly SFTime transmissionTimeDelay # [appinfo] Time delay before transmission begins. inputOnly SFTime set_transmissionTimeDelay # [appinfo] Time delay before transmission begins. inputOnly SFBool set_directionalTransmission # [appinfo] Select between directional (true) or omni-directional (false) transmission. initializeOnly SFBool directionalTransmission # [appinfo] Select between directional (true) or omni-directional (false) transmission. inputOnly SFString set_buoyType # [appinfo] Determine which buoy type to use. "Racom" for Racom Buoy. "Telesonar" for Telesonar Repeater. initializeOnly SFString buoyType # [appinfo] Determine which buoy type to use. "Racom" for Racom Buoy. "Telesonar" for Telesonar Repeater. inputOnly MFString set_textMessage initializeOnly MFString textMessage inputOutput SFColor textMessageColor inputOnly SFString set_description initializeOnly SFString description initializeOnly SFBool traceEnabled inputOnly SFFloat set_soundSpeedInWater # [appinfo] Sound speed in water default value 1500 m/s initializeOnly SFFloat soundSpeedInWater # [appinfo] Sound speed in water default value 1500 m/s ][ "../../CommunicationsAndSensors/SeaWeb/SeaWebBuoyPrototype.x3d#SeaWebBuoy" "https://savage.nps.edu/Savage/CommunicationsAndSensors/SeaWeb/SeaWebBuoyPrototype.x3d#SeaWebBuoy" "../../../Savage/CommunicationsAndSensors/SeaWeb/SeaWebBuoyPrototype.wrl#SeaWebBuoy" "https://savage.nps.edu/Savage/CommunicationsAndSensors/SeaWeb/SeaWebBuoyPrototype.wrl#SeaWebBuoy" ] EXTERNPROTO ViewPositionOrientation [ # [appinfo] ViewPositionOrientation prototype provides local position and orientation as user navigates with optional console output inputOutput SFBool enabled # [appinfo] Whether or not ViewPositionOrientation sends output to console. initializeOnly SFBool traceEnabled # [appinfo] Output internal trace messages for debugging this node - developer use only can be ignored. inputOnly SFBool set_traceEnabled # [appinfo] Ability to turn output tracing on/off at runtime. outputOnly SFVec3f position_changed # [appinfo] Output local position. outputOnly SFRotation orientation_changed # [appinfo] Output local orientation. outputOnly MFString outputViewpointString # [appinfo] MFString value of new Viewpoint for example: ][ "../../../Savage/Tools/Authoring/ViewPositionOrientationPrototype.x3d#ViewPositionOrientation" "https://savage.nps.edu/Savage/Tools/Authoring/ViewPositionOrientationPrototype.x3d#ViewPositionOrientation" "../../../Savage/Tools/Authoring/ViewPositionOrientationPrototype.wrl#ViewPositionOrientation" "https://savage.nps.edu/Savage/Tools/Authoring/ViewPositionOrientationPrototype.wrl#ViewPositionOrientation" ] EXTERNPROTO WaypointInterpolator [ # [appinfo] Reads waypoints and legSpeeds/legDurations/defaultSpeed to provide a customizable position/orientation interpolator. # Priority of use: legSpeeds (m/sec), legDurations (seconds), defaultSpeed (m/sec) initializeOnly SFString description # [appinfo] Short description of what is animated by this WaypointInterpolator. initializeOnly MFVec3f waypoints # [appinfo] Waypoints being traversed with interpolation of intermediate positions and orientations. inputOnly SFVec3f add_waypoint # [appinfo] Add another single waypoint to array of waypoints recalculate interpolator values. inputOnly MFVec3f set_waypoints # [appinfo] Replace all waypoints recalculate interpolator values. initializeOnly SFBool pitchUpDownForVerticalWaypoints # [appinfo] Whether to pitch child geometry (such as a vehicle) up or down to match vertical slope initializeOnly MFFloat legSpeeds # [appinfo] Units m/sec. If used array lengths for legSpeeds and legDurations must be one less than number of waypoints. initializeOnly MFTime legDurations # [appinfo] Units in seconds. If used array lengths for legSpeeds and legDurations must be one less than number of waypoints. initializeOnly SFFloat defaultSpeed # [appinfo] Units m/sec. initializeOnly SFFloat turningRate # [appinfo] turningRate (degrees/second) also determines standoff distance prior to waypoint where turn commences. If 0 turns are instantaneous. outputOnly SFTime totalDuration # [appinfo] Output calculation summing all leg durations, useful for setting TimeSensor cycleInterval. Units in seconds. # interpolation fields inputOnly SFFloat set_fraction # [appinfo] exposed PositionInterpolator and OrientationInterpolator setting outputOnly SFVec3f position_changed # [appinfo] exposed PositionInterpolator setting outputOnly SFRotation orientation_changed # [appinfo] exposed OrientationInterpolator setting # display-related fields inputOutput SFColor lineColor # [appinfo] default color for non-active line segments inputOutput SFColor highlightSegmentColor # [appinfo] active segment highlight color inputOutput SFFloat transparency # [appinfo] 1.0 is completely transparent, 0.0 is completely opaque. initializeOnly SFString labelDisplayMode # [appinfo] allowed values: none; waypoints (produce labels at each waypoint); or interpolation (produce single moving label at interpolator time course speed location) initializeOnly SFString heightLabel # [appinfo] allowed values: altitude depth (negate Y value) none initializeOnly SFVec3f labelOffset # [appinfo] heightLabel relative location initializeOnly SFFloat labelFontSize # [appinfo] heightLabel text size initializeOnly SFColor labelColor # [appinfo] heightLabel text color initializeOnly SFBool traceEnabled # [appinfo] enable console output to trace script computations and prototype progress initializeOnly SFBool outputInitializationComputations # [appinfo] Output the number of waypoints totalDistance and totalDuration to console upon initialization inputOutput SFColor verticalDropLineColor # [appinfo] default color for vertical drop-line segments inputOutput SFFloat verticalDropLineTransparency # [appinfo] 1.0 is completely transparent, 0.0 is completely opaque. ][ "../../../Savage/Tools/Animation/WaypointInterpolatorPrototype.x3d#WaypointInterpolator" "https://savage.nps.edu/Savage/Tools/Animation/WaypointInterpolatorPrototype.x3d#WaypointInterpolator" "../../../Savage/Tools/Animation/WaypointInterpolatorPrototype.wrl#WaypointInterpolator" "https://savage.nps.edu/Savage/Tools/Animation/WaypointInterpolatorPrototype.wrl#WaypointInterpolator" ] # ========== PROTO BuoyCommunicationsGrid [ # [appinfo] BuoyCommunicationsGrid prototype takes a communication-message input from a traversing vehicle (such as an AUV or submarine) then sets up the route/relay time delays directions animation and visualization of SeaWeb buoy communications among each other all the way to the SeaWeb RACOM RF-relay buoy at the surface. initializeOnly MFNode buoyArray [ ] # [appinfo] array of SeaWebBuoy nodes index starting at 0 # Example: initializeOnly MFInt32 buoyCommunicationsRoutingTable [ -1 2 2 2 5 6 6 6 5 6 6 6 5 6 6 6 1 -1 3 3 5 6 7 7 5 6 7 7 5 6 7 7 2 2 -1 4 6 6 7 8 6 6 7 8 6 6 7 8 3 3 3 -1 7 7 7 8 7 7 7 8 7 7 7 8 1 2 2 2 -1 6 6 6 9 10 10 10 9 10 10 10 1 2 3 3 5 -1 7 7 9 10 11 11 9 10 11 11 2 2 3 4 6 6 -1 8 10 10 11 12 10 10 11 12 3 3 3 4 7 7 7 -1 11 11 11 12 11 11 11 12 5 6 6 6 5 6 6 6 -1 10 10 10 13 14 14 14 5 6 7 7 5 6 7 7 9 -1 11 11 13 14 15 15 6 6 7 8 6 6 7 8 10 10 -1 12 14 14 15 16 7 7 7 8 7 7 7 8 11 11 11 -1 15 15 15 16 9 10 10 10 9 10 10 10 9 10 10 10 -1 14 14 14 9 10 11 11 9 10 11 11 9 10 11 11 13 -1 15 15 10 10 11 12 10 10 11 12 10 10 11 12 14 14 -1 16 11 11 11 12 11 11 11 12 11 11 11 12 15 15 15 -1 ] # [appinfo] 2D array of routing connectivity for buoys consisting either of index of next buoy in line -1 for same buoy or else 0 for no route connection. legal values range [-1..n-1] for n buoys. inputOnly SFVec3f set_senderPosition # [appinfo] set position of entity sending the message initializeOnly SFVec3f senderPosition 0 0 0 # [appinfo] position of entity sending the message inputOnly SFVec3f set_receiverPosition # [appinfo] set position of entity receiving the message initializeOnly SFVec3f receiverPosition 0 0 0 # [appinfo] position of entity receiving the message inputOnly MFString set_textMessage initializeOnly MFString textMessage [ "" ] inputOnly SFBool sendMessage # [appinfo] send it! (note: maybe should rename as 'activate') ] { DEF BuoyCommunicationsGridScript Script { initializeOnly MFNode buoyArray IS buoyArray # [appinfo] array of SeaWebBuoy nodes index starting at 0 # Example: initializeOnly MFInt32 buoyCommunicationsRoutingTable IS buoyCommunicationsRoutingTable # [appinfo] 2D array of routing connectivity for buoys -1 for no connection range [0..n-1] for n buoys. inputOnly SFVec3f set_senderPosition IS set_senderPosition # [appinfo] set position of entity sending the message initializeOnly SFVec3f senderPosition IS senderPosition # [appinfo] position of entity sending the message inputOnly SFVec3f set_receiverPosition IS set_receiverPosition # [appinfo] set position of entity receiving the message initializeOnly SFVec3f receiverPosition IS receiverPosition # [appinfo] position of entity receiving the message inputOnly MFString set_textMessage IS set_textMessage initializeOnly MFString textMessage IS textMessage inputOnly SFBool sendMessage IS sendMessage # [appinfo] send it! initializeOnly SFBool traceEnabled TRUE directOutput TRUE url [ "ecmascript: // ### X3D Browser.print() not supported by all VRML97 viewers, instead simply using print() function alwaysPrint (text) { Browser.println ('[BuoyCommunicationsGrid]' + text); } function tracePrint (text) { if (traceEnabled) Browser.println ('[BuoyCommunicationsGrid]' + text); } function set_senderPosition (value, timestamp) { senderPosition = value; } function set_receiverPosition (value, timestamp) { receiverPosition = value; } function set_textMessage (value, timestamp) { textMessage = value; } function distance (p1, p2) // inputs: SFVec3f, output: float { // square root of sum of sum of squares dx = (p1.x - p2.x); dy = (p1.y - p2.y); dz = (p1.z - p2.z); d = Math.sqrt (dx*dx + dy*dy + dz*dz); // tracePrint ('distance (' + p1 + ',' + p2 + ') =' + d); return d; } function timeSoundTravels (distance) // input: float meters, output: float seconds { // speed of sound in water = 1500 m/s timeInterval = distance / 1500; tracePrint ('sound travels' + Math.round(distance) + ' meters in' + 'timeInterval=' + Math.round(timeInterval*1000)/1000 + ' seconds'); return timeInterval; } function routingTableIndex (senderNodeIndex, destinationNodeIndex) { if (( senderNodeIndex < 0) || ( senderNodeIndex >= buoyArray.length) || (destinationNodeIndex < 0) || (destinationNodeIndex >= buoyArray.length)) alwaysPrint ('routingTableIndex () error, input index out of bounds: senderNodeIndex=' + senderNodeIndex + ', destinationNodeIndex=' + destinationNodeIndex); newIndex = buoyArray.length*senderNodeIndex + destinationNodeIndex; return newIndex; } function findClosestBuoyIndex (position) { closestBuoyIndex = 0; // initialize closestDistance = distance (position, buoyArray[0].position); // tracePrint ('distance(position, buoyArray[0].position)=' + Math.round(closestDistance)); if (buoyArray.length == 1) return closestBuoyIndex; for (i=1; i < buoyArray.length; i++) // start comparison loop at second buoy { d = distance (position, buoyArray[i].position); // tracePrint ('distance(position, buoyArray[' + i + '].position)=' + d); if (d < closestDistance) { closestBuoyIndex = i; closestDistance = d; // tracePrint (' closestBuoyIndex=' + closestBuoyIndex); } } tracePrint ('closest distance(position, buoyArray[' + closestBuoyIndex + '].position)=' + Math.round(closestDistance)); return closestBuoyIndex; } function initialize () { n = buoyArray.length; tracePrint ('initialize() buoyArray.length=' + buoyArray.length); tracePrint ('initialize() buoyCommunicationsRoutingTable=' + buoyCommunicationsRoutingTable); tracePrint ('initialize() buoyCommunicationsRoutingTable.length=' + buoyCommunicationsRoutingTable.length); // check that routing table is a properly sized square array if (buoyCommunicationsRoutingTable.length != n*n) { alwaysPrint ('initialize() invalid buoyCommunicationsRoutingTable.length=' + buoyCommunicationsRoutingTable.length + ', should = (' + n + '*' + n + ') =' + (n*n)); } tracePrint ('initialize() square table check complete'); // check for routing table loop from node to itself for (i=0; i < n; i++) { // tracePrint ('initialize() buoyCommunicationsRoutingTable[routingTableIndex(' + i + ',' + i + ')]=' + buoyCommunicationsRoutingTable[routingTableIndex(i,i)] ); if (buoyCommunicationsRoutingTable[routingTableIndex(i,i)] != -1) alwaysPrint ('initialize() invalid buoyCommunicationsRoutingTable[' + i + ']=' + buoyCommunicationsRoutingTable[i] + ' rather than -1, since node (' + i + ') cannot route to itself'); } tracePrint ('initialize() self route check complete'); // check routing table values are legal for (i=0; i < n; i++) { for (j=0; j < n; j++) { k = buoyCommunicationsRoutingTable[routingTableIndex (i, j)]; // tracePrint ('initialize() routingTableIndex (' + i + ',' + j + ') =' + k); if ((buoyCommunicationsRoutingTable[k] < -1) || (buoyCommunicationsRoutingTable[k] >= buoyCommunicationsRoutingTable.length)) alwaysPrint ('initialize() *** invalid buoyCommunicationsRoutingTable[' + i + ',' + j + ']=' + buoyCommunicationsRoutingTable[k]); } } // TODO: check for other routing table loops? tracePrint ('initialize() complete'); } function sendMessage (value, timestamp) { if (value != true) { if (value != false) tracePrint ('sendMessage() exiting, passed value=' + value); return; } // run-time setup happens here! execution of all buoys occurs upon returning. // prepare the scene graph for a message sequence, then start it. // first find shortest distances and thus closest buoys to sender and receiver senderNodeIndex = findClosestBuoyIndex(senderPosition); destinationNodeIndex = findClosestBuoyIndex(receiverPosition); tracePrint (' senderNodeIndex=' + senderNodeIndex + ' (' + senderPosition + ')'); tracePrint ('destinationNodeIndex=' + destinationNodeIndex + ' (' + receiverPosition + ')'); // TODO: sound beam from sender to senderNode or receiver (whichever is closest) if (senderNodeIndex == destinationNodeIndex) { tracePrint ('senderNode and destinationNode are the same, no message sent'); tracePrint ('============================================='); return; } transmissionDuration = 1; tracePrint ('transmissionDuration=' + transmissionDuration); // compute path (sequence of buoy IDs) from closest buoy to SeaWeb buoy // compute full buoy-to-buoy routing paths for current sender-receiver combination hopCount = 0; maxHopCount = buoyArray.length - 1; nextNodeIndex = -2; nodePath = new MFInt32(); nodePath[nodePath.length] = senderNodeIndex; nodePathString ='sender, buoys' + senderNodeIndex; currentNodeIndex = senderNodeIndex; d = distance (senderPosition, buoyArray[senderNodeIndex].position); dt = timeSoundTravels (d); accumulatedRange = d; accumulatedDelay = 2 * (dt + transmissionDuration); tracePrint ('distance=' + Math.round(d) + ', accumulatedRange=' + Math.round(accumulatedRange) + ', accumulatedDelay=' + Math.round(accumulatedDelay*1000)/1000); while ((nextNodeIndex != -1) && (hopCount <= maxHopCount)) { tracePrint ('====='); tableIndex = routingTableIndex (currentNodeIndex, destinationNodeIndex); nextNodeIndex = buoyCommunicationsRoutingTable[tableIndex]; tracePrint ('currentNodeIndex=' + currentNodeIndex + ', nextNodeIndex=' + nextNodeIndex + ', tableIndex=' + tableIndex); // check if dead end - incomplete communication path if (nextNodeIndex < 0) { alwaysPrint ('*** hit a dead end! no further routing possible.'); return nextNodeIndex; // consider not animating any buoys, i.e. whether or not partial routing allowed } hopCount++; // tracePrint ('hopCount=' + hopCount + ', maxHopCount=' + maxHopCount); // communicate from currentNodeIndex buoy to nextNodeIndex buoy // by sending initialization values to each buoy in path: // message, target buoy ID/position, and then compute distance/time to travel // to set time delay of each buoy prior to start of each transmission. buoyArray[currentNodeIndex].textMessage = textMessage; buoyArray[currentNodeIndex].targetIdNumber = nextNodeIndex; buoyArray[currentNodeIndex].targetPosition = buoyArray[nextNodeIndex].position; d = distance ( buoyArray[currentNodeIndex].position, buoyArray[nextNodeIndex].position); dt = timeSoundTravels (d); accumulatedRange += d; accumulatedDelay += 2 * (dt + transmissionDuration); buoyArray[currentNodeIndex].range = d; buoyArray[currentNodeIndex].transmissionDuration = transmissionDuration; buoyArray[currentNodeIndex].transmissionTimeDelay = accumulatedDelay; buoyArray[currentNodeIndex].set_activated = true; // set up for next time through loop: currentNodeIndex = nextNodeIndex; nodePath[nodePath.length] = nextNodeIndex; nodePathString +=',' + nextNodeIndex; tracePrint ('distance=' + Math.round(d) + ', accumulatedRange=' + Math.round(accumulatedRange) + ', accumulatedDelay=' + Math.round(accumulatedDelay*1000)/1000); if (nextNodeIndex == destinationNodeIndex) break; } tracePrint ('====='); // last node to destination follows tracePrint ('destinationNodeIndex=' + destinationNodeIndex + ' to receiver'); buoyArray[currentNodeIndex].textMessage = textMessage; buoyArray[currentNodeIndex].targetIdNumber = -2; buoyArray[currentNodeIndex].targetPosition = receiverPosition; d = distance ( buoyArray[destinationNodeIndex].position, receiverPosition); dt = timeSoundTravels (d); accumulatedRange += d; accumulatedDelay += 2 * (dt + transmissionDuration); buoyArray[currentNodeIndex].range = d; buoyArray[currentNodeIndex].transmissionDuration = transmissionDuration; buoyArray[destinationNodeIndex].transmissionTimeDelay = accumulatedDelay ; buoyArray[destinationNodeIndex].set_activated = true; tracePrint ('distance=' + Math.round(d) + ', accumulatedRange=' + Math.round(accumulatedRange) + ', accumulatedDelay=' + Math.round(accumulatedDelay*1000)/1000); tracePrint ('====='); tracePrint ('path destination found, buoy hopCount=' + hopCount + ', nodePath=' + nodePathString + ', receiver'); for (i=0; i < nodePath.length; i++) { j = nodePath[i]; tracePrint ('node=' + nodePath[i] + ', buoyArray[' + nodePath[i] + '].transmissionTimeDelay=' + Math.round(buoyArray[nodePath[i]].transmissionTimeDelay*1000)/1000); } tracePrint ('============================================='); // TODO: do we need to trigger the RACOM radio at this point? } " ] } } # ========== # Viewable geometry for this scene is anchored text that links to an example showing ExternProtoDeclare usage of a BuoyCommunicationsGridPrototype. WorldInfo { info [ "A BuoyCommunicationsGrid prototype" ] title "BuoyCommunicationsGridPrototype" } Viewpoint { description "BuoyCommunicationsGrid prototype definition" position 0 0 15 } Anchor { description "BuoyCommunicationsGrid Example" url [ "BuoyCommunicationsGridExample.x3d" "../../../Savage/CommunicationsAndSensors/SeaWeb/BuoyCommunicationsGridExample.x3d" "https://savage.nps.edu/Savage/CommunicationsAndSensors/SeaWeb/BuoyCommunicationsGridExample.x3d" "BuoyCommunicationsGridExample.wrl" "../../../Savage/CommunicationsAndSensors/SeaWeb/BuoyCommunicationsGridExample.wrl" "https://savage.nps.edu/Savage/CommunicationsAndSensors/SeaWeb/BuoyCommunicationsGridExample.wrl" ] children [ Shape { appearance Appearance { material Material { diffuseColor 0 1 1 emissiveColor 0 1 1 } } geometry Text { string [ "BuoyCommunicationsGridPrototype" "is a Prototype definition file." "" "To see an example scene" "click this text and view" "BuoyCommunicationsGridExample." ] fontStyle FontStyle { justify [ "MIDDLE" "MIDDLE" ] } } } ] }