From 61abb918929e9890e1d3722ee82d5020df8894d9 Mon Sep 17 00:00:00 2001 From: Christian Fritz Date: Sun, 12 Jun 2016 21:31:26 -0700 Subject: [PATCH] Find and parse .action files as required - in addition to .msg and .srv files we can now also require the generation of message classes for actionlib files (.action). This is in preparation for supporting actionlib as well. Example: ```js rosnodejs.initNode('/my_node', { messages: ['std_msgs/String', 'turtlesim/Pose'], services: ['std_srvs/SetBool', "turtlesim/TeleportRelative"], actions: ['actionlib/TwoInts'] }).then((rosNode) => { ... ``` --- index.js | 31 +++++++++++++++++++++++-------- utils/messages.js | 46 ++++++++++++++++++++++++++++++++++++++++------ 2 files changed, 63 insertions(+), 14 deletions(-) diff --git a/index.js b/index.js index 3616599..cef4d31 100644 --- a/index.js +++ b/index.js @@ -136,7 +136,7 @@ let Rosnodejs = { rosNode = new RosNode(nodeName, rosMasterUri); return new Promise((resolve, reject) => { - this.use(options.messages, options.services).then(() => { + this.use(options.messages, options.services, options.actions).then(() => { _checkMasterHelper(resolve, 0); }); }) @@ -165,15 +165,13 @@ let Rosnodejs = { /** create message classes and services classes for all the given * types before calling callback */ - use(messages, services) { + use(messages, services, actions) { const self = this; return new Promise((resolve, reject) => { self._useMessages(messages) - .then(() => { - return self._useServices(services); - }).then(() => { - resolve(); - }); + .then(() => { return self._useServices(services); }) + .then(() => { return self._useActions(actions); }) + .then(() => { resolve(); }); }); }, @@ -194,7 +192,7 @@ let Rosnodejs = { }); }, - /** create message classes for all the given types */ + /** create service classes for all the given types */ _useServices(types) { if (!types || types.length == 0) { return Promise.resolve(); @@ -213,6 +211,23 @@ let Rosnodejs = { }); }, + /** create action classes for all the given types */ + _useActions(types) { + if (!types || types.length == 0) { + return Promise.resolve(); + } + var count = types.length; + return new Promise((resolve, reject) => { + types.forEach(function(type) { + messages.getAction(type, function() { + if (--count == 0) { + resolve(); + } + }); + }); + }); + }, + /** * @return {NodeHandle} for initialized node */ diff --git a/utils/messages.js b/utils/messages.js index ca7e5d9..efe79c5 100644 --- a/utils/messages.js +++ b/utils/messages.js @@ -38,6 +38,16 @@ messages.getServiceResponse = function(messageType, callback) { getMessageFromPackage(messageType, ["srv", "Response"], callback); } +/** ensure the handlers for this action type (goal, result, and + * feedback) are in the registry, create them if they don't exist */ +messages.getAction = function(messageType, callback) { + getMessageFromPackage(messageType, ["action", "Goal"], function() { + getMessageFromPackage(messageType, ["action", "Result"], function() { + getMessageFromPackage(messageType, ["action", "Feedback"], callback); + }); + }); +} + // --------------------------------------------------------- // Registry @@ -61,7 +71,11 @@ var registry = {}; 'SetBool': classdef, ... } - } + }, + action: { Goal: .., + Result: .., + Feedback: .. + } }, 'packagename2': {..} }; @@ -104,25 +118,26 @@ function getMessageFromRegistry(messageType, type) { @param message is the message class definition */ function setMessageInRegistry(messageType, type, message) { + var packageName = getPackageNameFromMessageType(messageType); var messageName = getMessageNameFromMessageType(messageType); if (!registry[packageName]) { - registry[packageName] = { msg: {}, srv: {}}; + registry[packageName] = { msg: {}, srv: {}, action: {}}; } - var kind = type[0]; // "msg" or "srv" + var kind = type[0]; // "msg" or "srv" or "action" if (kind == "msg") { // message registry[packageName][kind][messageName] = message; } else { - // service + // service or action if (!registry[packageName][kind][messageName]) { registry[packageName][kind][messageName] = {}; } - var serviceType = type[1]; // "Request" or "Response" + var serviceType = type[1]; // "Request" or "Response", or "Goal", "Result", "Feedback" registry[packageName][kind][messageName][serviceType] = message; } } @@ -324,9 +339,10 @@ function extractFields(content, details, type, callback) { var lines = content.split('\n'); - if (type[0] != "msg") { + if (type[0] == "srv") { var divider = lines.indexOf("---"); if (type[1] == "Request") { + // request lines = lines.slice(0, divider); } else { // response @@ -334,6 +350,24 @@ function extractFields(content, details, type, callback) { } } + if (type[0] == "action") { + var divider = lines.indexOf("---"); + if (type[1] == "Goal") { + // goal + lines = lines.slice(0, divider); + } else { + var afterFirst = lines.slice(divider+1); + var divider2 = afterFirst.indexOf("---"); + if (type[1] == "Result") { + // result + lines = afterFirst.slice(0, divider2); + } else { + // feedback + lines = afterFirst.slice(divider2+1); + } + } + } + async.forEachSeries(lines, parseLine, function(error) { if (error) { callback(error);