使用原生的 JavaScript,不依赖于任何特定的库与 ROSBridge进行通信
创建与 ROS 的连接:
var rosbridge_url = "ws://localhost:9090";
var ws = new WebSocket(rosbridge_url);
ws.onopen = function(event) {
console.log('Connected to ' + rosbridge_url);
};
ws.onerror = function(error) {
console.log('WebSocket Error: ', error);
};
ws.onclose = function(event) {
console.log('Connection to ' + rosbridge_url + ' closed.');
};
发布一个话题:
var publishMessage = {
op: 'publish',
id: '1',
topic: '/cmd_vel_mux/input/teleop',
msg: {
linear: {
x: 1.0,
y: 0.0,
z: 0.0
},
angular: {
x: 0.0,
y: 0.0,
z: 0.0
}
}
};
ws.send(JSON.stringify(publishMessage));
订阅一个话题:
var subscribeMessage = {
op: 'subscribe',
id: '2',
topic: '/odom',
type: 'nav_msgs/Odometry'
};
ws.send(JSON.stringify(subscribeMessage));
ws.onmessage = function(event) {
var response = JSON.parse(event.data);
if (response.op === 'publish' && response.topic === '/odom') {
console.log('Received message: ', response.msg);
}
};
调用service服务:
var serviceCallMessage = {
op: 'call_service',
id: '3',
service: '/add_two_ints',
args: {
a: 1,
b: 2
}
};
ws.send(JSON.stringify(serviceCallMessage));
ws.onmessage = function(event) {
var response = JSON.parse(event.data);
if (response.op === 'service_response' && response.id === '3') {
console.log('Service response: ', response.values);
}
};
调用 ROS Action 需要多个步骤,因为 action 包含 goal、feedback 和 result,且 action server 是由多个话题组成的:
// 发送目标
var actionGoalMessage = {
op: 'publish',
id: 'action_goal_1',
topic: '/move_base/goal',
msg: {
goal_id: {
id: 'goal_1'
},
goal: {
target_pose: {
// Fill in the details of the target pose.
}
}
}
};
ws.send(JSON.stringify(actionGoalMessage));
// 订阅反馈
var actionFeedbackMessage = {
op: 'subscribe',
id: 'action_feedback_1',
topic: '/move_base/feedback',
};
ws.send(JSON.stringify(actionFeedbackMessage));
// 订阅结果
var actionResultMessage = {
op: 'subscribe',
id: 'action_result_1',
topic: '/move_base/result',
};
ws.send(JSON.stringify(actionResultMessage));
ws.onmessage = function(event) {
var response = JSON.parse(event.data);
if (response.op === 'publish' && response.topic === '/move_base/feedback') {
console.log('Action feedback: ', response.msg);
} else if (response.op === 'publish' && response.topic === '/move_base/result') {
console.log('Action result: ', response.msg);
}
};
在 rosbridge 的设计中,它是作为一个 ROS 的客户端,可以通过它订阅和发布话题、调用和提供服务、发送和接收 action 目标和反馈。但是,从设计上来看,rosbridge 并没有提供作为 ROS 服务或 action 服务器的功能。
服务端通常是由具体的 ROS 节点(通常是 Python 或 C++ 脚本)实现的,它们直接与 ROS 核心进行通信,提供实际的服务逻辑。
如果你希望在 JavaScript 环境中实现一个服务端,你可能需要使用一个可以直接与 ROS 核心通信的 JavaScript 库(例如 rosnodejs),而不是使用 rosbridge。rosbridge 的目标是提供一个方便的接口,使得在浏览器或其他 WebSocket 支持的环境中的应用可以与 ROS 进行通信,而不是直接实现 ROS 节点。
在 ROSBridge 的协议中,id
字段通常用来关联请求和响应。这个字段在调用服务或者订阅/取消订阅主题的时候通常会被用到。你可以为每个请求分配一个唯一的 id
,然后当你收到来自 ROSBridge 的响应时,这个 id
会被包含在响应中,这样你就可以知道这个响应是对哪个请求的回应。
例如,当你发送一个调用服务的请求时,你可以包含一个 id
字段:
var serviceCallMessage = {
op: 'call_service',
id: 'service_call_1',
service: '/add_two_ints',
args: {
a: 1,
b: 2
}
};
然后当你收到 ROSBridge 的响应时,这个 id
会被包含在响应中:
ws.onmessage = function(event) {
var response = JSON.parse(event.data);
if (response.op === 'service_response' && response.id === 'service_call_1') {
console.log('Service response: ', response.values);
}
};
通过这种方式,即使你同时发送了多个服务调用请求,你也能准确地知道每个响应对应的是哪个请求。
参考博客:
https://blog.csdn.net/lovely_yoshino/article/details/105324257?spm=1001.2014.3001.5506