Skip to content

Commit 5e47179

Browse files
committed
fix incorrect joystick mapping and freezing
1 parent 12484e5 commit 5e47179

9 files changed

+55
-84
lines changed

frontend/src/components/OnscreenGamepads.svelte

-6
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,6 @@
1414
let collapsedMode = false; //$rovDataChannelConnState === ConnectionState.connected || $rovDataChannelConnState === ConnectionState.connecting || $rovDataChannelConnState === ConnectionState.reconnecting || $peerServerConnState === ConnectionState.connecting || $peerServerConnState === ConnectionState.reconnecting || $peerServerConnState === ConnectionState.disconnected;
1515
1616
export let visible: boolean = false;
17-
// export let disabled: boolean = false;
18-
// $: if (visible && !disabled) {
19-
// gpadCtrl.clearExternalEventListenerCallbacks();
20-
// } else {
21-
// gpadCtrl.setupGamepadEvents(10);
22-
// }
2317
2418
// TODO? switch to onMount()?
2519
onMount(() => {

frontend/src/js/frontendConnManager.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ export class FrontendConnectionManager {
103103
this.openLivekitRoomInfo.set(openRoomInfo)
104104
}
105105
await listOpenRooms();
106-
this.livekitRoomPollingInterval = Number(setInterval(listOpenRooms, 3000))
106+
this.livekitRoomPollingInterval = Number(setInterval(listOpenRooms, 5000))
107107
}
108108

109109
/**

frontend/src/js/frontendConsts.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ export const EMOJI_MAP = ["🏔", "🏎", "🚃", "🕤", "🐔", "🛤", "🚖"
1919
export const MEMORABLE_PEER_ID_OFFSET = 74646;
2020

2121
export const PING_INTERVAL = 1000 // 1 second in ms
22-
export const MOVE_MSG_TIMEOUT = 300 // 0.8 seconds in ms
22+
export const MOVE_MSG_TIMEOUT = 100 // 0.8 seconds in ms
2323

2424
export enum ConnectionState {
2525
connecting = "Connecting",

frontend/src/js/gamepad.ts

+9-21
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,9 @@ import { GAME_CONTROLLER_BUTTON_CONFIG } from "./frontendConsts";
66
import { throttle } from "./util";
77
import { RovActions } from "./rovActions";
88
import { calculateDesiredMotion } from "./rovUtil";
9-
import { addTooltip } from "../components/HelpTooltips.svelte";
109
import { showToastMessage } from "./toastMessageManager";
1110
import { frontendConnMngr } from './frontendConnManager';
11+
import { addTooltip } from '../components/HelpTooltips.svelte';
1212

1313
// CONSTS
1414
const LEFT_X_AXIS_INDEX = 0;
@@ -26,7 +26,6 @@ export class GamepadController {
2626
gpadEmulator: GamepadEmulator;
2727
gpadApiWrapper: GamepadApiWrapper;
2828
touchedGpadButtonCount: number = 0;
29-
throttleDelay: number = 10;
3029
onAxisChange: null | ((gamepad: Gamepad) => void);
3130
onButtonChange: null | ((gamepad: Gamepad, buttonsChangedMask: (false | buttonChangeDetails)[]) => void);
3231

@@ -35,7 +34,7 @@ export class GamepadController {
3534
this.touchedGpadButtonCount = 0
3635
}
3736

38-
start(onAxisChange: null | ((gamepad: Gamepad) => void), onButtonChange: null | ((gamepad: Gamepad, buttonsChangedMask: (false | buttonChangeDetails)[]) => void), throttleDelay: number) {
37+
start(onAxisChange: null | ((gamepad: Gamepad) => void), onButtonChange: null | ((gamepad: Gamepad, buttonsChangedMask: (false | buttonChangeDetails)[]) => void)) {
3938
this.gpadUi.start();
4039
// override the default browser gamepad api with the gamepad emulator before setting up the events,
4140
// the emulator will either use the real gamepad api if a gamepad is plugged in or it will inject the onscreen gamepad as if it were comming from the gamepad api.
@@ -47,12 +46,17 @@ export class GamepadController {
4746
// initilize the GamepadInterface class with the config from the button consts file
4847
this.gpadApiWrapper = new GamepadApiWrapper({
4948
axisDeadZone: 0.05,
50-
updateDelay: 10,
49+
updateDelay: 28,
5150
buttonConfigs: GAME_CONTROLLER_BUTTON_CONFIG,
5251
});
52+
53+
// setup gpadApiWrapper gamepad events.
5354
this.onAxisChange = onAxisChange;
5455
this.onButtonChange = onButtonChange;
55-
this.setupGamepadEvents(throttleDelay);
56+
this.gpadApiWrapper.onGamepadConnect(this.gamepadConnectDisconnectHandler.bind(this));
57+
this.gpadApiWrapper.onGamepadDisconnect(this.gamepadConnectDisconnectHandler.bind(this));
58+
this.gpadApiWrapper.onGamepadAxisChange(this.handleAxisChange.bind(this));
59+
this.gpadApiWrapper.onGamepadButtonChange(this.handleButtonChange.bind(this));
5660
}
5761

5862
setupOnscreenGamepad(GPAD_DISPLAY_CONTAINER) {
@@ -73,25 +77,9 @@ export class GamepadController {
7377
if (connectedGamepadCount > 1) console.log("WARNING: More than one gamepad connected!", gamepads);
7478
}
7579

76-
setInputThrottle(throttleDelay) {
77-
this.throttleDelay = throttleDelay;
78-
this.gpadApiWrapper.onGamepadAxisChange(throttle(this.handleAxisChange.bind(this), this.throttleDelay, { trailing: true, leading: true }));
79-
this.gpadApiWrapper.onGamepadButtonChange(throttle(this.handleButtonChange.bind(this), this.throttleDelay, { trailing: true, leading: true }));
80-
}
81-
82-
setupGamepadEvents(throttleDelay) {
83-
// setup gpadApiWrapper gamepad events.
84-
this.gpadApiWrapper.onGamepadConnect(this.gamepadConnectDisconnectHandler.bind(this));
85-
this.gpadApiWrapper.onGamepadDisconnect(this.gamepadConnectDisconnectHandler.bind(this));
86-
this.setInputThrottle(throttleDelay);
87-
}
88-
8980
handleButtonChange(gpadIndex, gamepad, buttonsChangedMask) {
9081
if (gpadIndex != 0 || !gamepad || !gamepad.buttons) return;
9182
if (this.onButtonChange) this.onButtonChange(gamepad, buttonsChangedMask);
92-
if ((buttonsChangedMask[8] && buttonsChangedMask[8].released) || (buttonsChangedMask[9] && buttonsChangedMask[9].released)) {
93-
this.gpadUi.toggleGamepadHelpScreen();
94-
}
9583

9684
let noGamepadButtonTouched = true;
9785
for (let i = 0; i < buttonsChangedMask.length; i++) {

frontend/src/js/rovActions.ts

+3-15
Original file line numberDiff line numberDiff line change
@@ -57,18 +57,6 @@ class RovActionsClass {
5757
return val.pressed || val.heldDown;
5858
})
5959
this.sendButtonsToRov(pressedButtons);
60-
61-
// else if (gamepad.buttons[12].pressed) {
62-
// let delay = gpadCtrl.throttleDelay + 1;
63-
// // this.setInputThrottle(delay);
64-
// } else if (gamepad.buttons[13].pressed) {
65-
// let delay = Math.max(this.throttleDelay - 1, 1);
66-
// this.setInputThrottle(delay);
67-
// } else if (gamepad.buttons[14].pressed) {
68-
// this.setInputThrottle(10);
69-
// } else if (gamepad.buttons[15].pressed) {
70-
// this.setInputThrottle(100);
71-
// }
7260
}
7361

7462
gamepadAxisTriggers(gamepad: Gamepad) {
@@ -98,7 +86,7 @@ class RovActionsClass {
9886
this.lastPingTime = now;
9987
}
10088
if (now - this.lastMovementTime > MOVE_MSG_TIMEOUT) {
101-
this.moveRov(0, 0, 0, 0, 0);
89+
frontendRovMsgHandler.sendRovMessage({ Move: this.lastMove }, null);
10290
this.lastMovementTime = now;
10391
}
10492
}, 10))
@@ -135,13 +123,13 @@ class RovActionsClass {
135123
}
136124

137125
moveRov(VelocityX, VelocityY, VelocityZ, AngularVelocityYaw, btnBitmask: number = -1) {
138-
// FIXME: this is a hack to get the buttons to work with the mavlink message
139126
const ButtonBitmask = btnBitmask === -1 ? this.lastMove.ButtonBitmask : btnBitmask;
140127
const movementDelta = (VelocityX - this.lastMove.VelocityX) + (VelocityY - this.lastMove.VelocityY) + (VelocityZ - this.lastMove.VelocityZ) + (AngularVelocityYaw - this.lastMove.AngularVelocityYaw);
141128
const totalMovement = Math.abs(VelocityX) + Math.abs(VelocityY) + Math.abs(VelocityZ) + Math.abs(AngularVelocityYaw);
142129
// const timeSinceLastMoveCmd = Date.now() - this.lastMovementTime;
143130
// if (totalMovement > 0.1 && movementDelta < 0.01 && timeSinceLastMoveCmd < 400) return;
144-
const move = { VelocityX: VelocityY * 2, VelocityY: VelocityX, VelocityZ, AngularVelocityYaw, ButtonBitmask }
131+
const move = { VelocityX, VelocityY, VelocityZ, AngularVelocityYaw, ButtonBitmask }
132+
console.log("MOVE:", move.VelocityX, move.VelocityY, move.VelocityZ, move.AngularVelocityYaw, move.ButtonBitmask)
145133
frontendRovMsgHandler.sendRovMessage({ Move: move }, null);
146134
this.lastMove = move;
147135
this.lastMovementTime = Date.now();

frontend/src/js/rovMessageHandler.ts

+33-32
Original file line numberDiff line numberDiff line change
@@ -23,73 +23,74 @@ export class FrontendRovMsgHandlerClass {
2323
let rawData = new Uint8Array(msgBytes)
2424
if (!rawData || rawData.length === 0) return;
2525
const msgData = rov_actions_proto.RovResponse.decode(new Uint8Array(msgBytes));
26+
const ExchangeId = msgData.ExchangeId;
2627

27-
this.runExchangeCallback(msgData.ExchangeId, msgData);
28+
this.runExchangeCallback(msgData, ExchangeId);
2829
if (msgData.Done) {
29-
return this.handleDoneMsgRecived(msgData.ExchangeId, msgData.Done);
30+
return this.handleDoneMsgRecived(msgData.Done, ExchangeId);
3031
} else if (msgData.Error) {
31-
return this.handleErrorMsgRecived(msgData.ExchangeId, msgData.Error);
32+
return this.handleErrorMsgRecived(msgData.Error, ExchangeId);
3233
} else if (msgData.Pong) {
33-
return this.handlePongMsgRecived(msgData.ExchangeId, msgData.Pong);
34+
return this.handlePongMsgRecived(msgData.Pong, ExchangeId);
3435
} else if (msgData.ContinuedOutput) {
35-
return this.handleContinuedOutputMsgRecived(msgData.ExchangeId, msgData.ContinuedOutput);
36+
return this.handleContinuedOutputMsgRecived(msgData.ContinuedOutput, ExchangeId);
3637
} else if (msgData.SensorUpdates) {
37-
return this.handleSensorUpdatesMsgRecived(msgData.ExchangeId, msgData.SensorUpdates);
38+
return this.handleSensorUpdatesMsgRecived(msgData.SensorUpdates, ExchangeId);
3839
} else if (msgData.PasswordRequired) {
39-
return this.handlePasswordRequiredMsgRecived(msgData.ExchangeId, msgData.PasswordRequired);
40+
return this.handlePasswordRequiredMsgRecived(msgData.PasswordRequired, ExchangeId);
4041
} else if (msgData.PasswordAccepted) {
41-
return this.handlePasswordAcceptedMsgRecived(msgData.ExchangeId, msgData.PasswordAccepted);
42+
return this.handlePasswordAcceptedMsgRecived(msgData.PasswordAccepted, ExchangeId);
4243
} else if (msgData.PasswordInvalid) {
43-
return this.handlePasswordInvalidMsgRecived(msgData.ExchangeId, msgData.PasswordInvalid);
44+
return this.handlePasswordInvalidMsgRecived(msgData.PasswordInvalid, ExchangeId);
4445
} else if (msgData.DriverChanged) {
45-
return this.handleDriverChangedMsgRecived(msgData.ExchangeId, msgData.DriverChanged);
46+
return this.handleDriverChangedMsgRecived(msgData.DriverChanged, ExchangeId);
4647
} else if (msgData.ClientConnected) {
47-
return this.handleClientConnectedMsgRecived(msgData.ExchangeId, msgData.ClientConnected);
48+
return this.handleClientConnectedMsgRecived(msgData.ClientConnected, ExchangeId);
4849
} else if (msgData.ClientDisconnected) {
49-
return this.handleClientDisconnectedMsgRecived(msgData.ExchangeId, msgData.ClientDisconnected);
50+
return this.handleClientDisconnectedMsgRecived(msgData.ClientDisconnected, ExchangeId);
5051
} else if (msgData.SimplepeerSignal && msgData.SimplepeerSignal.Message) {
5152
frontendConnMngr.ingestSimplePeerSignallingMsg(msgData.SimplepeerSignal.Message);
5253
} else if (msgData.Mavlink) {
53-
return this.handleMavlinkMessageRecived(msgData.ExchangeId, msgData.Mavlink);
54+
return this.handleMavlinkMessageRecived(msgData.Mavlink, ExchangeId);
5455
} else if (msgData.SystemMonitor) {
55-
return this.handleSystemMonitorMsgRecived(msgData.ExchangeId, msgData.SystemMonitor);
56+
return this.handleSystemMonitorMsgRecived(msgData.SystemMonitor, ExchangeId);
5657
} else if (msgData.LogMessage) {
57-
return this.handleLogMsgRecived(msgData.ExchangeId, msgData.LogMessage);
58+
return this.handleLogMsgRecived(msgData.LogMessage, ExchangeId);
5859
} else {
5960
console.warn("Unhandled ROV message recived: ", msgData);
6061
}
6162
}
6263

63-
handleDoneMsgRecived(ExchangeId: number, msgData: rov_actions_proto.IDoneResponse) {
64+
handleDoneMsgRecived(msgData: rov_actions_proto.IDoneResponse, ExchangeId: number) {
6465
if (URL_PARAMS.DEBUG_MODE) console.debug("Done: ", msgData);
6566
}
6667

67-
handleErrorMsgRecived(ExchangeId: number, msgData: rov_actions_proto.IErrorResponse) {
68+
handleErrorMsgRecived(msgData: rov_actions_proto.IErrorResponse, ExchangeId: number) {
6869
console.warn("ROV Error: ", msgData);
6970
showToastMessage("ROV Error: " + msgData.Message, 2000, null);
7071
}
7172

72-
handlePongMsgRecived(ExchangeId: number, msgData: rov_actions_proto.IPongResponse) {
73+
handlePongMsgRecived(msgData: rov_actions_proto.IPongResponse, ExchangeId: number) {
7374
lastTimeRecvdPong = Date.now();
7475
const networkPingDelay = lastTimeRecvdPong - Number.parseFloat(msgData.Time) // since the rpi replies with the ms time we sent in the ping in the pong message
7576
networkLatencyMs.set(networkPingDelay);
7677
}
7778

78-
handleContinuedOutputMsgRecived(ExchangeId: number, msgData: rov_actions_proto.IContinuedOutputResponse) {
79+
handleContinuedOutputMsgRecived(msgData: rov_actions_proto.IContinuedOutputResponse, ExchangeId: number) {
7980
if (URL_PARAMS.DEBUG_MODE) console.debug("ContinuedOutput: ", ExchangeId, msgData);
8081
// pass
8182
}
8283

83-
handleSensorUpdatesMsgRecived(ExchangeId: number, msgData: rov_actions_proto.ISensorUpdatesResponse) {
84+
handleSensorUpdatesMsgRecived(msgData: rov_actions_proto.ISensorUpdatesResponse, ExchangeId: number) {
8485
if (URL_PARAMS.DEBUG_MODE) console.debug("SensorUpdates: ", msgData);
8586
updateSensorValues(msgData);
8687
}
8788

88-
handleSystemMonitorMsgRecived(ExchangeId: number, msgData: rov_actions_proto.ISystemMonitorResponse) {
89+
handleSystemMonitorMsgRecived(msgData: rov_actions_proto.ISystemMonitorResponse, ExchangeId: number) {
8990
updateSystemMonitorDisplay(msgData.CpuTemp, msgData.CpuUsage, msgData.MemoryUsage, msgData.DiskUsage, msgData.Warnings);
9091
}
9192

92-
handlePasswordRequiredMsgRecived(ExchangeId: number, msgData: rov_actions_proto.IPasswordRequiredResponse) {
93+
handlePasswordRequiredMsgRecived(msgData: rov_actions_proto.IPasswordRequiredResponse, ExchangeId: number) {
9394
if (URL_PARAMS.DEBUG_MODE) console.debug("PasswordRequired for rovId:", msgData.RovId);
9495
// TODO: use the rovId to determine if we have authtoken
9596
modalPasswordPrompt("Enter ROV Password", "").then((password) => {
@@ -106,17 +107,17 @@ export class FrontendRovMsgHandlerClass {
106107
})
107108
}
108109

109-
handlePasswordAcceptedMsgRecived(ExchangeId: number, msgData: rov_actions_proto.IPasswordAcceptedResponse) {
110+
handlePasswordAcceptedMsgRecived(msgData: rov_actions_proto.IPasswordAcceptedResponse, ExchangeId: number) {
110111
showToastMessage("Password Accepted", 1000, null);
111112
}
112113

113-
handlePasswordInvalidMsgRecived(ExchangeId: number, msgData: rov_actions_proto.IPasswordInvalidResponse) {
114+
handlePasswordInvalidMsgRecived(msgData: rov_actions_proto.IPasswordInvalidResponse, ExchangeId: number) {
114115
showToastMessage("Wrong Password", 1000, null);
115-
this.handlePasswordRequiredMsgRecived(ExchangeId, msgData);
116+
this.handlePasswordRequiredMsgRecived(msgData, ExchangeId);
116117
}
117118

118119
// TODO:
119-
handleDriverChangedMsgRecived(ExchangeId: number, msgData: rov_actions_proto.IDriverChangedResponse) {
120+
handleDriverChangedMsgRecived(msgData: rov_actions_proto.IDriverChangedResponse, ExchangeId: number) {
120121
let ourLivekitIdentity = frontendConnMngr.currentLivekitIdentity.get();
121122
if (msgData.DriverPeerId == ourLivekitIdentity) {
122123
showToastMessage("You are now the driver");
@@ -127,7 +128,7 @@ export class FrontendRovMsgHandlerClass {
127128
}
128129
}
129130

130-
handleMavlinkMessageRecived(ExchangeId: number, msgData: rov_actions_proto.IMavlinkResponse) {
131+
handleMavlinkMessageRecived(msgData: rov_actions_proto.IMavlinkResponse, ExchangeId: number) {
131132
if (!msgData.Message) return;
132133
const mavMessage = DECODE_TXT(msgData.Message)
133134
try {
@@ -138,21 +139,21 @@ export class FrontendRovMsgHandlerClass {
138139
}
139140
}
140141

141-
handleClientConnectedMsgRecived(ExchangeId: number, msgData: rov_actions_proto.IClientConnectedResponse) {
142+
handleClientConnectedMsgRecived(msgData: rov_actions_proto.IClientConnectedResponse, ExchangeId: number) {
142143
showToastMessage(msgData.ClientPeerId + " Connected to ROV", 1500, null);
143144
}
144145

145-
handleClientDisconnectedMsgRecived(ExchangeId: number, msgData: rov_actions_proto.IClientConnectedResponse) {
146+
handleClientDisconnectedMsgRecived(msgData: rov_actions_proto.IClientConnectedResponse, ExchangeId: number) {
146147
showToastMessage(msgData.ClientPeerId + " Disconnected from ROV", 1500, null);
147148
}
148149

149-
handleLogMsgRecived(ExchangeId: number, msgData: rov_actions_proto.ILogMessageResponse) {
150+
handleLogMsgRecived(msgData: rov_actions_proto.ILogMessageResponse, ExchangeId: number) {
150151
if (URL_PARAMS.SHOW_REMOTE_LOGS) {
151152
let logArgs = JSON.parse(msgData.Message);
152153
if (!Array.isArray(logArgs)) logArgs = [logArgs];
153154
if (logArgs.length === 0) return;
154155
if (typeof logArgs[0] === 'string') logArgs[0] = "REMOTE LOG: " + logArgs[0];
155-
else logArgs.unshift("REMOTE LOG: ");
156+
else logArgs.unshift("REMOTE LOG: "); // add "REMOTE LOG: " to the start of the logArgs
156157
if (msgData.Level == rov_actions_proto.LogLevel.Debug) console.debug(...logArgs);
157158
else if (msgData.Level == rov_actions_proto.LogLevel.Info) console.info(...logArgs);
158159
else if (msgData.Level == rov_actions_proto.LogLevel.Warning) console.warn(...logArgs);
@@ -178,7 +179,7 @@ export class FrontendRovMsgHandlerClass {
178179
}
179180
}
180181

181-
runExchangeCallback(ExchangeId: number, msgData: rov_actions_proto.RovResponse) {
182+
runExchangeCallback(msgData: rov_actions_proto.RovResponse, ExchangeId: number) {
182183
const replyExchageData = this.replyContinuityCallbacks[ExchangeId];
183184
if (replyExchageData) {
184185
replyExchageData.callback && replyExchageData.callback(msgData);

frontend/src/js/rovUtil.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@ export function calculateDesiredMotion(axes) {
44
let strafe = Number(axes[2].toFixed(3));
55
let vertical = -1 * Number(axes[3].toFixed(3));
66
return {
7-
VelocityX: strafe,
8-
VelocityY: forward,
7+
VelocityX: forward,
8+
VelocityY: strafe,
99
VelocityZ: vertical, // vector in the form [x,y,z]
1010
AngularVelocityYaw: turn,
1111
}

frontend/src/js/shared/mavlink2RestMessages.ts

+4-4
Original file line numberDiff line numberDiff line change
@@ -307,10 +307,10 @@ export const heartbeat = () => {
307307
export const manualControl = (x: number, y: number, z: number, r: number, buttonBitmask: number) => {
308308
return addMessageHeader({
309309
type: "MANUAL_CONTROL",
310-
x: Math.floor(x),
311-
y: Math.floor(y),
312-
z: Math.floor(z),
313-
r: Math.floor(r),
310+
x: Math.floor(x), // X is forward in the ROV
311+
y: Math.floor(y), // Y is left/right in the ROV
312+
z: Math.floor(z), // Z is up/down in the ROV
313+
r: Math.floor(r), // R is yaw in the ROV
314314
buttons: buttonBitmask,
315315
target: 1,
316316
} as MavMessages.ManualControl)

rov-internal-website/js/msgHandler.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@ function handleInternalWebpageActions(senderId: string, msgProto: rov_actions_pr
1212
return true;
1313
} else if (msgProto.Move) {
1414
if (designated_driver_user_id && designated_driver_user_id !== senderId) return false;
15-
let x = (msgProto.Move.VelocityX || 0) * 500
16-
let y = (msgProto.Move.VelocityY || 0) * 500
15+
let x = (msgProto.Move.VelocityX || 0) * 1000 // X is forward in the ROV
16+
let y = (msgProto.Move.VelocityY || 0) * 1000 // Y is left/right in the ROV)
1717
let z = (msgProto.Move.VelocityZ || 0) * 500 + 500
1818
let r = (msgProto.Move.AngularVelocityYaw || 0) * 500
1919
let buttonBitmask = msgProto.Move.ButtonBitmask || 0

0 commit comments

Comments
 (0)