@@ -10,7 +10,7 @@ interface TouchPosition {
1010}
1111
1212export default function VirtualGamepad ( ) {
13- const { isConnected, getRos, robotNamespace, connectionStatus } = useRos ( ) ;
13+ const { isConnected, getRos, robotNamespace, connectionStatus, ensureConnection } = useRos ( ) ;
1414
1515 // Settings modal state
1616 const [ showSettingsModal , setShowSettingsModal ] = useState ( false ) ;
@@ -35,12 +35,22 @@ export default function VirtualGamepad() {
3535 const [ isDraggingLeft , setIsDraggingLeft ] = useState ( false ) ;
3636 const [ isDraggingRight , setIsDraggingRight ] = useState ( false ) ;
3737 const [ isFullscreen , setIsFullscreen ] = useState ( false ) ;
38+
39+ // Track if joysticks have been touched to prevent initial cmd_vel sending
40+ const [ hasInteracted , setHasInteracted ] = useState ( false ) ;
3841
3942 const cmdVelRef = useRef < ROSLIB . Topic | null > ( null ) ;
4043 const kickRef = useRef < ROSLIB . Topic | null > ( null ) ;
4144 const leftJoystickRef = useRef < HTMLDivElement > ( null ) ;
4245 const rightJoystickRef = useRef < HTMLDivElement > ( null ) ;
4346
47+ // Ensure connection is maintained when component mounts
48+ useEffect ( ( ) => {
49+ if ( ensureConnection ) {
50+ ensureConnection ( ) ;
51+ }
52+ } , [ ensureConnection ] ) ;
53+
4454 // Initialize ROS topics when connected
4555 useEffect ( ( ) => {
4656 if ( ! isConnected ) {
@@ -155,9 +165,14 @@ export default function VirtualGamepad() {
155165 theta : Math . max ( - valueCaps . theta , Math . min ( valueCaps . theta , processedRightX * - valueCaps . theta ) ) // Rotation (clockwise is negative) with cap
156166 } ;
157167
168+ // Always update control values for display
158169 setControlValues ( newControlValues ) ;
159- sendTwist ( newControlValues . x , newControlValues . y , newControlValues . theta ) ;
160- } , [ leftJoystick , rightJoystick , sendTwist , valueCaps ] ) ;
170+
171+ // Only send cmd_vel after user has interacted with joysticks
172+ if ( hasInteracted ) {
173+ sendTwist ( newControlValues . x , newControlValues . y , newControlValues . theta ) ;
174+ }
175+ } , [ leftJoystick , rightJoystick , sendTwist , valueCaps , hasInteracted ] ) ;
161176
162177 // Get relative position within joystick area
163178 const getRelativePosition = ( element : HTMLElement , clientX : number , clientY : number ) : TouchPosition => {
@@ -199,6 +214,8 @@ export default function VirtualGamepad() {
199214 // For touch events, only handle the first touch to prevent multiple touch conflicts
200215 if ( 'touches' in e && e . touches . length > 1 ) return ;
201216
217+ // Mark that user has interacted with joysticks
218+ setHasInteracted ( true ) ;
202219 setIsDraggingLeft ( true ) ;
203220
204221 const clientX = 'touches' in e ? e . touches [ 0 ] . clientX : e . clientX ;
@@ -239,6 +256,8 @@ export default function VirtualGamepad() {
239256 // For touch events, only handle the first touch to prevent multiple touch conflicts
240257 if ( 'touches' in e && e . touches . length > 1 ) return ;
241258
259+ // Mark that user has interacted with joysticks
260+ setHasInteracted ( true ) ;
242261 setIsDraggingRight ( true ) ;
243262
244263 const clientX = 'touches' in e ? e . touches [ 0 ] . clientX : e . clientX ;
@@ -365,7 +384,7 @@ export default function VirtualGamepad() {
365384
366385 { /* Settings Modal - Only for control limits */ }
367386 { showSettingsModal && (
368- < div className = "fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50 p-4" >
387+ < div className = "fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-[75] p-4" >
369388 < div className = "bg-white rounded-lg p-6 w-full max-w-md max-h-[80vh] overflow-y-auto" >
370389 < div className = "flex justify-between items-center mb-4" >
371390 < h3 className = "text-lg font-semibold text-gray-900" > Control Limits</ h3 >
@@ -443,9 +462,12 @@ export default function VirtualGamepad() {
443462 < div className = "absolute top-20 left-1/2 transform -translate-x-1/2 z-40 mt-2" >
444463 < div className = "bg-black bg-opacity-80 text-white px-3 py-2 rounded-lg" >
445464 < div className = "flex gap-3 text-xs" >
446- < span > X: { controlValues . x . toFixed ( 2 ) } </ span >
447- < span > Y: { controlValues . y . toFixed ( 2 ) } </ span >
448- < span > θ: { controlValues . theta . toFixed ( 2 ) } </ span >
465+ < span > X: { hasInteracted ? controlValues . x . toFixed ( 2 ) : '0.00' } </ span >
466+ < span > Y: { hasInteracted ? controlValues . y . toFixed ( 2 ) : '0.00' } </ span >
467+ < span > θ: { hasInteracted ? controlValues . theta . toFixed ( 2 ) : '0.00' } </ span >
468+ { ! hasInteracted && (
469+ < span className = "text-gray-400 ml-2" > (Touch joysticks to activate)</ span >
470+ ) }
449471 </ div >
450472 </ div >
451473 </ div >
@@ -517,7 +539,10 @@ export default function VirtualGamepad() {
517539 < div className = "flex space-x-4" >
518540 { /* KICK Button */ }
519541 < button
520- onClick = { sendKick }
542+ onClick = { ( ) => {
543+ setHasInteracted ( true ) ;
544+ sendKick ( ) ;
545+ } }
521546 disabled = { ! isConnected }
522547 className = "w-12 h-12 sm:w-14 sm:h-14 md:w-16 md:h-16 bg-red-600 hover:bg-red-700 disabled:bg-gray-600 disabled:cursor-not-allowed rounded-full font-bold text-white shadow-lg border border-white transition-all duration-200 hover:scale-105"
523548 >
@@ -529,7 +554,10 @@ export default function VirtualGamepad() {
529554
530555 { /* STOP Button */ }
531556 < button
532- onClick = { ( ) => stopHandler ( ) }
557+ onClick = { ( ) => {
558+ setHasInteracted ( true ) ;
559+ stopHandler ( ) ;
560+ } }
533561 disabled = { ! isConnected }
534562 className = "w-12 h-12 sm:w-14 sm:h-14 md:w-16 md:h-16 bg-gray-700 hover:bg-gray-600 disabled:bg-gray-600 disabled:cursor-not-allowed rounded-full font-bold text-white shadow-lg border border-white transition-all duration-200 hover:scale-105"
535563 >
@@ -541,7 +569,10 @@ export default function VirtualGamepad() {
541569
542570 { /* WALK IN SPOT Button */ }
543571 < button
544- onClick = { ( ) => sendTwist ( 0 , 0 , 0 ) }
572+ onClick = { ( ) => {
573+ setHasInteracted ( true ) ;
574+ sendTwist ( 0 , 0 , 0 ) ;
575+ } }
545576 disabled = { ! isConnected }
546577 className = "w-12 h-12 sm:w-14 sm:h-14 md:w-16 md:h-16 bg-green-600 hover:bg-green-700 disabled:bg-gray-600 disabled:cursor-not-allowed rounded-full font-bold text-white shadow-lg border border-white transition-all duration-200 hover:scale-105"
547578 >
0 commit comments