-
Notifications
You must be signed in to change notification settings - Fork 68
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Pose stamped message not published #160
Comments
I can confirm the same problem, the /topic is listed, Could anyone please verify PoseStamped JSON structure below is valid?
|
Sorry for being late, would you please try
to see any useful debug information? |
Thanks very much for your response @minggangw
to which I've tried both: without success
~/ros2-web-bridge$ DEBUG=ros2-web-bridge* node bin/rosbridge.js
ros2-web-bridge:index ROS2 node started +0ms
ros2-web-bridge:index Starting server on port 9090 +1ms
Websocket started on ws://localhost:9090
ros2-web-bridge:Bridge Status level set to error (0) +0ms
ros2-web-bridge:Bridge Web bridge de9db5da-ecd4-4149-98ae-d8f3b6af7173 is created +0ms
(node:24134) DeprecationWarning: Deep requiring like `const uuidv4 = require('uuid/v4');` is deprecated as of [email protected]. Please require the top-level module when using the Node.js CommonJS module or use ECMAScript Modules when bundling for the browser. See https://github.com/uuidjs/uuid#deep-requires-now-deprecated for more information.
ros2-web-bridge:Bridge JSON command received: {"op":"advertise","id":"advertise:/move_base_simple/goal:1","type":"geometry_msgs/PoseStamped","topic":"/move_base_simple/goal","latch":false,"queue_size":100} +991ms
ros2-web-bridge:Bridge advertise a topic: /move_base_simple/goal +1ms
ros2-web-bridge:ResourceProvider Publisher has been created, and the topic name is /move_base_simple/goal. +0ms
ros2-web-bridge:Bridge Suppressed: {"op":"status","level":"none","msg":"OK","id":"advertise:/move_base_simple/goal:1"} +8ms
ros2-web-bridge:Bridge JSON command received: {"op":"publish","id":"publish:/move_base_simple/goal:2","topic":"/move_base_simple/goal","msg":{"isAdvertised":false,"compression":"none","throttle_rate":0,"latch":false,"queue_size":100,"queue_length":0,"reconnect_on_close":true},"latch":false} +35ms
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} +0ms
ros2-web-bridge:Bridge Response: {"op":"status","level":"error","msg":"publish: TypeError: Invalid argument: frame_id in Header","id":"publish:/move_base_simple/goal:2"} +1ms
ros2-web-bridge:Bridge JSON command received: {"op":"advertise","id":"advertise:/pose:3","type":"geometry_msgs/Pose","topic":"/pose","latch":false,"queue_size":100} +1ms
ros2-web-bridge:Bridge advertise a topic: /pose +0ms
ros2-web-bridge:ResourceProvider Publisher has been created, and the topic name is /pose. +39ms
ros2-web-bridge:Bridge Suppressed: {"op":"status","level":"none","msg":"OK","id":"advertise:/pose:3"} +1ms
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
ros2-web-bridge:Bridge JSON command received: {"op":"advertise","id":"advertise:/twist:5","type":"geometry_msgs/Twist","topic":"/twist","latch":false,"queue_size":100} +1ms
ros2-web-bridge:Bridge advertise a topic: /twist +0ms
ros2-web-bridge:ResourceProvider Publisher has been created, and the topic name is /twist. +3ms
ros2-web-bridge:Bridge Suppressed: {"op":"status","level":"none","msg":"OK","id":"advertise:/twist:5"} +2ms
ros2-web-bridge:Bridge JSON command received: {"op":"publish","id":"publish:/twist:6","topic":"/twist","msg":{"linear":{"x":0,"y":1,"z":0},"angular":{"x":0,"y":1,"z":0}},"latch":false} +0ms
ros2-web-bridge:Bridge Publish a topic named /twist with {"linear":{"x":0,"y":1,"z":0},"angular":{"x":0,"y":1,"z":0}} +0ms
ros2-web-bridge:Bridge Suppressed: {"op":"status","level":"none","msg":"OK","id":"publish:/twist:6"} +1ms
ros2-web-bridge:Bridge JSON command received: {"op":"advertise","id":"advertise:/empty:7","type":"std_msgs/Empty","topic":"/empty","latch":false,"queue_size":100} +0ms
|
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 error in Pose is do the errors originate from JSON? /PoseStamped
/pose
|
The |
thanks for the information! unfortunately, the Bridge response Error remains exactly the same as before. No dice. |
Sharing the complete code for verification:
```
<script src="https://static.robotwebtools.org/EventEmitter2/current/eventemitter2.min.js"></script>
<script src="https://static.robotwebtools.org/roslibjs/current/roslib.js"></script>
<script>
// Connecting to ROS
// -----------------
var ros = new ROSLIB.Ros();
// If there is an error on the backend, an 'error' emit will be emitted.
ros.on('error', function(error) {
document.getElementById('connecting').style.display = 'none';
document.getElementById('connected').style.display = 'none';
document.getElementById('closed').style.display = 'none';
document.getElementById('error').style.display = 'inline';
console.log(error);
});
// Find out exactly when we made a connection.
ros.on('connection', function() {
console.log('Connection made!');
document.getElementById('connecting').style.display = 'none';
document.getElementById('error').style.display = 'none';
document.getElementById('closed').style.display = 'none';
document.getElementById('connected').style.display = 'inline';
});
ros.on('close', function() {
console.log('Connection closed.');
document.getElementById('connecting').style.display = 'none';
document.getElementById('connected').style.display = 'none';
document.getElementById('closed').style.display = 'inline';
});
// Create a connection to the rosbridge WebSocket server.
ros.connect('ws://localhost:9090');
// Publish a Topic
var PoseStampedTopic = new ROSLIB.Topic({
ros : ros,
name : '/move_base_simple/goal',
messageType : 'geometry_msgs/PoseStamped'
});
/* ROS1 definition
let PoseStamped = new ROSLIB.Message({
header: {
seq: 0,
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
}
}
});
*/
var PoseStamped = new ROSLIB.Topic({
header: {
stamp: {
sec: 0,
nanosec: 100
},
frame_id: 'main 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
}
}
});
/*ROS2 time message
header: {
stamp: {
sec: 123456,
nanosec: 789,
},
frame_id: 'main frame',
},
name: ['Tom', 'Jerry'],
position: [1, 2],
velocity: [2, 3],
effort: [4, 5, 6],
});
console.log(`Publish ${++count} messages.`);
}, 1000);
rclnodejs.spin(node);
*/
/*
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
*/
// Publish a Topic
var PoseTopic = 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
}
});
var twist_publisher = new ROSLIB.Topic({
ros : ros,
name : '/twist',
messageType : 'geometry_msgs/Twist'
});
var twist_msg = new ROSLIB.Message({
linear: {
x: 0,
y: 1,
z: 0
},
angular: {
x: 0,
y: 1,
z: 0
}
});
var empty_publisher = new ROSLIB.Topic({
ros : ros,
name : '/empty',
messageType : 'std_msgs/Empty'
});
var empty_msg = new ROSLIB.Message({});
var count = 0;
setInterval(() => {
var msg = 'hello from ros2bridge ' + count++;
PoseStampedTopic.publish(PoseStamped);
PoseTopic.publish(pose_msg);
twist_publisher.publish(twist_msg);
empty_publisher.publish(empty_msg);
document.getElementById("publisher").innerText = count;
}, 1000);
</script>
Simple Publisher ExampleThis example will pubilish a topic named "example_topic". Connecting to rosbridge... Connected Error in the backend! Connection closed. 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 |
@minggangw how would you verify publishing PoseStamped using clientside ROSlib / JSON ? |
@minggangw
I tried importing rcl as a module:
but how to export it as a module within ros2-web-bridge/node_modules/rclnodejs/index.js ? |
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 Expand below for HTML
|
Hi @mis-eu thanks for your continuous investigation on this issue.
|
Hello @minggangw 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, |
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 |
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 The publisher-example.js template only specifies the message Name and Topic, not the object format. script: output:
PoseStamped is available under installed node_modules under:
```
// This file is automatically generated by Intel rclnodejs
//
// *** DO NOT EDIT directly
//
'use strict';
const ref = require('ref-napi');
const StructType = require('ref-struct-di')(ref);
const ArrayType = require('ref-array-di')(ref);
const primitiveTypes = require('../../rosidl_gen/primitive_types.js');
const deallocator = require('../../rosidl_gen/deallocator.js');
const translator = require('../../rosidl_gen/message_translator.js');
const HeaderWrapper = require('../../generated/std_msgs/std_msgs__msg__Header.js');
const PoseWrapper = require('../../generated/geometry_msgs/geometry_msgs__msg__Pose.js');
const PoseStampedRefStruct = StructType({
header: HeaderWrapper.refObjectType,
pose: PoseWrapper.refObjectType,
});
const PoseStampedRefArray = ArrayType(PoseStampedRefStruct);
const PoseStampedRefStructArray = StructType({
data: PoseStampedRefArray,
size: ref.types.size_t,
capacity: ref.types.size_t
});
// Define the wrapper class.
class PoseStampedWrapper {
constructor(other) {
this._wrapperFields = {};
if (typeof other === 'object' && other._refObject) {
this._refObject = new PoseStampedRefStruct(other._refObject.toObject());
this._wrapperFields.header = new HeaderWrapper(other._wrapperFields.header);
this._wrapperFields.pose = new PoseWrapper(other._wrapperFields.pose);
} else if (typeof other !== 'undefined') {
this._initMembers();
translator.constructFromPlanObject(this, other);
} else {
this._initMembers();
}
this.freeze();
}
_initMembers() {
this._refObject = new PoseStampedRefStruct();
this._wrapperFields.header = new HeaderWrapper();
this._wrapperFields.pose = new PoseWrapper();
}
static createFromRefObject(refObject) {
let self = new PoseStampedWrapper();
self.copyRefObject(refObject);
return self;
}
static createArray() {
return new PoseStampedArrayWrapper;
}
static get ArrayType() {
return PoseStampedArrayWrapper;
}
static get refObjectArrayType() {
return PoseStampedRefStructArray
}
static get refObjectType() {
return PoseStampedRefStruct;
}
toRawROS() {
this.freeze(true);
return this._refObject.ref();
}
freeze(own = false, checkConsistency = false) {
if (checkConsistency) {
}
this._wrapperFields.header.freeze(own, checkConsistency);
this._refObject.header = this._wrapperFields.header.refObject;
this._wrapperFields.pose.freeze(own, checkConsistency);
this._refObject.pose = this._wrapperFields.pose.refObject;
}
serialize() {
this.freeze(false, true);
return this._refObject.ref();
}
deserialize(refObject) {
this._wrapperFields.header.copyRefObject(refObject.header);
this._wrapperFields.pose.copyRefObject(refObject.pose);
}
toPlainObject(enableTypedArray) {
return translator.toPlainObject(this, enableTypedArray);
}
static freeStruct(refObject) {
HeaderWrapper.freeStruct(refObject.header);
PoseWrapper.freeStruct(refObject.pose);
}
static destoryRawROS(msg) {
PoseStampedWrapper.freeStruct(msg.refObject);
}
static type() {
return {pkgName: 'geometry_msgs', subFolder: 'msg', interfaceName: 'PoseStamped'};
}
static isPrimitive() {
return false;
}
static get isROSArray() {
return false;
}
get refObject() {
return this._refObject;
}
get header() {
return this._wrapperFields.header;
}
set header(value) {
if (value instanceof HeaderWrapper) {
this._wrapperFields.header.copy(value);
} else {
this._wrapperFields.header.copy(new HeaderWrapper(value));
}
}
get pose() {
return this._wrapperFields.pose;
}
set pose(value) {
if (value instanceof PoseWrapper) {
this._wrapperFields.pose.copy(value);
} else {
this._wrapperFields.pose.copy(new PoseWrapper(value));
}
}
copyRefObject(refObject) {
this._refObject = new PoseStampedRefStruct(refObject.toObject());
this._wrapperFields.header.copyRefObject(this._refObject.header);
this._wrapperFields.pose.copyRefObject(this._refObject.pose);
}
copy(other) {
this._refObject = new PoseStampedRefStruct(other._refObject.toObject());
this._wrapperFields.header.copy(other._wrapperFields.header);
this._wrapperFields.pose.copy(other._wrapperFields.pose);
}
static get classType() {
return PoseStampedWrapper;
}
static get ROSMessageDef() {
return {"constants":[],"fields":[{"name":"header","type":{"isArray":false,"arraySize":null,"isUpperBound":false,"isDynamicArray":false,"isFixedSizeArray":false,"pkgName":"std_msgs","type":"Header","stringUpperBound":null,"isPrimitiveType":false},"default_value":null},{"name":"pose","type":{"isArray":false,"arraySize":null,"isUpperBound":false,"isDynamicArray":false,"isFixedSizeArray":false,"pkgName":"geometry_msgs","type":"Pose","stringUpperBound":null,"isPrimitiveType":false},"default_value":null}],"baseType":{"pkgName":"geometry_msgs","type":"PoseStamped","stringUpperBound":null,"isPrimitiveType":false},"msgName":"PoseStamped"};
}
hasMember(name) {
let memberNames = ["header","pose"];
return memberNames.indexOf(name) !== -1;
}
}
// Define the wrapper of array class.
class PoseStampedArrayWrapper {
constructor(size = 0) {
this._resize(size);
}
toRawROS() {
return this._refObject.ref();
}
fill(values) {
const length = values.length;
this._resize(length);
values.forEach((value, index) => {
if (value instanceof PoseStampedWrapper) {
this._wrappers[index].copy(value);
} else {
this._wrappers[index] = new PoseStampedWrapper(value);
}
});
}
// Put all data currently stored in `this._wrappers` into `this._refObject`
freeze(own) {
this._wrappers.forEach((wrapper, index) => {
wrapper.freeze(own);
this._refArray[index] = wrapper.refObject;
});
this._refObject.size = this._wrappers.length;
this._refObject.capacity = this._wrappers.length;
if (this._refObject.capacity === 0) {
this._refObject.data = null
} else {
this._refObject.data = this._refArray.buffer;
}
}
get refObject() {
return this._refObject;
}
get data() {
return this._wrappers;
}
get size() {
return this._wrappers.length;
}
set size(value) {
if (typeof value != 'number') {
throw new TypeError('Invalid argument: should provide a number to PoseStampedArrayWrapper.size setter');
return;
}
return this._resize(value);
}
get capacity() {
return this._wrappers.length;
}
set capacity(value) {
if (typeof value != 'number') {
throw new TypeError('Invalid argument: should provide a number to PoseStampedArrayWrapper.capacity setter');
}
return this._resize(value);
}
get refObject() {
return this._refObject;
}
_resize(size) {
if (size < 0) {
throw new RangeError('Invalid argument: should provide a positive number');
return;
}
this._refArray = new PoseStampedRefArray(size);
this._refObject = new PoseStampedRefStructArray();
this._refObject.size = size;
this._refObject.capacity = size;
this._wrappers = new Array();
for (let i = 0; i < size; i++) {
this._wrappers.push(new PoseStampedWrapper());
}
}
// Copy all data from `this._refObject` into `this._wrappers`
copyRefObject(refObject) {
this._refObject = refObject;
let refObjectArray = this._refObject.data;
refObjectArray.length = this._refObject.size;
this._resize(this._refObject.size);
for (let index = 0; index < this._refObject.size; index++) {
this._wrappers[index].copyRefObject(refObjectArray[index]);
}
}
copy(other) {
if (! (other instanceof PoseStampedArrayWrapper)) {
throw new TypeError('Invalid argument: should provide "PoseStampedArrayWrapper".');
}
this._resize(other.size);
// Array deep copy
other._wrappers.forEach((wrapper, index) => {
this._wrappers[index].copy(wrapper);
});
}
static freeArray(refObject) {
let refObjectArray = refObject.data;
refObjectArray.length = refObject.size;
for (let index = 0; index < refObject.size; index++) {
PoseStampedWrapper.freeStruct(refObjectArray[index]);
}
}
static get elementType() {
return PoseStampedWrapper;
}
static get isROSArray() {
return true;
}
static get useTypedArray() {
return false;
}
get classType() {
return PoseStampedArrayWrapper;
}
}
module.exports = PoseStampedWrapper;
/*
* The following is the original spec object coming from parser:
{
"constants": [],
"fields": [
{
"name": "header",
"type": {
"isArray": false,
"arraySize": null,
"isUpperBound": false,
"isDynamicArray": false,
"isFixedSizeArray": false,
"pkgName": "std_msgs",
"type": "Header",
"stringUpperBound": null,
"isPrimitiveType": false
},
"default_value": null
},
{
"name": "pose",
"type": {
"isArray": false,
"arraySize": null,
"isUpperBound": false,
"isDynamicArray": false,
"isFixedSizeArray": false,
"pkgName": "geometry_msgs",
"type": "Pose",
"stringUpperBound": null,
"isPrimitiveType": false
},
"default_value": null
}
],
"baseType": {
"pkgName": "geometry_msgs",
"type": "PoseStamped",
"stringUpperBound": null,
"isPrimitiveType": false
},
"msgName": "PoseStamped"
}
*/
```
|
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
script:
|
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 I had to make just one change in the Subscriber script, to require (rclnodejs) instead of (../index.js) as below:
|
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!
The text was updated successfully, but these errors were encountered: