Skip to content

Commit

Permalink
Remove ROS assumptions when using services with foxglove websocket (#…
Browse files Browse the repository at this point in the history
…7102)

**User-Facing Changes**
Remove ROS assumptions when using services with foxglove websocket

**Description**
Updates the websocket player to comply with the latest `ws-protocol`
spec changes made in foxglove/ws-protocol#563.
This allows to remove some ROS specific assumptions which makes it
easier to advertise services from non-ROS systems.

Fixes #6970
Resolves FG-5280
  • Loading branch information
achim-k authored and pezy committed Sep 14, 2024
1 parent 99dcd4f commit c3fd09c
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 28 deletions.
2 changes: 1 addition & 1 deletion packages/studio-base/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@
"@foxglove/velodyne-cloud": "1.0.1",
"@foxglove/wasm-bz2": "0.1.1",
"@foxglove/wasm-lz4": "1.0.2",
"@foxglove/ws-protocol": "0.7.1",
"@foxglove/ws-protocol": "0.7.2",
"@mcap/core": "1.3.0",
"@mui/icons-material": "5.14.12",
"@mui/material": "5.14.10",
Expand Down
68 changes: 48 additions & 20 deletions packages/studio-base/src/players/FoxgloveWebSocketPlayer/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -637,47 +637,74 @@ export default class FoxgloveWebSocketPlayer implements Player {
return;
}

let schemaEncoding: string;
let defaultSchemaEncoding = "";
if (this.#serviceCallEncoding === "json") {
schemaEncoding = "jsonschema";
defaultSchemaEncoding = "jsonschema";
} else if (this.#serviceCallEncoding === "ros1") {
schemaEncoding = "ros1msg";
defaultSchemaEncoding = "ros1msg";
} else if (this.#serviceCallEncoding === "cdr") {
schemaEncoding = "ros2msg";
} else {
throw new Error(`Unsupported encoding "${this.#serviceCallEncoding}"`);
defaultSchemaEncoding = "ros2msg";
}

for (const service of services) {
const serviceProblemId = `service:${service.id}`;
// If not explicitly given, derive request / response type name from the service type
// (according to ROS convention).
const requestType = service.request?.schemaName ?? `${service.type}_Request`;
const responseType = service.response?.schemaName ?? `${service.type}_Response`;
const requestMsgEncoding = service.request?.encoding ?? this.#serviceCallEncoding;
const responseMsgEncoding = service.response?.encoding ?? this.#serviceCallEncoding;

try {
const requestType = `${service.type}_Request`;
const responseType = `${service.type}_Response`;
if (
(service.request == undefined && service.requestSchema == undefined) ||
(service.response == undefined && service.responseSchema == undefined)
) {
throw new Error("Invalid service definition, at least one required field is missing");
} else if (
!defaultSchemaEncoding &&
(service.request == undefined || service.response == undefined)
) {
throw new Error("Cannot determine service request or response schema encoding");
} else if (!SUPPORTED_SERVICE_ENCODINGS.includes(requestMsgEncoding)) {
const supportedEncodingsStr = SUPPORTED_SERVICE_ENCODINGS.join(", ");
throw new Error(
`Unsupported service request message encoding. ${requestMsgEncoding} not in list of supported encodings [${supportedEncodingsStr}]`,
);
}

const parsedRequest = parseChannel({
messageEncoding: this.#serviceCallEncoding,
messageEncoding: requestMsgEncoding,
schema: {
name: requestType,
encoding: schemaEncoding,
data: textEncoder.encode(service.requestSchema),
encoding: service.request?.schemaEncoding ?? defaultSchemaEncoding,
data: textEncoder.encode(service.request?.schema ?? service.requestSchema),
},
});
const parsedResponse = parseChannel({
messageEncoding: this.#serviceCallEncoding,
messageEncoding: responseMsgEncoding,
schema: {
name: responseType,
encoding: schemaEncoding,
data: textEncoder.encode(service.responseSchema),
encoding: service.response?.schemaEncoding ?? defaultSchemaEncoding,
data: textEncoder.encode(service.response?.schema ?? service.responseSchema),
},
});
const requestMsgDef = rosDatatypesToMessageDefinition(
parsedRequest.datatypes,
requestType,
);
const requestMessageWriter = ROS_ENCODINGS.includes(this.#serviceCallEncoding)
? this.#serviceCallEncoding === "ros1"
? new Ros1MessageWriter(requestMsgDef)
: new Ros2MessageWriter(requestMsgDef)
: new JsonMessageWriter();
let requestMessageWriter: MessageWriter | undefined;
if (requestMsgEncoding === "ros1") {
requestMessageWriter = new Ros1MessageWriter(requestMsgDef);
} else if (requestMsgEncoding === "cdr") {
requestMessageWriter = new Ros2MessageWriter(requestMsgDef);
} else if (requestMsgEncoding === "json") {
requestMessageWriter = new JsonMessageWriter();
}
if (!requestMessageWriter) {
// Should never go here as we sanity-checked the encoding already above
throw new Error(`Unsupported service request message encoding ${requestMsgEncoding}`);
}

// Add type definitions for service response and request
this.#updateDataTypes(parsedRequest.datatypes);
Expand Down Expand Up @@ -1059,10 +1086,11 @@ export default class FoxgloveWebSocketPlayer implements Player {

const { service, parsedResponse, requestMessageWriter } = resolvedService;

const requestMsgEncoding = service.request?.encoding ?? this.#serviceCallEncoding!;
const serviceCallRequest: ServiceCallPayload = {
serviceId: service.id,
callId: ++this.#nextServiceCallId,
encoding: this.#serviceCallEncoding!,
encoding: requestMsgEncoding,
data: new DataView(new Uint8Array().buffer),
};

Expand Down
14 changes: 7 additions & 7 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2568,7 +2568,7 @@ __metadata:
"@foxglove/velodyne-cloud": 1.0.1
"@foxglove/wasm-bz2": 0.1.1
"@foxglove/wasm-lz4": 1.0.2
"@foxglove/ws-protocol": 0.7.1
"@foxglove/ws-protocol": 0.7.2
"@mcap/core": 1.3.0
"@mui/icons-material": 5.14.12
"@mui/material": 5.14.10
Expand Down Expand Up @@ -2816,14 +2816,14 @@ __metadata:
languageName: node
linkType: hard

"@foxglove/ws-protocol@npm:0.7.1":
version: 0.7.1
resolution: "@foxglove/ws-protocol@npm:0.7.1"
"@foxglove/ws-protocol@npm:0.7.2":
version: 0.7.2
resolution: "@foxglove/ws-protocol@npm:0.7.2"
dependencies:
debug: ^4
eventemitter3: ^5.0.1
tslib: ^2.6.0
checksum: 913681bf45109f9989d60329270727381192e5fc278de1df50bb5c88f2376c7c97570e9a8c79c5761c3a6af0277e88b9a455c3973205c7d6bbdcf8f8a9dd3567
tslib: ^2.6.2
checksum: f6bfb467db8eec1290689364b9f5a2542a4248b41a214d88ee1ca1d56d160e178fa2eedd7211447d2c29e592ea2986643ad06f51283c4873848d28cb166c2bd9
languageName: node
linkType: hard

Expand Down Expand Up @@ -19834,7 +19834,7 @@ __metadata:
languageName: node
linkType: hard

"tslib@npm:2.6.2, tslib@npm:^2, tslib@npm:^2.0.0, tslib@npm:^2.0.1, tslib@npm:^2.0.3, tslib@npm:^2.1.0, tslib@npm:^2.4.0, tslib@npm:^2.5.0, tslib@npm:^2.6.0":
"tslib@npm:2.6.2, tslib@npm:^2, tslib@npm:^2.0.0, tslib@npm:^2.0.1, tslib@npm:^2.0.3, tslib@npm:^2.1.0, tslib@npm:^2.4.0, tslib@npm:^2.5.0, tslib@npm:^2.6.0, tslib@npm:^2.6.2":
version: 2.6.2
resolution: "tslib@npm:2.6.2"
checksum: 329ea56123005922f39642318e3d1f0f8265d1e7fcb92c633e0809521da75eeaca28d2cf96d7248229deb40e5c19adf408259f4b9640afd20d13aecc1430f3ad
Expand Down

0 comments on commit c3fd09c

Please sign in to comment.