Skip to content
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

Open
DentOpt opened this issue Dec 7, 2020 · 20 comments
Open

Pose stamped message not published #160

DentOpt opened this issue Dec 7, 2020 · 20 comments

Comments

@DentOpt
Copy link

DentOpt commented Dec 7, 2020

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:

var posestamped_msg = 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
             }
           }
 });

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!

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<script src="https://static.robotwebtools.org/EventEmitter2/current/eventemitter2.min.js"></script>
<script src="https://static.robotwebtools.org/roslibjs/current/roslib.js"></script>
<!--<script src="js/include/jscontroller/posestamped.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 posestamped_publisher = new ROSLIB.Topic({
    ros : ros,
    name : '/posestamped',
    messageType : 'geometry_msgs/PoseStamped'
  });

  var posestamped_msg = 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
              }
            }
  });

  // Publish a Topic
  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
    }        
  });

  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++;
    
    posestamped_publisher.publish(posestamped_msg);
    pose_publisher.publish(pose_msg);
    twist_publisher.publish(twist_msg);
    empty_publisher.publish(empty_msg);
    document.getElementById("publisher").innerText = count;
  }, 1000);
</script>
</head>

<body>
  <h1>Simple Publisher Example</h1>
  <p>This example will pubilish a topic named "example_topic".</p>
  <div id="statusIndicator">
    <p id="connecting">
      Connecting to rosbridge...
    </p>
    <p id="connected" style="color:#00D600; display:none">
      Connected
    </p>
    <p id="error" style="color:#FF0000; display:none">
      Error in the backend!
    </p>
    <p id="closed" style="display:none">
      Connection closed.
    </p>
  </div>
  <div>
    <p>
      <b>Publish message: </b>
      <span id="publisher"></span>
    </p>
  </div>
</body>
</html>
@mis-eu
Copy link

mis-eu commented Dec 9, 2020

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
                }
            }
        });

@minggangw
Copy link
Member

Sorry for being late, would you please try

DEBUG=ros2-web-bridge* node bin/rosbridge.js

to see any useful debug information?

@mis-eu
Copy link

mis-eu commented Dec 9, 2020

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

~/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

@minggangw
Copy link
Member

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

@mis-eu
Copy link

mis-eu commented Dec 9, 2020

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
    }
  });

@minggangw
Copy link
Member

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!

@mis-eu
Copy link

mis-eu commented Dec 9, 2020

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.

@mis-eu
Copy link

mis-eu commented Dec 9, 2020

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 Example

This example will pubilish a topic named "example_topic".

Connecting to rosbridge...

Connected

Error in the backend!

Connection closed.

Publish message:

```

@minggangw
Copy link
Member

  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)

@mis-eu
Copy link

mis-eu commented Dec 9, 2020

@minggangw how would you verify publishing PoseStamped using clientside ROSlib / JSON ?

@mis-eu
Copy link

mis-eu commented Dec 9, 2020

@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 ?

@mis-eu
Copy link

mis-eu commented Dec 10, 2020

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>

@minggangw
Copy link
Member

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!

@mis-eu
Copy link

mis-eu commented Dec 10, 2020

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. 🤔💭

@minggangw
Copy link
Member

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 😄

@mis-eu
Copy link

mis-eu commented Dec 11, 2020

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_msgs__msg__PoseStamped.js

``` // 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" } */ ```

@mis-eu
Copy link

mis-eu commented Dec 11, 2020

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);
});

@minggangw
Copy link
Member

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);
  });

@mis-eu
Copy link

mis-eu commented Dec 13, 2020

@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);
  });

image
image

@minggangw
Copy link
Member

That's it 🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants