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

Add ROS 2 action support #645

Merged
merged 76 commits into from
Dec 19, 2023
Merged
Show file tree
Hide file tree
Changes from 74 commits
Commits
Show all changes
76 commits
Select commit Hold shift + click to select a range
7dd2cd4
Add a simple tsconfig.json that allows JavaScript
EzraBrooks Nov 16, 2023
7c2123a
Auto-refactor protos to classes via IntelliSense
EzraBrooks Nov 16, 2023
3b7cc6a
Fix some missing imports
EzraBrooks Nov 16, 2023
1d88c5d
JSDoc syntax fixes for Ros.js
EzraBrooks Nov 16, 2023
c2de695
fix more callback jsdoc issues
EzraBrooks Nov 16, 2023
db78330
fix constructor docs
EzraBrooks Nov 16, 2023
c17d2e6
remove non-type-overlapping superconstructors
EzraBrooks Nov 16, 2023
7e084c7
Comment on weird type
EzraBrooks Nov 16, 2023
1090db7
couple more callback docs
EzraBrooks Nov 16, 2023
92e5c96
Vector3 options actually are optional
EzraBrooks Nov 17, 2023
b1ef2bb
Quaternion options are also actually optional
EzraBrooks Nov 17, 2023
a7d0f05
Pose options are actually optional as well
EzraBrooks Nov 17, 2023
b4970e4
Fix name clobbering in UrdfJoint
EzraBrooks Nov 17, 2023
b5d2314
Fix null case in UrdfSphere
EzraBrooks Nov 17, 2023
2bafd13
fix variable clobbering in `UrdfVisual`
EzraBrooks Nov 17, 2023
193a7b1
fix type of decodeNativeArray
EzraBrooks Nov 17, 2023
a4f01d8
Ignore some issues that aren't trivially fixable
EzraBrooks Nov 17, 2023
5705815
fix XML order of operations issue in urdfmodel
EzraBrooks Nov 17, 2023
e1aea21
Mark last non-trivial errors with ts-expect-error
EzraBrooks Nov 17, 2023
30f4b39
Oops, my autoformat broke single-quote standard
EzraBrooks Nov 17, 2023
2e42eb1
Bump esversion in jshint, decrease it in tsconfig
EzraBrooks Nov 17, 2023
5a4ec44
make jshint happy about "confusing pluses"
EzraBrooks Nov 17, 2023
2515fb8
Fix URDF tests with a quick hack
EzraBrooks Nov 17, 2023
787b89a
less overzealous removal of `options || {}`
EzraBrooks Nov 17, 2023
57f3332
add typescript to grunt
EzraBrooks Nov 17, 2023
3d5b9a1
expect some possible null current implementations
EzraBrooks Nov 17, 2023
24a9d3a
fix some class type errors
EzraBrooks Nov 17, 2023
e5dfbb3
replace deprecated prototype call with super()
EzraBrooks Nov 17, 2023
6c0f71d
Update build output
sea-bass Nov 20, 2023
7e39eff
Use more modern export syntax to enable types
EzraBrooks Nov 27, 2023
c24bc28
fix math index
EzraBrooks Nov 27, 2023
9d9b54b
more type fixes
EzraBrooks Nov 27, 2023
2eb4a98
quaternion type fix
EzraBrooks Nov 27, 2023
b521de2
fix this type AGAIN
EzraBrooks Nov 27, 2023
d607263
fix typescript issues in tests
EzraBrooks Nov 27, 2023
900ccf1
preserve mixin API without using mixin
EzraBrooks Nov 27, 2023
9a142a2
possibly fix topic stream type issues?
EzraBrooks Nov 27, 2023
a98a627
bump jshint again
EzraBrooks Nov 27, 2023
8ccdd43
Have RosTCP return a TopicStream
EzraBrooks Nov 27, 2023
82c438d
adding template types to jsdoc
EzraBrooks Nov 27, 2023
532c31b
simplify build
EzraBrooks Nov 28, 2023
6d372e7
Add action client support
sea-bass Nov 28, 2023
db8e26a
Merge branch 'develop' into add-typescript
EzraBrooks Nov 28, 2023
b12ea1a
lint
sea-bass Nov 6, 2023
7f438af
Implement action server and update example
sea-bass Nov 28, 2023
63744b3
Skip old Fibonacci test
sea-bass Nov 7, 2023
e08790c
Update examples
sea-bass Nov 7, 2023
53c4ca4
Remove old fibonacci test
sea-bass Nov 7, 2023
47e7aff
dDo not remove any ROS 1 functionality
sea-bass Nov 28, 2023
56b3d42
Revert unneeded formatting changes
sea-bass Nov 28, 2023
6770cba
update build
EzraBrooks Nov 28, 2023
b6c0cca
Fix typo from PR comment
sea-bass Nov 14, 2023
81ea422
Fix up more comments
sea-bass Nov 14, 2023
87e75be
Add more docstrings for completeness
sea-bass Nov 14, 2023
b5e943b
Add parameter ROS 2 example
sea-bass Nov 28, 2023
6f1043b
Use a bool instead of a string for true
sea-bass Nov 15, 2023
6629f31
Update actions to use TypeScript
sea-bass Nov 28, 2023
5d3b36a
Merge branch 'develop' into add-typescript
EzraBrooks Nov 28, 2023
7f9d34b
Update actions to latest TypeScript capabilities
sea-bass Nov 28, 2023
ee70d44
Merge remote-tracking branch 'ezra/add-typescript' into ros2-actions
sea-bass Nov 28, 2023
562dfde
Put ES5 module exports back
EzraBrooks Nov 28, 2023
4145d04
Merge remote-tracking branch 'ezra/add-typescript' into ros2-actions
sea-bass Nov 28, 2023
6a63a03
Fix Action advertise types
sea-bass Nov 28, 2023
102603d
Add action cancellation callback
sea-bass Dec 13, 2023
b8343d8
Add cancel callback to action server example
sea-bass Dec 13, 2023
522ff0b
Merge branch 'develop' into add-typescript
EzraBrooks Dec 14, 2023
8007272
remove extraneous templated tsconfig settings
EzraBrooks Dec 14, 2023
f60068b
Merge remote-tracking branch 'origin/develop' into ros2-actions
sea-bass Dec 14, 2023
d2b0619
Merge remote-tracking branch 'ezra/add-typescript' into ros2-actions
sea-bass Dec 14, 2023
872d950
Merge remote-tracking branch 'origin/develop' into ros2-actions
sea-bass Dec 14, 2023
53bc461
Remove lockfile
sea-bass Dec 14, 2023
9f3d91c
Small changes
sea-bass Dec 14, 2023
f6225a2
Remove extraneous HTML lines post merge
sea-bass Dec 14, 2023
afa5e4a
Remove action helper types
sea-bass Dec 14, 2023
34e4b81
Check data type for action callback
sea-bass Dec 14, 2023
8e0c16f
Merge branch 'develop' into ros2-actions
sea-bass Dec 19, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
File renamed without changes.
File renamed without changes.
85 changes: 85 additions & 0 deletions examples/ros2_action_client.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<script src="../build/roslib.js"></script>

<script>
// Connecting to ROS
// -----------------
var ros = new ROSLIB.Ros({
url : 'ws://localhost:9090'
});

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

// The ActionClient
// ----------------

var fibonacciClient = new ROSLIB.Action({
ros : ros,
name : '/fibonacci',
actionType : 'action_tutorials_interfaces/Fibonacci'
});

// Send an action goal
var goal = {order: 5};

var goal_id = fibonacciClient.sendGoal(goal,
function(result) {
console.log('Result for action goal on ' + fibonacciClient.name + ': ' + result.result.sequence);
},
function(feedback) {
console.log('Feedback for action on ' + fibonacciClient.name + ': ' + feedback.partial_sequence);
},
);
</script>
</head>

<body>
<h1>Fibonacci ActionClient Example</h1>
<p>Run the following commands in the terminal then refresh this page. Check the JavaScript
console for the output.</p>
<ol>
<li><tt>ros2 launch rosbridge_server rosbridge_websocket_launch.xml</tt></li>
<li><tt>ros2 run action_tutorials_py fibonacci_action_server</tt></li>
</ol>
<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>
</body>
</html>
74 changes: 74 additions & 0 deletions examples/ros2_action_server.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<script src="../build/roslib.js"></script>

<script>
// Connecting to ROS
// -----------------
var ros = new ROSLIB.Ros({
url : 'ws://localhost:9090'
});

// If there is an error on the backend, an 'error' emit will be emitted.
ros.on('error', function(error) {
console.log(error);
});

// The ActionServer
// ----------------

var fibonacciServer = new ROSLIB.Action({
ros : ros,
name : '/fibonacci',
actionType : 'action_tutorials_interfaces/Fibonacci'
});

var actionCallback = function(goal, id) {
console.log('Received action goal on ' + fibonacciServer.name + ', order: ' + goal.order);
console.log('ID: ' + id);
fibonacciSequence = [];
fibonacciSequence.push(0);
fibonacciSequence.push(1);

// failure case
if (goal.order > 47) {
console.log('Aborting. Value will exceed maximum signed integer value.');
fibonacciServer.setFailed(id);
return;
}

// publish feedback
for (var i = 1; i < goal.order; i++) {
fibonacciSequence.push( fibonacciSequence[i] + fibonacciSequence[i-1] );
console.log('Sending feedback: ' + fibonacciSequence);
fibonacciServer.sendFeedback(id, { partial_sequence : fibonacciSequence });
}

// send result
console.log('Sending result: ' + fibonacciSequence);
fibonacciServer.setSucceeded(id, { sequence: fibonacciSequence });
};
var cancelCallback = function(id) {
console.log('Canceled action with goal ID ' + id);
};

fibonacciServer.advertise(actionCallback, cancelCallback);
</script>
</head>

<body>
<h1>Fibonacci ActionServer Example</h1>
<p>Run the following commands in the terminal then refresh this page. Check the JavaScript
console for the output.</p>
<ol>
<li><tt>ros2 launch rosbridge_server rosbridge_websocket_launch.xml</tt></li>
<li><tt>refresh this page</tt></li>
<li><tt>ros2 run action_tutorials_py fibonacci_action_client</tt>
<br>or<br>
<tt>ros2 action send_goal --feedback /fibonacci action_tutorials_interfaces/action/Fibonacci order:\ 20\ </tt>
</li>
</ol>
</body>
</html>
173 changes: 173 additions & 0 deletions examples/ros2_simple.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<script src="https://static.robotwebtools.org/EventEmitter2/current/eventemitter2.min.js"></script>
<script src="../build/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');

// Publishing a Topic
// ------------------

// First, we create a Topic object with details of the topic's name and message type.
var cmdVel = new ROSLIB.Topic({
ros : ros,
name : '/cmd_vel',
messageType : 'geometry_msgs/Twist'
});

// Then we create the payload to be published. The object we pass in to ros.Message matches the
// fields defined in the geometry_msgs/Twist.msg definition.
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
}
});

// And finally, publish.
cmdVel.publish(twist);

// Subscribing to a Topic
// ----------------------

// Like when publishing a topic, we first create a Topic object with details of the topic's name
// and message type. Note that we can call publish or subscribe on the same topic object.
var listener = new ROSLIB.Topic({
ros : ros,
name : '/listener',
messageType : 'std_msgs/String'
});

// Then we add a callback to be called every time a message is published on this topic.
listener.subscribe(function(message) {
console.log('Received message on ' + listener.name + ': ' + message.data);

// If desired, we can unsubscribe from the topic as well.
listener.unsubscribe();
});

// Calling a service
// -----------------

// First, we create a Service client with details of the service's name and service type.
var addTwoIntsClient = new ROSLIB.Service({
ros : ros,
name : '/add_two_ints',
serviceType : 'example_interfaces/AddTwoInts'
});

// Then we create a Service Request. The object we pass in to ROSLIB.ServiceRequest matches the
// fields defined in the rospy_tutorials AddTwoInts.srv file.
var request = new ROSLIB.ServiceRequest({
a : 1,
b : 2
});

// Finally, we call the /add_two_ints service and get back the results in the callback. The result
// is a ROSLIB.ServiceResponse object.
addTwoIntsClient.callService(request, function(result) {
console.log('Result for service call on ' + addTwoIntsClient.name + ': ' + result.sum);
});

// Advertising a Service
// ---------------------

// The Service object does double duty for both calling and advertising services
var setBoolServer = new ROSLIB.Service({
ros : ros,
name : '/set_bool',
serviceType : 'std_srvs/SetBool'
});

// Use the advertise() method to indicate that we want to provide this service
setBoolServer.advertise(function(request, response) {
console.log('Received service request on ' + setBoolServer.name + ': ' + request.data);
response['success'] = true;
response['message'] = 'Set successfully';
return true;
});

// Getting a param value
// ---------------------

// In ROS 2, params are set in the format 'node_name:param_name'
var favoriteColor = new ROSLIB.Param({
ros : ros,
name : '/add_two_ints_server:use_sim_time'
});

favoriteColor.get(function(value) {
console.log('The value of use_sim_time before setting is ' + value);
});
favoriteColor.set(true);
favoriteColor.get(function(value) {
console.log('The value of use_sim_time after setting is ' + value);
});
</script>
</head>

<body>
<h1>Simple roslib Example</h1>
<p>Run the following commands in the terminal then refresh this page. Check the JavaScript
console for the output.</p>
<ol>
<li><tt>ros2 topic pub /listener std_msgs/msg/String "{ data: 'hello world' }" </tt></li>
<li><tt>ros2 topic echo /cmd_vel</tt></li>
<li><tt>ros2 run demo_nodes_py add_two_ints_server</tt></li>
<li><tt>ros2 launch rosbridge_server rosbridge_websocket_launch.xml</tt></li>
</ol>
<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>
</body>
</html>
6 changes: 3 additions & 3 deletions examples/simple.html
sea-bass marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
Expand Up @@ -65,8 +65,8 @@
// And finally, publish.
cmdVel.publish(twist);

//Subscribing to a Topic
//----------------------
// Subscribing to a Topic
// ----------------------

// Like when publishing a topic, we first create a Topic object with details of the topic's name
// and message type. Note that we can call publish or subscribe on the same topic object.
Expand Down Expand Up @@ -138,7 +138,7 @@
name : 'max_vel_y'
});

//Then we set the value of the param, which is sent to the ROS Parameter Server.
// Then we set the value of the param, which is sent to the ROS Parameter Server.
maxVelX.set(0.8);
maxVelX.get(function(value) {
console.log('MAX VAL: ' + value);
Expand Down
Loading