Multiple Vehicles
Use a multiple-vehicle setup when one operator station should keep several vehicles connected at the same time, for example to monitor a fleet and switch which vehicle receives control input. Each vehicle is connected through Fleet Client by name. Video layout and OCP control selection are handled from the operator-side web view.
Multiple-vehicle operation is a gated enterprise feature in the managed portal. This page describes the technical model so the shape is clear, but production fleet supervision usually needs Voysys involvement for portal provisioning, operator permissions, dispatch behavior, and custom UI decisions.
For the single-vehicle connection flow, see Connect Player and Streamer. For the lower-level webview API reference, see Webview and JavaScript SDK.
Before you start
Make sure the basic fleet flow works for one vehicle before adding more.
-
Each vehicle runs Oden Fleet Streamer or an Oden Streamer setup with Fleet Client configured.
-
The Player has the Fleet Client plugin enabled.
-
The Player has the Webview plugin enabled when the operator interface controls connections or video layout.
-
Enable Oden Control Pipeline when the operator station must receive vehicle feedback or send control/user data.
-
Use fleet connections that create Remote Streamer entities in the current Player project. Do not use project-based vehicle connections that download and open a different Player project when a vehicle connects.
-
Give every vehicle a stable, unique fleet name. The webview connection messages use the vehicle
name, not the vehicleid.
List online vehicles
Request the fleet list before showing connect buttons in the operator UI.
The response contains the fleet id, the name to use in connection messages, and the current availability.
const odenClient = getOrCreateOdenLayoutClient();
function updateVehicleList(vehicles) {
for (const vehicle of vehicles) {
console.log(vehicle.name, vehicle.availability);
}
}
odenClient.registerUserMessageCallback("fleet_online_vehicles", updateVehicleList);
odenClient.sendNamedUserMessage("fleet_list_vehicles", {});
Fleet availability values are:
| Availability | Meaning |
|---|---|
|
The vehicle is online and has no active fleet control or monitor session. |
|
The vehicle has an active monitor session, but no active control session. |
|
The vehicle already has an active control session. A second control connection is rejected by fleet management. |
Connect several vehicles
Send one fleet_connect message for each vehicle that should be connected.
Use the name value from fleet_online_vehicles.
const selectedVehicles = ["vehicle_a", "vehicle_b", "vehicle_c"];
for (const vehicleName of selectedVehicles) {
odenClient.sendNamedUserMessage("fleet_connect", {
vehicle_name: vehicleName,
});
}
When the connections are accepted, Fleet Client creates or updates one Remote Streamer per connected vehicle and publishes the vehicle-name-to-Remote-Streamer mapping used by Webview and OCP.
Lay out video for each vehicle
When several connected vehicles expose streams with the same camera names, address a stream as:
vehicle_name:stream_name
For example, if two vehicles both expose a Front stream, register vehicle_a:Front and vehicle_b:Front separately.
The webview layout server maps the vehicle-name prefix to the correct Remote Streamer.
<div id="vehicle-a-front" data-camera-id="vehicle_a:Front"></div>
<div id="vehicle-b-front" data-camera-id="vehicle_b:Front"></div>
odenClient.registerVideo(
"vehicle-a-front",
document.getElementById("vehicle-a-front")
);
odenClient.registerVideo(
"vehicle-b-front",
document.getElementById("vehicle-b-front")
);
You can also listen for video information and build the layout from the names Oden reports.
odenClient.registerCallback((videos) => {
// Example keys after multi-vehicle layout is active:
// "vehicle_a:Front", "vehicle_b:Front"
console.log("Videos available for layout:", videos);
});
See Player Layout and Webview and JavaScript SDK for the full layout API.
Select the active vehicle
OCP can send gamepad input to only one vehicle at a time.
Set active_vehicle in ocp_client_user_data to choose which connected vehicle receives gamepad input.
Changing active_vehicle switches control without disconnecting from the other vehicles.
function selectActiveVehicle(vehicleName) {
odenClient.sendNamedUserMessage("ocp_client_user_data", {
active_vehicle: vehicleName,
client_user_data: {
[vehicleName]: {
user_data: {},
ocp_disable_gamepad: false,
},
},
});
}
selectActiveVehicle("vehicle_a");
For a multi-vehicle session, always set active_vehicle.
If it is omitted while more than one vehicle is connected, OCP marks every connected vehicle as inactive for control and raises VehicleControlInactive.
Vehicles that are connected but not active also report VehicleControlInactive, which is expected.
If your web UI or another operator-side system sends its own control data instead of using OCP gamepad input, set ocp_disable_gamepad: true for that vehicle’s client_user_data.
Only one operator-side client data source should send OCP client data during a session.
Do not mix webview, plugin, and player-side TCP control data in the same session.
Show feedback for every vehicle
OCP publishes feedback for all connected vehicles in ocp_vehicle_user_data.
The vehicle_feedback object is keyed by vehicle name.
odenClient.registerUserMessageCallback("ocp_vehicle_user_data", (data) => {
for (const [vehicleName, feedback] of Object.entries(data.vehicle_feedback)) {
console.log(vehicleName, {
ping: feedback.ping_latency_ms,
roundtrip: feedback.message_latency_roundtrip,
senderFaults: feedback.sender_fault,
receiverFaults: feedback.receiver_fault,
vehicleData: feedback.vehicle_data,
});
}
});
Common fields to show in a multi-vehicle operator UI:
| Field | Use |
|---|---|
|
Network ping latency between operator and vehicle. |
|
OCP message round-trip latency through the control/video feedback path. |
|
How old the last |
|
Operator-side faults such as |
|
Vehicle-side faults such as |
|
Vehicle-side position and user data supplied by the vehicle integration. |
Disconnect a vehicle
Disconnect vehicles individually when the operator no longer needs their video or feedback.
odenClient.sendNamedUserMessage("fleet_disconnect", {
vehicle_name: "vehicle_b",
});
If the disconnected vehicle was the active vehicle, send a new ocp_client_user_data message with another active_vehicle.
Troubleshooting
- Vehicle does not appear in
fleet_online_vehicles -
Confirm that the vehicle is online in Bifrost, the Fleet Client plugin is enabled, and both the vehicle and Player are activated and able to reach the fleet service.
- Connect request does not attach the expected vehicle
-
Check that the UI sends
vehicle_namewith the fleetnamefield. Do not send the fleetid. If the vehicle isControlled, another operator already has a control session. - Only one vehicle shows video, or a camera name appears to collide
-
Use the
vehicle_name:stream_nameform for video layout entries. Without the vehicle prefix, the layout server falls back to the first Remote Streamer that matches the stream name. - No vehicle receives gamepad input
-
In a multi-vehicle session, send
ocp_client_user_datawithactive_vehicleset to one connected vehicle name. Checksender_faultforVehicleControlInactiveandInputLost. - The active vehicle changes but control data stops
-
Check that only one operator-side OCP client data source is active. If webview, plugin, and player-side TCP sources send client data in the same session, OCP stops client data communication and requires a restart.
- Latency or feedback values look stale
-
Check
ms_since_last_vehicle_data,NoFeedbackMessage,VehicleNoResponse, andHighLatency. For custom vehicle integrations, make sureack_timeandack_time_macare returned unmodified in the vehicle response path.