149149 color : # FFD700 ;
150150 }
151151
152+ # sensor-debug {
153+ position : absolute;
154+ top : 10px ;
155+ left : 10px ;
156+ background : rgba (0 , 0 , 0 , 0.8 );
157+ padding : 10px ;
158+ border-radius : 5px ;
159+ font-size : 12px ;
160+ font-family : monospace;
161+ z-index : 150 ;
162+ max-width : 200px ;
163+ }
164+
165+ # sensor-debug div {
166+ margin : 2px 0 ;
167+ }
168+
152169 # destination {
153170 background : rgba (0 , 0 , 0 , 0.5 );
154171 padding : 20px ;
@@ -225,6 +242,15 @@ <h1>🌊 Ocean Crosser</h1>
225242
226243 < div id ="compass-container ">
227244 < div id ="compass ">
245+ < div id ="sensor-debug " style ="display: none; ">
246+ < div > < strong > Raw Sensors:</ strong > </ div >
247+ < div id ="sensor-alpha "> α: --</ div >
248+ < div id ="sensor-beta "> β: --</ div >
249+ < div id ="sensor-gamma "> γ: --</ div >
250+ < div id ="sensor-absolute "> Absolute: --</ div >
251+ < div id ="sensor-webkit "> WebKit: --</ div >
252+ < div id ="sensor-calculated "> Calc: --</ div >
253+ </ div >
228254 < div id ="heading-display "> --°</ div >
229255 < div id ="crosshair "> </ div >
230256 < div id ="compass-strip ">
@@ -366,9 +392,17 @@ <h1>🌊 Ocean Crosser</h1>
366392 const locationInfoEl = document . getElementById ( 'location-info' ) ;
367393 const startBtn = document . getElementById ( 'start-btn' ) ;
368394 const debugEl = document . getElementById ( 'debug' ) ;
395+ const sensorDebugEl = document . getElementById ( 'sensor-debug' ) ;
396+ const sensorAlphaEl = document . getElementById ( 'sensor-alpha' ) ;
397+ const sensorBetaEl = document . getElementById ( 'sensor-beta' ) ;
398+ const sensorGammaEl = document . getElementById ( 'sensor-gamma' ) ;
399+ const sensorAbsoluteEl = document . getElementById ( 'sensor-absolute' ) ;
400+ const sensorWebkitEl = document . getElementById ( 'sensor-webkit' ) ;
401+ const sensorCalculatedEl = document . getElementById ( 'sensor-calculated' ) ;
369402
370403 if ( debugMode ) {
371404 debugEl . style . display = 'block' ;
405+ sensorDebugEl . style . display = 'block' ;
372406 }
373407
374408 // Create compass tape with cardinal directions
@@ -533,11 +567,42 @@ <h1>🌊 Ocean Crosser</h1>
533567 } ) ;
534568 }
535569
570+ // Calculate compass heading from device orientation for vertical phone position
571+ function calculateCompassHeading ( alpha , beta , gamma ) {
572+ // Convert to radians
573+ const alphaRad = toRadians ( alpha ) ;
574+ const betaRad = toRadians ( beta ) ;
575+ const gammaRad = toRadians ( gamma ) ;
576+
577+ // Calculate compass heading accounting for device tilt
578+ // This works when phone is held vertically (portrait mode)
579+ const compassHeading = Math . atan2 (
580+ - Math . sin ( gammaRad ) * Math . cos ( betaRad ) ,
581+ Math . cos ( gammaRad ) * Math . cos ( betaRad ) * Math . cos ( alphaRad ) +
582+ Math . sin ( betaRad ) * Math . sin ( alphaRad )
583+ ) ;
584+
585+ // Convert to degrees and normalize to 0-360
586+ let heading = toDegrees ( compassHeading ) ;
587+ heading = ( heading + 360 ) % 360 ;
588+
589+ return heading ;
590+ }
591+
536592 // Handle device orientation
537593 let orientationEventCount = 0 ;
538594 function handleOrientation ( event ) {
539595 if ( ! isCompassActive || ! userLocation ) return ;
540596
597+ // Update sensor debug display
598+ if ( sensorDebugEl ) {
599+ sensorAlphaEl . textContent = `α: ${ event . alpha !== null ? event . alpha . toFixed ( 1 ) : 'null' } °` ;
600+ sensorBetaEl . textContent = `β: ${ event . beta !== null ? event . beta . toFixed ( 1 ) : 'null' } °` ;
601+ sensorGammaEl . textContent = `γ: ${ event . gamma !== null ? event . gamma . toFixed ( 1 ) : 'null' } °` ;
602+ sensorAbsoluteEl . textContent = `Absolute: ${ event . absolute ? 'yes' : 'no' } ` ;
603+ sensorWebkitEl . textContent = `WebKit: ${ event . webkitCompassHeading !== undefined ? event . webkitCompassHeading . toFixed ( 1 ) + '°' : 'n/a' } ` ;
604+ }
605+
541606 // Log first event for debugging
542607 if ( orientationEventCount === 0 ) {
543608 log ( `First orientation event received - alpha: ${ event . alpha } , beta: ${ event . beta } , gamma: ${ event . gamma } , webkitCompassHeading: ${ event . webkitCompassHeading } ` ) ;
@@ -548,17 +613,28 @@ <h1>🌊 Ocean Crosser</h1>
548613 let heading = null ;
549614
550615 if ( event . webkitCompassHeading !== undefined ) {
551- // iOS
616+ // iOS - webkitCompassHeading is already calibrated
552617 heading = event . webkitCompassHeading ;
553618 if ( orientationEventCount === 1 ) log ( 'Using iOS webkitCompassHeading' ) ;
554- } else if ( event . alpha !== null ) {
555- // Android
556- heading = 360 - event . alpha ;
557- if ( orientationEventCount === 1 ) log ( 'Using Android alpha orientation' ) ;
619+ } else if ( event . alpha !== null && event . beta !== null && event . gamma !== null ) {
620+ // Android - calculate heading from orientation data
621+ // Check if phone is roughly vertical (beta between 45 and 135 degrees)
622+ if ( Math . abs ( event . beta ) > 45 && Math . abs ( event . beta ) < 135 ) {
623+ // Phone is vertical - use proper calculation
624+ heading = calculateCompassHeading ( event . alpha , event . beta , event . gamma ) ;
625+ if ( orientationEventCount === 1 ) log ( 'Using calculated heading for vertical orientation' ) ;
626+ } else {
627+ // Phone is flat - use simple alpha
628+ heading = 360 - event . alpha ;
629+ if ( orientationEventCount === 1 ) log ( 'Using simple alpha for flat orientation' ) ;
630+ }
558631 }
559632
560633 if ( heading !== null ) {
561634 currentHeading = heading ;
635+ if ( sensorDebugEl ) {
636+ sensorCalculatedEl . textContent = `Calc: ${ heading . toFixed ( 1 ) } °` ;
637+ }
562638 // Apply smoothing to reduce jitter
563639 smoothedHeading = orientationEventCount === 1 ? heading : smoothHeading ( heading , smoothedHeading ) ;
564640 updateDisplay ( Math . round ( smoothedHeading ) ) ;
@@ -573,12 +649,24 @@ <h1>🌊 Ocean Crosser</h1>
573649 if ( ! isCompassActive || ! userLocation ) return ;
574650
575651 if ( absoluteEventCount === 0 ) {
576- log ( `First absolute orientation event - absolute: ${ event . absolute } , alpha: ${ event . alpha } ` ) ;
652+ log ( `First absolute orientation event - absolute: ${ event . absolute } , alpha: ${ event . alpha } , beta: ${ event . beta } , gamma: ${ event . gamma } ` ) ;
577653 }
578654 absoluteEventCount ++ ;
579655
580- if ( event . absolute && event . alpha !== null ) {
581- let heading = 360 - event . alpha ;
656+ if ( event . absolute && event . alpha !== null && event . beta !== null && event . gamma !== null ) {
657+ let heading = null ;
658+
659+ // Check if phone is roughly vertical (beta between 45 and 135 degrees)
660+ if ( Math . abs ( event . beta ) > 45 && Math . abs ( event . beta ) < 135 ) {
661+ // Phone is vertical - use proper calculation
662+ heading = calculateCompassHeading ( event . alpha , event . beta , event . gamma ) ;
663+ if ( absoluteEventCount === 1 ) log ( 'Using calculated heading for vertical orientation (absolute)' ) ;
664+ } else {
665+ // Phone is flat - use simple alpha
666+ heading = 360 - event . alpha ;
667+ if ( absoluteEventCount === 1 ) log ( 'Using simple alpha for flat orientation (absolute)' ) ;
668+ }
669+
582670 currentHeading = heading ;
583671 // Apply smoothing to reduce jitter
584672 smoothedHeading = absoluteEventCount === 1 ? heading : smoothHeading ( heading , smoothedHeading ) ;
@@ -681,11 +769,18 @@ <h1>🌊 Ocean Crosser</h1>
681769 log ( 'Event listeners added' ) ;
682770
683771 isCompassActive = true ;
684- statusEl . textContent = 'Compass active - Point at the horizon ' ;
772+ statusEl . innerHTML = 'Compass active - <span style="color: #FFD700;">Wave phone in figure-8 to calibrate</span> ' ;
685773 startBtn . textContent = 'Compass Active' ;
686774
687775 log ( '=== Compass started successfully - waiting for orientation events ===' ) ;
688776
777+ // Show calibration reminder after 2 seconds
778+ setTimeout ( ( ) => {
779+ if ( isCompassActive ) {
780+ log ( 'TIP: Wave your phone in a figure-8 pattern to calibrate the magnetometer' ) ;
781+ }
782+ } , 2000 ) ;
783+
689784 // Set a timeout to check if we're receiving events
690785 setTimeout ( ( ) => {
691786 if ( orientationEventCount === 0 && absoluteEventCount === 0 ) {
0 commit comments