X3D Model Documentation: BuoyCommunicationsGridPrototype.x3d

  1  <?xml version="1.0" encoding="UTF-8"?>
  2  <!DOCTYPE X3D PUBLIC "ISO//Web3D//DTD X3D 3.3//EN" "https://www.web3d.org/specifications/x3d-3.3.dtd">
  3  <X3D profile='Immersive' version='3.3 xmlns:xsd='http://www.w3.org/2001/XMLSchema-instance' xsd:noNamespaceSchemaLocation='https://www.web3d.org/specifications/x3d-3.3.xsd'>
  4       <head>
  5            <meta name='titlecontent='BuoyCommunicationsGridPrototype.x3d'/>
  6            <meta name='descriptioncontent='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.'/>
  7            <meta name='creatorcontent='Don Brutzman and MV4205 class'/>
  8            <meta name='createdcontent='8 June 2004'/>
  9            <meta name='modifiedcontent='2 January 2025'/>
 10            <meta name='subjectcontent='Buoy, SeaWeb'/>
 11            <meta name='referencecontent='BuoyCommunicationsGridExampleRoutingTable.xls'/>
 12            <meta name=' warning content=' Under development, need to check timing and routing table '/>
 13            <meta name='identifiercontent='https://savage.nps.edu/Savage/CommunicationsAndSensors/SeaWeb/BuoyCommunicationsGridPrototype.x3d'/>
 14            <meta name='licensecontent='../../license.html'/>
 15       </head>
<!--

<!--
Event Graph ROUTE Table shows event connections.
-->

<!-- to top Index for DEF node: BuoyCommunicationsGridScript

Index for Viewpoint node: Viewpoint_1

Index for ExternProtoDeclare definitions: BeamCylinder, CameraCompass36, CrossHair, DvdController, GridXZ, SeaWebBuoy, ViewPositionOrientation, WaypointInterpolator

Index for ProtoDeclare definition: BuoyCommunicationsGrid
-->
 16       <Scene>
 17            <!-- ========== -->
 18            <!-- ExternProtoDeclare statements precede the scene elements utilizing them -->
 19            <!-- ========== -->
 20            <ExternProtoDeclare name='BeamCylinderappinfo='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).'   url=' "../../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" '>
 21                 <field name='contacttype='SFBoolaccessType='inputOnly'
                appinfo='(communications) is transmitted signal in contact with receiver or (sensor) is a target return detected?'/>
 22                 <field name='rangetype='SFFloataccessType='inputOnly'
                appinfo='distance in meters along x axis'/>
 23                 <field name='defaultRangetype='SFFloataccessType='initializeOnly'
                appinfo='distance in meters used until eventIn range sent'/>
 24                 <field name='wireframetype='SFBoolaccessType='initializeOnly'
                appinfo='whether wireframe beam is drawn'/>
 25                 <field name='solidtype='SFBoolaccessType='initializeOnly'
                appinfo='whether solid beam is drawn'/>
 26                 <field name='beamHeighttype='SFFloataccessType='initializeOnly'
                appinfo='meters across vertical y axis'/>
 27                 <field name='beamWidthtype='SFFloataccessType='initializeOnly'
                appinfo='meters across horizontal z axis'/>
 28                 <field name='contactColortype='SFColoraccessType='initializeOnly'
                appinfo='rendering color when contact=true'/>
 29                 <field name='noContactColortype='SFColoraccessType='initializeOnly'
                appinfo='rendering color when contact=false'/>
 30                 <field name='transparencytype='SFFloataccessType='inputOutput'
                appinfo='1 = fully transparent wireframe only'/>
 31            </ExternProtoDeclare>
 32            <ExternProtoDeclare name='CameraCompass36appinfo='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.'   url=' "../../../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" '>
 33                 <field name='enabledtype='SFBoolaccessType='inputOutput'/>
 34                 <field name='positionOffsetFromCameratype='SFVec3faccessType='inputOutput'/>
 35                 <field name='markerColortype='SFColoraccessType='inputOutput'/>
 36                 <field name='labelColortype='SFColoraccessType='inputOutput'/>
 37            </ExternProtoDeclare>
 38            <ExternProtoDeclare name='CrossHairappinfo='The CrossHair prototype provides a heads-up display (HUD) crosshair showing center of screen useful for assessing NavigationInfo lookAt point'   url=' "../../../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" '>
 39                 <field name='enabledtype='SFBoolaccessType='initializeOnly'/>
 40                 <field name='set_enabledtype='SFBoolaccessType='inputOnly'/>
 41                 <field name='markerColortype='SFColoraccessType='inputOutput'/>
 42                 <field name='scaletype='SFVec3faccessType='inputOutput'/>
 43                 <field name='positionOffsetFromCameratype='SFVec3faccessType='inputOutput'/>
 44            </ExternProtoDeclare>
 45            <ExternProtoDeclare name='DvdController'   url=' "../../../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" '>
 46                 <field name='descriptiontype='SFStringaccessType='initializeOnly'
                appinfo='Short description of what is animated by this DvdController.'/>
 47                 <field name='playEnabledtype='SFBoolaccessType='initializeOnly'
                appinfo='Whether or not play mode is enabled including during startup.'/>
 48                 <field name='displayModetype='SFStringaccessType='initializeOnly'
                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.'/>
 49                 <field name='setDisplayModetype='SFStringaccessType='inputOnly'
                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.'/>
 50                 <field name='buttonColortype='SFColoraccessType='initializeOnly'
                appinfo='Default button color.'/>
 51                 <field name='selectedButtonColortype='SFColoraccessType='initializeOnly'
                appinfo='Button color when selected by user.'/>
 52                 <field name='labelColortype='SFColoraccessType='initializeOnly'
                appinfo='Default label color.'/>
 53                 <field name='selectedLabelColortype='SFColoraccessType='initializeOnly'
                appinfo='Label color when selected by user.'/>
 54                 <field name='locationOffsettype='SFVec3faccessType='initializeOnly'
                appinfo='Modified screen location and distance (for size).'/>
 55                 <field name='clockEnabledtype='SFBoolaccessType='initializeOnly'/>
 56                 <field name='cycleIntervaltype='SFTimeaccessType='initializeOnly'
                appinfo='Time for complete loop cycle in seconds.'/>
 57                 <field name='set_cycleIntervaltype='SFTimeaccessType='inputOnly'/>
 58                 <field name='cycleInterval_changedtype='SFTimeaccessType='outputOnly'/>
 59                 <field name='speedFactortype='SFFloataccessType='initializeOnly'
                appinfo='Factor used to determine the speed increase/decrease for Fast Rewind and Fast Forward action.'/>
 60                 <field name='isActivetype='SFBoolaccessType='outputOnly'/>
 61                 <field name='startTime_changedtype='SFTimeaccessType='outputOnly'/>
 62                 <field name='stopTime_changedtype='SFTimeaccessType='outputOnly'/>
 63                 <field name='time_changedtype='SFTimeaccessType='outputOnly'/>
 64                 <field name='fraction_changedtype='SFFloataccessType='outputOnly'/>
 65                 <field name='secondsElapsedtype='SFTimeaccessType='outputOnly'/>
 66                 <field name='isMastertype='SFBoolaccessType='outputOnly'
                appinfo='isMaster isRemote and isLocal are booleans represent a 3-way toggle. Only one of them can have a true value at any time.'/>
 67                 <field name='isRemotetype='SFBoolaccessType='outputOnly'
                appinfo='isMaster isRemote and isLocal are booleans represent a 3-way toggle. Only one of them can have a true value at any time.'/>
 68                 <field name='isLocaltype='SFBoolaccessType='outputOnly'
                appinfo='isMaster isRemote and isLocal are booleans represent a 3-way toggle. Only one of them can have a true value at any time.'/>
 69                 <field name='isPausedtype='SFBoolaccessType='outputOnly'
                appinfo='isPaused and isRunning always have opposite values. When isPaused is true isRunning will be false and vice versa.'/>
 70                 <field name='isRunningtype='SFBoolaccessType='outputOnly'
                appinfo='isPaused and isRunning always have opposite values. When isPaused is true isRunning will be false and vice versa.'/>
 71                 <field name='traceEnabledtype='SFBoolaccessType='initializeOnly'
                appinfo='Enable/disable console output for troubleshooting.'/>
 72                 <field name='testTimeValtype='SFTimeaccessType='initializeOnly'/>
 73            </ExternProtoDeclare>
 74            <ExternProtoDeclare name='GridXZappinfo='Line grid authoring tool to enable precise measurement of objects in 3D space - fixed position. Oriented along XZ plane size 20m by 20m.'   url=' "../../../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" '>
 75                 <field name='descriptiontype='SFStringaccessType='initializeOnly'/>
 76                 <field name='labelColortype='SFColoraccessType='inputOutput'/>
 77                 <field name='scaletype='SFVec3faccessType='inputOutput'
                appinfo='default unscaled size: 10m by 10m'/>
 78                 <field name='originLabeltype='MFStringaccessType='inputOutput'/>
 79                 <field name='WestLabeltype='MFStringaccessType='inputOutput'
                appinfo='-X axis'/>
 80                 <field name='NorthWestLabeltype='MFStringaccessType='inputOutput'/>
 81                 <field name='NorthLabeltype='MFStringaccessType='inputOutput'
                appinfo='-Z axis'/>
 82                 <field name='NorthEastLabeltype='MFStringaccessType='inputOutput'/>
 83                 <field name='EastLabeltype='MFStringaccessType='inputOutput'
                appinfo='+X axis'/>
 84                 <field name='SouthEastLabeltype='MFStringaccessType='inputOutput'/>
 85                 <field name='SouthLabeltype='MFStringaccessType='inputOutput'
                appinfo='+Z axis'/>
 86                 <field name='SouthWestLabeltype='MFStringaccessType='inputOutput'/>
 87                 <field name='labelsOffsettype='SFVec3faccessType='inputOutput'
                appinfo='label location offset (in meters) to improve readability'/>
 88            </ExternProtoDeclare>
 89            <ExternProtoDeclare name='SeaWebBuoy'   url=' "../../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" '>
 90                 <field name='set_positiontype='SFVec3faccessType='inputOnly'
                appinfo='Position of buoy.'/>
 91                 <field name='positiontype='SFVec3faccessType='initializeOnly'
                appinfo='Position of buoy.'/>
 92                 <field name='set_targetPositiontype='SFVec3faccessType='inputOnly'
                appinfo='Position of target of transmission.'/>
 93                 <field name='targetPositiontype='SFVec3faccessType='initializeOnly'
                appinfo='Position of target of transmission.'/>
 94                 <field name='targetIdNumbertype='SFInt32accessType='initializeOnly'
                appinfo='Id number of target.'/>
 95                 <field name='set_targetIdNumbertype='SFInt32accessType='inputOnly'
                appinfo='Id number of target.'/>
 96                 <field name='set_enabledtype='SFBoolaccessType='inputOnly'
                appinfo='Enable buoy for transmission.'/>
 97                 <field name='enabledtype='SFBoolaccessType='initializeOnly'
                appinfo='Enable buoy for transmission.'/>
 98                 <field name='set_activatedtype='SFBoolaccessType='inputOnly'
                appinfo='Start transmission.'/>
 99                 <field name='activatedtype='SFBoolaccessType='initializeOnly'
                appinfo='Start transmission.'/>
100                 <field name='set_transmissionDurationtype='SFFloataccessType='inputOnly'
                appinfo='Duration in seconds needed to transmit message (does not include transmissionTimeDelay or propagation delay).'/>
101                 <field name='transmissionDurationtype='SFFloataccessType='initializeOnly'
                appinfo='Duration in seconds needed to transmit message (does not include transmissionTimeDelay or propagation delay).'/>
102                 <field name='transmissionTimeDelaytype='SFTimeaccessType='initializeOnly'
                appinfo='Time delay before transmission begins.'/>
103                 <field name='set_transmissionTimeDelaytype='SFTimeaccessType='inputOnly'
                appinfo='Time delay before transmission begins.'/>
104                 <field name='set_directionalTransmissiontype='SFBoolaccessType='inputOnly'
                appinfo='Select between directional (true) or omni-directional (false) transmission.'/>
105                 <field name='directionalTransmissiontype='SFBoolaccessType='initializeOnly'
                appinfo='Select between directional (true) or omni-directional (false) transmission.'/>
106                 <field name='set_buoyTypetype='SFStringaccessType='inputOnly'
                appinfo='Determine which buoy type to use. "Racom" for Racom Buoy. "Telesonar" for Telesonar Repeater.'/>
107                 <field name='buoyTypetype='SFStringaccessType='initializeOnly'
                appinfo='Determine which buoy type to use. "Racom" for Racom Buoy. "Telesonar" for Telesonar Repeater.'/>
108                 <field name='set_textMessagetype='MFStringaccessType='inputOnly'/>
109                 <field name='textMessagetype='MFStringaccessType='initializeOnly'/>
110                 <field name='textMessageColortype='SFColoraccessType='inputOutput'/>
111                 <field name='set_descriptiontype='SFStringaccessType='inputOnly'/>
112                 <field name='descriptiontype='SFStringaccessType='initializeOnly'/>
113                 <field name='traceEnabledtype='SFBoolaccessType='initializeOnly'/>
114                 <field name='set_soundSpeedInWatertype='SFFloataccessType='inputOnly'
                appinfo='Sound speed in water default value 1500 m/s'/>
115                 <field name='soundSpeedInWatertype='SFFloataccessType='initializeOnly'
                appinfo='Sound speed in water default value 1500 m/s'/>
116            </ExternProtoDeclare>
117            <ExternProtoDeclare name='ViewPositionOrientationappinfo='ViewPositionOrientation prototype provides local position and orientation as user navigates with optional console output'   url=' "../../../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" '>
118                 <field name='enabledtype='SFBoolaccessType='inputOutput'
                appinfo='Whether or not ViewPositionOrientation sends output to console.'/>
119                 <field name='traceEnabledtype='SFBoolaccessType='initializeOnly'
                appinfo='Output internal trace messages for debugging this node - developer use only can be ignored.'/>
120                 <field name='set_traceEnabledtype='SFBoolaccessType='inputOnly'
                appinfo='Ability to turn output tracing on/off at runtime.'/>
121                 <field name='position_changedtype='SFVec3faccessType='outputOnly'
                appinfo='Output local position.'/>
122                 <field name='orientation_changedtype='SFRotationaccessType='outputOnly'
                appinfo='Output local orientation.'/>
123                 <field name='outputViewpointStringtype='MFStringaccessType='outputOnly'
                appinfo='MFString value of new Viewpoint for example: <Viewpoint position="20 15 20" orientation="-0.516 0.83 0.212 0.9195"/>'/>
124            </ExternProtoDeclare>
125            <ExternProtoDeclare name='WaypointInterpolatorappinfo='Reads waypoints and legSpeeds/legDurations/defaultSpeed to provide a customizable position/orientation interpolator.'   url=' "../../../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" '>
126                 <!-- Priority of use: legSpeeds (m/sec), legDurations (seconds), defaultSpeed (m/sec) -->
127                 <field name='descriptiontype='SFStringaccessType='initializeOnly'
                appinfo='Short description of what is animated by this WaypointInterpolator.'/>
128                 <field name='waypointstype='MFVec3faccessType='initializeOnly'
                appinfo='Waypoints being traversed with interpolation of intermediate positions and orientations.'/>
129                 <field name='add_waypointtype='SFVec3faccessType='inputOnly'
                appinfo='Add another single waypoint to array of waypoints recalculate interpolator values.'/>
130                 <field name='set_waypointstype='MFVec3faccessType='inputOnly'
                appinfo='Replace all waypoints recalculate interpolator values.'/>
131                 <field name='pitchUpDownForVerticalWaypointstype='SFBoolaccessType='initializeOnly'
                appinfo='Whether to pitch child geometry (such as a vehicle) up or down to match vertical slope'/>
132                 <field name='legSpeedstype='MFFloataccessType='initializeOnly'
                appinfo='Units m/sec. If used array lengths for legSpeeds and legDurations must be one less than number of waypoints.'/>
133                 <field name='legDurationstype='MFTimeaccessType='initializeOnly'
                appinfo='Units in seconds. If used array lengths for legSpeeds and legDurations must be one less than number of waypoints.'/>
134                 <field name='defaultSpeedtype='SFFloataccessType='initializeOnly'
                appinfo='Units m/sec.'/>
135                 <field name='turningRatetype='SFFloataccessType='initializeOnly'
                appinfo='turningRate (degrees/second) also determines standoff distance prior to waypoint where turn commences. If 0 turns are instantaneous.'/>
136                 <field name='totalDurationtype='SFTimeaccessType='outputOnly'
                appinfo='Output calculation summing all leg durations, useful for setting TimeSensor cycleInterval. Units in seconds.'/>
137                 <!-- interpolation fields -->
138                 <field name='set_fractiontype='SFFloataccessType='inputOnly'
                appinfo='exposed PositionInterpolator and OrientationInterpolator setting'/>
139                 <field name='position_changedtype='SFVec3faccessType='outputOnly'
                appinfo='exposed PositionInterpolator setting'/>
140                 <field name='orientation_changedtype='SFRotationaccessType='outputOnly'
                appinfo='exposed OrientationInterpolator setting'/>
141                 <!-- display-related fields -->
142                 <field name='lineColortype='SFColoraccessType='inputOutput'
                appinfo='default color for non-active line segments'/>
143                 <field name='highlightSegmentColortype='SFColoraccessType='inputOutput'
                appinfo='active segment highlight color'/>
144                 <field name='transparencytype='SFFloataccessType='inputOutput'
                appinfo='1.0 is completely transparent, 0.0 is completely opaque.'/>
145                 <field name='labelDisplayModetype='SFStringaccessType='initializeOnly'
                appinfo='allowed values: none; waypoints (produce labels at each waypoint); or interpolation (produce single moving label at interpolator time course speed location)'/>
146                 <field name='heightLabeltype='SFStringaccessType='initializeOnly'
                appinfo='allowed values: altitude depth (negate Y value) none'/>
147                 <field name='labelOffsettype='SFVec3faccessType='initializeOnly'
                appinfo='heightLabel relative location'/>
148                 <field name='labelFontSizetype='SFFloataccessType='initializeOnly'
                appinfo='heightLabel text size'/>
149                 <field name='labelColortype='SFColoraccessType='initializeOnly'
                appinfo='heightLabel text color'/>
150                 <field name='traceEnabledtype='SFBoolaccessType='initializeOnly'
                appinfo='enable console output to trace script computations and prototype progress'/>
151                 <field name='outputInitializationComputationstype='SFBoolaccessType='initializeOnly'
                appinfo='Output the number of waypoints totalDistance and totalDuration to console upon initialization'/>
152                 <field name='verticalDropLineColortype='SFColoraccessType='inputOutput'
                appinfo='default color for vertical drop-line segments'/>
153                 <field name='verticalDropLineTransparencytype='SFFloataccessType='inputOutput'
                appinfo='1.0 is completely transparent, 0.0 is completely opaque.'/>
154            </ExternProtoDeclare>
155            <!-- ========== -->
156            <ProtoDeclare name='BuoyCommunicationsGridappinfo='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.'>
157                 <ProtoInterface>
158                      <field name='buoyArraytype='MFNodeaccessType='initializeOnly'
                     appinfo='array of SeaWebBuoy nodes index starting at 0'>
159                           <!-- Example: <ProtoInstance name='SeaWebBuoy' USE="SeaWebBuoy0"/> <ProtoInstance name='SeaWebBuoy' USE="SeaWebBuoy1"/> <ProtoInstance name='SeaWebBuoy' USE="SeaWebBuoy2"/> -->
160                      </field>
161                      <field name='buoyCommunicationsRoutingTabletype='MFInt32value='-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 -1accessType='initializeOnly'
                     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.'/>
162                      <field name='set_senderPositiontype='SFVec3faccessType='inputOnly'
                     appinfo='set position of entity sending the message'/>
163                      <field name='senderPositiontype='SFVec3fvalue='0 0 0accessType='initializeOnly'
                     appinfo='position of entity sending the message'/>
164                      <field name='set_receiverPositiontype='SFVec3faccessType='inputOnly'
                     appinfo='set position of entity receiving the message'/>
165                      <field name='receiverPositiontype='SFVec3fvalue='0 0 0accessType='initializeOnly'
                     appinfo='position of entity receiving the message'/>
166                      <field name='set_textMessagetype='MFStringaccessType='inputOnly'/>
167                      <field name='textMessagetype='MFStringaccessType='initializeOnly'/>
168                      <field name='sendMessagetype='SFBoolaccessType='inputOnly'
                     appinfo="send it! (note: maybe should rename as 'activate')"/>
169                 </ProtoInterface>
170                 <ProtoBody>
171                      <Script DEF='BuoyCommunicationsGridScriptdirectOutput='true'>
172                           <field name='buoyArraytype='MFNodeaccessType='initializeOnly'
                          appinfo='array of SeaWebBuoy nodes index starting at 0'>
173                                <!-- Example: <ProtoInstance name='SeaWebBuoy' USE="SeaWebBuoy0"/> <ProtoInstance name='SeaWebBuoy' USE="SeaWebBuoy1"/> <ProtoInstance name='SeaWebBuoy' USE="SeaWebBuoy2"/> -->
174                           </field>
175                           <field name='buoyCommunicationsRoutingTabletype='MFInt32accessType='initializeOnly'
                          appinfo='2D array of routing connectivity for buoys -1 for no connection range [0..n-1] for n buoys.'/>
176                           <field name='set_senderPositiontype='SFVec3faccessType='inputOnly'
                          appinfo='set position of entity sending the message'/>
177                           <field name='senderPositiontype='SFVec3faccessType='initializeOnly'
                          appinfo='position of entity sending the message'/>
178                           <field name='set_receiverPositiontype='SFVec3faccessType='inputOnly'
                          appinfo='set position of entity receiving the message'/>
179                           <field name='receiverPositiontype='SFVec3faccessType='initializeOnly'
                          appinfo='position of entity receiving the message'/>
180                           <field name='set_textMessagetype='MFStringaccessType='inputOnly'/>
181                           <field name='textMessagetype='MFStringaccessType='initializeOnly'/>
182                           <field name='sendMessagetype='SFBoolaccessType='inputOnly'
                          appinfo='send it!'/>
183                           <field name='traceEnabledtype='SFBoolvalue='trueaccessType='initializeOnly'/>
184                           <IS>
185                                <connect nodeField='buoyArrayprotoField='buoyArray'/>
186                                <connect nodeField='buoyCommunicationsRoutingTableprotoField='buoyCommunicationsRoutingTable'/>
187                                <connect nodeField='set_senderPositionprotoField='set_senderPosition'/>
188                                <connect nodeField='senderPositionprotoField='senderPosition'/>
189                                <connect nodeField='set_receiverPositionprotoField='set_receiverPosition'/>
190                                <connect nodeField='receiverPositionprotoField='receiverPosition'/>
191                                <connect nodeField='set_textMessageprotoField='set_textMessage'/>
192                                <connect nodeField='textMessageprotoField='textMessage'/>
193                                <connect nodeField='sendMessageprotoField='sendMessage'/>
194                           </IS>
  <![CDATA[
          
ecmascript:

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?
}

        
]]>
196                      </Script>
197                 </ProtoBody>
198            </ProtoDeclare>
199            <!-- ========== -->
200            <!-- Viewable geometry for this scene is anchored text that links to an example showing ExternProtoDeclare usage of a BuoyCommunicationsGridPrototype. -->
201            <WorldInfo info='"A BuoyCommunicationsGrid prototype"title='BuoyCommunicationsGridPrototype'/>
202            <Viewpoint description='BuoyCommunicationsGrid prototype definitionposition='0 0 15'/>
203            <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" '>
204                 <Shape>
205                      <Appearance>
206                           <Material diffuseColor='0 1 1emissiveColor='0 1 1'/>
207                      </Appearance>
208                      <Text string='"BuoyCommunicationsGridPrototype" "is a Prototype definition file." "" "To see an example scene" "click this text and view" "BuoyCommunicationsGridExample."'>
209                           <FontStyle justify='"MIDDLE" "MIDDLE"'/>
210                      </Text>
211                 </Shape>
212            </Anchor>
213       </Scene>
214  </X3D>
<!--

<!--
Event Graph ROUTE Table shows event connections.
-->

<!-- to top Index for DEF node: BuoyCommunicationsGridScript

Index for Viewpoint node: Viewpoint_1

Index for ExternProtoDeclare definitions: BeamCylinder, CameraCompass36, CrossHair, DvdController, GridXZ, SeaWebBuoy, ViewPositionOrientation, WaypointInterpolator

Index for ProtoDeclare definition: BuoyCommunicationsGrid
-->
X3D Tooltips element index: Anchor, Appearance, connect, ExternProtoDeclare, field, FontStyle, head, IS, Material, meta, ProtoBody, ProtoDeclare, ProtoInterface, Scene, Script, Shape, Text, Viewpoint, WorldInfo, X3D, accessType and type, XML data types, field types

-->
<!-- Online at
https://savage.nps.edu/Savage/CommunicationsAndSensors/SeaWeb/BuoyCommunicationsGridPrototypeIndex.html -->
<!-- Version control at
https://gitlab.nps.edu/Savage/Savage/CommunicationsAndSensors/SeaWeb/BuoyCommunicationsGridPrototype.x3d -->

<!-- Color legend: X3D terminology <X3dNode  DEF='idNamefield='value'/> matches XML terminology <XmlElement  DEF='idNameattribute='value'/>
(Light-blue background: event-based behavior node or statement) (Grey background inside box: inserted documentation) (Magenta background: X3D Extensibility)
    <ProtoDeclare name='ProtoName'> <field name='fieldName'/> ProtoDeclare> -->

to top <!-- For additional help information about X3D scenes, please see X3D Tooltips, X3D Resources, and X3D Scene Authoring Hints. -->