ANCHORLESS BOAT POSITIONING EMPLOYING GLOBAL POSITIONING SYSTEM

Abstract: An anchorless boat positioning system (20) dynamically and automatically maintains a boat (10) at a selected anchoring location within water without the use of a conventional anchor by using a steerable thruster (63) whose thrust and steering direction are determined on the basis of position information signals received from global positioning system (GPS) satellites (28) and heading indication signals from a magnetic compass (23). The anchorless positioning system (20) continuously monitors the position and heading of the boat (10) and compares it with the stored coordinates of the selected anchoring location to generate control signals for the steerable motor (63).

Description: ANCHORLESS BOAT POSITIONING EMPLOYING GLOBAL POSITIONING SYSTEM Background of the Invention This invention relates to an anchorless boat positioning system. Boat anchors have been used for thousands of years. The anchor is attached to the boat with a line or "rode" and then lowered overboard so that the flukes of the anchor dig into the water bottom. Problems exist, however, in using anchors in certain settings. The depth of the water may prohibit anchoring because the length of line needed to reach the water bottom is impractical. Moreover, even if the anchor reaches the water bottom, the depth of the water may be so great that it becomes difficult to maintain the anchored boat within close proximity to a desired position when varying wind or water currents are present. The line from the boat to the anchor acts as a tether allowing the boat, subject to the current and wind, to swing about an arc whose radius is nearly that of the length of the anchor line. In small craft, manually lowering and raising a conventional anchor is also strenuous and time consuming, plus there is always the possibility of the anchor becoming "fouled" on the bottom, a common aggravation for the skipper. Further, the use of anchors may be restricted in waters where, for example, underwater cabling has been installed (usually indicated on navigational charts) or where a salvage operation is taking place. The use of anchors which dig and plow has also come under criticism for causing severe damage to fragile underwater ecosystems. For example, anchors of fishing vessels have caused significant damage to long standing coral reefs, resulting in these areas being designated as "No Anchoring" areas. Summary of the Invention The invention allows a boat to be dynamically and automatically held in position at a selected anchoring location on the water without the use of a conventional anchor, line, or winch by controlling the thrust and steering of a thruster (e.g., trolling motor) attached to the boat. The thruster is controlled on the basis of signals received from global positioning system (GPS) satellites orbiting the earth and a digital magnetic compass mounted on the thruster. The signals from the GPS satellites provide an ongoing indication of the position of the boat in earth positional coordinates while the compass provides continuous heading indications of the thruster. With this information, a controller compares the positional coordinates of the selected anchoring location with the positional coordinates of the boat's current location and generates steering and thrust signals to the thruster to move the boat to the anchoring site. The global positioning system, available for use by both civilians and the military, is a multiple- satellite based radio positioning system, placed into orbit by The United States of America Department of Defense, in which each GPS satellite transmits data that allows a user to precisely measure the distance from selected ones of the GPS satellites to his antenna and to thereafter compute position, velocity, and time parameters to a high degree of accuracy, using known triangulation technigues. The signals provided by the GPS can be received worldwide twenty-four hours a day. The accuracy in determining the earth positional coordinates may be augmented through the use of a differential reference station for providing differential correction information (DGPS mode) to the receiver. In one general aspect of the invention, an anchorless boat positioning system for substantially maintaining the position of a boat at a desired location includes one or more thrusters attached to the boat for moving the boat to the selected location within the water, a GPS receiver receiving signals from GPS satellites for providing position information signals indicative of the position of the boat, a magnetic compass for providing a heading indication signal representative of the direction the thruster is pointed, and a controller (e.g. , computer) for providing control signals to control the magnitude and direction of the thrust of the thruster on the basis of the position information signals from the GPS receiver and the heading indication signal from the magnetic compass. Embodiments of the invention may include one or more of the following features. The control signals are based on the range, rate of change in range, and bearing from the present location of the boat to the selected anchoring location. A single thruster, fully rotatable about a vertical axis extending from above the surface of the water to below the surface of the water and transverse to the direction of propulsion of the thruster, is used to maintain the position of the boat. The control signals include thrust control signals for varying the amount of thrust generated by the thruster and steering control signals for controlling the direction of the thruster is pointing. The thruster is typically attached to the bow of the boat. The anchorless positioning system may include a GPS reference receiver positioned at a known location different from the position of the GPS receiver aboard the boat, with the GPS receiver on board the boat receiving signals from both the GPS reference receiver and the GPS satellites to provide position information signals in differential GPS mode, a technique for improving the accuracy in determining earth positional coordinates. The magnetic compass provides a heading indication signal representative of the heading of the thruster. The control signals relate to the difference between a present position and a selected location. A first non-rotatable thruster may be used for providing thrust in a direction along a long axis of the boat and a second non-rotatable thruster for providing thrust in a direction transverse to that of the first non-rotatable thruster may be used to maintain the heading of the boat toward the selected anchor location. The controller provides thrust control signals to the first non-rotatable thruster and steering control signals to the second non-rotatable thruster. An additional thruster may be positioned at the stern of the boat to assist in propelling the boat in the direction of the boat's heading. In another aspect of the invention a method of substantially maintaining a position of a boat at a selected location in water includes receiving and storing position information signals from GPS satellites with a GPS receiver to establish positional coordinates of a selected anchoring location; receiving, after a predetermined period of time, position information signals from the GPS satellites with the GPS receiver to determine a present location of the boat and a present heading indication of the thruster from the magnetic compass; and controlling the magnitude and direction of the thrust of at least one thruster on the basis of the difference between the positional coordinates of the anchoring location and the present location. The method may also include one or more of the following steps. Controlling the thruster includes determining the range, rate of change in the range, and bearing from the present location of the boat to the preselected anchoring location. A separate magnetic compass may be used to provide a heading indication of the boat, independent to that of the heading of the thruster, at the selected anchoring location, for maintaining the heading of the boat at the selected anchoring location. The method may also include receiving position correcting information signals from various sources including a reference GPS receiver positioned at a known location different from the position of the boat. In operation, the boat operator, upon reaching a desired location, merely presses a button on the console of the boat to establish the anchoring site coordinates. A receiver positioned on board the boat receives signals from GPS satellites orbiting the earth to accurately provide the latitude and longitude of the desired location. The differential GPS reference station may be located at a surveyed shore site. A controller uses the signals from the receiver and the reference station in conjunction with signals from a heading indicating compass mounted on the thruster, to generate control signals to point the thruster so that the boat maintains its position over the " desired location until the operator decides to move on. The use of the GPS system has advantages not seen with other radio navigation systems. For example, the LORAN land-based system is generally only effective for maritime applications where operation is along the coastline. Further, the LORAN system is subject to the errors caused by land masses and weather disturbances. The GPS system is the only source of accurate geographical position information having submeter accuracy and providing worldwide coverage to users. In fact, more recently, commercial services have become available for providing DGPS mode of operation to civilian users in areas remote from offshore reference stations. These commercial services use satellites (not part of the GPS system) to provide, at a price, differential correction signals from their satellites to improve the user's resolution in positioning. Although the system is generally intended for short duration situations (e.g., a few hours) the system may be used for longer periods while being properly monitored. Moreover, the anchorless boat positioning system may be used to complement good anchoring devices and practices. For example, in extreme weather and/or current conditions a conventional anchor may be required to maintain the position of the boat. Other advantages and features of the invention will be apparent from the following description and from the claims. Brief Description of the Drawing Figure 1 is a diagrammatic view of a boat having a thruster positioning motor mounted to the bow of the boat; Figure 2 is a block diagram illustrating the primary components of the anchorless boat positioning system; Figure 3 is a block diagram of an alternative version of the anchorless boat positioning system; Figure 4 is a diagrammatic sketch showing the repositioning of a floating boat in accordance with the invention; Figures 5A and 5B are flow diagrams for maintaining the position of the boat using the system of Figure 1; and Figure 6 is a top view of another embodiment of an anchorless boat positioning system. Description of the Preferred Embodiments Referring to Figure 1, a boat 10 is shown positioned over a school of fish 12, located, perhaps, using known fish-finding equipment aboard the boat. The operator of the boat, desiring to maintain this favorable fishing location 14 (designated by dashed line) , effectively "anchors" the boat by pressing a button located on the operator console. The anchorless positioning system 20 (Fig. 2) determines the earth positional coordinates of the selected location from global positioning system signals received by a GPS antenna 22 and stores the coordinates. As the boat begins to drift from location 14 (Fig. 4) , the anchorless positioning system continuously receives positional information from receiver 26 (Fig. 2) and heading information from digital compass 23 to generate signals for controlling the thrust and direction of thruster 24 to maintain the bow of the boat at essentially location 14. Trolling motor 24 is preferably mounted at the bow of boat 10 which generally has a more streamlined and contoured design for minimizing resistance as it moves through the water. Thus, when anchored at the bow, the boat is more easily aligned with forces caused by changing currents and winds and can better deflect these disturbing forces. Moreover, the stern of the boat is left free for other activities (e.g., fishing, working, or diving) by the operators and passengers. Referring to the block diagram of Figure 2, the anchorless positioning system 20 includes a differential global positioning satellite (DGPS) receiver 26 located aboard boat 10 for receiving, with antenna 22, coarse acquisition code (C/A-code) signals transmitted at a frequency of 1575.42 MHz from orbiting GPS satellites 28. C/A-code is also often referred to as civilian accuracy code to distinguish it from the longer P-code which provides higher position resolution but is restricted for use by the Department of Defense. Receiver 26 is a Model XR-4G Ver. 2.15 receiver, manufactured by Navstar Ltd., Daventry, Northants, England. The navigation processing and memory functions performed by DGPS receiver 26 include satellite orbit calculations and satellite selection, atmospheric delay correction calculations, navigation solution computation, clock bias and rate estimates, computation of output information, and coordinate conversion of the position information. The accuracy in calculating the position, time and velocity parameters by receiver 26 is significantly improved using differential GPS (DGPS) techniques. This technique involves the use of a DGPS reference station 30 operating at a surveyed location, generally onshore. Reference station 30 includes a DGPS reference receiver 32, which may be of the same type as receiver 26, for receiving signals from satellites 28 and computing satellite pseudo range correction data using prior knowledge of the correct satellite pseudo ranges. The satellite pseudo range correction data is converted to radio frequency shift modulated signals with reference station modem 34 and then broadcast to users within communication range in the same geographic area with transmitter 36 over a radio digital data link 38. The radio frequency shift modulated signals are in the HF, VHF or UHF frequency bands. The pseudo range corrections are received by a radio frequency receiver 40 aboard boat 10 and demodulated with modem 42 as digital data. The digital data is provided to DGPS receiver 26 over a data line 44 (1200-9600 baud) in Radio Technical Committee Maritime format (RTCM 104) for incorporation into the calculation of the navigation solution and to correct for the observed satellite pseudo range measurements, thereby improving the accuracy of the position determination to within 2-5 meters or better. The accuracy of the position determination is on the order of 2 to 5 meters for the initial embodiment and can be sub-meter with more sophisticated DGPS receivers. Correlation of the errors experienced at reference station 30 and at the user location 14 is minimal for a user within 100 kilometers of the reference station. Another factor affecting the accuracy of the computed position and velocity parameters is the positional geometry of the satellites selected for measurement of ranges. Generally, the best position solution is obtained using satellites having wide angles of separation. One satellite near the zenith with three others just above the horizon at a 120 degree azimuth separation generally provide the best achievable satellite geometry. DGPS receiver 26 includes an RF assembly for mixing the 1575.42 MHz GPS signal down to a convenient IF frequency and then, using techniques well known in the art, tracking the pseudo random code (PRN) code used to modulate the signal through code-correlation to measure the time of transmission of the signals from the satellite. The signal may also be measured through a carrier tracking loop. Combined code correlation and carrier tracking function can be performed using either analog or digital processing. The control of. the code and carrier tracking loops is provided by a DGPS processor within receiver 26. By differencing this measurement with the time of reception, as determined by a clock in receiver 26, the pseudo range between the receiver and the satellite being tracked is determined. This pseudo range includes both the range to the satellite and the offset of the receiver's clock from the GPS master time reference. The pseudo range measurements and navigation data from four satellites are used to accurately compute the latitude and longitude position of the bow mounted GPS antenna in a selected geographic coordinate system. The boat's bow position data is then provided as a navigational message over data line 46 (1200 baud) to a system interface module 48. The navigational messages are provided in standard National Marine Electronics Association (NMEA) format. Similarly, NMEA formatted signals from a digital flux gate compass 23 indicating the trolling motor's heading are provided over data line 50 (4800 baud) to interface module 48. Digital compass 23 is a programmable Azimuth Model C100 compass, available from KVH Industries, Inc., Middletown, RI, which includes the feature of automatically converting the magnetic heading to the true digital heading. Interface module 48 passes the signals from DGPS receiver 26 and compass 23, via RS-232 serial data lines 54, 56 to a computer 58, an IBM compatible personal computer having dual serial ports and a parallel printer port. Note that the positional and heading signals from DGPS receiver 28 and compass 23, respectively, may have been provided directly to computer 58; however, because interface module 48 provides power supply signals to both receiver 28 and compass 23, passing the positional and heading signals through interface module 48 simplifies the wiring between the components. Computer 58 uses the positional and heading information to calculate range and bearing data for moving the boat toward the desired anchoring site. More specifically, the range and the rate of change of the range are calculated in the form of digital thruster power signals while the heading and bearing information are used to calculate digital thruster steering signals. The digital thruster power signals are sent back, via data line 59, to interface module 48 over the parallel printer port of computer 58 where they are converted using D/A converters into analog signals for driving a bow thruster motor 24. Digital thruster steering signals are similarly converted by interface module 48 and provided to steering servo 60 which controls the steering direction of motor 24. Bow thruster motor 24 is a commercially available trolling motor, Model 812 Turbo Pro A, manufactured by MinnKota Electric Fishing Motors, Mankota, MN, which has been modified by adding a slip- ring assembly 62, Model AC4023, available from Litton Poly-Scientific, Blacksburg, VA. Slip-ring assembly 62 allows motor 24 to fully rotate about the axis of a shaft 63 which connects the steering servo 60 to the thruster motor while maintaining the electrical connection between the motor and the power source. The built-in compass auto pilot in the Model 812 trolling motor is not used. The use of computer 58 provides the operator with a large degree of flexibility in receiving signals and generating signals in various formats and for different types of motors depending on, for example, the size of the boat. In a preferred embodiment, however, shown in Fig. 3, interface module 48 and computer 58 can be replaced with a system controller 70 and associated propeller controller circuits 72, 74. Certain commercially available programmable microcomputer controllers used in industrial process applications may be used for this application. Similarly, off-the-shelf circuits which provide digital/analog conversion may be used for propeller controller circuits 72, 74. It is appreciated that one of skill in the art, would be able to select suitable circuitry to fulfill the system requirements. Controller 70 uses the positional and heading information provided from receiver 26 and compass 23, respectively, to calculate range and bearing data in the form of thruster power and steering signals. Switches 76 connected to controller 70 offer the operator the ability to switch between several different modes of operation that are generally dependent on the size of the boat and thruster ., as well as prevailing sea conditions. The size of the boat influences the magnitude and duration of thrust signals needed to initiate movement of the boat and to compensate for the momentum once the boat has started moving. Others characteristics related to the physical configuration of the boat such as, for example, the hull displacement, hull drag coefficient, and wetted hull surface area of the boat also effect the mode of operation chosen. Sea conditions, such as, wind and water currents, are also a large variable effecting the mode of operation selected. Referring to the diagram of Figure 4 and the flow diagrams of Figures 5A and 5B, the operation of the anchorless positioning system is described. The operator of boat 10 having selected anchor site 14 as his desired anchor position simply depresses a button switch located on the console within the cabin to activate the system. A computer program written in Turbo C ++ Programming Language, a product of Borland International, Inc. , Scotts Valley, CA, uses information provided from receiver 26 and compass 23 to generate signals for controlling motor 24. Source code software for implementing the system is included as a microfiche appendix. The program includes a buffer which is continuously updated with the present position of the boat, even when the boat is not anchored. When the operator selects a desired anchoring position, the positional data in the buffer is stored (100) . Further, the program includes a subroutine READ KEYS (110) to constantly monitor the state of the switch (111) . Because button switches are used to both activate and deactivate the system, subroutine READ KEYS uses an anchor flag to constantly monitor whether the system is in an activated or deactivated state (112) . If the anchor flag has not been previously set (anchor position not established) the anchor flag is set (114) . On the other hand, if the flag has previously been set, subroutine READ KEYS determines (116) whether the anchor position is to be maintained, whereupon it returns (118) to the main program loop, or if the system is to be deactivated the anchor flag is reset (119) . In this example, as shown in Figure 4, the system anchor flag is set to establish the position of boat 10 at anchor site 14. Because anchorless positioning system continuously monitors the boat's position every second, the allowed amount of drift from anchor site 14 would normally be small. In order to better describe the system's operation, however, it is assumed that the boat has drifted an exaggerated distance from anchor site 14 to a position A. Receiver 26 monitors, in one second intervals, the boat's current differential GPS latitudinal and longitudinal position and generates the navigational messages to computer 58. The latitudinal and longitudinal position information is provided with resolution where each minute (1/60 of a degree) is expressed to four decimal places. If the anchor flag has been set (120) the program computes the range 80 (the distance between boat 10 and anchoring site 14) and bearing 82 (the direction to the anchoring site with respect to direction north) . Using the DGPS coordinates of the anchor site stored in the computer's memory and the DGPS coordinates of the present position of the boat (122) . The rate of the change of range is also calculated to determine the proper thrust of the motor in proportion to the velocity of the boat. In this way, a steadier and more uniform movement toward the anchor site is achieved. An alarm, preferably an audible signal, is activated to alert the operator that a malfunction in the system prevents the anchorless positioning system from properly maintaining the anchor site (124) . The angular difference between the heading of the trolling motor and magnetic north, referred to as the thruster heading 84 is measured at one tenth of a second intervals using compass 23 (126) with an accuracy of ± 1 degree and sent as navigation messages to computer 58. The program calculates the steering error 86 (118) using the thruster heading 84 and the bearing 82 to anchoring site 14 and generates steering signals (130) for driving servo 60 (Fig. 3) which rotates motor 24 and redirects boat 10 toward anchor site 14. The program then uses the range and rate of change of range information to generate the thrust signals (132) to control the amount of thrust driving 24 (134) . The steering and thruster output signals are generated at one second intervals to progressively close in from position A to position B and on to position C, the desired anchoring position established by the operator. In this embodiment, motor 24 is a variable speed motor that is modulated to vary the magnitude of the thrust applied by the motor. The program provides fifteen incremental levels of increasing thrust. In this example, the selected anchoring location is defined only by the positional data received by GPS receiver 26, with the boat eventually becoming positioned by the wind and sea currents with its bow pointed in opposition to the disturbing forces. However, it is appreciated that in certain situations, (e.g., mooring) it may be desired to fix the orientation of the boat at the selected anchoring site. In these circumstances, the desired heading of the boat is indicated by a separate digital magnetic compass and is stored at the time the anchoring location is established so that the program provides thrust control and steering control signals which maintain not only the position but also the heading of the boat. In this way, the boat's stern is not allowed to freely rotate about the anchoring location. When it is desired to "pick up anchor" and move on, the operator simply depresses a button switch to reset the anchor flag. A second small electric motor mounted perpendicular to the keel, controlled directly by a magnetic compass, may be attached to the stern of the boat to provide small bursts of thrust, forward or reverse, in the heading direction to help in maintaining the heading of the boat. Because a tendency exists for the boat to "fishtail" as the motor 24 works to maintain the bow position at the anchoring location, this second motor provides a right or left force to maintain the boat's heading, thereby minimizing the fishtail effect and reducing drift. Referring to Fig. 6, a variation of the anchorless positioning system uses a pair of non-rotating thruster motors 90, 92 fixed in stationary alignment to the bow of the boat. More particularly, motor 90 is positioned to propel the boat in a .direction along the long axis of the boat with thruster motor 92 positioned transverse to that of motor 90. The amount of thrust generated by each of the motors is controlled by signals provided by the system controller so that thruster motor 90 controls the boat's heading to maintain its alignment with the anchor site, while thruster motor 92 propels the boat to the anchor site. In other embodiments, steerable thrusters or motors, of the type described above in conjunction with Figures 1-5, may be positioned at both the bow and stern of the boat to provide anchoring while preventing rotation of the boat. Using such an arrangement allows, for example, anchorless mooring of the boat at a pier without the use of cables. Each thruster may be associated with its own GPS receiver or may use a single receiver on a time-sharing basis. Alternatively, the system may be used in conjunction with an angular resolver so that the position of the stern is in a fixed relationship with the position of the thruster motor at the bow. Other variations and modifications are within the scope of the following claims. For example, on larger vessels, with larger drift inducements, the main propulsion system of the vessel may be utilized to provide part of the correcting force needed. In other words, when the heading of the boat is substantially that of the heading of the thruster, the main propulsion motor of the vessel provides assistance, in a complementary fashion, in propelling the boat toward the desired anchoring location. A portion of the disclosure of this patent document contains material which is subjected to copyright protection. • The copyright owner has no objection to the facsimile reproduction by anyone of the patent document or patent disclosure, as it appears in the Patent and Trademark Office file or records, but otherwise reserves all copyright rights whatsoever. What is claimed is: D:\TC\GLEN\GLENS5G.CPP //GLENSδg.CPP //A program to read DGPS receiver position data and Magnetic Compass data //via Serial ports 1 and 2 of an IBM AT compatible computer.... //and to calculate range and bearing to target location. //The program also generates steering and thruster commands via the parallel printer po //and requires a simple custom Interface (D to A) Box to interpret those outputs. //copyright 1993 and 1994 John L. Webster of Hoist-Webster Enterprises //9606 Todd Mill Rd. Huntsville, Alabama 35803-1108. char version[10] = " Ver.5G"; tinclude <stdio.h> tinclude <conio.h> tinclude <time.h> tinclude <stdlib.h> tinclude <math.h> tinclude <string.h> tinelude "sernewO2.hp " serialobject Serial; tdefine DIST 111296.139 //meters per degree longitude at equator tdefine RIGHT 1 tdefine LEFT -1 tdefine NONE 0 tdefine THRUSTON 1 tdefine THRUSTOFF 0 tdefine PARPORT 0x378 //Parallel Printer Port Address //SYSTEM VARIABLES clock_t startsteer.presenttime; //LONG INTEGERS ?????? char KVHmsg[40]; char GPSmsg[125]; extern int outpl_index; extern int outp2_index; char msgl[1000]; char msg2[1000]; //FLAGS USED int Anchorflag = 0; int KVHmsgflag; int GPsmsgflag; int NFflag; -18- int Logflag; int turnmotor =1; int lasttime =0; int trialptr=0; int outval; float loginterval; char logfilename[30]; char rangetxt[10]; char bearingtxt[10]; char serfilename[20]="serSETUP.DAT"; char tcfilename[20]="testcond.dat"; char trialtxt[200]; char mytextflOO] ; char UTCtxt[8] ="240000"; char KVHhdg[6] = "270.5"; char lonlastfix[15] = "08232.3510W"; char latlastfix[15] = "2719.3430N"; char fixtxt[3] ="NF"; char lonanchor[15] = "08232.3510W"; char latanchor[15] = "2719.3430N"; float deglatLF; float deglonLF; float latLFdeg; float lonLFdeg; float lonANCHdeg; float latANCHdeg; float brg; float hdg; float rangerate; float range; float delrange; int steerror; int turnmask; int thistime; int thrust; int power; int deltime; //SERIAL SETUP STRUCTURE struct sersetup { char KVHPorttxt[5]; char GPSPorttxt[5]; char MousePorttxt[5]; char KVHbaudtxt[5] ; char GPSbaudtxt[5]; }sersetup; //SERIAL PORT DEFAULT SETTINGS char *KVHPorttxt ="1"; char *GPSPorttxt ="2"; char *MousePorttxt="3"; char *KVHbaudtxt="4800" , char *GPSbaudtxt=" 1200" ; int KVHPort = atoi(sersetup.KVHPorttxt) ; int GPSPort = atoi(sersetup.GPSPorttxt) ; int MousePort=atoi(sersetup.MousePorttxt) ; int KVHbaud = atoi(sersetup.KVHbaudtxt) ; int GPSbaud = atoi(sersetup.GPSbaudtxt) ; struct testsetup { char Kltxt[5]; char 2txt[5]; char MinRangetxt[5]; char steerDeadBandtxt[5]; char ThrustAngletxt[5]; char TurnRatetxt[3] ; }testsetup; //DEFAULT SETTINGS char *Kltxt ="1.00"; char *K2txt ="25.00"; char *MinRangetxt="1.0"; char *SteerDeadBandtxt="10"; char *ThrustAngletxt="30"; char *TurnRatetxt="60"; float Kl = atof(testsetup.Kltxt); float K2 = atof( estsetup.K2txt) ; float MinRange=atof(testsetup.MinRangetxt) ; float steerDeadBand = atof(testsetup.SteerDeadBandtxt) ; float ThrustAngle = atof(testsetup. hrustAngletxt) ; int TURNRATE = atoi(testsetup.TurnRatetxt); /************************** Border(sx,sy,ex,ex, attr) *******************/ /* creates a non-graphic border around a text window */ /* this should be under a windows object class */ void Border(int startx, int starty, int endx, int endy, int attr) { int j; textattr(attr) ; window(l,1,80,25) ; gotoxy(startx,starty) ; putch(0xC9); /* top left corner */ gotoxy(endx, starty); putch(OxBB); /*top right corner*/ gotoxy(s artx+1, starty) ; for(j =startx+l; j <= endx-1; j++) { gotoxy(j,starty) ; putch(OxCD); /* top border */ gotoxy(j, endy) ; putch(Oxcd); /* bottom border */ } gotoxy(startx, endy); putch(OxCβ); /* bottom left corner */ if( endy 1= 25) { gotoxy(endx,endy) ; putch(OxBC) ; } /* bot right */ for ( j = starty+1 ; _ <= endy-1 ; j++) { gotoxy(startx, j) ; putch(OxBA); /* left side border */ gotoxy(end , j); putch(OxBA); /* right side border */ } /********************** screen display windows ********************/ void winl() // GPS receive window { window( 2, 5, 78, 10); textattr(BLUE *16 | CYAN); } void win2() // KVH receive window { window( 2, 13, 20, 13); textattr(BLUE *16] WHITE); } void win4() // output data display window { window( 2, 18, 78, 21); textattr(CYAN *16 | BLACK); } void win5() // transmit window { window( 2, 24, 78, 24); textattr(BLUE *16 | YELLOW); } void win6() //Anchor site window { window(23,13,49,15) ; textattr(CYAN *16 | BLACK); } void win7() //Fix status window { window(52,13,79,13);textattr(BLUE *16 | LIGHTGRAY); } void win8() //debugging data display { window(2,16,79,16) ;textattr(CYAN *16| BLACK);} void win9() { window(2,10,79,12);textattr(CYAN *16j BLACK);} void winl0() { windo (2,15,19,15);textattr(BLUE *16| LIGHTGRA );} void winll( ) { window(2,16,19,16);textattr(BLUE *16| LIGHTGRAY);} void winl2() //timer window { window(52,15,79,16); textattr(BLUE*16I LIGHTGRAY);} void winl3() //log file name window { window(25,16,51,16); textattr(BLUE *16| LIGHTGRAY);} /******************************* make win() **************************/ void make_win( ) { int attr; // create menu window attr = (BLACK *16 I WHITE); textattr(attr); Border(l,1,80,3,attr) ; textattr(BLACK *16 I YELLOW); gotoxy(20,l) ; cpn..-.f("Rhodan Marine Electronic Virtual Λ-ichor"); cprintf("%s",version) ; window(2,2,79,2) ; clrscrf); // create window winl for GPS port receive data attr = (BLUE *16 I LIGHTGRAY); textattr(attr); Border(l, 4, 80, 11, attr); gotoxy(20, ); cprintf(" GPS Port %d Re •d. Data ",GPSPort) ; window(2,5,79,10) ; clrscr(); // create window win2 for KVH port receive data attr = (BLUE *16 I LIGHTGRAY); Border(1, 12, 21, 14, attr); gotoxy(5,12); cprintf(" KVH Port %d",KVHPort) ; window(2,13,20,13) ; clrscr(); // create window win4 for output Data attr = (CYAN *16 I BLACK); Border(1,17,80,22,attr) ; gotoxy(37,17); cprintf(" Output Data "); window(2,18,79,21) ; clrscr(); // create window win5 for transmit data attr = (BLUE *16 I LIGHTGRAY); Border(l,23,80,25,attr) ; gotoxy(20,23) ; cprintf(" KVH Port KB Data "); window(2,24,79,24) ; clrscr(); // create window winβ for Anchor Location display attr = (CYAN *16I BLACK); Border(22,12,50,15,attr) ; gotoxy(27,12); cprintf(" Anchor Site "); window(23,13,49,14) ; clrscr(); //create window win7 for Fix status Display attr = (BLUE *16ILIGHTGRAY); Border(51,12,80,14,attr) ; gotoxy(60,12); cprintf(" Fix Status ") ; window(52,13,79,13) ; clrscr(); } /************************** menu () *************************/ void menu() { window(2,2,79,2) ; textattr(LIGHTGRAY *16j BLACK); gotoxy(l,l); cprintf("Fl AnchorI") ; gotoxy(12,1); cprintf("F3 Cut Anchor"); gotoxy(28,1); cprintf("F4 LOG •• ) ; gotoxy(40,1) ; cprintf("F5 KB site"); gotoxy(55,1) ; cprintf("F8 KB Coef.s"); gotoxy(70,1); cprintf("F10 Quit"); } /********************************************************/ void loadsetup() { int i,j; FILE *fp; if( 1 (fp = fopen(serfilename, "r") ) ) { cprintf("CANNOT FIND %s FILE I\n\r",serfilename) ; cprintf("Will use default settings.\n\r") ; //delay(1500) ; return; } fread(&sersetup,sizeof(sersetup) ,l,fp) ; fclose(fp) ; //transfer values read from file KVHPort = atoi(sersetup.KVHPorttxt) ; GPSPort = atoi(sersetup.GPSPorttx ) ; MousePort = atoi(sersetup.MousePorttxt) ; KVHbaud = atoi(sersetu .KVHbaudtx ) ; GPSbaud = atoi(sersetup.GPSbaudtxt) ; } /*********************** loadtestcond( ) ****************************/ //THIS MODULE LOOKS FOR THE testCOnd.DAT FILE AND LOADS IT'S DATA, void loadtestcond() { int i,j; FILE *fp; if( 1 (fp = fopen(tcfilename,"r") ) ) { cprintf("CANNOT FIND %s FILE I\n\r",tcfilename); cprintf("Will use default settings.\n\r") ; delay(2000) ; return; } fread(&testsetup,sizeof(testsetup) ,l,fp); fclose(fp) ; //transfer values read from file Kl = atof(testsetup.Kltxt) ; K2 = atof(testsetup.K2txt) ; MinRange=atof(testsetup.MinRangetxt) ; SteerDeadBand = atof(testsetup.SteerDeadBandtxt) ; ThrustAngle = atof(testsetup.ThrustAngletxt) ; TURNRATE = atoi(testsetup.TurnRatetxt) ; /******************************* savegpsdata( ) *******************/ void savegpsdata( ) { FILE *fp ; //strcpy(GPSmsg,"This is a test!"); if( (fp=fopen(logfilename, "at")) == NULL) { cprintf("CANNOT OPEN %s FILEI\n\r",logfilename) ; return; } fprintf(fp,"%s",GPSmsg) ; //+5 will cut off ID & 1st. comma //Keeping whole GPSmsg allows future use of parsing routine fprintf(fp,"%4.If & %4.If\n\r",range,brg) ; fclose(fp) ; } /******************************* chklogtimer ( ) **********************/ void chklogtimer() { float elapsed2; static float lasttime; float nowti e; nowtime=clock() ; elapsed2 = (nowtime - lasttime)/CLK_TCK; winl2() ; gotoxy(2,1) ;cprintf("lnterval=%4.2f",loginterval) ; gotoxy(2,2) ;cprintf("Elapsed=%4.2f",elapsed2) ; if(elapsed2 > loginterval) { savegpsdata() ; printf("%c",7); lasttime=nowtime; } } /****************************** logstat( ) *********************/ void logstat( ) { char temp[5]; if(Logflag==l) Logflag=0; else { winl() ; clrscr() ; gotoxy(2,2); printf("Enter Log File namel\n\r") ; gotoxy(2,3); gets(logfilename); if(strlen(logfilename)<1) strcpy(logfilename,"templog.dat") ; //default filename gotoxy(2,5); printf("Enter Log IntervalI\n\r") ; gotoxy(2,6); gets(temp); if(strlen(temp)<l) strcpy(temp,"30") ; //default interval clrscr( ) ; loginterval = atof(temp) ; Logflag=l; } clrscr ( ) ; } /************************* kbcoef() *************************/ //THIS MODULE IS INTENDED TO ALLOW EXPERIMENTAL MODIFICATION //OF THE THRUSTER GAIN COEFFICIENTS, void kbcoef() { int c; char temptext[10]; window(2,5,70,10) ; textattr( CYAN *16| YELLOW); top: clrscr(); gotoxy(5,1); cprintf("Kl=%4.2f K2=%4.2f\n\r",Kl,K2) ; gotoxy(5,2); cprintf("Enter new Kl\n\r"); gotoxy(5,3); gets(temptext) ; if(strlen( emptext)<1) strcpy(temptext,"1.00") ; Kl=atof(temptext) ; gotoxy(5,4); cprintf("Enter new K2\n\r"); gotoxy(5,5); gets(temptext); if(strlen(temptext)<1) strcpy(temptext,"25.00") ; K2=atof(temptext) ; gotoxy(5,6); cprintf("Kl=%4.2f K2=%4.2f\n\r ",Kl,K2); cprintf("Hit Enter to accept! or n or N to reject"); c=getche( ); if(c == • n' M c == • ' ) goto top; else { textattr(BLUE *16| YELLOW); clrscr(); } /************************* deg2gps ***************************/ float deg2gps(float deg) { int wholedeg; float remainder; float minutes; float gpsnumber; char gpstext[12] ; wholedeg = (int) deg; remainder= deg-wholedeg; minutes= remainder*60; //gpsnumber=( (int)deg*100) + minutes; gpsnumber=wholedeg*100+minutes; return gpsnumber; } /************************* gps2deg ***************************/ float gps2deg(char *gpstxtin) { int j,k,decimal; char temptxt[125]; char fractxt[6]; char degtxt[4]; char mintxt[3]; float tempval; float degpart; float minpart; float fracpart; //PARSE THE TEXT STRING FOR CONVERSION PROCESS strcpy(temptxt,gpstxtin) ; //LOCATE DECIMAL PLACE IN STRING for(j=0;j<9;j++) {if(temptxt[j]=='.' ) break;} decimal = j; //GET DEGREES PORTION OF TEXT if(decimal==4) { k=0; for (j=decimal-4;j<=decimal-3;j++) {degtxt[k]=temptxt[j]; k++;} degtxt[k]='\0'; } if(decimal==5) { k=0; for (j=decimal-5;j<=decimal-3;j++) {degtxt[k]=temptxt[j]; k++;} degtxt[k]='\0' ; } //GET MINUTES PORTION OF TEXT k=0; for (j=decimal-2;j<=decimal-l;j++) {mintx [k]=temptxt[j] ; k++;} mintxt[k]='\0'; //GET DECIMAL PORTION OF TEXT STRING k=0; for (j=decimal+l; j<=decimal+4;j++) {fractxt[k]=temptxt[j]; k++;} fractxt[k]='\0' ; degpart=atof(degtxt) ; minpart=atof(mintxt)/60; fracpart=atof(fractxt)/600000; tempval = degpart+minpart+fracpart; return tempval; /*★****************** tur ( in ) *************** * *************/ void turn(int direction) { switch(direction) { case RIGHT: turnmask=0x80; break; case LEFT: turnmask=0x40; break; case NONE: turnmask=0x00; break; default: turnmask=0x00; //no turn } // need to generate new output word based on turnmask.... } /******************* calcsteer( ) ******************************/ void calcsteer() { float turntime; float settletime=0.5; float elapsedl; static int busyturningflag; float busytime; if(TURNRATE==0) TURNRATE=60; steerror = brg-hdg; if(steerror < -180) steerror=steerror+360; if(steerror > +180) steerror=steerror-360; //FOLLOWING STATEMENT IS TO AVOID WRAPPING UP THE CABLES if(range <= MinRange) steerror=0; //Don't try to turn when we are at site! if(steerror > SteerDeadBand) turn(RIGHT); if(steerror < SteerDeadBand && steerror > -SteerDeadBand) turn(NONE); if(steerror < -SteerDeadBand) turn(LEFT); if(abs(steerror) > SteerDeadBand) { turntime = (float) steerror/TURNRATE; //FORCE turntime TO BE FLOAT VALUE if(turntime<0) turntime=turntime*(-1.0) ; //AVOID NEGATIVE TIME turntime =0.80 * turntime; //Go for 80% of calc'd. busytime = turntime + settletime; i (busyturningflag == 0) { startsteer = clock(); busyturningflag=l; } if (busyturningflag ■= 1 ) { presenttime = clock(); elapsedl = (float) (presenttime-startsteer)/CLK_TCK; //NOTE PRESENT TIME AND START STEER ARE LONG VALUES //ELAPSED IS A FLOAT if(elapsedl < turntime) turnmotor=l; if(elapsedl >= turntime) turnmotor=0; if(elapsedl >= busytime) busyturningflag = 0; } } /************************* calcrange ( ) *************************/ //Range is a function of latitude... //Northvec = k * delta lat //Eastvec = k * delta Ion * cosine(avg lat) //Hypot = Square root of( Northvec squared + Eastvec squared) //At equator 1 degree = 69.171 miles //69.171 * 1609 = 111296.139 meters/degree void calcrange() { float deltalon,deltalat,vector; float latrads; float cosdelon; float bearing; latANCHdeg = gps2deg(latanchor) ; lonANCHdeg = gps2deg(lonanchor) ; latLFdeg = gps2deg(latlastfix) ; lonLFdeg = gps2deg(lonlastfix) ; deltalat = latANCHdeg - latLFdeg; deltalon = lonLFdeg - lonANCHdeg; latrads = latANCHdeg/57.325; cosdelon= deltalon*cos(latrads); //NOTE COSDELON GOES TO 0 WHEN WE ARRIVE AT ANCHOR OR DELTALON=0 vector = hypot(cosdelon,deltalat) ; range = DIST * vector; if(range > 1000) range = 1000; //LIMIT FOR INSANITY NUMBERS //ARCSIN OF INFINITY GOES BERSERK SO TEST FOR ZERO VECTOR if(vector == 0) bearing = 0; else bearing=asin(cosdelon/vector) ; brg = (bearing * 57.325); //QUADRANT 2 NORTHWEST if(deltalat>0 && deltal--n<0) brg = brg+360; //DUE WEST SITUATION if(deltalat==0 & deltalon<0) brg = 270; //QUADRANT 3 SOUTH WEST if(deltalat <0 && deltalon <0) brg=180-brg; //QUADRANT 4 SOUTH EAST if(deltalat <0 && deltalon >0) brg=180-brg; //DUE SOUTH SITUATION if(deltalat <0 && deltalon==0) brg = 180; } /************************* calcthrust ( ) *************************/ void calcthrust() { static float oldrange; // WE NEED TO READ LASTFIX AND COMPUTE OUR OWN RANGE TO ANCHOR //DISTANCES ARE A FUNCTION OF LATITUDE //NOTE: THIS SECTION REQUIRES DATA FROM THE GPS SET.... // IT CAN GET GARBAGED IF USED WITH NO VALID GPS DATA.. thistime = atoi(UTCtxt+4) ; //THIS IS GPS TIME FROM GPS DATA! deltime = thistime - lasttime; if(deltime < 0) deltime = deltime + 60; if(deltime < 1) return; //THIS SHOULD NEVER OCCUR //don't do calculations if time elapsed less than 1 second. //if we had run this routine every loop lasttime will always equal thistime //and deltime will always be zero. //WE WILL ONLY CALC. THRUST ONCE PER SECOND if(oldrange != 0) delrange = oldrange - range; oldrange = range; rangerate = delrange/deltime; //delrange div. by deltime AND deltime = 1 //THE FOLLOWING ASSUMES RANGE IS ALWAYS A POSITIVE NUMBER if(range > MinRange && abs(steerror) < ThrustAngle) thrust=THRUSTON; else thrust=THRUSTOFF; power = (range * Kl - rangerate * K2); //LIMIT POWER TO OUR D/A RANGE OF 0 TO 15 if(power > 15) power = 15; if(power < 0) power = 0; lasttime = thistime; } /************************** genoutput() ******************/ void genoutput( ) { if(turnmotor == 1) { outval=outval & 0x3F; // clear the old turn bits outval=outval | turnmask; //set the appropriate turn bit } else outval= outval & 0x3f; //just clear turn bits if(thrust==l) { outval = outval | 0x20; // set thrust on! outval = outval & OxfO; // clear old power bits outval = outval | power; //set new power bits } else outval = outval & OxσO; if(Anchorflag==0) outval=0x00; //NO OUTPUT IF ANCHOR UP! if(NFflag) outval=0x00; //NO OUTPUT IF NO FIX! //send outval to parallel port outportb(PARPORT,outval); } /A************************ char *float2text(float) *********************/ //THIS ROUTINE CONVERTS A FLOAT VARIABLE INTO A STRING // WITH TWO DECIMAL PLACES char *float2text(float value) { int j; int decpnt,sign; char *temptext; //A STRING AT TEMPTEXT LENGTH ? char newtext[10]; //A STRING AT NEWTEXT 10 CHAR. LONG for(j=0;j<=strlen(temptext) ;j++) temptext[j]=•\0' ; for(j=0;j<=10;j++) newtext[j]=•\0' ; temptext = ecvt(value,4,&decpnt,&sign) ; if(sign 1= 0) strcpy(newtext,"-") ; strncat(newtext,temptext,decpnt) ; //COPY UP TO DECIMAL PLACE strncat(newtext,".",1); //INSERT DECIMAL POINT strncat(newtext,temptext+decpnt,2) ; //COPY TWO PLACES FOLLOWING DECIMAL strncat(newtext, '\0* ,1); return (newtext); //RETURN POINTER ADDRESS OF STRING } /it************************* display() ***********************/ //DISPLAY OUTPUT DATA void display() { winl0(); cprintf("Kl=%4.2f ",K1); winll(); cprintf("K2=%4.2f ",K2); winl3( ) ; cprintf("%s",logfilename) ; win () ; gotoxy(12,4); textattr(CYAN *16| BLACK); printf("Power = %d ",power); gotoxy(l,l); cprintf("Range = %5.2f meters ",range): gotoxy(l,2); cprintf("Speed = %5.2f m/s ",rangerate) ; gotoxy(l,3); printf("Bearing= %5.2f degrees ",brg); gotoxy(l,4); textattr(CYAN *16|BLACK) ; if(Ithrust) cprintf("Thrust Off"); else { textattr(CYAN *16 | RED) ; cprintf("Thrust on!") ; textattr(C AN *16 | BLACK) ; } gotoxy(30,1); //if<isdigit(UTCtxt[l]) ) cprintf("GPS time = %s",UTCtxt); cprintf("GPS time = %s",UTCtxt); gotoxy(30,2); cprintf("Thruster hdg = %5.2f ",hdg); gotoxy(30,3) ; cprintf("Steering error = %d ",steerror); cprintf("Turnmask = hex %x ",turnmask); gotoxy(30,4) ; cprintf("Output value = %d or hex %x ",outval,outval) ; window(51,15,80,17) ; gotoxy(2,l); strcpy(rangetxt,float2text(range) ); //printf("Range = %s meters",rangetxt) ; gotoxy(2,2); strcpy(bearingtxt,float2text(brg) ); //printf("Bearing = %s degrees",bearingtxt) ; //NOTE rangetxt and bearingtxt will be used in PrintData } /************************** reset A nchor() ********************/ void resetAnchor() { if(Anchorflag==l) Anchorflag=0; win6() ;clrscr(); gotoxy(2,l); if( !Anchorflag) cprintf("Anchor Released") ; else { gotoxy(2,1);cprintf("Anchor Lat. = %s ",latanchor) ; gotoxy(2,2);cprintf("Anchor Lon. = %s ",lonanchor) ; } } /************************** set A nchor() ********************/ //Input msg to Set Anchor Waypoint to last fix void setAnchor() { if(Anchorflag==0) Anchorflag=l; win6( );clrscr( ); gotoxy(2,1);cprintf("Anchor Lat. = %s ",latanchor) ; gotoxy(2,2);cprintf("Anchor Lon.= %s ",lonanchor) ; } /**********»*************** keyinanchor() *****************/ void keyinanchor() { char ch; char temptxt[12]; window(2,5,70,10) ; textattr( CYAN *16 | YELLOW); topa: clrscr(); gotoxy(5,1); cprint ("Enter Anchor Latitude in GPS coordinates"); gotoxy(5,2); //put old lat anchor in temptxt strcpy(temptxt,latanchor) ; cprintf("Current value = %s\n\r",temptxt) ; //input new lat anchor gets(latanchor) ; //if enter key only...restore to old value if(strle (latanchor)<1)strcpy(latanchor,temptxt) ; gotoxy(5,3); cprintf("Enter Anchor Longitude in GPS coordinates"); gotoxy(5,4); strcpy(temptxt,lonanchor) ; cprintf("Current value = %s\n\r",temptxt) ; gets(lonanchor) ; if(strlen(lonanchor)<1)strcpy(lonanchor,temptxt) ; gotoxy(3,5); cprintf("latanchor=%s\n\r",latanchor) ; gotoxy(3,6); cprintf("lonanchor=%s\n\r",lonanchor); cprintf("Hit Enter to accept! or n or N to reject!"); ch = getche( ); if(ch == 'n' || ch == 'N') goto topa; textattr(BLUE * 16 | LIGHTGRAY); clrscr( ); setAnchor() ; window(0,0,80,25) ; textattr( BLUE *16| YELLOW); } /************************** fiχstat() ***********************/ void fixstat() { int outval; win7( ) ; gotoxy(3,l); cprintf("%s =",fixtxt); if( !strncmp(fixtxt,"G3",2) ) { gotoxy(8,1); textattr(MAGENTA *16IWHITE) ; cprintf(" 3D NON-DIFF ") ; NFflag=0; } if( lstrncmp(fixtxt,"D3",2) ) { gotoxy(8,1); textattr(GREEN *16|WHITE) ; cprintf(" 3D DIFFERENTIAL ") ; NFflag=0; } if( tstrncmp(fixtxt,"D2",2) ) { gotoxy(8,1); textattr(CYAN *16 | «HITE) ; cprintf(" 2D DIFFERENTIAL ") ; NFflag=0; } if( !strncmp(fixtxt,"G2",2) ) { gotoxy(8,1); textattr(BROWN *16|WHITE) ; cprintf(" 2D NON DIFF ") ; NFflag=0; } if( !strncm (fixtxt,"NF",2) ) { gotoxy(8,1); textattr(RED *16| HITE) ; cprintf(" NO FIX! it ' • ) ; NFflag=l; //NEED TO DISABLE OUTPUT IF NO FIX } textattr(BLUE *16|YELLO ) ; } /************************* parseGPSmsg ( ) ********************/ void parseGPSmsg() { int j,k,n,comma; char tempmsgtxt[125]; //LOCATE TEXT RELATED TO POSITION //By finding # marker for(j=0;j<=strlen(GPSmsg) ;j++) if(GPSmsg[j]=='f ) break; if(j==strlen(GPSmsg) ) return; else strcpy(tempmsgtxt,GPSmsg+j) ; //UNPACK THE LATITUDE AND LONGITUDE PORTION OF GPS msg SENTENCE for(j=0;j<=strlen(tempmsgtxt) ;j++) // if(tempmsgtxt[j]==',' ) break; //look for first comma if(j==strlen(tempmsgtxt)) return; //didn't fine a comma else comma=j; //UNPACK UTC TIME TXT k=0; for(j=comma+7;j<=comma+7+5;j++) { UTCtxt[k]=tempmsgtxt[j]; // Get UTC text k++; } UTCtxt[k]='\0' ; //UNPACK LATITUDE TXT k=0; for(j=comma+14;j<=comma+14+8;j++) { latlastfix[k]=tempmsgtxt[j] ; //Get latitude of last fix } latlastfix[k]="\0" ; //terminate the new string! latlastfix[9]='\0' ; //UNPACK LONGITUDE TXT k=0; for(j=comma+25;j<=comma+25+9;j++) { lonlastfix[k]=tempmsgtxt[j] ; //Get longitude of last fix k++; } lonlastfix[k]='\0' ; //UNPACK TYPE OF FIX TXT k=0; for(j=comma+44;j<=comma+44+l;j++) { fixtx [k]=tempmsgtxt[j]; k++; } fixtxt[k]='\0' ; fixstat( ) ; deglatLF = gps2deg(latlastfix); deglonLF = gps2deg(lonlastfix) ; } /********************* parseKVHmsg() *********************/ //extract KVH heading text from NMEA string //and convert to float variable hdg void parseKVHmsg() { int j,comma; for(j=0;j<=strlen(KVHmsg) ;j++) { if(KVHmsg[j]==',' ) break; } //j now = location of first comma comma=j; strncpy(KVHhdg,KVHmsg+comma+l,5) ; hdg=atof(KVHhdg) ; //winl();cprintf("kvh reads %s\n\r %s\n\r%f",msgl,KVHhdg,hdg); } /it******************** getmsg2() ***************************/ void getmsg2(void) { //uses extern int outpl_index extern char queue2[ ]; int dif2; int j,k; //static int dif2; static int prior2; dif2=outp2_index-prior2; //Take care of buffer wrap around case if(dif2< 0) { dif2=dif2+ QUELEN;} // Copy last msg from queue2 k=0; for(j=outp2_index-dif2; j<=outp2_index; j++) { msg2[k]=queue2[j] & 0x7f; // ASCII only k++; } msg2[k]='\0' ; prior2=outp2_index; /********************* getmsgl () ***************************/ // This routine gets msgl string from queuel which was updated // by the serial port 1 interrupt handler void getmsgl() { //uses extern int outpl_index extern char queuel[]; int j,k; int difl; static int priori; difl=outpl_index-priorl; priorl=outpl_inde ; //Take care of buffer wrap around case if(difl< 0) { difl=difl+ QUELEN;} // clear buffers for msg and xreport for(j=0;j<=999;j++) {msgl[j]='\0' ; } // Copy last msg from queuel k=0; for(j=outpl_index-dif1; j<=outpl_index; j++) { msgl[k]=queuel[j] & 0x7f; // ASCII only k++; } msgl[k]='\0' ;// put null terminator at end of msg string msgl[999]='\0' ; //insurance. } /*************** searchKVH (int) **************************/ void searchKVH(int KVHPort) { int j,k; switch(KVHPort) { case 1: { getmsgl() ; { if( 1strncmp(msgl+j,"$HCHD",5) ) strncpy(KVHmsg,msgl+j,19); } break; } case 2: { getmsg2() ; for(j=0;j<=strlen(msg2) ;j++) if( !strncmp(msg2+j,"$HCHD",5) ) strncpy(KVHmsg,msg2+j,19) ; break; } }// end of switch case KVHmsgflag=0; //reset message flag } /******************* searchGPS(int GPSPort) **************/ void searchGPS(int GPSPort) { int j; switch(GPSPort) { case 1: { getmsgl(); for(j=0;j<=strlen(msgl) ;j++) { if(msgl[j]=='f) strcpy(GPSmsg,msgl+j); } break; } case 2: { getmsg2(); for(j=0;j<=strlen(msg2) ;j++) if(msg2[j]=='f) strcpy(GPSmsg,msg2+j); break; } }// end of switch case GPSmsgflag=0; //reset flag } /★a*********************************************************/ void route(int cmd) { int outval; switch(cmd) { case 59: // Fl Set Anchor site { setAnchor( ) ; break; } case 61: // F3 key Raise Anchorl { resetAnchor( ) ; break; } case 62: // F4 Log toggle! { logstat( ); break; } case 63: // F5 key in anchor site { keyinanchor( ); break; } case 64: // F6 preset anchor site { strcpy(latanchor,"2719.3430") ; strcpy(lonanchor,"8232.3510") ; setAnchor() ; break; } case 66: // F8 key-in Kl & K2 { kbcoef() ; break; } case 68: // F10 { outval=outval & 0x00; //turn off output lines outportb(PARPORT,outval) ; win5( ) ; Serial.Cleanu () ; exit(0) ; break; } default: break; } } /************************* terminal( ) ***********************/ // Basic serial communincatiσns terminal emulator void terminal(void) { int j,k,c,ch,ch2,cmd; static int saverlx, saverly; static int saver2x, saver2y; static int savetx,-avety; // display KVH port data if available while((ch = Serial.Getserch(KVHPort) ) 1= S_EOF) // if ser char avail { win2( ) ; gotoxy(saverlx,saverly) ; ch «- ch & 0x7f; if(ch==0x0a)ch=32; putch(ch) ; if(ch==0x0D) KVHmsgflag=l; //look for ending delimiter saverlx=wherex(); saverly = wherey(); } /* end of while 1= s_EOF */ //display GPS port data if available while((ch2 = serial.Getserch(GPSPort)) != s_EOF) // if ser char avail { winl(); gotoxy(saver2x,saver2y) ; ch2 = ch2 & 0x7f; putch(ch2); if(ch2==0x0d) GPSmsgflag=l; saver2x=wherex() ; saver2y = wherey(); } /* end of while 1= S_EOF */ if (kbhit()) { c = getch(); switch(c) { case 0:{cmd = getch();route(cmd) ;break;} case 27: {cmd=68;route(cmd) ;break;} default: break; }/* end of switch */ Serial.PutSerch(KVHPort,c) ; // send c via KVH Port if(c==0x0d) { Serial.Putserch(KVHPort,0x0a); serial.Putserch(KVHPort,OxOd) ; } win5() ; gotoxy(savet ,savety) ; putch(c); if(c == '\r') putch('\n'); savetx=where (); savety=wherey(); } /* end of if kbhit */ /****************************** main( ) *********************/ void main( ) { char ch; directvideo = 0; textmode(C80) ; clrscr( ) ; printf("RHODAN MARINE EQUIPMENT, Inc.\n\r"); printf("Virtual Anchoring system %s\n\n\n\r", ersion); strcpy(UTCtxt,"240000") ; UTCtxt[7]='\0- ; strcpy(lonanchor,"08232.3700W"); strcpy(latanchor,"2719.3230N"); strcpy(lonlastfix,"08232.2860W") ; strcpy(latlastfix,"2719.3240N"); strcpy(fixtxt,"NF") ; loadsetup( ) ; Serial.setu (KVHPort,KVHbaud,8,0,1); serial.setup(GPSPort,GPSbaud,8,0,1); loadtestcond(); printf("KVH Port %d baud = %d and GPS Port %d baud = %d\n\r", VHPort,KVHbaud,GPSPo cprintf("\nTEST CONDITIONS: \r\n") ; cprintf("\n\rl) Kl = %4.2f", Kl); cprintf(" Thrust versus Range\n\r"); cprintf("\n\r2) K2 = %4.2f", K2); cprintf(" Thrust versus Velocity\n\r"); cprintf("\n\r3) Minimum Range = %4.2f meters.",MinRange); cprintf("\n\r (No steering this close to anchor site.)\n"); cprintf("\n\r4) Steering Dead Band = %4.2f degrees.",SteerDeadBand) ; cprintf(' • \n\r (No steering this close to heading.)\n"); cprintf("\n\r5) Thrust Limit Angle = %4.2f degrees.",ThrustAngle); cprintf("\n\r (No Thrust if heading error is larger then this.)\n"); cprintf("\n\r6) TURN RATE = %d",TURNRATE) ; cprintf("\n\rlat anchor - %s & Ion anchor = %s",latanchor,lonanchor) ; cprintf("\n\rHit any key to continue1") ; getch(); clrscr(); trialptr=0; turnmotor=0; make_win(); menu(); NFflag=l;//set no fix flag ....a good fix will clear it! while(FOREVER) { _setcursortype(_NORMALCURSOR) ; terminal(); _setcursortype(_NOCURSOR); if(KVHmsgflag)searchKVH(KVHPort) ; if(GPSmsgflag)searchGPS(GPSPort) ; parseGPSmsg(); parseKVHmsg( ); if(IAnchorflag && INFflag) { strcpy(latanchor,latlastfix) ; strcpy(lonanchor,lonlastfix); } calcrange() ; calcsteer( ) ; calcthrust(); genoutput( ) ; display() ; if(Logflag) ..iklogtimer () ; } D:\TC\GLEN\SERNEW02.CPP // sernew02.cpp // by John Webster 9606 Todd Mill Rd., Huntsville, AL 35803-1108 // copyright 1992 exclusive of Interrupt routines serial_isrl() // and serial_isr2() . tinclude "sernew02.hpp" int break_detect = 0 int char_overrun = 0 int frame_error = 0 int parity_error = 0 int ring_detect = 0 unsigned E; int Mx,My; char queue1[QUELEN]; char queue2[QUELEN]; int inpl_index = 0; int outpl_index = 0; int inp2_index = 0; int outp2_index = 0; int irqx[5] = {0, 0x0c, 0x0b, 0x0c, 0x0b}; int basex[5] = {0, 0x3f8, 0x2f8, 0x3e8, 0x2e8}; int IRQ_MASK[5] = {0, Oxef, 0xf7, Oxef, 0xf }; int baudx[5] = {0, 9600, 4800, 9600, 9600,}; int bitsx[5] = {0,8,8,8,8}; int parityx[5] = {0,0,0,0,0}; int stopbitx[5] = {0,1,1,1,1}; void interrupt (*oldvectorl) (...); /* This form required by C++ */ void interrupt (*oldvector2)(...); void interrupt serial_isrl(...); void interrupt serial_isr2(...); /******************************************************* /*** Note:interrupt service routines are not in serial class object ***/ /**************************** serial isrl() *************************/ /** This routine was in C-Programmer's Journal April 91 **/ void interrupt serial_isrl(...) { char ch; int ml; // temp index extern basex[5 j . enable( ) ; ch = inportb(basex[l] +IIR) ; // port 1 switch(ch) { case 6: inportb(basex[1] ) ; break; case 4: ch = inportb(basex[l] ) ; ml = inpl_index + 1; if(ml >= QUELEN) ml = 0; if(ml != outpl_index) { queuel[ml] = ch; inpl_index = ml; } break; } outportb( CR, EOI) ; } /ft***************************- serial isr2( ) *************************/ /** This routine was in C-Programmer's Journal April 91 **/ void interrupt serial_isr2(...) { char ch; int m2; // temp index extern basex[5]; enable(); ch = inportb(basexf2] +IIR); switch(ch) { case 6: ch = inportb(basexf2] + LSR); if(ch & PE) parity_error++; if(ch & OE) char_overrun++; if(ch & FE) frame_error++; if(ch & BI) break_detect++; inportb(base [2] ); break; case 4: ch = inportb(basex[2]); m2 = inp2_index + 1; if(m2 >= QUELEN) m2 = 0; if(m2 != outp2_index) { queue2[m2] = ch; inp2_index = m2; } break; case 0: ch = inportb(basex[2] +MSR) ; if(ch & DCTS) { /* a routine to handle CTS changes would go he } if(ch & DDSR) { } if(ch & TERI) { ring_detect = 1; } if(ch & DDCD) { } } outportb(ICR, EOI) ; } /*********** serial class implementation routines *******************/ /****************** serialobject constructor ******************/ Serialobject: :serialobject(void) { printf(" Activating Serialobject "); } /************************** Setbaud( ) ************************/ void serialobject: :Setbaud(int port) { int n; int c; extern int baudx[5]; extern int basex[5]; if(baudx[port]==0) baudx[port] = 9600; // default baud n = (int) (115200L / baudx[port] ); disable(); c = inportb(basex[port] + LCR) ; outportb(base [port] + LCR, (c | DLAB)); outportb(base [port] + DLL, n & OxOOff); outportb(basex[port] + DLH, (n » 8) & OxOOff); outportb(basex[port] + LCR, c); enable( ); }/* end of setbaud() */ /***************************** setform(int port) ***************************/ void serialobject: :Setform(int) { int n; extern int basex[5]; extern int parityx[5]; extern int bitsx[5]; extern int stopbitx[5]; if(parityx[port] < Nθ_PARlTY || parity > ODD_PARITY) returπ, if(bits f ort] < 5 | | bits > 8) return; if(stopbitx[port] <1 | | stopbit > 2) return; n = bitsx[port] - 5; n |= ( (stopbitx[port] == 1) ? 0 : 4); switch (parity [port] ) { case NO_PARITY: break; case ODD_PARITY: n |= 0x08; break; case EVEN_PARITY: n |= 0x18; break; } disable() ; outportb(base [port] + LCR, n); enable() ; }/* end of set_form */ /at*************************** ntr Set(port) ****************************/ /* This routine used to open Com Port in arg */ /* set up for interrupts */ void Serialobject::Intr_Set(int port) { int j; extern int basex[5]; extern int IRQ_MASK[5]; disable(); if(port==l) { oldvectorl = getvect(12); setvect (12, serial_isrl) ; } if(port==2) { oldvector2 = getvect(ll); setvect (11, serial_isr2) ; } outportb(basex[port] + MCR, inportb(basex[port] + MCR) | MC_INT | DTR | RTS); /* assert GPθ2, DTR and RTS */ outportb(basex[port] + IER, RX_INT) ; /* permit rec data interrupts */ outportb(IMR, inportb(IMR) & IRQ_MASK[port] ) ; for(j=0; j<=6; j++) // read port registers inportb(basex[port] + j); enable() ; } /**************************** int Getserch(port) *********************/ int serialobject: :Getserch(int port) int m; switch(port) { case 1; if(outpl_index j= inpl_index) { m=outpl_index +1; if(m >= QUELEN) m = 0; SerCh = queuel[m]; outpl_index = m; return(serch); } else return(s_EOF) ; break; case 2: if(outp2_index 1= inp2_index) { m=outp2_index +1; if( >= QUELEN) = 0; Serch = queue2[m]; outp2_index = m; return(Serch); } else return(s_EOF) ; break; defaul : return(S_EOF); break; }//end of switch /**************************** putSerCh(port, char SerCh ) **************/ void Serialobject: :PutserCh(int port, char SerCh) { while(inportb(base [port] + LSR) & 0x20 == 0) r outportb(basex[ ort], SerCh); return; > /******************** sendstr(int port, char str2send[]) -**************/ void Serialobject::Sendstr(int port, char str2send[]) { int i; for (i=0; i < strlen(str2send) ; i++) { PutserCh(port, str2send[i]); while(inportb(base [port] + LSR) & 0x20 == 0) ; //wait for TBE delay(5); // this delay needed by HF radio data link //won't work with 2 ms delay } } /****************** Setup(.....) ****************•***/ void Serialobject: :Setup(int port,int baud,int bits,int parity,int stopbit) { extern int bas« .[5]; extern int baudx[5]; extern int parityx[5]; extern int bitsx[5]; extern int stopbitx[5]; port=port; baud [ ort]=baud; bits [port]=bits; parityx[port]=parity; stopbitx[port]=stopbit; Intr_Set(port); Setbaud(port); Setform(port) ; /******************************** setupl ( ) *******************/ void Serialobject: :Setupl() { int port; port=l; Intr_set(port) ; Setbaud(port) ; Setform(port) ; } /******************************** setup2 ( ) *******************/ void Serialobject: :Setup2() { int port; port=2; // base and irq must change to match port.. Intr_Set( ort); Setbaud(port) ; Setfor (port); } /******************************* cleanup( ) ******************/ void Serialobject::Cleanup() { char ch; extern int basex[4]; extern int IRQ_MASK[4]; outportb(basex[l] + IER, 0); outportb(basex[l] + MCR, 0); outportb(basex[2] + IER, 0) ; outportb(basex[2] + MCR, 0); ch = inportb(IMR); ch |= 1 (IRQ_MASK[1]); outportb(lMR, ch); ch = inportb(IMR); ch |= ! (IRQ_MASK[2]); outportb(IMR, ch) ; setvect(12, oldvectorl); setvect(11, oldvector2) ; printf("PROGRAM TERMINATED!\n") ; delay(1500); D:\TC\GLEN\SERSETUP.CPP // serSETUP.cpp //This program serves as utility for sernew02.cpp and allows the //reassignment of computer serial ports and their baud rate setups. //COPYRIGHT 1993 BY JOHN L. WEBSTER, 9606 TODD MILL RD., HUNTSVILLE, AL 35803 tinclude <stdio.h> tinclude <conio.h> tinclude <stdlib.h> tinclude <string.h> struct sersetup { char KVHPorttxt[5]; char GPSPorttxt[5]; char MousePorttxt[5] ; char KVHbaudtxt[5]; char GPSbaudtxt[5]; }sersetup; //DEFAULT SETTINGS char *KVHPorttxt ="1"; char *GPSPorttxt ="2"; char *MousePorttxt="3"; char *KVHbaudtxt="4800"; char *GPSbaudtxt="4800"; int KVHPort = atoi(sersetup.KVHPorttxt) ; int GPSPort = atoi(sersetup.GPSPorttxt); int MousePort=atoi(sersetup.MousePorttxt); int KVHbaud = atoi(sersetup.KVHbaudtxt); int GPSbaud = atoi(sersetup.GPSbaudtxt); char filename[20]="serSETUP.DAT"; /★•A*****************************************************/ void loadsetup() { int i,j; FILE *fp; if( ! (fp = fopen(filename,"r") ) ) { cprintf("CANNOT FIND %s FILE !\n\r",filename) ; cprintf("Will use default settings.\n\r") ; //delay(1500) ; return; } fread(..sersetup,sizeof(sersetup) ,l,fp) ; fclose(fp) ; //transfer val..a read from file KVHPort = atoi(sersetup.KVHPorttxt) ; GPSPort = atoi(sersetup.GPSPorttxt) ; MousePort = atoi(sersetup.MousePorttxt) ; KVHbaud = atoi(sersetup.KVHbaudtx ) ; GPSbaud = atoi(sersetup.GPSbaudtxt) ; } void dsplyparam() { window(0,0,80,25) ; textattr(BLUE *16 | YELLOW); clrscr(); cprintf("SERIAL PORT SET UPs for Program\r\n\n\n"); cprintf("\n\r PARAMETERS:"); cprintf("\n\rl) KVH Port =. %d", KVHPort); cprintf("\n\r2) GPS Port = %d", GPSPort); cprintf("\n\r3) Mouse Port = %d",MousePort); cprintf("\n\r4) KVHbaud = %d",KVHbaud); cprintf("\n\r5) GPSbaud = %d",GPSbaud); cprintf("\n\rselect the number you wish to change.\n\r") ; cprintf("Hit enter to accept parameters shown.\n\r"); } /**************************************************** void main() { FILE *fp; char c; char *baudstr; loadsetu ( ) ; do { dsplyparam(); c = getche(); switch(c) { case '1' : { Loopl:; cprintf("\n\rEnter new KVH Port t. 1 or 2?"); gets(sersetup.KVHPorttxt) ; KVHPort=atoi(sersetup.KVHPorttxt) ; cprintf("KVH Port = %d\n\r",KVHPort); if(KVHPort >2) goto Loopl; break; } case '2' : { Loop2:; cprintf("\n\rEnter new GPS Port #. 1 or 2?"); gets(sersetup.GPSPorttxt) ; GPSPort=atoi(sersetup.GPSPorttxt) ; cprintf("GPS Port = %d\n\r",GPSPort) ; if(GPSPort >2 ) goto Loop2; break; } case '3' : { Loop3:; cprintf("\n\rEnter new Mouse Port. 0(none), or 3(bus)?"); gets(sersetup.MousePorttx ) ; MousePort=atoi(sersetup.MousePorttxt) ; cprintf("Mouse Port = %d\n\r",MousePort); if(MousePort >3) goto Loop3; break; } case { cprintf("\n\rEnter new KVH Baud rate.") ; gets(sersetup.KVHbaudtxt) ; KVHbaud = atoi(sersetup.KVHbaudtx ); cprintf("KVH Baud = %d",KVHbaud) ; break; } case { cprintf("\n\rEnter new GPS Baud rate.") ; gets(sersetup.GPSbaudtxt) ; GPSbaud = atoi(sersetup.GPSbaudtx ); cprintf("GPS Baud = %d",GPSbaud); break; } } } while ( c 1= '\r'); cprintf("\n\rsave Setup?...y/n?") ; do { c = getche() ; } while(c ι= -y && c != - Y - && c l='n' && c != 'N'); if(c == -y I I c == -Y') { if( (fp=fopen(filename, "w") ) == NULL) { cprintf("CANNOT OPEN %s FILE!\n\r",filename); return; } fwrite(Ssersetu , sizeof(sersetup) ,1,fp); fclose(fp); } D:\TC\GLEN\TESTCOND.CPP // TESTCOND.cpp //This program serves as a utility for Glens5.cpp and permits the altering //of program constants that affect the dynamic operation of that program. //COPYRIGHT 1993 BY JOHN L. WEBSTER, 9606 TODD MILL RD., HUNTSVILLE, AL 35803 tinclude <stdio.h> tinclude <conio.h> tinclude <stdlib.h> tinclude <string.h> struct testsetup { char Kltxt[5]; char K2txt[5]; char MinRangetxt[5]; char SteerDeadBandtxt[5]; char ThrustAngletxt[5] ; char TurnRatetxt[3]; }testsetup; //DEFAULT SETTINGS char *Kltxt ="1.00"; char *K2txt ="25.00"; char *MinRangetxt="1.00" char *SteerDeadBandtxt="10"; char *ThrustAngletxt="30"; char *TurnRatetxt="60"; float Kl = atof(testsetup.Kltxt) ; float K2 = atof(testsetup.K2txt); float MinRange=atof(testsetup.MinRangetxt) ; float SteerDeadBand = atof(testsetup.SteerDeadBandtxt) ; float ThrustAngle = atof(testsetup.ThrustAngletxt) ; int TURNRATE = atoi(testsetup.TurnRatetxt) ; char filename[20]="TESTCOND.DAT"; void loadsetup() { int i,j; FILE *fp; if( l (fp = fopen(filename,"r"))) { cprintf("CANNOT FIND %s FILE !\n\r",filename) ; cprintf("Will use default settings.\n\r") ; //delay(1500); return; } fread( fitestset J -., sizeof (testsetup ) , l , fp ) ; fclose (fp) ; //transfer values read from file Kl = atof(testsetup.Kltxt) ; K2 = atof(testsetup.K2txt) ; MinRange=atof(testsetup.MinRangetxt); SteerDeadBand = atof(testsetup.SteerDeadBandtx ) ; ThrustAngle = atof(testsetu .ThrustAngletxt) ; TURNRATΞ = atoi(testsetup.TurnRatetxt) ; } void displayparam() { window(0,0,80,25) ; textattr(BLUE *16 | YELLOW); clrscr() ; cprintf("TEST CONDITIONS: \r\n\n") ; cprintf("\n\rl) Kl = %4.2f", Kl); • cprintf(" Thrust versus Range\n\r"); cprintf("\n\r2) K2 = %4.2f", K2); cprintf(" Thrust versus Velocity\n\r"); cprintf("\n\r3) Minimum Range = %4.2f meters.",MinRange) ; cprintf("\n\r (No steering this close to anchor site.)\n"); cprintf("\n\r4) steering Dead Band = %4.2f degrees.",SteerDeadBand); cprintf("\n\r (No steering this close to heading.)\n") ; cprintf("\n\r5) Thrust Limit Angle = %4.2f degrees.",ThrustAngle); cprintf("\n\r (No Thrust if heading error is larger then this.)\n"); cprintf("\n\r6 Assumed Turn Rate = %d deg./sec.",TURNRATE); cprintf("\n\n\rSelect the number you wish to change.\n\r") ; cprintf("Hit enter to accept parameters shown.\n\r"); } /A************************************************************/ void main() { FILE *fp; char c; char *baudstr; loadsetup(); do { displayparam() ; c = getche(); switch(c) { case '1* : { Loopl:; cprintf("\n\rEnter new Kl Value\n"); gets(testsetup.Kltxt); Kl=atof(testsetup.Kltxt) ; cprintf("Kl = %f\n\r",κi); break; } case { Loo 2:; cprintf("\n\rEnter new K2 Value\n"); gets(testsetup.K2 xt); K2=atof(testsetup.K2txt) ; cprintf("K2 = %f\n\r",K2); break; } case *3 < { Loop3:; cprintf(* • \n\rEnter new Min Range.\n"); gets(testsetup. inRangetxt); MinRange=atof(testsetup. inRangetx ); cprintf("Minimum Range = %f\n\r",MinRange) ; break; } case { cprintf("\n\rEnter new steering Dead Band.Xn"); gets(testsetup.SteerDeadBandtxt) ; SteerDeadBand = atof(testsetup.SteerDeadBandtxt); cprintf("Steering Dead Band = %f",SteerDeadBand) ; break; } case { cprintf( •• \n\rEnter new Thrust Angle.\n"); gets(testsetup. hrustAngletxt); ThrustAngle = atof(testsetup. hrustAngletxt) ; cprintf("Thrust Angle Lim. = %f",ThrustAngle) ; break; } { cprintf("\n\rEnter new Assumed Turn Rate.\n"); gets(testsetup. urnRatetxt) ; TURNRATE = atoi(testsetup.TurnRatetx ) ; cprintf("Assumed Turn Rate = %d",TURNRATE); break; } } } while ( c I= •\r• ) ; cprintf("\n\rsave setup?...y/n?") ; do { c = getche( ) ; } while(c 1= 'y' && c != • " ' && c I='n' && c 1= 'N'); if(c == -y I I c == Υ') { if( (fp=fopen(filename, "w")) == NULL) { cprint ("CANNOT OPEN %s FILE!\n\r",filename) ; return; } f rite(&testsetu , sizeof(testsetup) ,1,fp); fclose(fp); }

Claims: 1. A system for substantially maintaining the position of a boat at an anchoring location in water selected by an operator of the boat, the system comprising: at least one thruster attached to the boat for moving the boat to the selected amcjpromg location within the water; a GPS receiver located on board the boat for receiving signals from GPS satellites and for providing position information signals indicative of the position of the at least one thruster; a magnetic compass for providing a heading indication signal representative of the heading of the thruster; and a controller providing control signals to the at least one thruster for steering and propelling the boat to the selected anchoring location, the control signals related to the difference between position information signals received at the selected location and position information and heading indication signals received at a present location. 2. The system of claim 1 wherein the control signals are based on a range and a bearing from the present location of the thruster to the selected anchoring location. 3. The system of claim 2 wherein the control signals are further based on the rate of change in range from the present location of the boat to the selected anchoring location. 4. The system of claim 1 wherein the at least one thruster comprises a single thruster fully rotatable about a vertical axis extending from above the surface of the water to below the surface of the water and transverse to the direction of propulsion of the single thruster. 5. The system of claim 4 wherein the control signals include thrust control signals for propelling the single thruster and steering control signals for rotating the single thruster. . 6. The system of claim 4 wherein the single thruster is attached to the bow of the boat. 7. The system of claim 1 further comprising a reference GPS receiver positioned at a known location different from the position of the GPS receiver located on board the boat, wherein the on board GPS receiver receives signals from the reference GPS receiver and the GPS satellites to provide position information signals providing differential GPS mode operation. 8. The system of claim 1 wherein the magnetic compass provides a heading indication signal representative of the heading of the thruster toward the selected location and the control signals relate to the difference between position information and heading indication signals received at the selected location and position information and heading indication signals received at a present location. 9. The system of claim 1 wherein the at least one thruster comprises a first non-rotatable thruster for providing thrust in a direction along a long axis of the boat and a second non-rotatable thruster for providing thrust in a direction transverse to that of the first non-rotatable thruster. 10. The system of claim 1 further comprising a second magnetic compass for providing a second heading indication signal representative of the heading of the boat, with the control signals provided to the thruster further relating to the difference between a second heading indication signal received at the selected location and a second heading signal received at the present location. 11. The system of claim 6 further comprising a second thruster positioned at the stern of the boat for propelling the boat in the direction of the boat's heading. 12. A method of substantially maintaining a position of a boat at an anchoring location in water, selected by an operator, the boat including a steerable thruster, a GPS receiver, and a magnetic compass, the method comprising the steps of: receiving and' storing position information signals from GPS satellites with the GPS receiver to establish positional coordinates of a selected anchoring location, receiving, after a predetermined interval of time, position information signals from the GPS satellites with the GPS receiver to determine a present location of the sterrable thruster and a present heading indication of the steerable thruster from the magnetic compass, and controlling the magnitude and direction of the thrust of the thruster on the basis of the difference between the positional coordinates of the selected anchoring location and the position information and heading indication signals corresponding to the present location. 13. The method of claim 12 wherein controlling the thruster further comprises the steps of: determining a range and bearing from the present location of the thruster to the anchoring location on the basis of the positional coordinates of the selected anchoring location and the position information and heading indication signals corresponding to the present location. 14. The method of claim 13 wherein controlling the thruster further comprises the steps of: determining the rate of change in the range from the present location of the thruster to the anchoring location. 15. The method of claim 12 wherein the receiving and storing step further comprises: receiving and storing, from a second magnetic compass, a heading indication of the boat at the selected anchoring location. 16. The method of claim 12 wherein the receiving position information signals steps further comprise: receiving position information signals from the GPS satellites with a reference GPS receiver positioned at a known location different from the position of the boat. 17. A system for substantially maintaining the position of a boat at a selected location in water, the system comprising: propelling means, attached to the boat, for maintaining the boat at the selected location within the water; receiving means, located on board the boat, for receiving signals from GPS satellites and for providing position information signals indicative of the position of the propelling means; means for providing a heading indication signal representative of the heading of the propelling means; and means for providing control signals to the propelling means for steering and propelling the boat to the selected location, the control signals related to the difference between position information signals received at the selected location and position information and heading indication signals received at a present location.

Inventors: ROBERTSON GLEN E, WEBSTER JOHN L, ROBERTSON, GLEN, E., WEBSTER, JOHN, L.
Applicants: ROBERTSON GLEN E, ROBERTSON, GLEN, E.
Application year: 1995
Main classification: G06F165
IPC codes: B63H25, G01S5, G05D1