/**
* @fileOverview
* @author Russell Toris - rctoris@wpi.edu
*/
var Topic = require('../core/Topic');
var Message = require('../core/Message');
var EventEmitter2 = require('eventemitter2').EventEmitter2;
/**
* An actionlib action client.
*
* Emits the following events:
* * 'timeout' - If a timeout occurred while sending a goal.
* * 'status' - The status messages received from the action server.
* * 'feedback' - The feedback messages received from the action server.
* * 'result' - The result returned from the action server.
*
* @constructor
* @param {Object} options
* @param {Ros} options.ros - The ROSLIB.Ros connection handle.
* @param {string} options.serverName - The action server name, like '/fibonacci'.
* @param {string} options.actionName - The action message name, like 'actionlib_tutorials/FibonacciAction'.
* @param {number} [options.timeout] - The timeout length when connecting to the action server.
* @param {boolean} [options.omitFeedback] - The flag to indicate whether to omit the feedback channel or not.
* @param {boolean} [options.omitStatus] - The flag to indicate whether to omit the status channel or not.
* @param {boolean} [options.omitResult] - The flag to indicate whether to omit the result channel or not.
*/
function ActionClient(options) {
var that = this;
options = options || {};
this.ros = options.ros;
this.serverName = options.serverName;
this.actionName = options.actionName;
this.timeout = options.timeout;
this.omitFeedback = options.omitFeedback;
this.omitStatus = options.omitStatus;
this.omitResult = options.omitResult;
this.goals = {};
// flag to check if a status has been received
var receivedStatus = false;
// create the topics associated with actionlib
this.feedbackListener = new Topic({
ros : this.ros,
name : this.serverName + '/feedback',
messageType : this.actionName + 'Feedback'
});
this.statusListener = new Topic({
ros : this.ros,
name : this.serverName + '/status',
messageType : 'actionlib_msgs/GoalStatusArray'
});
this.resultListener = new Topic({
ros : this.ros,
name : this.serverName + '/result',
messageType : this.actionName + 'Result'
});
this.goalTopic = new Topic({
ros : this.ros,
name : this.serverName + '/goal',
messageType : this.actionName + 'Goal'
});
this.cancelTopic = new Topic({
ros : this.ros,
name : this.serverName + '/cancel',
messageType : 'actionlib_msgs/GoalID'
});
// advertise the goal and cancel topics
this.goalTopic.advertise();
this.cancelTopic.advertise();
// subscribe to the status topic
if (!this.omitStatus) {
this.statusListener.subscribe(function(statusMessage) {
receivedStatus = true;
statusMessage.status_list.forEach(function(status) {
var goal = that.goals[status.goal_id.id];
if (goal) {
goal.emit('status', status);
}
});
});
}
// subscribe the the feedback topic
if (!this.omitFeedback) {
this.feedbackListener.subscribe(function(feedbackMessage) {
var goal = that.goals[feedbackMessage.status.goal_id.id];
if (goal) {
goal.emit('status', feedbackMessage.status);
goal.emit('feedback', feedbackMessage.feedback);
}
});
}
// subscribe to the result topic
if (!this.omitResult) {
this.resultListener.subscribe(function(resultMessage) {
var goal = that.goals[resultMessage.status.goal_id.id];
if (goal) {
goal.emit('status', resultMessage.status);
goal.emit('result', resultMessage.result);
}
});
}
// If timeout specified, emit a 'timeout' event if the action server does not respond
if (this.timeout) {
setTimeout(function() {
if (!receivedStatus) {
that.emit('timeout');
}
}, this.timeout);
}
}
ActionClient.prototype.__proto__ = EventEmitter2.prototype;
/**
* Cancel all goals associated with this ActionClient.
*/
ActionClient.prototype.cancel = function() {
var cancelMessage = new Message();
this.cancelTopic.publish(cancelMessage);
};
/**
* Unsubscribe and unadvertise all topics associated with this ActionClient.
*/
ActionClient.prototype.dispose = function() {
this.goalTopic.unadvertise();
this.cancelTopic.unadvertise();
if (!this.omitStatus) {this.statusListener.unsubscribe();}
if (!this.omitFeedback) {this.feedbackListener.unsubscribe();}
if (!this.omitResult) {this.resultListener.unsubscribe();}
};
module.exports = ActionClient;