Using rosbridge to develop a web version of action client.
1: rosbridge principle:
rosbridge protocol: the basic idea of this protocol is to change the distributed communication between nodes into "client node" for C/S communication with a proxy node, and then the proxy node forwards the request to the server node, so that the client does not need to implement the whole ROS platform, but only needs to communicate with the proxy node.
The web page encapsulates the published information into json and parses it to the proxy node through websocket. The proxy node can be transformed into a ros node to communicate and publish it to the Server.
Official rosbridge tutorial: rosbridge
Introduction to ROSBridge and understanding the use of Blog: rosbridge
2, Simple executable analysis:
Code for web page implementation:
Part I: link to two roslib.js. The two official files are used to link to the local websocket to interact with ros.
<script type="text/javascript" src="http://static.robotwebtools.org/EventEmitter2/current/eventemitter2.min.js"></script> <script type="text/javascript" src="http://static.robotwebtools.org/roslibjs/current/roslib.min.js"></script>
Part II: publish and subscribe information.
/*Send information to the node and create a topic with the name '/ position' and the message type 'geometry'_ msgs/Twist'*/ var cmdVel = new ROSLIB.Topic({ ros : ros, name : '/position', messageType : 'geometry_msgs/Twist' }); var twist = new ROSLIB.Message({ linear : { x : 0.1, y : 0.2, z : 0.3 }, angular : { x : -0.1, y : -0.2, z : -0.3 } });//Create a message function func()//Post the message after clicking the "Publish" button { cmdVel.publish(twist);//Post twist message } /*Get information from node*/ var listener = new ROSLIB.Topic({ ros : ros, name : '/chatter', messageType : 'std_msgs/String' }); //Create a topic with the name '/ chatter' and the message type 'STD'_ msgs/String' function subscribe()//After clicking the "Subscribe" button, Subscribe to the message of '/ chatter' and display it in the web page { listener.subscribe(function(message) { document.getElementById("output").innerHTML = ('Received message on ' + listener.name + ': ' + message.data); }); }
Start the websocket proxy node locally, listen to the information from the port, and then start the server node to communicate:
$roslaunch rosbridge_server rosbridge_websocket.launch
Summary: the above communication method is simple topic communication. No custom information content. It uses the official information format: geometry_msgs/Twist and std_msgs/String.
2: Problem Description: the official rosbridge action communication example:
The code is as follows (only see the code of the definition message part and the complete code appendix)
var fibonacciClient = new ROSLIB.ActionClient({ ros : ros, serverName : '/fibonacci', actionName : 'actionlib_tutorials/FibonacciAction' }); var goal = new ROSLIB.Goal({ actionClient : fibonacciClient, goalMessage : { order : 7 } }); goal.on('feedback', function(feedback) { console.log('Feedback: ' + feedback.sequence); }); goal.on('result', function(result) { console.log('Final Result: ' + result.sequence); }); ros.on('connection', function() { console.log('Connected to websocket server.'); }); ros.on('error', function(error) { console.log('Error connecting to websocket server: ', error); }); ros.on('close', function() { console.log('Connection to websocket server closed.'); }); goal.send(); </html>
Question: the message definition of this action is' actionlib '_ tutorials/FibonacciAction'. It is also a message format that can be directly recognized. The question now is: how to use custom action messages on Web pages
Scheme 1: because web pages do not recognize header files, js and c + + are also completely two languages. I need to find out where the official message definition is? How is it defined?
The two js linked on the web page have no message customization. But in the official rosbridge_ There are many message defined function packages in the library folder of the server package, as shown in the figure:
├── CHANGELOG.rst ├── CMakeLists.txt ├── msg #Define message │ ├── Num.msg #Define digital messages │ ├── TestChar.msg #Define character message │ ├── TestDurationArray.msg #Define Duration array messages │ ├── TestHeaderArray.msg #Define Header array messages │ ├── TestHeader.msg #Define Header message │ ├── TestHeaderTwo.msg #Define Header message │ ├── TestTimeArray.msg #Define Time array messages │ ├── TestUInt8FixedSizeArray16.msg #Define Unit8[16] message │ └── TestUInt8.msg #Define Unit8 [] message ├── package.xml ├── setup.py #python installation script ├── src │ └── rosbridge_library #Core library │ ├── capabilities #Function pack │ │ ├── advertise.py #Perform broadcast and cancellation of topics │ │ ├── advertise_service.py #Broadcast of execution service │ │ ├── call_service.py #Call service │ │ ├── defragmentation.py #Parsing message content │ │ ├── fragmentation.py #Encapsulate message content │ │ ├── __init__.py #Declare as Python Library │ │ ├── publish.py #Release topic │ │ ├── service_response.py #Service feedback processing │ │ ├── subscribe.py #Subscribe to topics │ │ └── unadvertise_service.py #Cancel service broadcast │ ├── capability.py │ ├── __init__.py │ ├── internal #Internal function realization │ │ ├── exceptions.py #exception handling │ │ ├── __init__.py │ │ ├── message_conversion.py #Message conversion │ │ ├── pngcompression.py #image compression │ │ ├── publishers.py #Tracks clients that use a particular publisher. Provides API s for publishing messages and registering clients that use this publisher │ │ ├── ros_loader.py #ros related core class import │ │ ├── services.py #Create a service caller for a specific service, start a separate thread with start(), or use the run() function in the thread. │ │ ├── subscribers.py #Manage and interface with ROS subscriber object. A single subscriber is shared among multiple clients │ │ ├── subscription_modifiers.py #It is a publishing method between incoming and outgoing messages from subscriptions and provides restriction / buffering functions. When parameters change, handlers can be converted to different types of handlers │ │ └── topics.py #Code and exception handling common to publishers and subscribers │ ├── protocol.py #The interface between a single client and ROS │ ├── rosbridge_protocol.py #Inherit the protocol protocol and initialize the rosbridge function list │ └── util │ └── __init__.py ├── srv #Service definition │ ├── AddTwoInts.srv # │ ├── SendBytes.srv #Send content definition │ ├── TestArrayRequest.srv │ ├── TestEmpty.srv │ ├── TestMultipleRequestFields.srv │ ├── TestMultipleResponseFields.srv │ ├── TestNestedService.srv │ ├── TestRequestAndResponse.srv │ ├── TestRequestOnly.srv │ └── TestResponseOnly.srv └── test #Relevant tests, including core functions, extended functions and internal execution
At present, the idea is to find out the official definition method, and then learn to customize action s.
Scheme 2: split action communication into basic communication mode. (standby, preferably user-defined action communication)
For more detailed action s, please refer to Official website tutorial
action code appendix:
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <script src="http://static.robotwebtools.org/EventEmitter2/current/eventemitter2.js"></script> <script src="http://static.robotwebtools.org/roslibjs/current/roslib.js"></script> <script> var ros = new ROSLIB.Ros({ url : 'ws://localhost:9090' }); var fibonacciClient = new ROSLIB.ActionClient({ ros : ros, serverName : '/fibonacci', actionName : 'actionlib_tutorials/FibonacciAction' }); var goal = new ROSLIB.Goal({ actionClient : fibonacciClient, goalMessage : { order : 7 } }); goal.on('feedback', function(feedback) { console.log('Feedback: ' + feedback.sequence); }); goal.on('result', function(result) { console.log('Final Result: ' + result.sequence); }); ros.on('connection', function() { console.log('Connected to websocket server.'); }); ros.on('error', function(error) { console.log('Error connecting to websocket server: ', error); }); ros.on('close', function() { console.log('Connection to websocket server closed.'); }); goal.send(); </script> </head> <body> <h1>Fibonacci ActionClient Example</h1> <p>Check the Web Console for output</p> </body> </html>