Open DentOpt opened 3 years ago
I can confirm the same problem, the /topic is listed, but the PoseStamped message echo does not appear
Could anyone please verify PoseStamped JSON structure below is valid? (slightly linted from above post, with added sequence int)
let PoseStamped = new ROSLIB.Message({
header: {
seq: 1,
stamp: {
secs: 0,
nsecs: 100
},
frame_id: "world"
},
pose: {
position: {
x: 0.0,
y: 0.0,
z: 0.0
},
orientation: {
x: 0.0,
y: 0.0,
z: 0.0,
w: 1.0
}
}
});
Sorry for being late, would you please try
DEBUG=ros2-web-bridge* node bin/rosbridge.js
to see any useful debug information?
Thanks very much for your response @minggangw
Bridge Response: {"op":"status","level":"error","msg":"publish: TypeError: Invalid argument: frame_id in Header","id"
to which I've tried both: frame_id : "map" and frame_id : "world"
without success
I noticed there was an error
ros2-web-bridge:Bridge JSON command received: {"op":"publish","id":"publish:/pose:4","topic":"/pose","msg":{"isAdvertised":false,"compression":"none","throttle_rate":0,"latch":false,"queue_size":100,"queue_length":0,"reconnect_on_close":true},"latch":false} +0ms ros2-web-bridge:Bridge Publish a topic named /pose with {"isAdvertised":false,"compression":"none","throttle_rate":0,"latch":false,"queue_size":100,"queue_length":0,"reconnect_on_close":true} +0ms ros2-web-bridge:Bridge Response: {"op":"status","level":"error","msg":"publish: TypeError: Invalid argument: x in Point","id":"publish:/pose:4"} +0ms
error in PoseStamped is "msg":"publish: TypeError: Invalid argument: frame_id in Header","id":"publish:/move_base_simple/goal:2"}
error in Pose is "msg":"publish: TypeError: Invalid argument: x in Point","id":"publish:/pose:4"}
do the errors originate from JSON?
/PoseStamped
var PoseStamped = new ROSLIB.Topic({
header: {
stamp: {
secs: 0,
nsecs: 100
},
frame_id: "world" //tf_prefix+"/"+map_frame;
},
pose: {
position: {
x: 0.0,
y: 0.0,
z: 0.0
},
orientation: {
x: 0.0,
y: 0.0,
z: 0.0,
w: 1.0
}
}
});
/pose
var pose_publisher = new ROSLIB.Topic({
ros : ros,
name : '/pose',
messageType : 'geometry_msgs/Pose'
});
var pose_msg = new ROSLIB.Topic({
position: {
x: 0.0,
y: 0.0,
z: 0.0
},
orientation: {
x: 0.0,
y: 0.0,
z: 0.0,
w: 1.0
}
});
The Time.msg
is ROS2 is different from that of ROS1, please see https://github.com/ros2/rcl_interfaces/blob/master/builtin_interfaces/msg/Time.msg, please reference the example to see if it will work, thanks!
thanks for the information!
unfortunately, the Bridge response Error remains exactly the same as before. I´ve matched the ROS2 Time.msg definition you referenced above, as well as tried variations in frame id: main frame, world frame, map frame.
No dice.
Sharing the complete code for verification:
This example will pubilish a topic named "example_topic".
Connecting to rosbridge...
Publish message:
ros2-web-bridge:Bridge Publish a topic named /move_base_simple/goal with {"isAdvertised":false,"compression":"none","throttle_rate":0,"latch":false,"queue_size":100,"queue_length":0,"reconnect_on_close":true} +1ms
ros2-web-bridge:Bridge Response: {"op":"status","level":"error","msg":"publish: TypeError: Invalid argument: frame_id in Header","id":"publish:/move_base_simple/goal:77"} +0ms
The JSON string that the bridge received is
{"isAdvertised":false,"compression":"none","throttle_rate":0,"latch":false,"queue_size":100,"queue_length":0,"reconnect_on_close":true}
I think that is why there was an error thrown, this JSON is supposed to carry PoseStamped
object, apparently, it was not. (The string was sent by ROSLib through websockets)
@minggangw how would you verify publishing PoseStamped using clientside ROSlib / JSON ?
@minggangw
otherwise, how can the rclnodejs module be implemented in clientside HTML,
where require
is not supported?
const rclnodejs = require('rclnodejs');
rclnodejs.init().then(() => {
const node = rclnodejs.createNode('publisher_example_node');
const publisher = node.createPublisher('std_msgs/msg/String', 'topic');
publisher.publish(`Hello ROS 2 from rclnodejs`);
rclnodejs.spin(node);
});
I tried importing rcl as a module:
<script type="module" src="/ros2-web-bridge/examples/html/publishnode.js"></script>
import {rclnodejs} from '../../node_modules/rclnodejs/index.js'
//const rclnodejs = require('rclnodejs');
rclnodejs.init().then(() => {
const node = rclnodejs.createNode('publisher_example_node');
const publisher = node.createPublisher('std_msgs/msg/String', 'topic');
publisher.publish(`Hello ROS 2 from rclnodejs`);
rclnodejs.spin(node);
});
but how to export it as a module within ros2-web-bridge/node_modules/rclnodejs/index.js ?
The
Time.msg
is ROS2 is different from that of ROS1, please see https://github.com/ros2/rcl_interfaces/blob/master/builtin_interfaces/msg/Time.msg, please reference the example to see if it will work, thanks!
Here is the above Example plugged into the /demo/ index.html
The problem is that even when loaded into the HTML page, the same error is thrown, making it not possible to spin the rclnode publisher:
publisher-message-example.js:19 Uncaught ReferenceError: require is not defined at publisher-message-example.js:19
Expand below for HTML
<!DOCTYPE html>
<html lang="en" class="no-js">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>ROS</title>
<meta name="keywords" content="roslibjs, ros2-web-bridge and rclnodejs" />
<meta name="author" content="ros" />
<link rel="stylesheet" type="text/css" href="css/demo.css" />
<link rel="stylesheet" type="text/css" href="css/component.css" />
<script src="https://static.robotwebtools.org/EventEmitter2/current/eventemitter2.min.js"></script>
<script src="https://static.robotwebtools.org/roslibjs/current/roslib.min.js"></script>
<script src="https://static.robotwebtools.org/EaselJS/current/easeljs.min.js"></script>
<script src="https://static.robotwebtools.org/ros2djs/current/ros2d.min.js"></script>
</head>
<body>
<div id="perspective" class="perspective effect-movedown">
<div class="container">
<div class="wrapper">
<div class="log" id="log"></div>
</div>
</div>
</div>
<script src="publisher-message-example.js"></script>
<script>
let ros = new ROSLIB.Ros();
let bridgeHost = window.location.hostname;
let bridgePort = 9090;
ros.on('connection', function() {
console.log('bridge connected');
});
ros.on('error', function(data) {
console.log('error');
});
ros.on('closed', function() {
console.log('bridge closed');
});
ros.connect('ws://' + bridgeHost + ':' + bridgePort);
let publisher = new rclnodejs(ros, {
divName: 'log',
//width: 400,
//height: 400
});
//let webRosController = new WebRosController(ros, ros2dmap);
//let btnState = new ButtonState();
</script>
</body>
</html>
Hi @mis-eu thanks for your continuous investigation on this issue. require
is kind of CommonJS module concept, which the browser doesn't support directly. Some library, e.g. browserify, can support it in your browser. But rclnodejs
will load a C++ addon that has to use a Node.js, so you cannot import the module in your browser. My suggestion is:
If you have to use the browser to provide a GUI, I suggest you could leverage electron that can support Node.js in your web app, because as you know, rosbridge v2.0 Protocol implemented by this ros2-web-bridge
is designed for ROS 1, aslo the ROSLib library. So it's hard to support full features of ROS2, while the rclnodejs
can support ROS2 well as a Node.js client.
If you can use Node.js directly, I encourage you to migrate to it! rclnodejs
always tracks the latest stable version of ROS2. Hope it's helpful to you, thanks!
Hello @minggangw thanks very much for the extensive examples provided in rclnodejs package as well as the good rclnodejs typescript use-cases documentation.
I suspected the C++ codebase could not be made available to the Browser without a JavaScript loader.
Thanks for confirming this and the electron recommendation,
though the question remains why ROSlib is not tunneling the Pose
and PoseStamped
JSON object correctly. 🤔💭
Maybe you could log in the roslibjs at https://github.com/RobotWebTools/roslibjs/blob/969f568ceeb15600ebea1a5047bca5b34b7e58ad/src/util/workerSocketImpl.js#L27 to see if the JSON string is correct practically when it's being sent, and if you want to do more in ROS2 by JavaScript, using rclnodejs
is a good idea in the long term :smile:
It is interesting that Node is throwing the same error rosbridge returned for the ROSlib JSON of PoseStamped discussed above.
Running node on the publisher-example.js updated to geometry_msgs/msg/PoseStamped
also returns TypeError: Invalid argument: frame_id in Header
The publisher-example.js template only specifies the message Name and Topic, not the object format.
script: $ node publisher-example-posestamped.js
output:
Publishing message: 0
/home/user/ros2-web-bridge/node_modules/rclnodejs/generated/std_msgs/std_msgs__msg__Header.js:71
throw new TypeError('Invalid argument: frame_id in Header');
^
TypeError: Invalid argument: frame_id in Header
at HeaderWrapper.freeze (/home/user/ros2-web-bridge/node_modules/rclnodejs/generated/std_msgs/std_msgs__msg__Header.js:71:15)
at PoseStampedWrapper.freeze (/home/user/ros2-web-bridge/node_modules/rclnodejs/generated/geometry_msgs/geometry_msgs__msg__PoseStamped.js:69:32)
at PoseStampedWrapper.serialize (/home/user/ros2-web-bridge/node_modules/rclnodejs/generated/geometry_msgs/geometry_msgs__msg__PoseStamped.js:75:10)
at Publisher.publish (/home/user/ros2-web-bridge/node_modules/rclnodejs/lib/publisher.js:58:38)
at Timeout.setInterval [as _onTimeout] (/home/user/ros2-web-bridge/publishnode_posestamped.js:26:15)
at ontimeout (timers.js:436:11)
at tryOnTimeout (timers.js:300:5)
at listOnTimeout (timers.js:263:5)
at Timer.processTimers (timers.js:223:10)
PoseStamped is available under installed node_modules under: ros2-web-bridge/node_modules/rclnodejs/generated/geometry_msgs/geometry_msgsmsgPoseStamped.js
and running node on that same publisher-example.js but with geometry_msgs/msg/Twist on /cmd_vel topic throws the same Invalid argument: x in Vector 3 error as with roslibjs
$ node publisher-example-posestamped.js output error:
(node:6128) UnhandledPromiseRejectionWarning: TypeError: Invalid argument: x in Vector3
at Vector3Wrapper.freeze (/home/user/ros2-web-bridge/node_modules/rclnodejs/generated/geometry_msgs/geometry_msgs__msg__Vector3.js:70:15)
at TwistWrapper.freeze (/home/user/ros2-web-bridge/node_modules/rclnodejs/generated/geometry_msgs/geometry_msgs__msg__Twist.js:68:32)
at TwistWrapper.serialize (/home/user/ros2-web-bridge/node_modules/rclnodejs/generated/geometry_msgs/geometry_msgs__msg__Twist.js:74:10)
at Publisher.publish (/home/user/ros2-web-bridge/node_modules/rclnodejs/lib/publisher.js:58:38)
at rclnodejs.init.then (/home/user/ros2-web-bridge/publishnode_nobindings.js:19:13)
(node:6128) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 1)
(node:6128) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
script: publisher-example-twist.js
#!/usr/bin/env node
'use strict';
/* eslint-disable camelcase */
const rclnodejs = require('rclnodejs');
const debug = require('debug')('rclnodejs:publisher');
const Entity = require('./entity.js');
rclnodejs.init().then(() => {
const node = rclnodejs.createNode('publisher_example_node');
const publisher = node.createPublisher('geometry_msgs/msg/Twist', 'cmd_vel');
publisher.publish('cmd_vel');
console.log('cmd_vel');
rclnodejs.spin(node);
});
I think the case is a little mess here, let me clarify it. I tried the example below and it works, and you can verify by writing a subscriber to log the topic you received. My env is: Nodejs v12.20.0, rclnodejs v0.17.0, ROS2 Foxy patch release3.
'use strict';
/* eslint-disable camelcase */
const rclnodejs = require('rclnodejs');
rclnodejs
.init()
.then(() => {
const node = rclnodejs.createNode('publisher_message_example_node');
const publisher = node.createPublisher(
'geometry_msgs/msg/PoseStamped',
'PoseStamped'
);
let count = 0;
setInterval(function () {
publisher.publish({
header: {
stamp: {
sec : 0,
nanosec : 100
},
frame_id : "world" //tf_prefix+"/"+map_frame;
},
pose: {
position: {
x : 0.0,
y : 0.0,
z : 0.0
},
orientation: {
x : 0.0,
y : 0.0,
z : 0.0,
w : 1.0
}
}
});
console.log(`Publish ${++count} messages.`);
}, 1000);
rclnodejs.spin(node);
})
.catch((e) => {
console.log(e);
});
and to subscribe the topic
'use strict';
const rclnodejs = require('../index.js');
rclnodejs
.init()
.then(() => {
const node = rclnodejs.createNode('subscription_message_example_node');
let count = 0;
node.createSubscription(
'geometry_msgs/msg/PoseStamped',
'PoseStamped',
(pose) => {
console.log(`Received message No. ${++count}: `, pose);
}
);
rclnodejs.spin(node);
})
.catch((e) => {
console.log(e);
});
@minggangw Thanks very much!
These validate publishing of PoseStamped
also on WSL2 ROS2 env: Foxy (Debian), Node v10.19.0, rclnodejs v0.17.0
I had to make just one change in the Subscriber script, to require (rclnodejs) instead of (../index.js) as below:
'use strict';
const rclnodejs = require('rclnodjejs');
rclnodejs
.init()
.then(() => {
const node = rclnodejs.createNode('subscription_message_example_node');
let count = 0;
node.createSubscription(
'geometry_msgs/msg/PoseStamped',
'PoseStamped',
(pose) => {
console.log(`Received message No. ${++count}: `, pose);
}
);
rclnodejs.spin(node);
})
.catch((e) => {
console.log(e);
});
That's it 🚀
Hi y'all,
I am using your minimum example to build a publisher for a pose stamped message. I can publishing an empty message, a twist message, but no Pose and no PoseStamped message.
It is creating their publishers as I can echo the topic, but nothing is written into the Pose and PoseStamped topics. Either my way of defining the topic message variable is wrong:
or this is a bug in ROSLIB. You can find my example.html file bellow. It would be great if you could give me hint on how to debug this issue. Thanks in advance!